From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:59731) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2lF5-0005aW-FX for qemu-devel@nongnu.org; Wed, 29 Feb 2012 10:15:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S2lEw-0003UI-It for qemu-devel@nongnu.org; Wed, 29 Feb 2012 10:14:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:21703) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2lEw-0003TZ-B9 for qemu-devel@nongnu.org; Wed, 29 Feb 2012 10:14:50 -0500 From: Kevin Wolf Date: Wed, 29 Feb 2012 16:17:49 +0100 Message-Id: <1330528688-21996-9-git-send-email-kwolf@redhat.com> In-Reply-To: <1330528688-21996-1-git-send-email-kwolf@redhat.com> References: <1330528688-21996-1-git-send-email-kwolf@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 08/27] fdc: check if media rate is correct before doing any transfer List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: anthony@codemonkey.ws Cc: kwolf@redhat.com, qemu-devel@nongnu.org From: Herv=C3=A9 Poussineau The programmed rate has to be the same as the required rate for the floppy format ; if that's not the case, the transfer should abort. This check can be disabled by using the 'check_media_rate' property. Save media rate value only if media rate check is enabled. Signed-off-by: Herv=C3=A9 Poussineau Signed-off-by: Kevin Wolf --- hw/fdc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 50 insertions(+), 3 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index 1c7e775..cc03326 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -62,12 +62,15 @@ #define FD_SECTOR_SC 2 /* Sector size code */ #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESE= T */ =20 +typedef struct FDCtrl FDCtrl; + /* Floppy disk drive emulation */ typedef enum FDiskFlags { FDISK_DBL_SIDES =3D 0x01, } FDiskFlags; =20 typedef struct FDrive { + FDCtrl *fdctrl; BlockDriverState *bs; /* Drive status */ FDriveType drive; @@ -83,6 +86,7 @@ typedef struct FDrive { uint16_t bps; /* Bytes per sector */ uint8_t ro; /* Is read-only */ uint8_t media_changed; /* Is media changed */ + uint8_t media_rate; /* Data rate of medium */ } FDrive; =20 static void fd_init(FDrive *drv) @@ -195,6 +199,7 @@ static void fd_revalidate(FDrive *drv) drv->last_sect =3D last_sect; drv->ro =3D ro; drv->drive =3D drive; + drv->media_rate =3D rate; } else { FLOPPY_DPRINTF("No disk in drive\n"); drv->last_sect =3D 0; @@ -206,8 +211,6 @@ static void fd_revalidate(FDrive *drv) /********************************************************/ /* Intel 82078 floppy disk controller emulation */ =20 -typedef struct FDCtrl FDCtrl; - static void fdctrl_reset(FDCtrl *fdctrl, int do_irq); static void fdctrl_reset_fifo(FDCtrl *fdctrl); static int fdctrl_transfer_handler (void *opaque, int nchan, @@ -303,6 +306,7 @@ enum { }; =20 enum { + FD_SR1_MA =3D 0x01, /* Missing address mark */ FD_SR1_NW =3D 0x02, /* Not writable */ FD_SR1_EC =3D 0x80, /* End of cylinder */ }; @@ -549,6 +553,24 @@ static const VMStateDescription vmstate_fdrive_media= _changed =3D { } }; =20 +static bool fdrive_media_rate_needed(void *opaque) +{ + FDrive *drive =3D opaque; + + return drive->fdctrl->check_media_rate; +} + +static const VMStateDescription vmstate_fdrive_media_rate =3D { + .name =3D "fdrive/media_rate", + .version_id =3D 1, + .minimum_version_id =3D 1, + .minimum_version_id_old =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT8(media_rate, FDrive), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_fdrive =3D { .name =3D "fdrive", .version_id =3D 1, @@ -565,6 +587,9 @@ static const VMStateDescription vmstate_fdrive =3D { .vmsd =3D &vmstate_fdrive_media_changed, .needed =3D &fdrive_media_changed_needed, } , { + .vmsd =3D &vmstate_fdrive_media_rate, + .needed =3D &fdrive_media_rate_needed, + } , { /* empty */ } } @@ -1078,6 +1103,19 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, = int direction) break; } =20 + /* Check the data rate. If the programmed data rate does not match + * the currently inserted medium, the operation has to fail. */ + if (fdctrl->check_media_rate && + (fdctrl->dsr & FD_DSR_DRATEMASK) !=3D cur_drv->media_rate) { + FLOPPY_DPRINTF("data rate mismatch (fdc=3D%d, media=3D%d)\n", + fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_ra= te); + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); + fdctrl->fifo[3] =3D kt; + fdctrl->fifo[4] =3D kh; + fdctrl->fifo[5] =3D ks; + return; + } + /* Set the FIFO state */ fdctrl->data_dir =3D direction; fdctrl->data_pos =3D 0; @@ -1800,7 +1838,15 @@ static void fdctrl_result_timer(void *opaque) if (cur_drv->last_sect !=3D 0) { cur_drv->sect =3D (cur_drv->sect % cur_drv->last_sect) + 1; } - fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + /* READ_ID can't automatically succeed! */ + if (fdctrl->check_media_rate && + (fdctrl->dsr & FD_DSR_DRATEMASK) !=3D cur_drv->media_rate) { + FLOPPY_DPRINTF("read id rate mismatch (fdc=3D%d, media=3D%d)\n", + fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_ra= te); + fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00); + } else { + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + } } =20 static void fdctrl_change_cb(void *opaque, bool load) @@ -1822,6 +1868,7 @@ static int fdctrl_connect_drives(FDCtrl *fdctrl) =20 for (i =3D 0; i < MAX_FD; i++) { drive =3D &fdctrl->drives[i]; + drive->fdctrl =3D fdctrl; =20 if (drive->bs) { if (bdrv_get_on_error(drive->bs, 0) !=3D BLOCK_ERR_STOP_ENOS= PC) { --=20 1.7.6.5