Excluded charset.c from the build: it's unused except for one short
[AROS.git] / rom / filesys / fat / main.c
blobfa5510a5e35152ea1646346d5654b72a96027ffd
1 /*
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.
10 * $Id$
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>
18 #include <dos/dos.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>
26 #include <string.h>
28 #include "fat_fs.h"
29 #include "fat_protos.h"
31 #define DEBUG DEBUG_MISC
32 #include "debug.h"
34 #undef SysBase
35 #undef UtilityBase
37 static void InitCharsetTables(struct Globals *glob)
39 int i;
41 for (i = 0; i < 65536; i++)
42 if (i < 256) {
43 glob->from_unicode[i] = i;
44 glob->to_unicode[i] = i;
45 } else
46 glob->from_unicode[i] = '_';
49 static struct Globals *fat_init(struct Process *proc, struct DosPacket *dp, struct ExecBase *SysBase)
51 struct Globals *glob;
53 glob = AllocVec(sizeof(struct Globals), MEMF_ANY | MEMF_CLEAR);
54 if (glob) {
55 glob->gl_SysBase = SysBase;
56 if ((glob->gl_DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0))) {
57 if ((glob->gl_UtilityBase = OpenLibrary("utility.library", 0))) {
58 NEWLIST(&glob->sblist);
59 glob->ourtask = &proc->pr_Task;
60 glob->ourport = &proc->pr_MsgPort;
62 glob->devnode = BADDR(dp->dp_Arg3);
64 D(bug("\nFATFS: opening libraries.\n"));
65 D(bug("\tFS task: %lx, port %lx\n", glob->ourtask, glob->ourport));
67 glob->notifyport = CreateMsgPort();
69 glob->fssm = BADDR(dp->dp_Arg2);
71 if ((glob->mempool = CreatePool(MEMF_PUBLIC, DEF_POOL_SIZE, DEF_POOL_THRESHOLD))) {
72 LONG error = InitTimer(glob);
73 if (!error) {
74 InitCharsetTables(glob);
75 if ((error = InitDiskHandler(glob)) == 0) {
76 return glob;
79 CleanupTimer(glob);
81 DeletePool(glob->mempool);
84 CloseLibrary(glob->gl_UtilityBase);
87 CloseLibrary((struct Library *)glob->gl_DOSBase);
90 FreeVec(glob);
93 return NULL;
96 static void fat_exit(struct Globals *glob)
98 struct ExecBase *SysBase = glob->gl_SysBase;
99 CleanupDiskHandler(glob);
100 CleanupTimer(glob);
101 DeletePool(glob->mempool);
103 DeleteMsgPort(glob->notifyport);
105 CloseLibrary(glob->gl_UtilityBase);
106 CloseLibrary((struct Library *)glob->gl_DOSBase);
108 FreeVec(glob);
111 LONG handler(struct ExecBase *SysBase) {
112 struct Globals *glob;
113 struct Process *proc;
114 struct MsgPort *mp;
115 struct DosPacket *dp;
117 D(bug("%s: start\n", __func__));
119 proc = (struct Process *)FindTask(NULL);
120 mp = &proc->pr_MsgPort;
121 WaitPort(mp);
122 dp = (struct DosPacket *)GetMsg(mp)->mn_Node.ln_Name;
124 D(bug("%s: mp=%p, path='%b'\n", __func__, mp, dp->dp_Arg1));
126 glob = fat_init(proc, dp, SysBase);
128 if (!glob) {
129 D(bug("%s: %b - error %d\n", __func__, dp->dp_Arg1, retval));
130 dp->dp_Res1 = DOSFALSE;
131 dp->dp_Res2 = ERROR_NO_FREE_STORE;
132 ReplyPacket(dp, SysBase);
133 return RETURN_FAIL;
134 } else {
135 ULONG pktsig = 1 << glob->ourport->mp_SigBit;
136 ULONG diskchgsig = 1 << glob->diskchgsig_bit;
137 ULONG notifysig = 1 << glob->notifyport->mp_SigBit;
138 ULONG timersig = 1 << glob->timerport->mp_SigBit;
139 ULONG mask = pktsig | diskchgsig | notifysig | timersig;
140 ULONG sigs;
142 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob->devnode->dol_Name)));
144 glob->devnode->dol_Task = glob->ourport;
146 D(bug("[fat] returning startup packet\n"));
148 dp->dp_Res1 = DOSTRUE;
149 dp->dp_Res2 = 0;
150 ReplyPacket(dp, SysBase);
152 D(bug("Handler init finished.\n"));
154 ProcessDiskChange(glob); /* insert disk */
156 while(!glob->quit) {
157 sigs = Wait(mask);
158 if (sigs & diskchgsig)
159 ProcessDiskChange(glob);
160 if (sigs & pktsig)
161 ProcessPackets(glob);
162 if (sigs & notifysig)
163 ProcessNotify(glob);
164 if (sigs & timersig)
165 HandleTimer(glob);
168 D(bug("\nHandler shutdown initiated\n"));
170 dp = NULL;
172 if (glob->death_packet != NULL)
173 ReplyPacket(glob->death_packet, SysBase);
175 fat_exit(glob);
177 D(bug("The end.\n"));
179 return RETURN_OK;
182 static AROS_INTH1(DiskChangeIntHandler, struct IntData *, MyIntData)
184 AROS_INTFUNC_INIT
186 struct ExecBase *SysBase = MyIntData->SysBase;
188 Signal(MyIntData->task, MyIntData->signal);
189 return 0;
191 AROS_INTFUNC_EXIT
194 LONG InitDiskHandler (struct Globals *glob) {
195 struct FileSysStartupMsg *fssm = glob->fssm;
196 LONG err;
197 ULONG diskchgintbit, flags;
198 IPTR unit;
199 UBYTE *device;
201 unit = fssm->fssm_Unit;
202 flags = fssm->fssm_Flags;
204 device = AROS_BSTR_ADDR(fssm->fssm_Device);
206 if ((diskchgintbit = AllocSignal(-1)) >= 0) {
207 glob->diskchgsig_bit = diskchgintbit;
209 if ((glob->diskport = CreateMsgPort())) {
211 if ((glob->diskioreq = CreateIORequest(glob->diskport, sizeof(struct IOExtTD)))) {
213 if (OpenDevice(device, unit, (struct IORequest *)glob->diskioreq, flags) == 0) {
214 D(bug("\tDevice successfully opened\n"));
215 Probe_64bit_support(glob);
217 if ((glob->diskchgreq = AllocVec(sizeof(struct IOExtTD), MEMF_PUBLIC))) {
218 CopyMem(glob->diskioreq, glob->diskchgreq, sizeof(struct IOExtTD));
220 /* fill interrupt data */
221 glob->DiskChangeIntData.SysBase = SysBase;
222 glob->DiskChangeIntData.task = glob->ourtask;
223 glob->DiskChangeIntData.signal = 1 << diskchgintbit;
225 glob->DiskChangeIntData.Interrupt.is_Node.ln_Type = NT_INTERRUPT;
226 glob->DiskChangeIntData.Interrupt.is_Node.ln_Pri = 0;
227 glob->DiskChangeIntData.Interrupt.is_Node.ln_Name = "FATFS";
228 glob->DiskChangeIntData.Interrupt.is_Data = &glob->DiskChangeIntData;
229 glob->DiskChangeIntData.Interrupt.is_Code = (VOID_FUNC)AROS_ASMSYMNAME(DiskChangeIntHandler);
231 /* fill io request data */
232 glob->diskchgreq->iotd_Req.io_Command = TD_ADDCHANGEINT;
233 glob->diskchgreq->iotd_Req.io_Data = &glob->DiskChangeIntData.Interrupt;
234 glob->diskchgreq->iotd_Req.io_Length = sizeof(struct Interrupt);
235 glob->diskchgreq->iotd_Req.io_Flags = 0;
237 SendIO((struct IORequest*)glob->diskchgreq);
239 D(bug("\tDisk change interrupt handler installed\n"));
241 return 0;
243 else
244 err = ERROR_NO_FREE_STORE;
246 CloseDevice((struct IORequest *)glob->diskioreq);
248 else
249 err = ERROR_DEVICE_NOT_MOUNTED;
251 DeleteIORequest(glob->diskioreq);
252 glob->diskioreq = NULL;
254 else
255 err = ERROR_NO_FREE_STORE;
257 DeleteMsgPort(glob->diskport);
258 glob->diskport = NULL;
260 else
261 err = ERROR_NO_FREE_STORE;
263 FreeSignal(diskchgintbit);
265 glob->diskchgsig_bit = 0;
267 else
268 err = ERROR_NO_FREE_STORE;
270 return err;
273 void CleanupDiskHandler(struct Globals *glob) {
274 D(bug("\tFreeing handler resources:\n"));
276 /* remove disk change interrupt */
277 glob->diskchgreq->iotd_Req.io_Command = TD_REMCHANGEINT;
278 glob->diskchgreq->iotd_Req.io_Data = &glob->DiskChangeIntData.Interrupt;
279 glob->diskchgreq->iotd_Req.io_Length = sizeof(struct Interrupt);
280 glob->diskchgreq->iotd_Req.io_Flags = 0;
282 DoIO((struct IORequest*)glob->diskchgreq);
283 D(bug("\tDisk change interrupt handler removed\n"));
285 CloseDevice((struct IORequest *)glob->diskioreq);
286 DeleteIORequest(glob->diskioreq);
287 FreeVec(glob->diskchgreq);
288 DeleteMsgPort(glob->diskport);
289 D(bug("\tDevice closed\n"));
291 glob->diskioreq = NULL;
292 glob->diskchgreq = NULL;
293 glob->diskport = NULL;
295 FreeSignal(glob->diskchgsig_bit);
297 D(bug("\tDone.\n"));