grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / filesys / fat / disk.c
blobe140871223f9a0027810d071727e1486095c8070
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 #define USE_INLINE_STDARG
15 #include <exec/types.h>
16 #include <exec/errors.h>
18 #include <devices/newstyle.h>
19 #include <devices/trackdisk.h>
21 #include <proto/exec.h>
23 #include <string.h>
24 #include <stdio.h>
26 #include "fat_fs.h"
27 #include "fat_protos.h"
29 #define DEBUG DEBUG_MISC
30 #include "debug.h"
32 /* TD64 commands */
33 #ifndef TD_READ64
34 #define TD_READ64 24
35 #define TD_WRITE64 25
36 #endif
38 void ProcessDiskChange(struct Globals *glob)
40 D(bug("\nGot disk change request\n"));
42 if (glob->disk_inhibited != 0)
44 D(bug("Disk is inhibited, ignoring disk change\n"));
45 return;
48 glob->diskioreq->iotd_Req.io_Command = TD_CHANGESTATE;
49 glob->diskioreq->iotd_Req.io_Data = NULL;
50 glob->diskioreq->iotd_Req.io_Length = 0;
51 glob->diskioreq->iotd_Req.io_Flags = IOF_QUICK;
52 DoIO((struct IORequest *)glob->diskioreq);
54 if (glob->diskioreq->iotd_Req.io_Error == 0
55 && glob->diskioreq->iotd_Req.io_Actual == 0)
57 /* Disk has been inserted. */
58 D(bug("\tDisk has been inserted\n"));
59 glob->disk_inserted = TRUE;
60 DoDiskInsert(glob);
62 else
64 /* Disk has been removed. */
65 D(bug("\tDisk has been removed\n"));
66 glob->disk_inserted = FALSE;
67 DoDiskRemove(glob);
70 D(bug("Done\n"));
73 void UpdateDisk(struct Globals *glob)
75 if (glob->sb)
76 Cache_Flush(glob->sb->cache);
78 glob->diskioreq->iotd_Req.io_Command = CMD_UPDATE;
79 DoIO((struct IORequest *)glob->diskioreq);
81 /* Turn off motor (where applicable) if nothing has happened during the
82 * last timer period */
83 if (!glob->restart_timer)
85 D(bug("Stopping drive motor\n"));
86 glob->diskioreq->iotd_Req.io_Command = TD_MOTOR;
87 glob->diskioreq->iotd_Req.io_Length = 0;
88 DoIO((struct IORequest *)glob->diskioreq);
92 /* Probe the device to determine 64-bit support */
93 void Probe64BitSupport(struct Globals *glob)
95 struct NSDeviceQueryResult nsd_query;
96 UWORD *nsd_cmd;
98 glob->readcmd = CMD_READ;
99 glob->writecmd = CMD_WRITE;
101 /* Probe TD64 */
102 glob->diskioreq->iotd_Req.io_Command = TD_READ64;
103 glob->diskioreq->iotd_Req.io_Offset = 0;
104 glob->diskioreq->iotd_Req.io_Length = 0;
105 glob->diskioreq->iotd_Req.io_Actual = 0;
106 glob->diskioreq->iotd_Req.io_Data = 0;
108 if (DoIO((struct IORequest *)glob->diskioreq) != IOERR_NOCMD)
110 D(bug("Probe_64bit_support:"
111 " device supports 64-bit trackdisk extensions\n"));
112 glob->readcmd = TD_READ64;
113 glob->writecmd = TD_WRITE64;
116 /* Probe NSD */
117 glob->diskioreq->iotd_Req.io_Command = NSCMD_DEVICEQUERY;
118 glob->diskioreq->iotd_Req.io_Length =
119 sizeof(struct NSDeviceQueryResult);
120 glob->diskioreq->iotd_Req.io_Data = (APTR) &nsd_query;
122 if (DoIO((struct IORequest *)glob->diskioreq) == 0)
123 for (nsd_cmd = nsd_query.SupportedCommands; *nsd_cmd != 0;
124 nsd_cmd++)
126 if (*nsd_cmd == NSCMD_TD_READ64)
128 D(bug("Probe_64bit_support:"
129 " device supports NSD 64-bit trackdisk extensions\n"));
130 glob->readcmd = NSCMD_TD_READ64;
131 glob->writecmd = NSCMD_TD_WRITE64;
132 break;
137 /* N.B. returns an Exec error code, not a DOS error code! */
138 LONG AccessDisk(BOOL do_write, ULONG num, ULONG nblocks, ULONG block_size,
139 UBYTE *data, APTR priv)
141 struct Globals *glob = priv;
142 UQUAD off;
143 ULONG err;
144 ULONG start, end;
145 BOOL retry = TRUE;
146 TEXT vol_name[100];
148 #if DEBUG_CACHESTATS > 1
149 ErrorMessage("Accessing %lu sector(s) starting at %lu.\n"
150 "First volume sector is %lu, sector size is %lu.\n", "OK", nblocks,
151 num, glob->sb->first_device_sector, block_size);
152 #endif
154 /* Adjust parameters if range is partially outside boundaries, or
155 * warn user and bale out if completely outside boundaries */
156 if (glob->sb)
158 start = glob->sb->first_device_sector;
159 if (num + nblocks <= glob->sb->first_device_sector)
161 if (num != glob->last_num)
163 glob->last_num = num;
164 ErrorMessage("A handler attempted to %s %lu sector(s)\n"
165 "starting from %lu, before the actual volume space.\n"
166 "First volume sector is %lu, sector size is %lu.\n"
167 "Either your disk is damaged or it is a bug in\n"
168 "the handler. Please check your disk and/or\n"
169 "report this problem to the developers team.", "OK",
170 (IPTR) (do_write ? "write" : "read"), nblocks, num,
171 glob->sb->first_device_sector, block_size);
173 return IOERR_BADADDRESS;
175 else if (num < start)
177 nblocks -= start - num;
178 data += (start - num) * block_size;
179 num = start;
182 end = glob->sb->first_device_sector + glob->sb->total_sectors;
183 if (num >= end)
185 if (num != glob->last_num)
187 glob->last_num = num;
188 ErrorMessage("A handler attempted to %s %lu sector(s)\n"
189 "starting from %lu, beyond the actual volume space.\n"
190 "Last volume sector is %lu, sector size is %lu.\n"
191 "Either your disk is damaged or it is a bug in\n"
192 "the handler. Please check your disk and/or\n"
193 "report this problem to the developers team.", "OK",
194 (IPTR) (do_write ? "write" : "read"), nblocks, num,
195 end - 1, block_size);
197 return IOERR_BADADDRESS;
199 else if (num + nblocks > end)
200 nblocks = end - num;
203 off = ((UQUAD) num) * block_size;
205 while (retry)
207 glob->diskioreq->iotd_Req.io_Offset = off & 0xFFFFFFFF;
208 glob->diskioreq->iotd_Req.io_Actual = off >> 32;
210 glob->diskioreq->iotd_Req.io_Length = nblocks * block_size;
211 glob->diskioreq->iotd_Req.io_Data = data;
212 glob->diskioreq->iotd_Req.io_Command =
213 do_write ? glob->writecmd : glob->readcmd;
215 err = DoIO((struct IORequest *)glob->diskioreq);
217 if (err != 0)
219 if (glob->sb && glob->sb->volume.name[0] != '\0')
220 snprintf(vol_name, 100, "Volume %s",
221 glob->sb->volume.name + 1);
222 else
223 snprintf(vol_name, 100, "Device %s",
224 AROS_BSTR_ADDR(glob->devnode->dol_Name));
226 if (nblocks > 1)
227 retry = ErrorMessage("%s\nhas a %s error\n"
228 "in the block range\n%lu to %lu",
229 "Retry|Cancel", (IPTR)vol_name,
230 (IPTR)(do_write ? "write" : "read"), num,
231 num + nblocks - 1);
232 else
233 retry = ErrorMessage("%s\nhas a %s error\n"
234 "on block %lu",
235 "Retry|Cancel", (IPTR)vol_name,
236 (IPTR)(do_write ? "write" : "read"), num);
238 else
239 retry = FALSE;
242 return err;