|
@@ -52,6 +52,113 @@
|
|
/********************************************************/
|
|
/********************************************************/
|
|
/* Floppy drive emulation */
|
|
/* Floppy drive emulation */
|
|
|
|
|
|
|
|
+typedef enum FDriveRate {
|
|
|
|
+ FDRIVE_RATE_500K = 0x00, /* 500 Kbps */
|
|
|
|
+ FDRIVE_RATE_300K = 0x01, /* 300 Kbps */
|
|
|
|
+ FDRIVE_RATE_250K = 0x02, /* 250 Kbps */
|
|
|
|
+ FDRIVE_RATE_1M = 0x03, /* 1 Mbps */
|
|
|
|
+} FDriveRate;
|
|
|
|
+
|
|
|
|
+typedef struct FDFormat {
|
|
|
|
+ FDriveType drive;
|
|
|
|
+ uint8_t last_sect;
|
|
|
|
+ uint8_t max_track;
|
|
|
|
+ uint8_t max_head;
|
|
|
|
+ FDriveRate rate;
|
|
|
|
+} FDFormat;
|
|
|
|
+
|
|
|
|
+static const FDFormat fd_formats[] = {
|
|
|
|
+ /* First entry is default format */
|
|
|
|
+ /* 1.44 MB 3"1/2 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_144, 18, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 20, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 21, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 21, 82, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 21, 83, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 22, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 23, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_144, 24, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ /* 2.88 MB 3"1/2 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_288, 36, 80, 1, FDRIVE_RATE_1M, },
|
|
|
|
+ { FDRIVE_DRV_288, 39, 80, 1, FDRIVE_RATE_1M, },
|
|
|
|
+ { FDRIVE_DRV_288, 40, 80, 1, FDRIVE_RATE_1M, },
|
|
|
|
+ { FDRIVE_DRV_288, 44, 80, 1, FDRIVE_RATE_1M, },
|
|
|
|
+ { FDRIVE_DRV_288, 48, 80, 1, FDRIVE_RATE_1M, },
|
|
|
|
+ /* 720 kB 3"1/2 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_144, 9, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_144, 10, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_144, 10, 82, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_144, 10, 83, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_144, 13, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_144, 14, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ /* 1.2 MB 5"1/4 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_120, 15, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_120, 18, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_120, 18, 82, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_120, 18, 83, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ { FDRIVE_DRV_120, 20, 80, 1, FDRIVE_RATE_500K, },
|
|
|
|
+ /* 720 kB 5"1/4 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_120, 9, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_120, 11, 80, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ /* 360 kB 5"1/4 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_120, 9, 40, 1, FDRIVE_RATE_300K, },
|
|
|
|
+ { FDRIVE_DRV_120, 9, 40, 0, FDRIVE_RATE_300K, },
|
|
|
|
+ { FDRIVE_DRV_120, 10, 41, 1, FDRIVE_RATE_300K, },
|
|
|
|
+ { FDRIVE_DRV_120, 10, 42, 1, FDRIVE_RATE_300K, },
|
|
|
|
+ /* 320 kB 5"1/4 floppy disks */
|
|
|
|
+ { FDRIVE_DRV_120, 8, 40, 1, FDRIVE_RATE_250K, },
|
|
|
|
+ { FDRIVE_DRV_120, 8, 40, 0, FDRIVE_RATE_250K, },
|
|
|
|
+ /* 360 kB must match 5"1/4 better than 3"1/2... */
|
|
|
|
+ { FDRIVE_DRV_144, 9, 80, 0, FDRIVE_RATE_250K, },
|
|
|
|
+ /* end */
|
|
|
|
+ { FDRIVE_DRV_NONE, -1, -1, 0, 0, },
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void pick_geometry(BlockDriverState *bs, int *nb_heads,
|
|
|
|
+ int *max_track, int *last_sect,
|
|
|
|
+ FDriveType drive_in, FDriveType *drive,
|
|
|
|
+ FDriveRate *rate)
|
|
|
|
+{
|
|
|
|
+ const FDFormat *parse;
|
|
|
|
+ uint64_t nb_sectors, size;
|
|
|
|
+ int i, first_match, match;
|
|
|
|
+
|
|
|
|
+ bdrv_get_geometry(bs, &nb_sectors);
|
|
|
|
+ match = -1;
|
|
|
|
+ first_match = -1;
|
|
|
|
+ for (i = 0; ; i++) {
|
|
|
|
+ parse = &fd_formats[i];
|
|
|
|
+ if (parse->drive == FDRIVE_DRV_NONE) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (drive_in == parse->drive ||
|
|
|
|
+ drive_in == FDRIVE_DRV_NONE) {
|
|
|
|
+ size = (parse->max_head + 1) * parse->max_track *
|
|
|
|
+ parse->last_sect;
|
|
|
|
+ if (nb_sectors == size) {
|
|
|
|
+ match = i;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (first_match == -1) {
|
|
|
|
+ first_match = i;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (match == -1) {
|
|
|
|
+ if (first_match == -1) {
|
|
|
|
+ match = 1;
|
|
|
|
+ } else {
|
|
|
|
+ match = first_match;
|
|
|
|
+ }
|
|
|
|
+ parse = &fd_formats[match];
|
|
|
|
+ }
|
|
|
|
+ *nb_heads = parse->max_head + 1;
|
|
|
|
+ *max_track = parse->max_track;
|
|
|
|
+ *last_sect = parse->last_sect;
|
|
|
|
+ *drive = parse->drive;
|
|
|
|
+ *rate = parse->rate;
|
|
|
|
+}
|
|
|
|
+
|
|
#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
|
|
#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
|
|
#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
|
|
#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
|
|
|
|
|
|
@@ -187,8 +294,8 @@ static void fd_revalidate(FDrive *drv)
|
|
FLOPPY_DPRINTF("revalidate\n");
|
|
FLOPPY_DPRINTF("revalidate\n");
|
|
if (drv->bs != NULL) {
|
|
if (drv->bs != NULL) {
|
|
ro = bdrv_is_read_only(drv->bs);
|
|
ro = bdrv_is_read_only(drv->bs);
|
|
- bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
|
|
|
|
- &last_sect, drv->drive, &drive, &rate);
|
|
|
|
|
|
+ pick_geometry(drv->bs, &nb_heads, &max_track,
|
|
|
|
+ &last_sect, drv->drive, &drive, &rate);
|
|
if (!bdrv_is_inserted(drv->bs)) {
|
|
if (!bdrv_is_inserted(drv->bs)) {
|
|
FLOPPY_DPRINTF("No disk in drive\n");
|
|
FLOPPY_DPRINTF("No disk in drive\n");
|
|
} else {
|
|
} else {
|
|
@@ -2054,18 +2161,13 @@ static int sun4m_fdc_init1(SysBusDevice *dev)
|
|
return fdctrl_init_common(fdctrl);
|
|
return fdctrl_init_common(fdctrl);
|
|
}
|
|
}
|
|
|
|
|
|
-void fdc_get_bs(BlockDriverState *bs[], ISADevice *dev)
|
|
|
|
|
|
+FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
|
|
{
|
|
{
|
|
- FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, dev);
|
|
|
|
- FDCtrl *fdctrl = &isa->state;
|
|
|
|
- int i;
|
|
|
|
|
|
+ FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, fdc);
|
|
|
|
|
|
- for (i = 0; i < MAX_FD; i++) {
|
|
|
|
- bs[i] = fdctrl->drives[i].bs;
|
|
|
|
- }
|
|
|
|
|
|
+ return isa->state.drives[i].drive;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
static const VMStateDescription vmstate_isa_fdc ={
|
|
static const VMStateDescription vmstate_isa_fdc ={
|
|
.name = "fdc",
|
|
.name = "fdc",
|
|
.version_id = 2,
|
|
.version_id = 2,
|