summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell2016-01-26 10:16:07 +0100
committerPeter Maydell2016-01-26 10:16:07 +0100
commit1535a6d699487740b490369e44f9ca8d305463cd (patch)
tree6e26639d54ebf2ceadb8b60a889f5f87a3a42307
parentMerge remote-tracking branch 'remotes/lalrae/tags/mips-20160125' into staging (diff)
parentfdc: change auto fallback drive for ISA FDC to 288 (diff)
downloadqemu-1535a6d699487740b490369e44f9ca8d305463cd.tar.gz
qemu-1535a6d699487740b490369e44f9ca8d305463cd.tar.xz
qemu-1535a6d699487740b490369e44f9ca8d305463cd.zip
Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging
# gpg: Signature made Mon 25 Jan 2016 19:39:58 GMT using RSA key ID AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" * remotes/jnsnow/tags/ide-pull-request: fdc: change auto fallback drive for ISA FDC to 288 qtest/fdc: Support for 2.88MB drives fdc: rework pick_geometry fdc: add physical disk sizes fdc: add drive type option fdc: Add fallback option fdc: add pick_drive fdc: Throw an assertion on misconfigured fd_formats table fdc: add disk field fdc: add drive type qapi enum fdc: reduce number of pick_geometry arguments fdc: move pick_geometry ide: Correct the CHS 'cyls_max' limit to be 65535 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/block/fdc.c326
-rw-r--r--hw/core/qdev-properties.c11
-rw-r--r--hw/i386/pc.c17
-rw-r--r--hw/ide/qdev.c2
-rw-r--r--include/hw/block/fdc.h9
-rw-r--r--include/hw/compat.h4
-rw-r--r--include/hw/qdev-properties.h1
-rw-r--r--qapi/block.json16
-rw-r--r--tests/fdc-test.c2
9 files changed, 271 insertions, 117 deletions
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 6711c6ac1a..e3b0e1e60c 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -60,104 +60,82 @@ typedef enum FDriveRate {
FDRIVE_RATE_1M = 0x03, /* 1 Mbps */
} FDriveRate;
+typedef enum FDriveSize {
+ FDRIVE_SIZE_UNKNOWN,
+ FDRIVE_SIZE_350,
+ FDRIVE_SIZE_525,
+} FDriveSize;
+
typedef struct FDFormat {
- FDriveType drive;
+ FloppyDriveType drive;
uint8_t last_sect;
uint8_t max_track;
uint8_t max_head;
FDriveRate rate;
} FDFormat;
+/* In many cases, the total sector size of a format is enough to uniquely
+ * identify it. However, there are some total sector collisions between
+ * formats of different physical size, and these are noted below by
+ * highlighting the total sector size for entries with collisions. */
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, },
+ { FLOPPY_DRIVE_TYPE_144, 18, 80, 1, FDRIVE_RATE_500K, }, /* 3.5" 2880 */
+ { FLOPPY_DRIVE_TYPE_144, 20, 80, 1, FDRIVE_RATE_500K, }, /* 3.5" 3200 */
+ { FLOPPY_DRIVE_TYPE_144, 21, 80, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_144, 21, 82, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_144, 21, 83, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_144, 22, 80, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_144, 23, 80, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_288, 36, 80, 1, FDRIVE_RATE_1M, },
+ { FLOPPY_DRIVE_TYPE_288, 39, 80, 1, FDRIVE_RATE_1M, },
+ { FLOPPY_DRIVE_TYPE_288, 40, 80, 1, FDRIVE_RATE_1M, },
+ { FLOPPY_DRIVE_TYPE_288, 44, 80, 1, FDRIVE_RATE_1M, },
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_144, 9, 80, 1, FDRIVE_RATE_250K, }, /* 3.5" 1440 */
+ { FLOPPY_DRIVE_TYPE_144, 10, 80, 1, FDRIVE_RATE_250K, },
+ { FLOPPY_DRIVE_TYPE_144, 10, 82, 1, FDRIVE_RATE_250K, },
+ { FLOPPY_DRIVE_TYPE_144, 10, 83, 1, FDRIVE_RATE_250K, },
+ { FLOPPY_DRIVE_TYPE_144, 13, 80, 1, FDRIVE_RATE_250K, },
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_120, 15, 80, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_120, 18, 80, 1, FDRIVE_RATE_500K, }, /* 5.25" 2880 */
+ { FLOPPY_DRIVE_TYPE_120, 18, 82, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_120, 18, 83, 1, FDRIVE_RATE_500K, },
+ { FLOPPY_DRIVE_TYPE_120, 20, 80, 1, FDRIVE_RATE_500K, }, /* 5.25" 3200 */
/* 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, },
+ { FLOPPY_DRIVE_TYPE_120, 9, 80, 1, FDRIVE_RATE_250K, }, /* 5.25" 1440 */
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_120, 9, 40, 1, FDRIVE_RATE_300K, }, /* 5.25" 720 */
+ { FLOPPY_DRIVE_TYPE_120, 9, 40, 0, FDRIVE_RATE_300K, },
+ { FLOPPY_DRIVE_TYPE_120, 10, 41, 1, FDRIVE_RATE_300K, },
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_120, 8, 40, 1, FDRIVE_RATE_250K, },
+ { FLOPPY_DRIVE_TYPE_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, },
+ { FLOPPY_DRIVE_TYPE_144, 9, 80, 0, FDRIVE_RATE_250K, }, /* 3.5" 720 */
/* end */
- { FDRIVE_DRV_NONE, -1, -1, 0, 0, },
+ { FLOPPY_DRIVE_TYPE_NONE, -1, -1, 0, 0, },
};
-static void pick_geometry(BlockBackend *blk, int *nb_heads,
- int *max_track, int *last_sect,
- FDriveType drive_in, FDriveType *drive,
- FDriveRate *rate)
+static FDriveSize drive_size(FloppyDriveType drive)
{
- const FDFormat *parse;
- uint64_t nb_sectors, size;
- int i, first_match, match;
-
- blk_get_geometry(blk, &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];
+ switch (drive) {
+ case FLOPPY_DRIVE_TYPE_120:
+ return FDRIVE_SIZE_525;
+ case FLOPPY_DRIVE_TYPE_144:
+ case FLOPPY_DRIVE_TYPE_288:
+ return FDRIVE_SIZE_350;
+ default:
+ return FDRIVE_SIZE_UNKNOWN;
}
- *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)
@@ -179,13 +157,14 @@ typedef struct FDrive {
FDCtrl *fdctrl;
BlockBackend *blk;
/* Drive status */
- FDriveType drive;
+ FloppyDriveType drive; /* CMOS drive type */
uint8_t perpendicular; /* 2.88 MB access mode */
/* Position */
uint8_t head;
uint8_t track;
uint8_t sect;
/* Media */
+ FloppyDriveType disk; /* Current disk type */
FDiskFlags flags;
uint8_t last_sect; /* Nb sector per track */
uint8_t max_track; /* Nb of tracks */
@@ -195,16 +174,22 @@ typedef struct FDrive {
uint8_t media_rate; /* Data rate of medium */
bool media_inserted; /* Is there a medium in the tray */
+ bool media_validated; /* Have we validated the media? */
} FDrive;
+
+static FloppyDriveType get_fallback_drive_type(FDrive *drv);
+
static void fd_init(FDrive *drv)
{
/* Drive */
- drv->drive = FDRIVE_DRV_NONE;
drv->perpendicular = 0;
/* Disk */
+ drv->disk = FLOPPY_DRIVE_TYPE_NONE;
drv->last_sect = 0;
drv->max_track = 0;
+ drv->ro = true;
+ drv->media_changed = 1;
}
#define NUM_SIDES(drv) ((drv)->flags & FDISK_DBL_SIDES ? 2 : 1)
@@ -287,39 +272,146 @@ static void fd_recalibrate(FDrive *drv)
fd_seek(drv, 0, 0, 1, 1);
}
+/**
+ * Determine geometry based on inserted diskette.
+ * Will not operate on an empty drive.
+ *
+ * @return: 0 on success, -1 if the drive is empty.
+ */
+static int pick_geometry(FDrive *drv)
+{
+ BlockBackend *blk = drv->blk;
+ const FDFormat *parse;
+ uint64_t nb_sectors, size;
+ int i;
+ int match, size_match, type_match;
+ bool magic = drv->drive == FLOPPY_DRIVE_TYPE_AUTO;
+
+ /* We can only pick a geometry if we have a diskette. */
+ if (!drv->media_inserted || drv->drive == FLOPPY_DRIVE_TYPE_NONE) {
+ return -1;
+ }
+
+ /* We need to determine the likely geometry of the inserted medium.
+ * In order of preference, we look for:
+ * (1) The same drive type and number of sectors,
+ * (2) The same diskette size and number of sectors,
+ * (3) The same drive type.
+ *
+ * In all cases, matches that occur higher in the drive table will take
+ * precedence over matches that occur later in the table.
+ */
+ blk_get_geometry(blk, &nb_sectors);
+ match = size_match = type_match = -1;
+ for (i = 0; ; i++) {
+ parse = &fd_formats[i];
+ if (parse->drive == FLOPPY_DRIVE_TYPE_NONE) {
+ break;
+ }
+ size = (parse->max_head + 1) * parse->max_track * parse->last_sect;
+ if (nb_sectors == size) {
+ if (magic || parse->drive == drv->drive) {
+ /* (1) perfect match -- nb_sectors and drive type */
+ goto out;
+ } else if (drive_size(parse->drive) == drive_size(drv->drive)) {
+ /* (2) size match -- nb_sectors and physical medium size */
+ match = (match == -1) ? i : match;
+ } else {
+ /* This is suspicious -- Did the user misconfigure? */
+ size_match = (size_match == -1) ? i : size_match;
+ }
+ } else if (type_match == -1) {
+ if ((parse->drive == drv->drive) ||
+ (magic && (parse->drive == get_fallback_drive_type(drv)))) {
+ /* (3) type match -- nb_sectors mismatch, but matches the type
+ * specified explicitly by the user, or matches the fallback
+ * default type when using the drive autodetect mechanism */
+ type_match = i;
+ }
+ }
+ }
+
+ /* No exact match found */
+ if (match == -1) {
+ if (size_match != -1) {
+ parse = &fd_formats[size_match];
+ FLOPPY_DPRINTF("User requested floppy drive type '%s', "
+ "but inserted medium appears to be a "
+ "%d sector '%s' type\n",
+ FloppyDriveType_lookup[drv->drive],
+ nb_sectors,
+ FloppyDriveType_lookup[parse->drive]);
+ }
+ match = type_match;
+ }
+
+ /* No match of any kind found -- fd_format is misconfigured, abort. */
+ if (match == -1) {
+ error_setg(&error_abort, "No candidate geometries present in table "
+ " for floppy drive type '%s'",
+ FloppyDriveType_lookup[drv->drive]);
+ }
+
+ parse = &(fd_formats[match]);
+
+ out:
+ if (parse->max_head == 0) {
+ drv->flags &= ~FDISK_DBL_SIDES;
+ } else {
+ drv->flags |= FDISK_DBL_SIDES;
+ }
+ drv->max_track = parse->max_track;
+ drv->last_sect = parse->last_sect;
+ drv->disk = parse->drive;
+ drv->media_rate = parse->rate;
+ return 0;
+}
+
+static void pick_drive_type(FDrive *drv)
+{
+ if (drv->drive != FLOPPY_DRIVE_TYPE_AUTO) {
+ return;
+ }
+
+ if (pick_geometry(drv) == 0) {
+ drv->drive = drv->disk;
+ } else {
+ drv->drive = get_fallback_drive_type(drv);
+ }
+
+ g_assert(drv->drive != FLOPPY_DRIVE_TYPE_AUTO);
+}
+
/* Revalidate a disk drive after a disk change */
static void fd_revalidate(FDrive *drv)
{
- int nb_heads, max_track, last_sect, ro;
- FDriveType drive;
- FDriveRate rate;
+ int rc;
FLOPPY_DPRINTF("revalidate\n");
if (drv->blk != NULL) {
- ro = blk_is_read_only(drv->blk);
- pick_geometry(drv->blk, &nb_heads, &max_track,
- &last_sect, drv->drive, &drive, &rate);
+ drv->ro = blk_is_read_only(drv->blk);
if (!drv->media_inserted) {
FLOPPY_DPRINTF("No disk in drive\n");
- } else {
- FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
- max_track, last_sect, ro ? "ro" : "rw");
- }
- if (nb_heads == 1) {
- drv->flags &= ~FDISK_DBL_SIDES;
- } else {
- drv->flags |= FDISK_DBL_SIDES;
+ drv->disk = FLOPPY_DRIVE_TYPE_NONE;
+ } else if (!drv->media_validated) {
+ rc = pick_geometry(drv);
+ if (rc) {
+ FLOPPY_DPRINTF("Could not validate floppy drive media");
+ } else {
+ drv->media_validated = true;
+ FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n",
+ (drv->flags & FDISK_DBL_SIDES) ? 2 : 1,
+ drv->max_track, drv->last_sect,
+ drv->ro ? "ro" : "rw");
+ }
}
- drv->max_track = max_track;
- drv->last_sect = last_sect;
- drv->ro = ro;
- drv->drive = drive;
- drv->media_rate = rate;
} else {
FLOPPY_DPRINTF("No drive connected\n");
drv->last_sect = 0;
drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES;
+ drv->drive = FLOPPY_DRIVE_TYPE_NONE;
+ drv->disk = FLOPPY_DRIVE_TYPE_NONE;
}
}
@@ -569,11 +661,17 @@ struct FDCtrl {
FDrive drives[MAX_FD];
int reset_sensei;
uint32_t check_media_rate;
+ FloppyDriveType fallback; /* type=auto failure fallback */
/* Timers state */
uint8_t timer0;
uint8_t timer1;
};
+static FloppyDriveType get_fallback_drive_type(FDrive *drv)
+{
+ return drv->fdctrl->fallback;
+}
+
#define TYPE_SYSBUS_FDC "base-sysbus-fdc"
#define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC)
@@ -2190,6 +2288,7 @@ static void fdctrl_change_cb(void *opaque, bool load)
drive->media_inserted = load && drive->blk && blk_is_inserted(drive->blk);
drive->media_changed = 1;
+ drive->media_validated = false;
fd_revalidate(drive);
}
@@ -2226,11 +2325,12 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
}
fd_init(drive);
- fdctrl_change_cb(drive, 0);
if (drive->blk) {
blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
drive->media_inserted = blk_is_inserted(drive->blk);
+ pick_drive_type(drive);
}
+ fd_revalidate(drive);
}
}
@@ -2307,6 +2407,10 @@ static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp)
int i, j;
static int command_tables_inited = 0;
+ if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) {
+ error_setg(errp, "Cannot choose a fallback FDrive type of 'auto'");
+ }
+
/* Fill 'command_to_handler' lookup table */
if (!command_tables_inited) {
command_tables_inited = 1;
@@ -2407,7 +2511,7 @@ static void sysbus_fdc_common_realize(DeviceState *dev, Error **errp)
fdctrl_realize_common(fdctrl, errp);
}
-FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
+FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
{
FDCtrlISABus *isa = ISA_FDC(fdc);
@@ -2432,6 +2536,15 @@ static Property isa_fdc_properties[] = {
DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].blk),
DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
0, true),
+ DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlISABus, state.drives[0].drive,
+ FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
+ DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlISABus, state.drives[1].drive,
+ FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
+ DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
+ FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2480,6 +2593,15 @@ static const VMStateDescription vmstate_sysbus_fdc ={
static Property sysbus_fdc_properties[] = {
DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].blk),
DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].blk),
+ DEFINE_PROP_DEFAULT("fdtypeA", FDCtrlSysBus, state.drives[0].drive,
+ FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
+ DEFINE_PROP_DEFAULT("fdtypeB", FDCtrlSysBus, state.drives[1].drive,
+ FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
+ DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
+ FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2500,6 +2622,12 @@ static const TypeInfo sysbus_fdc_info = {
static Property sun4m_fdc_properties[] = {
DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].blk),
+ DEFINE_PROP_DEFAULT("fdtype", FDCtrlSysBus, state.drives[0].drive,
+ FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
+ DEFINE_PROP_DEFAULT("fallback", FDCtrlISABus, state.fallback,
+ FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
+ FloppyDriveType),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 3572810b42..aacad669e3 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -541,6 +541,17 @@ PropertyInfo qdev_prop_bios_chs_trans = {
.set = set_enum,
};
+/* --- FDC default drive types */
+
+PropertyInfo qdev_prop_fdc_drive_type = {
+ .name = "FdcDriveType",
+ .description = "FDC drive type, "
+ "144/288/120/none/auto",
+ .enum_table = FloppyDriveType_lookup,
+ .get = get_enum,
+ .set = set_enum
+};
+
/* --- pci address --- */
/*
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 838636cfba..78cf8fa0f0 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -199,24 +199,24 @@ static void pic_irq_request(void *opaque, int irq, int level)
#define REG_EQUIPMENT_BYTE 0x14
-static int cmos_get_fd_drive_type(FDriveType fd0)
+static int cmos_get_fd_drive_type(FloppyDriveType fd0)
{
int val;
switch (fd0) {
- case FDRIVE_DRV_144:
+ case FLOPPY_DRIVE_TYPE_144:
/* 1.44 Mb 3"5 drive */
val = 4;
break;
- case FDRIVE_DRV_288:
+ case FLOPPY_DRIVE_TYPE_288:
/* 2.88 Mb 3"5 drive */
val = 5;
break;
- case FDRIVE_DRV_120:
+ case FLOPPY_DRIVE_TYPE_120:
/* 1.2 Mb 5"5 drive */
val = 2;
break;
- case FDRIVE_DRV_NONE:
+ case FLOPPY_DRIVE_TYPE_NONE:
default:
val = 0;
break;
@@ -287,7 +287,8 @@ static void pc_boot_set(void *opaque, const char *boot_device, Error **errp)
static void pc_cmos_init_floppy(ISADevice *rtc_state, ISADevice *floppy)
{
int val, nb, i;
- FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+ FloppyDriveType fd_type[2] = { FLOPPY_DRIVE_TYPE_NONE,
+ FLOPPY_DRIVE_TYPE_NONE };
/* floppy type */
if (floppy) {
@@ -301,10 +302,10 @@ static void pc_cmos_init_floppy(ISADevice *rtc_state, ISADevice *floppy)
val = rtc_get_memory(rtc_state, REG_EQUIPMENT_BYTE);
nb = 0;
- if (fd_type[0] < FDRIVE_DRV_NONE) {
+ if (fd_type[0] != FLOPPY_DRIVE_TYPE_NONE) {
nb++;
}
- if (fd_type[1] < FDRIVE_DRV_NONE) {
+ if (fd_type[1] != FLOPPY_DRIVE_TYPE_NONE) {
nb++;
}
switch (nb) {
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 1f831098c7..fea54256ad 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -172,7 +172,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
blkconf_serial(&dev->conf, &dev->serial);
if (kind != IDE_CD) {
- blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255, &err);
+ blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
if (err) {
error_report_err(err);
return -1;
diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h
index d48b2f860c..adce14f479 100644
--- a/include/hw/block/fdc.h
+++ b/include/hw/block/fdc.h
@@ -6,13 +6,6 @@
/* fdc.c */
#define MAX_FD 2
-typedef enum FDriveType {
- FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */
- FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */
- FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */
- FDRIVE_DRV_NONE = 0x03, /* No drive connected */
-} FDriveType;
-
#define TYPE_ISA_FDC "isa-fdc"
ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds);
@@ -21,6 +14,6 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
DriveInfo **fds, qemu_irq *fdc_tc);
-FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
+FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i);
#endif
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 491884ba49..2ebe739fcb 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -3,6 +3,10 @@
#define HW_COMPAT_2_5 \
{\
+ .driver = "isa-fdc",\
+ .property = "fallback",\
+ .value = "144",\
+ },{\
.driver = "pvscsi",\
.property = "x-old-pci-configuration",\
.value = "on",\
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 254afd8859..03a1b91f31 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -20,6 +20,7 @@ extern PropertyInfo qdev_prop_ptr;
extern PropertyInfo qdev_prop_macaddr;
extern PropertyInfo qdev_prop_losttickpolicy;
extern PropertyInfo qdev_prop_bios_chs_trans;
+extern PropertyInfo qdev_prop_fdc_drive_type;
extern PropertyInfo qdev_prop_drive;
extern PropertyInfo qdev_prop_netdev;
extern PropertyInfo qdev_prop_vlan;
diff --git a/qapi/block.json b/qapi/block.json
index 84022f12be..ed61f82359 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -40,6 +40,22 @@
'data': ['auto', 'none', 'lba', 'large', 'rechs']}
##
+# @FloppyDriveType
+#
+# Type of Floppy drive to be emulated by the Floppy Disk Controller.
+#
+# @144: 1.44MB 3.5" drive
+# @288: 2.88MB 3.5" drive
+# @120: 1.2MB 5.25" drive
+# @none: No drive connected
+# @auto: Automatically determined by inserted media at boot
+#
+# Since: 2.6
+##
+{ 'enum': 'FloppyDriveType',
+ 'data': ['144', '288', '120', 'none', 'auto']}
+
+##
# @BlockdevSnapshotInternal
#
# @device: the name of the device to generate the snapshot from
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index b5a4696d86..526d4595c3 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -267,7 +267,7 @@ static void test_cmos(void)
uint8_t cmos;
cmos = cmos_read(CMOS_FLOPPY);
- g_assert(cmos == 0x40);
+ g_assert(cmos == 0x40 || cmos == 0x50);
}
static void test_no_media_on_start(void)