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.
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>
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>
29 #include "fat_protos.h"
31 #define DEBUG DEBUG_MISC
37 static LONG
InitDiskHandler(struct Globals
*glob
);
38 static void CleanupDiskHandler(struct Globals
*glob
);
40 static void InitCharsetTables(struct Globals
*glob
)
44 for (i
= 0; i
< 65536; i
++)
48 glob
->from_unicode
[i
] = i
;
49 glob
->to_unicode
[i
] = i
;
52 glob
->from_unicode
[i
] = '_';
56 static struct Globals
*fat_init(struct Process
*proc
, struct DosPacket
*dp
,
57 struct ExecBase
*SysBase
)
61 glob
= AllocVec(sizeof(struct Globals
), MEMF_ANY
| MEMF_CLEAR
);
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
,
80 glob
->notifyport
= CreateMsgPort();
82 glob
->fssm
= BADDR(dp
->dp_Arg2
);
84 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
,
87 LONG error
= InitTimer(glob
);
90 InitCharsetTables(glob
);
91 if ((error
= InitDiskHandler(glob
)) == 0)
98 DeletePool(glob
->mempool
);
101 CloseLibrary(glob
->gl_UtilityBase
);
104 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
113 static void fat_exit(struct Globals
*glob
)
115 struct ExecBase
*SysBase
= glob
->gl_SysBase
;
116 CleanupDiskHandler(glob
);
118 DeletePool(glob
->mempool
);
120 DeleteMsgPort(glob
->notifyport
);
122 CloseLibrary(glob
->gl_UtilityBase
);
123 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
128 LONG
handler(struct ExecBase
*SysBase
)
130 struct Globals
*glob
;
131 struct Process
*proc
;
133 struct DosPacket
*dp
;
135 D(bug("%s: start\n", __func__
));
137 proc
= (struct Process
*)FindTask(NULL
);
138 mp
= &proc
->pr_MsgPort
;
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
);
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
);
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
;
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
;
172 ReplyPacket(dp
, SysBase
);
174 D(bug("Handler init finished.\n"));
177 ProcessDiskChange(glob
);
182 if (sigs
& diskchgsig
)
183 ProcessDiskChange(glob
);
185 ProcessPackets(glob
);
186 if (sigs
& notifysig
)
192 D(bug("\nHandler shutdown initiated\n"));
196 if (glob
->death_packet
!= NULL
)
197 ReplyPacket(glob
->death_packet
, SysBase
);
201 D(bug("The end.\n"));
206 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
210 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
212 Signal(MyIntData
->task
, MyIntData
->signal
);
218 static LONG
InitDiskHandler(struct Globals
*glob
)
220 struct ExecBase
*SysBase
= glob
->gl_SysBase
;
221 struct FileSysStartupMsg
*fssm
= glob
->fssm
;
223 ULONG diskchgintbit
, flags
;
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
=
261 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
=
263 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
=
265 glob
->DiskChangeIntData
.Interrupt
.is_Data
=
266 &glob
->DiskChangeIntData
;
267 glob
->DiskChangeIntData
.Interrupt
.is_Code
=
269 AROS_ASMSYMNAME(DiskChangeIntHandler
);
271 /* Fill I/O request data */
272 glob
->diskchgreq
->iotd_Req
.io_Command
=
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"));
287 err
= ERROR_NO_FREE_STORE
;
289 CloseDevice((struct IORequest
*)glob
->diskioreq
);
292 err
= ERROR_DEVICE_NOT_MOUNTED
;
294 DeleteIORequest(glob
->diskioreq
);
295 glob
->diskioreq
= NULL
;
298 err
= ERROR_NO_FREE_STORE
;
300 DeleteMsgPort(glob
->diskport
);
301 glob
->diskport
= NULL
;
304 err
= ERROR_NO_FREE_STORE
;
306 FreeSignal(diskchgintbit
);
308 glob
->diskchgsig_bit
= 0;
311 err
= ERROR_NO_FREE_STORE
;
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
);