From 2e1280e8ff95b3145bc6262accc9d447718e5318 Mon Sep 17 00:00:00 2001 From: Max Reitz Date: Mon, 19 Oct 2015 17:53:16 +0200 Subject: [PATCH] hw/block/fdc: Implement tray status The tray of an FDD is open iff there is no medium inserted (there are only two states for an FDD: "medium inserted" or "no medium inserted"). Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- hw/block/fdc.c | 20 ++++++++++++++++---- tests/fdc-test.c | 4 +--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 6686a72803..4292eced32 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -192,6 +192,8 @@ typedef struct FDrive { uint8_t ro; /* Is read-only */ uint8_t media_changed; /* Is media changed */ uint8_t media_rate; /* Data rate of medium */ + + bool media_inserted; /* Is there a medium in the tray */ } FDrive; static void fd_init(FDrive *drv) @@ -261,7 +263,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, #endif drv->head = head; if (drv->track != track) { - if (drv->blk != NULL && blk_is_inserted(drv->blk)) { + if (drv->media_inserted) { drv->media_changed = 0; } ret = 1; @@ -270,7 +272,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect, drv->sect = sect; } - if (drv->blk == NULL || !blk_is_inserted(drv->blk)) { + if (!drv->media_inserted) { ret = 2; } @@ -296,7 +298,7 @@ static void fd_revalidate(FDrive *drv) ro = blk_is_read_only(drv->blk); pick_geometry(drv->blk, &nb_heads, &max_track, &last_sect, drv->drive, &drive, &rate); - if (!blk_is_inserted(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, @@ -692,7 +694,7 @@ static bool fdrive_media_changed_needed(void *opaque) { FDrive *drive = opaque; - return (drive->blk != NULL && drive->media_changed != 1); + return (drive->media_inserted && drive->media_changed != 1); } static const VMStateDescription vmstate_fdrive_media_changed = { @@ -2184,12 +2186,21 @@ static void fdctrl_change_cb(void *opaque, bool load) { FDrive *drive = opaque; + drive->media_inserted = load && drive->blk && blk_is_inserted(drive->blk); + drive->media_changed = 1; fd_revalidate(drive); } +static bool fdctrl_is_tray_open(void *opaque) +{ + FDrive *drive = opaque; + return !drive->media_inserted; +} + static const BlockDevOps fdctrl_block_ops = { .change_media_cb = fdctrl_change_cb, + .is_tray_open = fdctrl_is_tray_open, }; /* Init functions */ @@ -2217,6 +2228,7 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp) 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); } } } diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 416394fc77..b5a4696d86 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -304,9 +304,7 @@ static void test_media_insert(void) qmp_discard_response("{'execute':'change', 'arguments':{" " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}", test_image); - qmp_discard_response(""); /* ignore event - (FIXME open -> open transition?!) */ - qmp_discard_response(""); /* ignore event */ + qmp_discard_response(""); /* ignore event (open -> close) */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG);