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
;
39 struct Device
*TimerBase
;
41 struct Globals global_data
;
42 struct Globals
*glob
= &global_data
;
44 LONG
handler(struct ExecBase
*SysBase
) {
46 struct DosPacket
*startuppacket
;
47 LONG error
= ERROR_NO_FREE_STORE
;
49 memset(glob
, 0, sizeof(struct Globals
));
50 NEWLIST(&glob
->sblist
);
51 glob
->ourtask
= FindTask(NULL
);
52 glob
->ourport
= &((struct Process
*)glob
->ourtask
)->pr_MsgPort
;
53 WaitPort(glob
->ourport
);
55 msg
= GetMsg(glob
->ourport
);
56 startuppacket
= (struct DosPacket
*) msg
->mn_Node
.ln_Name
;
57 glob
->devnode
= BADDR(startuppacket
->dp_Arg3
);
59 D(bug("\nFATFS: opening libraries.\n"));
60 D(bug("\tFS task: %lx, port %lx\n", glob
->ourtask
, glob
->ourport
));
62 glob
->notifyport
= CreateMsgPort();
64 if ((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 37))) {
65 if ((IntuitionBase
= OpenLibrary("intuition.library", 37))) {
66 if ((UtilityBase
= OpenLibrary("utility.library", 37))) {
67 glob
->fssm
= BADDR(startuppacket
->dp_Arg2
);
69 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
, DEF_POOL_THRESHOLD
))) {
73 TimerBase
= glob
->timereq
->tr_node
.io_Device
;
76 if ((error
= InitDiskHandler(glob
->fssm
)) == 0) {
77 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
78 ULONG diskchgsig
= 1 << glob
->diskchgsig_bit
;
79 ULONG notifysig
= 1 << glob
->notifyport
->mp_SigBit
;
80 ULONG timersig
= 1 << glob
->timerport
->mp_SigBit
;
81 ULONG mask
= pktsig
| diskchgsig
| notifysig
| timersig
;
85 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob
->devnode
->dol_Name
)));
87 glob
->devnode
->dol_Task
= glob
->ourport
;
89 D(bug("[fat] returning startup packet\n"));
91 rp
= startuppacket
->dp_Port
;
92 startuppacket
->dp_Port
= glob
->ourport
;
93 startuppacket
->dp_Res1
= DOSTRUE
;
94 startuppacket
->dp_Res2
= 0;
95 PutMsg(rp
, startuppacket
->dp_Link
);
97 D(bug("Handler init finished.\n"));
99 ProcessDiskChange(); /* insert disk */
103 if (sigs
& diskchgsig
)
107 if (sigs
& notifysig
)
113 D(bug("\nHandler shutdown initiated\n"));
116 startuppacket
= NULL
;
118 CleanupDiskHandler();
122 DeletePool(glob
->mempool
);
125 error
= ERROR_NO_FREE_STORE
;
127 CloseLibrary(UtilityBase
);
129 CloseLibrary(IntuitionBase
);
131 CloseLibrary((struct Library
*)DOSBase
);
134 DeleteMsgPort(glob
->notifyport
);
136 if (glob
->death_packet
!= NULL
)
137 ReplyPacket(glob
->death_packet
);
139 D(bug("The end.\n"));
141 if (startuppacket
!= NULL
) {
142 D(bug("[fat] returning startup packet\n"));
144 startuppacket
->dp_Res1
= DOSTRUE
;
145 startuppacket
->dp_Res2
= 0;
146 ReplyPacket(startuppacket
);
152 static struct IntData
{
153 struct Interrupt Interrupt
;
154 struct ExecBase
*SysBase
;
159 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
163 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
165 Signal(MyIntData
->task
, MyIntData
->signal
);
171 LONG
InitDiskHandler (struct FileSysStartupMsg
*fssm
) {
173 ULONG diskchgintbit
, flags
;
177 unit
= fssm
->fssm_Unit
;
178 flags
= fssm
->fssm_Flags
;
180 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
182 if ((diskchgintbit
= AllocSignal(-1)) >= 0) {
183 glob
->diskchgsig_bit
= diskchgintbit
;
185 if ((glob
->diskport
= CreateMsgPort())) {
187 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
, sizeof(struct IOExtTD
)))) {
189 if (OpenDevice(device
, unit
, (struct IORequest
*)glob
->diskioreq
, flags
) == 0) {
190 D(bug("\tDevice successfully opened\n"));
191 Probe_64bit_support();
193 if ((glob
->diskchgreq
= AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
))) {
194 CopyMem(glob
->diskioreq
, glob
->diskchgreq
, sizeof(struct IOExtTD
));
196 /* fill interrupt data */
197 DiskChangeIntData
.SysBase
= SysBase
;
198 DiskChangeIntData
.task
= glob
->ourtask
;
199 DiskChangeIntData
.signal
= 1 << diskchgintbit
;
201 DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
202 DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
= 0;
203 DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
= "FATFS";
204 DiskChangeIntData
.Interrupt
.is_Data
= &DiskChangeIntData
;
205 DiskChangeIntData
.Interrupt
.is_Code
= (VOID_FUNC
)AROS_ASMSYMNAME(DiskChangeIntHandler
);
207 /* fill io request data */
208 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_ADDCHANGEINT
;
209 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
210 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
211 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
213 SendIO((struct IORequest
*)glob
->diskchgreq
);
215 D(bug("\tDisk change interrupt handler installed\n"));
220 err
= ERROR_NO_FREE_STORE
;
222 CloseDevice((struct IORequest
*)glob
->diskioreq
);
225 err
= ERROR_DEVICE_NOT_MOUNTED
;
227 DeleteIORequest(glob
->diskioreq
);
228 glob
->diskioreq
= NULL
;
231 err
= ERROR_NO_FREE_STORE
;
233 DeleteMsgPort(glob
->diskport
);
234 glob
->diskport
= NULL
;
237 err
= ERROR_NO_FREE_STORE
;
239 FreeSignal(diskchgintbit
);
241 glob
->diskchgsig_bit
= 0;
244 err
= ERROR_NO_FREE_STORE
;
249 void CleanupDiskHandler(void) {
250 D(bug("\tFreeing handler resources:\n"));
252 /* remove disk change interrupt */
253 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
254 glob
->diskchgreq
->iotd_Req
.io_Data
= &DiskChangeIntData
.Interrupt
;
255 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
256 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
258 DoIO((struct IORequest
*)glob
->diskchgreq
);
259 D(bug("\tDisk change interrupt handler removed\n"));
261 CloseDevice((struct IORequest
*)glob
->diskioreq
);
262 DeleteIORequest(glob
->diskioreq
);
263 FreeVec(glob
->diskchgreq
);
264 DeleteMsgPort(glob
->diskport
);
265 D(bug("\tDevice closed\n"));
267 glob
->diskioreq
= NULL
;
268 glob
->diskchgreq
= NULL
;
269 glob
->diskport
= NULL
;
271 FreeSignal(glob
->diskchgsig_bit
);