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.
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>
27 #include "fat_protos.h"
29 #define DEBUG DEBUG_MISC
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"));
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
;
64 /* Disk has been removed. */
65 D(bug("\tDisk has been removed\n"));
66 glob
->disk_inserted
= FALSE
;
73 void UpdateDisk(struct Globals
*glob
)
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
;
98 glob
->readcmd
= CMD_READ
;
99 glob
->writecmd
= CMD_WRITE
;
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
;
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;
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
;
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
;
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
);
154 /* Adjust parameters if range is partially outside boundaries, or
155 * warn user and bale out if completely outside boundaries */
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
;
182 end
= glob
->sb
->first_device_sector
+ glob
->sb
->total_sectors
;
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
)
203 off
= ((UQUAD
) num
) * block_size
;
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
);
219 if (glob
->sb
&& glob
->sb
->volume
.name
[0] != '\0')
220 snprintf(vol_name
, 100, "Volume %s",
221 glob
->sb
->volume
.name
+ 1);
223 snprintf(vol_name
, 100, "Device %s",
224 AROS_BSTR_ADDR(glob
->devnode
->dol_Name
));
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
,
233 retry
= ErrorMessage("%s\nhas a %s error\n"
235 "Retry|Cancel", (IPTR
)vol_name
,
236 (IPTR
)(do_write
? "write" : "read"), num
);