2 * fat.handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2008 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"
34 #define DEBUG DEBUG_MISC
37 struct DosLibrary
*DOSBase
;
38 struct Library
*UtilityBase
;
39 struct Library
*IntuitionBase
;
41 struct Globals global_data
;
42 struct Globals
*glob
= &global_data
;
46 struct DosPacket
*startuppacket
;
48 LONG error
= ERROR_NO_FREE_STORE
;
50 glob
->ourtask
= FindTask(NULL
);
51 glob
->ourport
= &((struct Process
*)glob
->ourtask
)->pr_MsgPort
;
52 WaitPort(glob
->ourport
);
54 msg
= GetMsg(glob
->ourport
);
55 startuppacket
= (struct DosPacket
*) msg
->mn_Node
.ln_Name
;
56 glob
->devnode
= BADDR(startuppacket
->dp_Arg3
);
58 D(bug("\nFATFS: opening libraries.\n"));
59 D(bug("\tFS task: %lx, port %lx\n"));
61 glob
->notifyport
= CreateMsgPort();
63 if ((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 37))) {
64 if ((IntuitionBase
= OpenLibrary("intuition.library", 37))) {
65 if ((UtilityBase
= OpenLibrary("utility.library", 37))) {
66 glob
->fssm
= BADDR(startuppacket
->dp_Arg2
);
68 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
, DEF_POOL_THRESHOLD
))) {
75 if ((error
= InitDiskHandler(glob
->fssm
, &diskchgsig_bit
)) == 0) {
76 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
77 ULONG diskchgsig
= 1 << 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"));
100 glob
->disk_inserted
= FALSE
;
101 glob
->disk_inhibited
= FALSE
;
104 ProcessDiskChange(); /* insert disk */
108 if (sigs
& diskchgsig
)
112 if (sigs
& notifysig
)
118 D(bug("\nHandler shutdown initiated\n"));
121 startuppacket
= NULL
;
123 dl
= LockDosList(LDF_WRITE
| LDF_DEVICES
);
126 RemDosEntry(glob
->devnode
);
127 FreeDosEntry(glob
->devnode
);
128 UnLockDosList(LDF_WRITE
| LDF_DEVICES
);
131 CleanupDiskHandler(diskchgsig_bit
);
135 DeletePool(glob
->mempool
);
138 error
= ERROR_NO_FREE_STORE
;
140 CloseLibrary(UtilityBase
);
142 CloseLibrary(IntuitionBase
);
144 CloseLibrary((struct Library
*)DOSBase
);
147 DeleteMsgPort(glob
->notifyport
);
149 D(bug("The end.\n"));
151 if (startuppacket
!= NULL
) {
154 D(bug("[fat] returning startup packet\n"));
156 rp
= startuppacket
->dp_Port
;
157 startuppacket
->dp_Port
= glob
->ourport
;
158 startuppacket
->dp_Res1
= DOSTRUE
;
159 startuppacket
->dp_Res2
= 0;
160 PutMsg(rp
, startuppacket
->dp_Link
);
166 static struct IntData
{
167 struct Interrupt Interrupt
;
168 struct ExecBase
*SysBase
;
173 AROS_UFH3(static BOOL
, DiskChangeIntHandler
,
174 AROS_UFHA(struct IntData
*, MyIntData
, A1
),
175 AROS_UFHA(APTR
, dummy
, A5
),
176 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)) {
180 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
182 Signal(MyIntData
->task
, MyIntData
->signal
);
188 LONG
InitDiskHandler (struct FileSysStartupMsg
*fssm
, ULONG
*diskchgsig_bit
) {
190 ULONG diskchgintbit
, flags
, unit
;
193 unit
= fssm
->fssm_Unit
;
194 flags
= fssm
->fssm_Flags
;
196 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
198 if ((diskchgintbit
= AllocSignal(-1)) >= 0) {
199 *diskchgsig_bit
= diskchgintbit
;
201 if ((glob
->diskport
= CreateMsgPort())) {
203 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
, sizeof(struct IOExtTD
)))) {
205 if (OpenDevice(device
, unit
, (struct IORequest
*)glob
->diskioreq
, flags
) == 0) {
206 D(bug("\tDevice successfully opened\n"));
207 Probe_64bit_support();
209 if ((glob
->diskchgreq
= AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
))) {
210 CopyMem(glob
->diskioreq
, glob
->diskchgreq
, sizeof(struct IOExtTD
));
212 /* fill interrupt data */
213 DiskChangeIntData
.SysBase
= SysBase
;
214 DiskChangeIntData
.task
= glob
->ourtask
;
215 DiskChangeIntData
.signal
= 1 << diskchgintbit
;
217 DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
218 DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
= 0;
219 DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
= "FATFS";
220 DiskChangeIntData
.Interrupt
.is_Data
= &DiskChangeIntData
;
221 DiskChangeIntData
.Interrupt
.is_Code
= (void (*)(void))AROS_ASMSYMNAME(DiskChangeIntHandler
);
223 /* fill io request data */
224 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_ADDCHANGEINT
;
225 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
226 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
227 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
229 SendIO((struct IORequest
*)glob
->diskchgreq
);
231 D(bug("\tDisk change interrupt handler installed\n"));
236 err
= ERROR_NO_FREE_STORE
;
238 CloseDevice((struct IORequest
*)glob
->diskioreq
);
241 err
= ERROR_DEVICE_NOT_MOUNTED
;
243 DeleteIORequest(glob
->diskioreq
);
244 glob
->diskioreq
= NULL
;
247 err
= ERROR_NO_FREE_STORE
;
249 DeleteMsgPort(glob
->diskport
);
250 glob
->diskport
= NULL
;
253 err
= ERROR_NO_FREE_STORE
;
255 FreeSignal(diskchgintbit
);
260 err
= ERROR_NO_FREE_STORE
;
265 void CleanupDiskHandler(ULONG diskchgsig_bit
) {
266 D(bug("\tFreeing handler resources:\n"));
268 /* remove disk change interrupt */
269 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
270 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
271 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
272 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
274 DoIO((struct IORequest
*)glob
->diskchgreq
);
275 D(bug("\tDisk change interrupt handler removed\n"));
277 CloseDevice((struct IORequest
*)glob
->diskioreq
);
278 DeleteIORequest(glob
->diskioreq
);
279 FreeVec(glob
->diskchgreq
);
280 DeleteMsgPort(glob
->diskport
);
281 D(bug("\tDevice closed\n"));
283 glob
->diskioreq
= NULL
;
284 glob
->diskchgreq
= NULL
;
285 glob
->diskport
= NULL
;
287 FreeSignal(diskchgsig_bit
);