Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / fs / fat / main.c
blob97c60949f5e278cb0d9aba5262f80060b5218678
1 /*
2 * fat.handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2008 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"
32 #include "timer.h"
34 #define DEBUG DEBUG_MISC
35 #include "debug.h"
37 struct DosLibrary *DOSBase;
38 struct Library *UtilityBase;
39 struct Library *IntuitionBase;
41 struct Globals global_data;
42 struct Globals *glob = &global_data;
44 void handler(void) {
45 struct Message *msg;
46 struct DosPacket *startuppacket;
47 struct DosList *dl;
48 LONG error = ERROR_NO_FREE_STORE;
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"));
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 ULONG diskchgsig_bit;
74 InitCharsetTables();
75 if ((error = InitDiskHandler(glob->fssm, &diskchgsig_bit)) == 0) {
76 ULONG pktsig = 1 << glob->ourport->mp_SigBit;
77 ULONG diskchgsig = 1 << diskchgsig_bit;
78 ULONG notifysig = 1 << glob->notifyport->mp_SigBit;
79 ULONG timersig = 1 << glob->timerport->mp_SigBit;
80 ULONG mask = pktsig | diskchgsig | notifysig | timersig;
81 ULONG sigs;
82 struct MsgPort *rp;
84 D(bug("\tInitiated device: %s\n", AROS_BSTR_ADDR(glob->devnode->dol_Name)));
86 glob->devnode->dol_Task = glob->ourport;
88 D(bug("[fat] returning startup packet\n"));
90 rp = startuppacket->dp_Port;
91 startuppacket->dp_Port = glob->ourport;
92 startuppacket->dp_Res1 = DOSTRUE;
93 startuppacket->dp_Res2 = 0;
94 PutMsg(rp, startuppacket->dp_Link);
96 D(bug("Handler init finished.\n"));
98 glob->sb = NULL;
99 glob->sblist = NULL;
100 glob->disk_inserted = FALSE;
101 glob->disk_inhibited = FALSE;
102 glob->quit = FALSE;
104 ProcessDiskChange(); /* insert disk */
106 while(!glob->quit) {
107 sigs = Wait(mask);
108 if (sigs & diskchgsig)
109 ProcessDiskChange();
110 if (sigs & pktsig)
111 ProcessPackets();
112 if (sigs & notifysig)
113 ProcessNotify();
114 if (sigs & timersig)
115 HandleTimer();
118 D(bug("\nHandler shutdown initiated\n"));
120 error = 0;
121 startuppacket = NULL;
123 dl = LockDosList(LDF_WRITE | LDF_DEVICES);
124 if (dl)
126 RemDosEntry(glob->devnode);
127 FreeDosEntry(glob->devnode);
128 UnLockDosList(LDF_WRITE | LDF_DEVICES);
131 CleanupDiskHandler(diskchgsig_bit);
133 CleanupTimer();
135 DeletePool(glob->mempool);
137 else
138 error = ERROR_NO_FREE_STORE;
140 CloseLibrary(UtilityBase);
142 CloseLibrary(IntuitionBase);
144 CloseLibrary((struct Library*)DOSBase);
147 DeleteMsgPort(glob->notifyport);
149 D(bug("The end.\n"));
151 if (startuppacket != NULL) {
152 struct MsgPort *rp;
154 D(bug("[fat] returning startup packet\n"));
156 rp = startuppacket->dp_Port;
157 startuppacket->dp_Port = glob->ourport;
158 startuppacket->dp_Res1 = DOSTRUE;
159 startuppacket->dp_Res2 = 0;
160 PutMsg(rp, startuppacket->dp_Link);
163 return;
166 static struct IntData {
167 struct Interrupt Interrupt;
168 struct ExecBase *SysBase;
169 struct Task *task;
170 ULONG signal;
171 } DiskChangeIntData;
173 AROS_UFH3(static BOOL, DiskChangeIntHandler,
174 AROS_UFHA(struct IntData *, MyIntData, A1),
175 AROS_UFHA(APTR, dummy, A5),
176 AROS_UFHA(struct ExecBase *, SysBase, A6)) {
178 AROS_USERFUNC_INIT
180 struct ExecBase *SysBase = MyIntData->SysBase;
182 Signal(MyIntData->task, MyIntData->signal);
183 return 0;
185 AROS_USERFUNC_EXIT
188 LONG InitDiskHandler (struct FileSysStartupMsg *fssm, ULONG *diskchgsig_bit) {
189 LONG err;
190 ULONG diskchgintbit, flags, unit;
191 UBYTE *device;
193 unit = fssm->fssm_Unit;
194 flags = fssm->fssm_Flags;
196 device = AROS_BSTR_ADDR(fssm->fssm_Device);
198 if ((diskchgintbit = AllocSignal(-1)) >= 0) {
199 *diskchgsig_bit = diskchgintbit;
201 if ((glob->diskport = CreateMsgPort())) {
203 if ((glob->diskioreq = CreateIORequest(glob->diskport, sizeof(struct IOExtTD)))) {
205 if (OpenDevice(device, unit, (struct IORequest *)glob->diskioreq, flags) == 0) {
206 D(bug("\tDevice successfully opened\n"));
207 Probe_64bit_support();
209 if ((glob->diskchgreq = AllocVec(sizeof(struct IOExtTD), MEMF_PUBLIC))) {
210 CopyMem(glob->diskioreq, glob->diskchgreq, sizeof(struct IOExtTD));
212 /* fill interrupt data */
213 DiskChangeIntData.SysBase = SysBase;
214 DiskChangeIntData.task = glob->ourtask;
215 DiskChangeIntData.signal = 1 << diskchgintbit;
217 DiskChangeIntData.Interrupt.is_Node.ln_Type = NT_INTERRUPT;
218 DiskChangeIntData.Interrupt.is_Node.ln_Pri = 0;
219 DiskChangeIntData.Interrupt.is_Node.ln_Name = "FATFS";
220 DiskChangeIntData.Interrupt.is_Data = &DiskChangeIntData;
221 DiskChangeIntData.Interrupt.is_Code = (void (*)(void))AROS_ASMSYMNAME(DiskChangeIntHandler);
223 /* fill io request data */
224 glob->diskchgreq->iotd_Req.io_Command = TD_ADDCHANGEINT;
225 glob->diskchgreq->iotd_Req.io_Data = &DiskChangeIntData.Interrupt;
226 glob->diskchgreq->iotd_Req.io_Length = sizeof(struct Interrupt);
227 glob->diskchgreq->iotd_Req.io_Flags = 0;
229 SendIO((struct IORequest*)glob->diskchgreq);
231 D(bug("\tDisk change interrupt handler installed\n"));
233 return 0;
235 else
236 err = ERROR_NO_FREE_STORE;
238 CloseDevice((struct IORequest *)glob->diskioreq);
240 else
241 err = ERROR_DEVICE_NOT_MOUNTED;
243 DeleteIORequest(glob->diskioreq);
244 glob->diskioreq = NULL;
246 else
247 err = ERROR_NO_FREE_STORE;
249 DeleteMsgPort(glob->diskport);
250 glob->diskport = NULL;
252 else
253 err = ERROR_NO_FREE_STORE;
255 FreeSignal(diskchgintbit);
257 *diskchgsig_bit = 0;
259 else
260 err = ERROR_NO_FREE_STORE;
262 return err;
265 void CleanupDiskHandler(ULONG diskchgsig_bit) {
266 D(bug("\tFreeing handler resources:\n"));
268 /* remove disk change interrupt */
269 glob->diskchgreq->iotd_Req.io_Command = TD_REMCHANGEINT;
270 glob->diskchgreq->iotd_Req.io_Data = &DiskChangeIntData.Interrupt;
271 glob->diskchgreq->iotd_Req.io_Length = sizeof(struct Interrupt);
272 glob->diskchgreq->iotd_Req.io_Flags = 0;
274 DoIO((struct IORequest*)glob->diskchgreq);
275 D(bug("\tDisk change interrupt handler removed\n"));
277 CloseDevice((struct IORequest *)glob->diskioreq);
278 DeleteIORequest(glob->diskioreq);
279 FreeVec(glob->diskchgreq);
280 DeleteMsgPort(glob->diskport);
281 D(bug("\tDevice closed\n"));
283 glob->diskioreq = NULL;
284 glob->diskchgreq = NULL;
285 glob->diskport = NULL;
287 FreeSignal(diskchgsig_bit);
289 D(bug("\tDone.\n"));