Revision 5bbdbb46
b/block.c | ||
---|---|---|
1319 | 1319 |
*psecs = bs->secs; |
1320 | 1320 |
} |
1321 | 1321 |
|
1322 |
/* Recognize floppy formats */ |
|
1323 |
typedef struct FDFormat { |
|
1324 |
FDriveType drive; |
|
1325 |
uint8_t last_sect; |
|
1326 |
uint8_t max_track; |
|
1327 |
uint8_t max_head; |
|
1328 |
} FDFormat; |
|
1329 |
|
|
1330 |
static const FDFormat fd_formats[] = { |
|
1331 |
/* First entry is default format */ |
|
1332 |
/* 1.44 MB 3"1/2 floppy disks */ |
|
1333 |
{ FDRIVE_DRV_144, 18, 80, 1, }, |
|
1334 |
{ FDRIVE_DRV_144, 20, 80, 1, }, |
|
1335 |
{ FDRIVE_DRV_144, 21, 80, 1, }, |
|
1336 |
{ FDRIVE_DRV_144, 21, 82, 1, }, |
|
1337 |
{ FDRIVE_DRV_144, 21, 83, 1, }, |
|
1338 |
{ FDRIVE_DRV_144, 22, 80, 1, }, |
|
1339 |
{ FDRIVE_DRV_144, 23, 80, 1, }, |
|
1340 |
{ FDRIVE_DRV_144, 24, 80, 1, }, |
|
1341 |
/* 2.88 MB 3"1/2 floppy disks */ |
|
1342 |
{ FDRIVE_DRV_288, 36, 80, 1, }, |
|
1343 |
{ FDRIVE_DRV_288, 39, 80, 1, }, |
|
1344 |
{ FDRIVE_DRV_288, 40, 80, 1, }, |
|
1345 |
{ FDRIVE_DRV_288, 44, 80, 1, }, |
|
1346 |
{ FDRIVE_DRV_288, 48, 80, 1, }, |
|
1347 |
/* 720 kB 3"1/2 floppy disks */ |
|
1348 |
{ FDRIVE_DRV_144, 9, 80, 1, }, |
|
1349 |
{ FDRIVE_DRV_144, 10, 80, 1, }, |
|
1350 |
{ FDRIVE_DRV_144, 10, 82, 1, }, |
|
1351 |
{ FDRIVE_DRV_144, 10, 83, 1, }, |
|
1352 |
{ FDRIVE_DRV_144, 13, 80, 1, }, |
|
1353 |
{ FDRIVE_DRV_144, 14, 80, 1, }, |
|
1354 |
/* 1.2 MB 5"1/4 floppy disks */ |
|
1355 |
{ FDRIVE_DRV_120, 15, 80, 1, }, |
|
1356 |
{ FDRIVE_DRV_120, 18, 80, 1, }, |
|
1357 |
{ FDRIVE_DRV_120, 18, 82, 1, }, |
|
1358 |
{ FDRIVE_DRV_120, 18, 83, 1, }, |
|
1359 |
{ FDRIVE_DRV_120, 20, 80, 1, }, |
|
1360 |
/* 720 kB 5"1/4 floppy disks */ |
|
1361 |
{ FDRIVE_DRV_120, 9, 80, 1, }, |
|
1362 |
{ FDRIVE_DRV_120, 11, 80, 1, }, |
|
1363 |
/* 360 kB 5"1/4 floppy disks */ |
|
1364 |
{ FDRIVE_DRV_120, 9, 40, 1, }, |
|
1365 |
{ FDRIVE_DRV_120, 9, 40, 0, }, |
|
1366 |
{ FDRIVE_DRV_120, 10, 41, 1, }, |
|
1367 |
{ FDRIVE_DRV_120, 10, 42, 1, }, |
|
1368 |
/* 320 kB 5"1/4 floppy disks */ |
|
1369 |
{ FDRIVE_DRV_120, 8, 40, 1, }, |
|
1370 |
{ FDRIVE_DRV_120, 8, 40, 0, }, |
|
1371 |
/* 360 kB must match 5"1/4 better than 3"1/2... */ |
|
1372 |
{ FDRIVE_DRV_144, 9, 80, 0, }, |
|
1373 |
/* end */ |
|
1374 |
{ FDRIVE_DRV_NONE, -1, -1, 0, }, |
|
1375 |
}; |
|
1376 |
|
|
1377 |
void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads, |
|
1378 |
int *max_track, int *last_sect, |
|
1379 |
FDriveType drive_in, FDriveType *drive) |
|
1380 |
{ |
|
1381 |
const FDFormat *parse; |
|
1382 |
uint64_t nb_sectors, size; |
|
1383 |
int i, first_match, match; |
|
1384 |
|
|
1385 |
bdrv_get_geometry_hint(bs, nb_heads, max_track, last_sect); |
|
1386 |
if (*nb_heads != 0 && *max_track != 0 && *last_sect != 0) { |
|
1387 |
/* User defined disk */ |
|
1388 |
} else { |
|
1389 |
bdrv_get_geometry(bs, &nb_sectors); |
|
1390 |
match = -1; |
|
1391 |
first_match = -1; |
|
1392 |
for (i = 0; ; i++) { |
|
1393 |
parse = &fd_formats[i]; |
|
1394 |
if (parse->drive == FDRIVE_DRV_NONE) { |
|
1395 |
break; |
|
1396 |
} |
|
1397 |
if (drive_in == parse->drive || |
|
1398 |
drive_in == FDRIVE_DRV_NONE) { |
|
1399 |
size = (parse->max_head + 1) * parse->max_track * |
|
1400 |
parse->last_sect; |
|
1401 |
if (nb_sectors == size) { |
|
1402 |
match = i; |
|
1403 |
break; |
|
1404 |
} |
|
1405 |
if (first_match == -1) { |
|
1406 |
first_match = i; |
|
1407 |
} |
|
1408 |
} |
|
1409 |
} |
|
1410 |
if (match == -1) { |
|
1411 |
if (first_match == -1) { |
|
1412 |
match = 1; |
|
1413 |
} else { |
|
1414 |
match = first_match; |
|
1415 |
} |
|
1416 |
parse = &fd_formats[match]; |
|
1417 |
} |
|
1418 |
*nb_heads = parse->max_head + 1; |
|
1419 |
*max_track = parse->max_track; |
|
1420 |
*last_sect = parse->last_sect; |
|
1421 |
*drive = parse->drive; |
|
1422 |
} |
|
1423 |
} |
|
1424 |
|
|
1322 | 1425 |
int bdrv_get_type_hint(BlockDriverState *bs) |
1323 | 1426 |
{ |
1324 | 1427 |
return bs->type; |
b/block.h | ||
---|---|---|
166 | 166 |
void bdrv_set_translation_hint(BlockDriverState *bs, int translation); |
167 | 167 |
void bdrv_get_geometry_hint(BlockDriverState *bs, |
168 | 168 |
int *pcyls, int *pheads, int *psecs); |
169 |
typedef enum FDriveType { |
|
170 |
FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */ |
|
171 |
FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */ |
|
172 |
FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */ |
|
173 |
FDRIVE_DRV_NONE = 0x03, /* No drive connected */ |
|
174 |
} FDriveType; |
|
175 |
|
|
176 |
void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads, |
|
177 |
int *max_track, int *last_sect, |
|
178 |
FDriveType drive_in, FDriveType *drive); |
|
169 | 179 |
int bdrv_get_type_hint(BlockDriverState *bs); |
170 | 180 |
int bdrv_get_translation_hint(BlockDriverState *bs); |
171 | 181 |
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error, |
b/hw/fdc.c | ||
---|---|---|
63 | 63 |
#define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */ |
64 | 64 |
|
65 | 65 |
/* Floppy disk drive emulation */ |
66 |
typedef enum FDiskType { |
|
67 |
FDRIVE_DISK_288 = 0x01, /* 2.88 MB disk */ |
|
68 |
FDRIVE_DISK_144 = 0x02, /* 1.44 MB disk */ |
|
69 |
FDRIVE_DISK_720 = 0x03, /* 720 kB disk */ |
|
70 |
FDRIVE_DISK_USER = 0x04, /* User defined geometry */ |
|
71 |
FDRIVE_DISK_NONE = 0x05, /* No disk */ |
|
72 |
} FDiskType; |
|
73 |
|
|
74 |
typedef enum FDriveType { |
|
75 |
FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */ |
|
76 |
FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */ |
|
77 |
FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */ |
|
78 |
FDRIVE_DRV_NONE = 0x03, /* No drive connected */ |
|
79 |
} FDriveType; |
|
80 |
|
|
81 | 66 |
typedef enum FDiskFlags { |
82 | 67 |
FDISK_DBL_SIDES = 0x01, |
83 | 68 |
} FDiskFlags; |
... | ... | |
178 | 163 |
drv->sect = 1; |
179 | 164 |
} |
180 | 165 |
|
181 |
/* Recognize floppy formats */ |
|
182 |
typedef struct FDFormat { |
|
183 |
FDriveType drive; |
|
184 |
FDiskType disk; |
|
185 |
uint8_t last_sect; |
|
186 |
uint8_t max_track; |
|
187 |
uint8_t max_head; |
|
188 |
const char *str; |
|
189 |
} FDFormat; |
|
190 |
|
|
191 |
static const FDFormat fd_formats[] = { |
|
192 |
/* First entry is default format */ |
|
193 |
/* 1.44 MB 3"1/2 floppy disks */ |
|
194 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", }, |
|
195 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", }, |
|
196 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", }, |
|
197 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", }, |
|
198 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", }, |
|
199 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", }, |
|
200 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", }, |
|
201 |
{ FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", }, |
|
202 |
/* 2.88 MB 3"1/2 floppy disks */ |
|
203 |
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", }, |
|
204 |
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", }, |
|
205 |
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", }, |
|
206 |
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", }, |
|
207 |
{ FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", }, |
|
208 |
/* 720 kB 3"1/2 floppy disks */ |
|
209 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", }, |
|
210 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", }, |
|
211 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", }, |
|
212 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", }, |
|
213 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", }, |
|
214 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", }, |
|
215 |
/* 1.2 MB 5"1/4 floppy disks */ |
|
216 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", }, |
|
217 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", }, |
|
218 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", }, |
|
219 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", }, |
|
220 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", }, |
|
221 |
/* 720 kB 5"1/4 floppy disks */ |
|
222 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", }, |
|
223 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", }, |
|
224 |
/* 360 kB 5"1/4 floppy disks */ |
|
225 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", }, |
|
226 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", }, |
|
227 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", }, |
|
228 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", }, |
|
229 |
/* 320 kB 5"1/4 floppy disks */ |
|
230 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", }, |
|
231 |
{ FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", }, |
|
232 |
/* 360 kB must match 5"1/4 better than 3"1/2... */ |
|
233 |
{ FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", }, |
|
234 |
/* end */ |
|
235 |
{ FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, }, |
|
236 |
}; |
|
237 |
|
|
238 | 166 |
/* Revalidate a disk drive after a disk change */ |
239 | 167 |
static void fd_revalidate(FDrive *drv) |
240 | 168 |
{ |
241 |
const FDFormat *parse; |
|
242 |
uint64_t nb_sectors, size; |
|
243 |
int i, first_match, match; |
|
244 | 169 |
int nb_heads, max_track, last_sect, ro; |
170 |
FDriveType drive; |
|
245 | 171 |
|
246 | 172 |
FLOPPY_DPRINTF("revalidate\n"); |
247 | 173 |
if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { |
248 | 174 |
ro = bdrv_is_read_only(drv->bs); |
249 |
bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect); |
|
175 |
bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track, |
|
176 |
&last_sect, drv->drive, &drive); |
|
250 | 177 |
if (nb_heads != 0 && max_track != 0 && last_sect != 0) { |
251 | 178 |
FLOPPY_DPRINTF("User defined disk (%d %d %d)", |
252 | 179 |
nb_heads - 1, max_track, last_sect); |
253 | 180 |
} else { |
254 |
bdrv_get_geometry(drv->bs, &nb_sectors); |
|
255 |
match = -1; |
|
256 |
first_match = -1; |
|
257 |
for (i = 0;; i++) { |
|
258 |
parse = &fd_formats[i]; |
|
259 |
if (parse->drive == FDRIVE_DRV_NONE) |
|
260 |
break; |
|
261 |
if (drv->drive == parse->drive || |
|
262 |
drv->drive == FDRIVE_DRV_NONE) { |
|
263 |
size = (parse->max_head + 1) * parse->max_track * |
|
264 |
parse->last_sect; |
|
265 |
if (nb_sectors == size) { |
|
266 |
match = i; |
|
267 |
break; |
|
268 |
} |
|
269 |
if (first_match == -1) |
|
270 |
first_match = i; |
|
271 |
} |
|
272 |
} |
|
273 |
if (match == -1) { |
|
274 |
if (first_match == -1) |
|
275 |
match = 1; |
|
276 |
else |
|
277 |
match = first_match; |
|
278 |
parse = &fd_formats[match]; |
|
279 |
} |
|
280 |
nb_heads = parse->max_head + 1; |
|
281 |
max_track = parse->max_track; |
|
282 |
last_sect = parse->last_sect; |
|
283 |
drv->drive = parse->drive; |
|
284 |
FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str, |
|
285 |
nb_heads, max_track, last_sect, ro ? "ro" : "rw"); |
|
181 |
FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads, |
|
182 |
max_track, last_sect, ro ? "ro" : "rw"); |
|
286 | 183 |
} |
287 | 184 |
if (nb_heads == 1) { |
288 | 185 |
drv->flags &= ~FDISK_DBL_SIDES; |
... | ... | |
292 | 189 |
drv->max_track = max_track; |
293 | 190 |
drv->last_sect = last_sect; |
294 | 191 |
drv->ro = ro; |
192 |
drv->drive = drive; |
|
295 | 193 |
} else { |
296 | 194 |
FLOPPY_DPRINTF("No disk in drive\n"); |
297 | 195 |
drv->last_sect = 0; |
Also available in: Unified diff