- Round up modification time to the next even second because of FAT's
[AROS.git] / rom / filesys / fat / main.c
bloba62bd64d2bfe2e99553aef2d330c2988e9418a71
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>
25 #include <proto/dos.h>
27 #include <string.h>
29 #include "fat_fs.h"
30 #include "fat_protos.h"
31 #include "charset.h"
33 #define DEBUG DEBUG_MISC
34 #include "debug.h"
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) {
44 struct Message *msg;
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))) {
70 error = InitTimer();
71 if (!error) {
72 InitCharsetTables();
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;
79 ULONG sigs;
80 struct MsgPort *rp;
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 */
98 while(!glob->quit) {
99 sigs = Wait(mask);
100 if (sigs & diskchgsig)
101 ProcessDiskChange();
102 if (sigs & pktsig)
103 ProcessPackets();
104 if (sigs & notifysig)
105 ProcessNotify();
106 if (sigs & timersig)
107 HandleTimer();
110 D(bug("\nHandler shutdown initiated\n"));
112 error = 0;
113 startuppacket = NULL;
115 CleanupDiskHandler();
117 CleanupTimer();
119 DeletePool(glob->mempool);
121 else
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);
146 return RETURN_OK;
149 static struct IntData {
150 struct Interrupt Interrupt;
151 struct ExecBase *SysBase;
152 struct Task *task;
153 ULONG signal;
154 } DiskChangeIntData;
156 static AROS_INTH1(DiskChangeIntHandler, struct IntData *, MyIntData)
158 AROS_INTFUNC_INIT
160 struct ExecBase *SysBase = MyIntData->SysBase;
162 Signal(MyIntData->task, MyIntData->signal);
163 return 0;
165 AROS_INTFUNC_EXIT
168 LONG InitDiskHandler (struct FileSysStartupMsg *fssm) {
169 LONG err;
170 ULONG diskchgintbit, flags;
171 IPTR unit;
172 UBYTE *device;
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"));
214 return 0;
216 else
217 err = ERROR_NO_FREE_STORE;
219 CloseDevice((struct IORequest *)glob->diskioreq);
221 else
222 err = ERROR_DEVICE_NOT_MOUNTED;
224 DeleteIORequest(glob->diskioreq);
225 glob->diskioreq = NULL;
227 else
228 err = ERROR_NO_FREE_STORE;
230 DeleteMsgPort(glob->diskport);
231 glob->diskport = NULL;
233 else
234 err = ERROR_NO_FREE_STORE;
236 FreeSignal(diskchgintbit);
238 glob->diskchgsig_bit = 0;
240 else
241 err = ERROR_NO_FREE_STORE;
243 return err;
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);
270 D(bug("\tDone.\n"));