- Implemented ACTION_FORMAT.
[AROS.git] / rom / filesys / fat / main.c
blob83c517ce65e933553eab38812671e98bef94a1d8
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;
39 struct Device *TimerBase;
41 struct Globals global_data;
42 struct Globals *glob = &global_data;
44 LONG handler(struct ExecBase *SysBase) {
45 struct Message *msg;
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))) {
71 error = InitTimer();
72 if (!error) {
73 TimerBase = glob->timereq->tr_node.io_Device;
75 InitCharsetTables();
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;
82 ULONG sigs;
83 struct MsgPort *rp;
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 */
101 while(!glob->quit) {
102 sigs = Wait(mask);
103 if (sigs & diskchgsig)
104 ProcessDiskChange();
105 if (sigs & pktsig)
106 ProcessPackets();
107 if (sigs & notifysig)
108 ProcessNotify();
109 if (sigs & timersig)
110 HandleTimer();
113 D(bug("\nHandler shutdown initiated\n"));
115 error = 0;
116 startuppacket = NULL;
118 CleanupDiskHandler();
120 CleanupTimer();
122 DeletePool(glob->mempool);
124 else
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);
149 return RETURN_OK;
152 static struct IntData {
153 struct Interrupt Interrupt;
154 struct ExecBase *SysBase;
155 struct Task *task;
156 ULONG signal;
157 } DiskChangeIntData;
159 static AROS_INTH1(DiskChangeIntHandler, struct IntData *, MyIntData)
161 AROS_INTFUNC_INIT
163 struct ExecBase *SysBase = MyIntData->SysBase;
165 Signal(MyIntData->task, MyIntData->signal);
166 return 0;
168 AROS_INTFUNC_EXIT
171 LONG InitDiskHandler (struct FileSysStartupMsg *fssm) {
172 LONG err;
173 ULONG diskchgintbit, flags;
174 IPTR unit;
175 UBYTE *device;
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"));
217 return 0;
219 else
220 err = ERROR_NO_FREE_STORE;
222 CloseDevice((struct IORequest *)glob->diskioreq);
224 else
225 err = ERROR_DEVICE_NOT_MOUNTED;
227 DeleteIORequest(glob->diskioreq);
228 glob->diskioreq = NULL;
230 else
231 err = ERROR_NO_FREE_STORE;
233 DeleteMsgPort(glob->diskport);
234 glob->diskport = NULL;
236 else
237 err = ERROR_NO_FREE_STORE;
239 FreeSignal(diskchgintbit);
241 glob->diskchgsig_bit = 0;
243 else
244 err = ERROR_NO_FREE_STORE;
246 return err;
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);
273 D(bug("\tDone.\n"));