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
++)
45 glob
->from_unicode
[i
] = i
;
46 glob
->to_unicode
[i
] = i
;
49 glob
->from_unicode
[i
] = '_';
53 static struct Globals
*fat_init(struct Process
*proc
, struct DosPacket
*dp
,
54 struct ExecBase
*SysBase
)
58 glob
= AllocVec(sizeof(struct Globals
), MEMF_ANY
| MEMF_CLEAR
);
61 glob
->gl_SysBase
= SysBase
;
62 if ((glob
->gl_DOSBase
=
63 (struct DosLibrary
*)OpenLibrary("dos.library", 0)))
65 if ((glob
->gl_UtilityBase
= OpenLibrary("utility.library", 0)))
67 NEWLIST(&glob
->sblist
);
68 glob
->ourtask
= &proc
->pr_Task
;
69 glob
->ourport
= &proc
->pr_MsgPort
;
71 glob
->devnode
= BADDR(dp
->dp_Arg3
);
73 D(bug("\nFATFS: opening libraries.\n"));
74 D(bug("\tFS task: %lx, port %lx\n", glob
->ourtask
,
77 glob
->notifyport
= CreateMsgPort();
79 glob
->fssm
= BADDR(dp
->dp_Arg2
);
81 if ((glob
->mempool
= CreatePool(MEMF_PUBLIC
, DEF_POOL_SIZE
,
84 LONG error
= InitTimer(glob
);
87 InitCharsetTables(glob
);
88 if ((error
= InitDiskHandler(glob
)) == 0)
95 DeletePool(glob
->mempool
);
98 CloseLibrary(glob
->gl_UtilityBase
);
101 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
110 static void fat_exit(struct Globals
*glob
)
112 struct ExecBase
*SysBase
= glob
->gl_SysBase
;
113 CleanupDiskHandler(glob
);
115 DeletePool(glob
->mempool
);
117 DeleteMsgPort(glob
->notifyport
);
119 CloseLibrary(glob
->gl_UtilityBase
);
120 CloseLibrary((struct Library
*)glob
->gl_DOSBase
);
125 LONG
handler(struct ExecBase
*SysBase
)
127 struct Globals
*glob
;
128 struct Process
*proc
;
130 struct DosPacket
*dp
;
132 D(bug("%s: start\n", __func__
));
134 proc
= (struct Process
*)FindTask(NULL
);
135 mp
= &proc
->pr_MsgPort
;
137 dp
= (struct DosPacket
*)GetMsg(mp
)->mn_Node
.ln_Name
;
139 D(bug("%s: mp=%p, path='%b'\n", __func__
, mp
, dp
->dp_Arg1
));
141 glob
= fat_init(proc
, dp
, SysBase
);
145 D(bug("%s: %b - error %d\n", __func__
, dp
->dp_Arg1
, RETURN_FAIL
));
146 dp
->dp_Res1
= DOSFALSE
;
147 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
148 ReplyPacket(dp
, SysBase
);
153 ULONG pktsig
= 1 << glob
->ourport
->mp_SigBit
;
154 ULONG diskchgsig
= 1 << glob
->diskchgsig_bit
;
155 ULONG notifysig
= 1 << glob
->notifyport
->mp_SigBit
;
156 ULONG timersig
= 1 << glob
->timerport
->mp_SigBit
;
157 ULONG mask
= pktsig
| diskchgsig
| notifysig
| timersig
;
160 D(bug("\tInitiated device: %s\n",
161 AROS_BSTR_ADDR(glob
->devnode
->dol_Name
)));
163 glob
->devnode
->dol_Task
= glob
->ourport
;
165 D(bug("[fat] returning startup packet\n"));
167 dp
->dp_Res1
= DOSTRUE
;
169 ReplyPacket(dp
, SysBase
);
171 D(bug("Handler init finished.\n"));
174 ProcessDiskChange(glob
);
179 if (sigs
& diskchgsig
)
180 ProcessDiskChange(glob
);
182 ProcessPackets(glob
);
183 if (sigs
& notifysig
)
189 D(bug("\nHandler shutdown initiated\n"));
193 if (glob
->death_packet
!= NULL
)
194 ReplyPacket(glob
->death_packet
, SysBase
);
198 D(bug("The end.\n"));
203 static AROS_INTH1(DiskChangeIntHandler
, struct IntData
*, MyIntData
)
207 struct ExecBase
*SysBase
= MyIntData
->SysBase
;
209 Signal(MyIntData
->task
, MyIntData
->signal
);
215 LONG
InitDiskHandler(struct Globals
*glob
)
217 struct FileSysStartupMsg
*fssm
= glob
->fssm
;
219 ULONG diskchgintbit
, flags
;
223 unit
= fssm
->fssm_Unit
;
224 flags
= fssm
->fssm_Flags
;
226 device
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
228 if ((diskchgintbit
= AllocSignal(-1)) >= 0)
230 glob
->diskchgsig_bit
= diskchgintbit
;
232 if ((glob
->diskport
= CreateMsgPort()))
235 if ((glob
->diskioreq
= CreateIORequest(glob
->diskport
,
236 sizeof(struct IOExtTD
))))
238 if (OpenDevice(device
, unit
,
239 (struct IORequest
*)glob
->diskioreq
, flags
) == 0)
241 D(bug("\tDevice successfully opened\n"));
242 Probe_64bit_support(glob
);
244 if ((glob
->diskchgreq
=
245 AllocVec(sizeof(struct IOExtTD
), MEMF_PUBLIC
)))
247 CopyMem(glob
->diskioreq
, glob
->diskchgreq
,
248 sizeof(struct IOExtTD
));
250 /* fill interrupt data */
251 glob
->DiskChangeIntData
.SysBase
= SysBase
;
252 glob
->DiskChangeIntData
.task
= glob
->ourtask
;
253 glob
->DiskChangeIntData
.signal
= 1 << diskchgintbit
;
255 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Type
=
257 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Pri
=
259 glob
->DiskChangeIntData
.Interrupt
.is_Node
.ln_Name
=
261 glob
->DiskChangeIntData
.Interrupt
.is_Data
=
262 &glob
->DiskChangeIntData
;
263 glob
->DiskChangeIntData
.Interrupt
.is_Code
=
265 AROS_ASMSYMNAME(DiskChangeIntHandler
);
267 /* fill io request data */
268 glob
->diskchgreq
->iotd_Req
.io_Command
=
270 glob
->diskchgreq
->iotd_Req
.io_Data
=
271 &glob
->DiskChangeIntData
.Interrupt
;
272 glob
->diskchgreq
->iotd_Req
.io_Length
=
273 sizeof(struct Interrupt
);
274 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
276 SendIO((struct IORequest
*)glob
->diskchgreq
);
278 D(bug("\tDisk change interrupt handler installed\n"));
283 err
= ERROR_NO_FREE_STORE
;
285 CloseDevice((struct IORequest
*)glob
->diskioreq
);
288 err
= ERROR_DEVICE_NOT_MOUNTED
;
290 DeleteIORequest(glob
->diskioreq
);
291 glob
->diskioreq
= NULL
;
294 err
= ERROR_NO_FREE_STORE
;
296 DeleteMsgPort(glob
->diskport
);
297 glob
->diskport
= NULL
;
300 err
= ERROR_NO_FREE_STORE
;
302 FreeSignal(diskchgintbit
);
304 glob
->diskchgsig_bit
= 0;
307 err
= ERROR_NO_FREE_STORE
;
312 void CleanupDiskHandler(struct Globals
*glob
)
314 D(bug("\tFreeing handler resources:\n"));
316 /* remove disk change interrupt */
317 glob
->diskchgreq
->iotd_Req
.io_Command
= TD_REMCHANGEINT
;
318 glob
->diskchgreq
->iotd_Req
.io_Data
= &glob
->DiskChangeIntData
.Interrupt
;
319 glob
->diskchgreq
->iotd_Req
.io_Length
= sizeof(struct Interrupt
);
320 glob
->diskchgreq
->iotd_Req
.io_Flags
= 0;
322 DoIO((struct IORequest
*)glob
->diskchgreq
);
323 D(bug("\tDisk change interrupt handler removed\n"));
325 CloseDevice((struct IORequest
*)glob
->diskioreq
);
326 DeleteIORequest(glob
->diskioreq
);
327 FreeVec(glob
->diskchgreq
);
328 DeleteMsgPort(glob
->diskport
);
329 D(bug("\tDevice closed\n"));
331 glob
->diskioreq
= NULL
;
332 glob
->diskchgreq
= NULL
;
333 glob
->diskport
= NULL
;
335 FreeSignal(glob
->diskchgsig_bit
);