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>
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 LONG
handler(struct ExecBase
*SysBase
) {
45 struct DosPacket
*startuppacket
;
46 LONG error
= ERROR_NO_FREE_STORE
;
48 memset(glob
, 0, sizeof(struct Globals
));
49 NEWLIST(&glob
->sblist
);
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", glob
->ourtask
, glob
->ourport
));
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
))) {
73 if ((error
= InitDiskHandler(glob
->fssm
)) == 0) {
74 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
75 ULONG diskchgsig
= 1 << glob
->diskchgsig_bit
;
76 ULONG notifysig
= 1 << glob
->notifyport
->mp_SigBit
;
77 ULONG timersig
= 1 << glob
->timerport
->mp_SigBit
;
78 ULONG mask
= pktsig
| diskchgsig
| notifysig
| timersig
;
82 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob
->devnode
->dol_Name
)));
84 glob
->devnode
->dol_Task
= glob
->ourport
;
86 D(bug("[fat] returning startup packet\n"));
88 rp
= startuppacket
->dp_Port
;
89 startuppacket
->dp_Port
= glob
->ourport
;
90 startuppacket
->dp_Res1
= DOSTRUE
;
91 startuppacket
->dp_Res2
= 0;
92 PutMsg(rp
, startuppacket
->dp_Link
);
94 D(bug("Handler init finished.\n"));
96 ProcessDiskChange(); /* insert disk */
100 if (sigs
& diskchgsig
)
104 if (sigs
& notifysig
)
110 D(bug("\nHandler shutdown initiated\n"));
113 startuppacket
= NULL
;
115 CleanupDiskHandler();
119 DeletePool(glob
->mempool
);
122 error
= ERROR_NO_FREE_STORE
;
124 CloseLibrary(UtilityBase
);
126 CloseLibrary(IntuitionBase
);
128 CloseLibrary((struct Library
*)DOSBase
);
131 DeleteMsgPort(glob
->notifyport
);
133 if (glob
->death_packet
!= NULL
)
134 ReplyPacket(glob
->death_packet
);
136 D(bug("The end.\n"));
138 if (startuppacket
!= NULL
) {
139 D(bug("[fat] returning startup packet\n"));
141 startuppacket
->dp_Res1
= DOSTRUE
;
142 startuppacket
->dp_Res2
= 0;
143 ReplyPacket(startuppacket
);
149 static struct IntData
{
150 struct Interrupt Interrupt
;
151 struct ExecBase
*SysBase
;
156 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
160 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
162 Signal(MyIntData
->task
, MyIntData
->signal
);
168 LONG
InitDiskHandler (struct FileSysStartupMsg
*fssm
) {
170 ULONG diskchgintbit
, flags
;
174 unit
= fssm
->fssm_Unit
;
175 flags
= fssm
->fssm_Flags
;
177 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
179 if ((diskchgintbit
= AllocSignal(-1)) >= 0) {
180 glob
->diskchgsig_bit
= diskchgintbit
;
182 if ((glob
->diskport
= CreateMsgPort())) {
184 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
, sizeof(struct IOExtTD
)))) {
186 if (OpenDevice(device
, unit
, (struct IORequest
*)glob
->diskioreq
, flags
) == 0) {
187 D(bug("\tDevice successfully opened\n"));
188 Probe_64bit_support();
190 if ((glob
->diskchgreq
= AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
))) {
191 CopyMem(glob
->diskioreq
, glob
->diskchgreq
, sizeof(struct IOExtTD
));
193 /* fill interrupt data */
194 DiskChangeIntData
.SysBase
= SysBase
;
195 DiskChangeIntData
.task
= glob
->ourtask
;
196 DiskChangeIntData
.signal
= 1 << diskchgintbit
;
198 DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
199 DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
= 0;
200 DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
= "FATFS";
201 DiskChangeIntData
.Interrupt
.is_Data
= &DiskChangeIntData
;
202 DiskChangeIntData
.Interrupt
.is_Code
= (VOID_FUNC
)AROS_ASMSYMNAME(DiskChangeIntHandler
);
204 /* fill io request data */
205 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_ADDCHANGEINT
;
206 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
207 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
208 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
210 SendIO((struct IORequest
*)glob
->diskchgreq
);
212 D(bug("\tDisk change interrupt handler installed\n"));
217 err
= ERROR_NO_FREE_STORE
;
219 CloseDevice((struct IORequest
*)glob
->diskioreq
);
222 err
= ERROR_DEVICE_NOT_MOUNTED
;
224 DeleteIORequest(glob
->diskioreq
);
225 glob
->diskioreq
= NULL
;
228 err
= ERROR_NO_FREE_STORE
;
230 DeleteMsgPort(glob
->diskport
);
231 glob
->diskport
= NULL
;
234 err
= ERROR_NO_FREE_STORE
;
236 FreeSignal(diskchgintbit
);
238 glob
->diskchgsig_bit
= 0;
241 err
= ERROR_NO_FREE_STORE
;
246 void CleanupDiskHandler(void) {
247 D(bug("\tFreeing handler resources:\n"));
249 /* remove disk change interrupt */
250 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
251 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
252 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
253 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
255 DoIO((struct IORequest
*)glob
->diskchgreq
);
256 D(bug("\tDisk change interrupt handler removed\n"));
258 CloseDevice((struct IORequest
*)glob
->diskioreq
);
259 DeleteIORequest(glob
->diskioreq
);
260 FreeVec(glob
->diskchgreq
);
261 DeleteMsgPort(glob
->diskport
);
262 D(bug("\tDevice closed\n"));
264 glob
->diskioreq
= NULL
;
265 glob
->diskchgreq
= NULL
;
266 glob
->diskport
= NULL
;
268 FreeSignal(glob
->diskchgsig_bit
);