2 * fat.handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2011 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>
25 #include <proto/dos.h>
30 #include "fat_protos.h"
33 #define DEBUG DEBUG_MISC
36 struct DosLibrary
*DOSBase
;
37 struct Library
*UtilityBase
;
38 struct Library
*IntuitionBase
;
40 struct Globals global_data
;
41 struct Globals
*glob
= &global_data
;
43 const TEXT version_string
[] = "$VER: fat.handler 41.52 (28.12.2011)";
45 LONG
handler(struct ExecBase
*SysBase
) {
47 struct DosPacket
*startuppacket
;
48 LONG error
= ERROR_NO_FREE_STORE
;
50 memset(glob
, 0, sizeof(struct Globals
));
51 NEWLIST(&glob
->sblist
);
52 glob
->ourtask
= FindTask(NULL
);
53 glob
->ourport
= &((struct Process
*)glob
->ourtask
)->pr_MsgPort
;
54 WaitPort(glob
->ourport
);
56 msg
= GetMsg(glob
->ourport
);
57 startuppacket
= (struct DosPacket
*) msg
->mn_Node
.ln_Name
;
58 glob
->devnode
= BADDR(startuppacket
->dp_Arg3
);
60 D(bug("\nFATFS: opening libraries.\n"));
61 D(bug("\tFS task: %lx, port %lx\n", glob
->ourtask
, glob
->ourport
));
63 glob
->notifyport
= CreateMsgPort();
65 if ((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 37))) {
66 if ((IntuitionBase
= OpenLibrary("intuition.library", 37))) {
67 if ((UtilityBase
= OpenLibrary("utility.library", 37))) {
68 glob
->fssm
= BADDR(startuppacket
->dp_Arg2
);
70 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
, DEF_POOL_THRESHOLD
))) {
75 if ((error
= InitDiskHandler(glob
->fssm
)) == 0) {
76 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
77 ULONG diskchgsig
= 1 << glob
->diskchgsig_bit
;
78 ULONG notifysig
= 1 << glob
->notifyport
->mp_SigBit
;
79 ULONG timersig
= 1 << glob
->timerport
->mp_SigBit
;
80 ULONG mask
= pktsig
| diskchgsig
| notifysig
| timersig
;
84 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob
->devnode
->dol_Name
)));
86 glob
->devnode
->dol_Task
= glob
->ourport
;
88 D(bug("[fat] returning startup packet\n"));
90 rp
= startuppacket
->dp_Port
;
91 startuppacket
->dp_Port
= glob
->ourport
;
92 startuppacket
->dp_Res1
= DOSTRUE
;
93 startuppacket
->dp_Res2
= 0;
94 PutMsg(rp
, startuppacket
->dp_Link
);
96 D(bug("Handler init finished.\n"));
98 ProcessDiskChange(); /* insert disk */
102 if (sigs
& diskchgsig
)
106 if (sigs
& notifysig
)
112 D(bug("\nHandler shutdown initiated\n"));
115 startuppacket
= NULL
;
117 CleanupDiskHandler();
121 DeletePool(glob
->mempool
);
124 error
= ERROR_NO_FREE_STORE
;
126 CloseLibrary(UtilityBase
);
128 CloseLibrary(IntuitionBase
);
130 CloseLibrary((struct Library
*)DOSBase
);
133 DeleteMsgPort(glob
->notifyport
);
135 if (glob
->death_packet
!= NULL
)
136 ReplyPacket(glob
->death_packet
);
138 D(bug("The end.\n"));
140 if (startuppacket
!= NULL
) {
141 D(bug("[fat] returning startup packet\n"));
143 startuppacket
->dp_Res1
= DOSTRUE
;
144 startuppacket
->dp_Res2
= 0;
145 ReplyPacket(startuppacket
);
151 static struct IntData
{
152 struct Interrupt Interrupt
;
153 struct ExecBase
*SysBase
;
158 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
162 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
164 Signal(MyIntData
->task
, MyIntData
->signal
);
170 LONG
InitDiskHandler (struct FileSysStartupMsg
*fssm
) {
172 ULONG diskchgintbit
, flags
;
176 unit
= fssm
->fssm_Unit
;
177 flags
= fssm
->fssm_Flags
;
179 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
181 if ((diskchgintbit
= AllocSignal(-1)) >= 0) {
182 glob
->diskchgsig_bit
= diskchgintbit
;
184 if ((glob
->diskport
= CreateMsgPort())) {
186 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
, sizeof(struct IOExtTD
)))) {
188 if (OpenDevice(device
, unit
, (struct IORequest
*)glob
->diskioreq
, flags
) == 0) {
189 D(bug("\tDevice successfully opened\n"));
190 Probe_64bit_support();
192 if ((glob
->diskchgreq
= AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
))) {
193 CopyMem(glob
->diskioreq
, glob
->diskchgreq
, sizeof(struct IOExtTD
));
195 /* fill interrupt data */
196 DiskChangeIntData
.SysBase
= SysBase
;
197 DiskChangeIntData
.task
= glob
->ourtask
;
198 DiskChangeIntData
.signal
= 1 << diskchgintbit
;
200 DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
201 DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
= 0;
202 DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
= "FATFS";
203 DiskChangeIntData
.Interrupt
.is_Data
= &DiskChangeIntData
;
204 DiskChangeIntData
.Interrupt
.is_Code
= (VOID_FUNC
)AROS_ASMSYMNAME(DiskChangeIntHandler
);
206 /* fill io request data */
207 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_ADDCHANGEINT
;
208 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
209 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
210 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
212 SendIO((struct IORequest
*)glob
->diskchgreq
);
214 D(bug("\tDisk change interrupt handler installed\n"));
219 err
= ERROR_NO_FREE_STORE
;
221 CloseDevice((struct IORequest
*)glob
->diskioreq
);
224 err
= ERROR_DEVICE_NOT_MOUNTED
;
226 DeleteIORequest(glob
->diskioreq
);
227 glob
->diskioreq
= NULL
;
230 err
= ERROR_NO_FREE_STORE
;
232 DeleteMsgPort(glob
->diskport
);
233 glob
->diskport
= NULL
;
236 err
= ERROR_NO_FREE_STORE
;
238 FreeSignal(diskchgintbit
);
240 glob
->diskchgsig_bit
= 0;
243 err
= ERROR_NO_FREE_STORE
;
248 void CleanupDiskHandler(void) {
249 D(bug("\tFreeing handler resources:\n"));
251 /* remove disk change interrupt */
252 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
253 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
254 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
255 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
257 DoIO((struct IORequest
*)glob
->diskchgreq
);
258 D(bug("\tDisk change interrupt handler removed\n"));
260 CloseDevice((struct IORequest
*)glob
->diskioreq
);
261 DeleteIORequest(glob
->diskioreq
);
262 FreeVec(glob
->diskchgreq
);
263 DeleteMsgPort(glob
->diskport
);
264 D(bug("\tDevice closed\n"));
266 glob
->diskioreq
= NULL
;
267 glob
->diskchgreq
= NULL
;
268 glob
->diskport
= NULL
;
270 FreeSignal(glob
->diskchgsig_bit
);