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