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 void InitCharsetTables(struct Globals
*glob
)
41 for (i
= 0; i
< 65536; i
++)
43 glob
->from_unicode
[i
] = i
;
44 glob
->to_unicode
[i
] = i
;
46 glob
->from_unicode
[i
] = '_';
49 static struct Globals
*fat_init(struct Process
*proc
, struct DosPacket
*dp
, struct ExecBase
*SysBase
)
53 glob
= AllocVec(sizeof(struct Globals
), MEMF_ANY
| MEMF_CLEAR
);
55 glob
->gl_SysBase
= SysBase
;
56 if ((glob
->gl_DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 0))) {
57 if ((glob
->gl_UtilityBase
= OpenLibrary("utility.library", 0))) {
58 NEWLIST(&glob
->sblist
);
59 glob
->ourtask
= &proc
->pr_Task
;
60 glob
->ourport
= &proc
->pr_MsgPort
;
62 glob
->devnode
= BADDR(dp
->dp_Arg3
);
64 D(bug("\nFATFS: opening libraries.\n"));
65 D(bug("\tFS task: %lx, port %lx\n", glob
->ourtask
, glob
->ourport
));
67 glob
->notifyport
= CreateMsgPort();
69 glob
->fssm
= BADDR(dp
->dp_Arg2
);
71 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
, DEF_POOL_THRESHOLD
))) {
72 LONG error
= InitTimer(glob
);
74 InitCharsetTables(glob
);
75 if ((error
= InitDiskHandler(glob
)) == 0) {
81 DeletePool(glob
->mempool
);
84 CloseLibrary(glob
->gl_UtilityBase
);
87 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
96 static void fat_exit(struct Globals
*glob
)
98 struct ExecBase
*SysBase
= glob
->gl_SysBase
;
99 CleanupDiskHandler(glob
);
101 DeletePool(glob
->mempool
);
103 DeleteMsgPort(glob
->notifyport
);
105 CloseLibrary(glob
->gl_UtilityBase
);
106 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
111 LONG
handler(struct ExecBase
*SysBase
) {
112 struct Globals
*glob
;
113 struct Process
*proc
;
115 struct DosPacket
*dp
;
117 D(bug("%s: start\n", __func__
));
119 proc
= (struct Process
*)FindTask(NULL
);
120 mp
= &proc
->pr_MsgPort
;
122 dp
= (struct DosPacket
*)GetMsg(mp
)->mn_Node
.ln_Name
;
124 D(bug("%s: mp=%p, path='%b'\n", __func__
, mp
, dp
->dp_Arg1
));
126 glob
= fat_init(proc
, dp
, SysBase
);
129 D(bug("%s: %b - error %d\n", __func__
, dp
->dp_Arg1
, retval
));
130 dp
->dp_Res1
= DOSFALSE
;
131 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
132 ReplyPacket(dp
, SysBase
);
135 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
136 ULONG diskchgsig
= 1 << glob
->diskchgsig_bit
;
137 ULONG notifysig
= 1 << glob
->notifyport
->mp_SigBit
;
138 ULONG timersig
= 1 << glob
->timerport
->mp_SigBit
;
139 ULONG mask
= pktsig
| diskchgsig
| notifysig
| timersig
;
142 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob
->devnode
->dol_Name
)));
144 glob
->devnode
->dol_Task
= glob
->ourport
;
146 D(bug("[fat] returning startup packet\n"));
148 dp
->dp_Res1
= DOSTRUE
;
150 ReplyPacket(dp
, SysBase
);
152 D(bug("Handler init finished.\n"));
154 ProcessDiskChange(glob
); /* insert disk */
158 if (sigs
& diskchgsig
)
159 ProcessDiskChange(glob
);
161 ProcessPackets(glob
);
162 if (sigs
& notifysig
)
168 D(bug("\nHandler shutdown initiated\n"));
172 if (glob
->death_packet
!= NULL
)
173 ReplyPacket(glob
->death_packet
, SysBase
);
177 D(bug("The end.\n"));
182 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
186 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
188 Signal(MyIntData
->task
, MyIntData
->signal
);
194 LONG
InitDiskHandler (struct Globals
*glob
) {
195 struct FileSysStartupMsg
*fssm
= glob
->fssm
;
197 ULONG diskchgintbit
, flags
;
201 unit
= fssm
->fssm_Unit
;
202 flags
= fssm
->fssm_Flags
;
204 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
206 if ((diskchgintbit
= AllocSignal(-1)) >= 0) {
207 glob
->diskchgsig_bit
= diskchgintbit
;
209 if ((glob
->diskport
= CreateMsgPort())) {
211 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
, sizeof(struct IOExtTD
)))) {
213 if (OpenDevice(device
, unit
, (struct IORequest
*)glob
->diskioreq
, flags
) == 0) {
214 D(bug("\tDevice successfully opened\n"));
215 Probe_64bit_support(glob
);
217 if ((glob
->diskchgreq
= AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
))) {
218 CopyMem(glob
->diskioreq
, glob
->diskchgreq
, sizeof(struct IOExtTD
));
220 /* fill interrupt data */
221 glob
->DiskChangeIntData
.SysBase
= SysBase
;
222 glob
->DiskChangeIntData
.task
= glob
->ourtask
;
223 glob
->DiskChangeIntData
.signal
= 1 << diskchgintbit
;
225 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
226 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
= 0;
227 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
= "FATFS";
228 glob
->DiskChangeIntData
.Interrupt
.is_Data
= &glob
->DiskChangeIntData
;
229 glob
->DiskChangeIntData
.Interrupt
.is_Code
= (VOID_FUNC
)AROS_ASMSYMNAME(DiskChangeIntHandler
);
231 /* fill io request data */
232 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_ADDCHANGEINT
;
233 glob
->diskchgreq
->iotd_Req
.io_Data
= &glob
->DiskChangeIntData
.Interrupt
;
234 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
235 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
237 SendIO((struct IORequest
*)glob
->diskchgreq
);
239 D(bug("\tDisk change interrupt handler installed\n"));
244 err
= ERROR_NO_FREE_STORE
;
246 CloseDevice((struct IORequest
*)glob
->diskioreq
);
249 err
= ERROR_DEVICE_NOT_MOUNTED
;
251 DeleteIORequest(glob
->diskioreq
);
252 glob
->diskioreq
= NULL
;
255 err
= ERROR_NO_FREE_STORE
;
257 DeleteMsgPort(glob
->diskport
);
258 glob
->diskport
= NULL
;
261 err
= ERROR_NO_FREE_STORE
;
263 FreeSignal(diskchgintbit
);
265 glob
->diskchgsig_bit
= 0;
268 err
= ERROR_NO_FREE_STORE
;
273 void CleanupDiskHandler(struct Globals
*glob
) {
274 D(bug("\tFreeing handler resources:\n"));
276 /* remove disk change interrupt */
277 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
278 glob
->diskchgreq
->iotd_Req
.io_Data
= &glob
->DiskChangeIntData
.Interrupt
;
279 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
280 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
282 DoIO((struct IORequest
*)glob
->diskchgreq
);
283 D(bug("\tDisk change interrupt handler removed\n"));
285 CloseDevice((struct IORequest
*)glob
->diskioreq
);
286 DeleteIORequest(glob
->diskioreq
);
287 FreeVec(glob
->diskchgreq
);
288 DeleteMsgPort(glob
->diskport
);
289 D(bug("\tDevice closed\n"));
291 glob
->diskioreq
= NULL
;
292 glob
->diskchgreq
= NULL
;
293 glob
->diskport
= NULL
;
295 FreeSignal(glob
->diskchgsig_bit
);