revert between 56095 -> 55830 in arch
[AROS.git] / rom / filesys / fat / main.c
blob43f02fcfe70d1382f2af313e3abb389eaa5cf752
1 /*
2 * fat-handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2015 The AROS Development Team
7 * This program is free software; you can redistribute it and/or modify it
8 * under the same terms as AROS itself.
10 * $Id$
13 #include <aros/asmcall.h>
14 #include <aros/macros.h>
15 #include <exec/types.h>
16 #include <exec/execbase.h>
17 #include <exec/memory.h>
18 #include <dos/dos.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <dos/filehandler.h>
22 #include <devices/trackdisk.h>
24 #include <proto/exec.h>
26 #include <string.h>
28 #include "fat_fs.h"
29 #include "fat_protos.h"
31 #define DEBUG DEBUG_MISC
32 #include "debug.h"
34 #undef SysBase
35 #undef UtilityBase
37 static LONG InitDiskHandler(struct Globals *glob);
38 static void CleanupDiskHandler(struct Globals *glob);
40 static void InitCharsetTables(struct Globals *glob)
42 int i;
44 for (i = 0; i < 65536; i++)
46 if (i < 256)
48 glob->from_unicode[i] = i;
49 glob->to_unicode[i] = i;
51 else
52 glob->from_unicode[i] = '_';
56 static struct Globals *fat_init(struct Process *proc, struct DosPacket *dp,
57 struct ExecBase *SysBase)
59 struct Globals *glob;
61 glob = AllocVec(sizeof(struct Globals), MEMF_ANY | MEMF_CLEAR);
62 if (glob)
64 glob->gl_SysBase = SysBase;
65 if ((glob->gl_DOSBase =
66 (struct DosLibrary *)OpenLibrary("dos.library", 0)))
68 if ((glob->gl_UtilityBase = OpenLibrary("utility.library", 0)))
70 NEWLIST(&glob->sblist);
71 glob->ourtask = &proc->pr_Task;
72 glob->ourport = &proc->pr_MsgPort;
74 glob->devnode = BADDR(dp->dp_Arg3);
76 D(bug("\nFATFS: opening libraries.\n"));
77 D(bug("\tFS task: %lx, port %lx\n", glob->ourtask,
78 glob->ourport));
80 glob->notifyport = CreateMsgPort();
82 glob->fssm = BADDR(dp->dp_Arg2);
84 if ((glob->mempool = CreatePool(MEMF_PUBLIC, DEF_POOL_SIZE,
85 DEF_POOL_THRESHOLD)))
87 LONG error = InitTimer(glob);
88 if (!error)
90 InitCharsetTables(glob);
91 if ((error = InitDiskHandler(glob)) == 0)
93 return glob;
96 CleanupTimer(glob);
98 DeletePool(glob->mempool);
101 CloseLibrary(glob->gl_UtilityBase);
104 CloseLibrary((struct Library *)glob->gl_DOSBase);
107 FreeVec(glob);
110 return NULL;
113 static void fat_exit(struct Globals *glob)
115 struct ExecBase *SysBase = glob->gl_SysBase;
116 CleanupDiskHandler(glob);
117 CleanupTimer(glob);
118 DeletePool(glob->mempool);
120 DeleteMsgPort(glob->notifyport);
122 CloseLibrary(glob->gl_UtilityBase);
123 CloseLibrary((struct Library *)glob->gl_DOSBase);
125 FreeVec(glob);
128 LONG handler(struct ExecBase *SysBase)
130 struct Globals *glob;
131 struct Process *proc;
132 struct MsgPort *mp;
133 struct DosPacket *dp;
135 D(bug("%s: start\n", __func__));
137 proc = (struct Process *)FindTask(NULL);
138 mp = &proc->pr_MsgPort;
139 WaitPort(mp);
140 dp = (struct DosPacket *)GetMsg(mp)->mn_Node.ln_Name;
142 D(bug("%s: mp=%p, path='%b'\n", __func__, mp, dp->dp_Arg1));
144 glob = fat_init(proc, dp, SysBase);
146 if (!glob)
148 D(bug("%s: %b - error %d\n", __func__, dp->dp_Arg1, RETURN_FAIL));
149 dp->dp_Res1 = DOSFALSE;
150 dp->dp_Res2 = ERROR_NO_FREE_STORE;
151 ReplyPacket(dp, SysBase);
152 return RETURN_FAIL;
154 else
156 ULONG pktsig = 1 << glob->ourport->mp_SigBit;
157 ULONG diskchgsig = 1 << glob->diskchgsig_bit;
158 ULONG notifysig = 1 << glob->notifyport->mp_SigBit;
159 ULONG timersig = 1 << glob->timerport->mp_SigBit;
160 ULONG mask = pktsig | diskchgsig | notifysig | timersig;
161 ULONG sigs;
163 D(bug("\tInitiated device: %s\n",
164 AROS_BSTR_ADDR(glob->devnode->dol_Name)));
166 glob->devnode->dol_Task = glob->ourport;
168 D(bug("[fat] returning startup packet\n"));
170 dp->dp_Res1 = DOSTRUE;
171 dp->dp_Res2 = 0;
172 ReplyPacket(dp, SysBase);
174 D(bug("Handler init finished.\n"));
176 /* Insert disk */
177 ProcessDiskChange(glob);
179 while (!glob->quit)
181 sigs = Wait(mask);
182 if (sigs & diskchgsig)
183 ProcessDiskChange(glob);
184 if (sigs & pktsig)
185 ProcessPackets(glob);
186 if (sigs & notifysig)
187 ProcessNotify(glob);
188 if (sigs & timersig)
189 HandleTimer(glob);
192 D(bug("\nHandler shutdown initiated\n"));
194 dp = NULL;
196 if (glob->death_packet != NULL)
197 ReplyPacket(glob->death_packet, SysBase);
199 fat_exit(glob);
201 D(bug("The end.\n"));
203 return RETURN_OK;
206 static AROS_INTH1(DiskChangeIntHandler, struct IntData *, MyIntData)
208 AROS_INTFUNC_INIT
210 struct ExecBase *SysBase = MyIntData->SysBase;
212 Signal(MyIntData->task, MyIntData->signal);
213 return 0;
215 AROS_INTFUNC_EXIT
218 static LONG InitDiskHandler(struct Globals *glob)
220 struct ExecBase *SysBase = glob->gl_SysBase;
221 struct FileSysStartupMsg *fssm = glob->fssm;
222 LONG err;
223 ULONG diskchgintbit, flags;
224 IPTR unit;
225 UBYTE *device;
227 unit = fssm->fssm_Unit;
228 flags = fssm->fssm_Flags;
230 device = AROS_BSTR_ADDR(fssm->fssm_Device);
232 if ((diskchgintbit = AllocSignal(-1)) >= 0)
234 glob->diskchgsig_bit = diskchgintbit;
236 if ((glob->diskport = CreateMsgPort()))
239 if ((glob->diskioreq = CreateIORequest(glob->diskport,
240 sizeof(struct IOExtTD))))
242 if (OpenDevice(device, unit,
243 (struct IORequest *)glob->diskioreq, flags) == 0)
245 D(bug("\tDevice successfully opened\n"));
246 Probe64BitSupport(glob);
248 if ((glob->diskchgreq =
249 AllocVec(sizeof(struct IOExtTD), MEMF_PUBLIC)))
251 CopyMem(glob->diskioreq, glob->diskchgreq,
252 sizeof(struct IOExtTD));
254 /* Fill interrupt data */
255 glob->DiskChangeIntData.SysBase = SysBase;
256 glob->DiskChangeIntData.task = glob->ourtask;
257 glob->DiskChangeIntData.signal = 1 << diskchgintbit;
259 glob->DiskChangeIntData.Interrupt.is_Node.ln_Type =
260 NT_INTERRUPT;
261 glob->DiskChangeIntData.Interrupt.is_Node.ln_Pri =
263 glob->DiskChangeIntData.Interrupt.is_Node.ln_Name =
264 "FATFS";
265 glob->DiskChangeIntData.Interrupt.is_Data =
266 &glob->DiskChangeIntData;
267 glob->DiskChangeIntData.Interrupt.is_Code =
268 (VOID_FUNC)
269 AROS_ASMSYMNAME(DiskChangeIntHandler);
271 /* Fill I/O request data */
272 glob->diskchgreq->iotd_Req.io_Command =
273 TD_ADDCHANGEINT;
274 glob->diskchgreq->iotd_Req.io_Data =
275 &glob->DiskChangeIntData.Interrupt;
276 glob->diskchgreq->iotd_Req.io_Length =
277 sizeof(struct Interrupt);
278 glob->diskchgreq->iotd_Req.io_Flags = 0;
280 SendIO((struct IORequest *)glob->diskchgreq);
282 D(bug("\tDisk change interrupt handler installed\n"));
284 return 0;
286 else
287 err = ERROR_NO_FREE_STORE;
289 CloseDevice((struct IORequest *)glob->diskioreq);
291 else
292 err = ERROR_DEVICE_NOT_MOUNTED;
294 DeleteIORequest(glob->diskioreq);
295 glob->diskioreq = NULL;
297 else
298 err = ERROR_NO_FREE_STORE;
300 DeleteMsgPort(glob->diskport);
301 glob->diskport = NULL;
303 else
304 err = ERROR_NO_FREE_STORE;
306 FreeSignal(diskchgintbit);
308 glob->diskchgsig_bit = 0;
310 else
311 err = ERROR_NO_FREE_STORE;
313 return err;
316 static void CleanupDiskHandler(struct Globals *glob)
318 struct ExecBase *SysBase = glob->gl_SysBase;
320 D(bug("\tFreeing handler resources:\n"));
322 /* Remove disk change interrupt */
323 glob->diskchgreq->iotd_Req.io_Command = TD_REMCHANGEINT;
324 glob->diskchgreq->iotd_Req.io_Data = &glob->DiskChangeIntData.Interrupt;
325 glob->diskchgreq->iotd_Req.io_Length = sizeof(struct Interrupt);
326 glob->diskchgreq->iotd_Req.io_Flags = 0;
328 DoIO((struct IORequest *)glob->diskchgreq);
329 D(bug("\tDisk change interrupt handler removed\n"));
331 CloseDevice((struct IORequest *)glob->diskioreq);
332 DeleteIORequest(glob->diskioreq);
333 FreeVec(glob->diskchgreq);
334 DeleteMsgPort(glob->diskport);
335 D(bug("\tDevice closed\n"));
337 glob->diskioreq = NULL;
338 glob->diskchgreq = NULL;
339 glob->diskport = NULL;
341 FreeSignal(glob->diskchgsig_bit);
343 D(bug("\tDone.\n"));