Patchwork [v4,09/11] fdc: check if media rate is correct before doing any transfer

login
register
mail settings
Submitter Hervé Poussineau
Date Feb. 6, 2012, 9:29 p.m.
Message ID <1328563752-3976-10-git-send-email-hpoussin@reactos.org>
Download mbox | patch
Permalink /patch/139814/
State New
Headers show

Comments

Hervé Poussineau - Feb. 6, 2012, 9:29 p.m.
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é Poussineau <hpoussin@reactos.org>
---
 hw/fdc.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 50 insertions(+), 3 deletions(-)
Kevin Wolf - Feb. 14, 2012, 3:16 p.m.
Am 06.02.2012 22:29, schrieb Hervé 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é Poussineau <hpoussin@reactos.org>
> ---
>  hw/fdc.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 files changed, 50 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/fdc.c b/hw/fdc.c
> index af007ae..d2a22fa 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 RESET */
>  
> +typedef struct FDCtrl FDCtrl;
> +
>  /* Floppy disk drive emulation */
>  typedef enum FDiskFlags {
>      FDISK_DBL_SIDES  = 0x01,
>  } FDiskFlags;
>  
>  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;
>  
>  static void fd_init(FDrive *drv)
> @@ -195,6 +199,7 @@ static void fd_revalidate(FDrive *drv)
>          drv->last_sect = last_sect;
>          drv->ro = ro;
>          drv->drive = drive;
> +        drv->media_rate = rate;
>      } else {
>          FLOPPY_DPRINTF("No disk in drive\n");
>          drv->last_sect = 0;
> @@ -206,8 +211,6 @@ static void fd_revalidate(FDrive *drv)
>  /********************************************************/
>  /* Intel 82078 floppy disk controller emulation          */
>  
> -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 {
>  };
>  
>  enum {
> +    FD_SR1_MA       = 0x01, /* Missing address mark */
>      FD_SR1_NW       = 0x02, /* Not writable */
>      FD_SR1_EC       = 0x80, /* End of cylinder */
>  };
> @@ -549,6 +553,24 @@ static const VMStateDescription vmstate_fdrive_media_changed = {
>      }
>  };
>  
> +static bool fdrive_media_rate_needed(void *opaque)
> +{
> +    FDrive *drive = opaque;
> +
> +    return drive->fdctrl->check_media_rate;
> +}
> +
> +static const VMStateDescription vmstate_fdrive_media_rate = {
> +    .name = "fdrive/media_rate",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT8(media_rate, FDrive),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};

Juan, Paolo, this is a subsection in a struct array. Does this work
meanwhile or is it still broken?

Kevin
Paolo Bonzini - Feb. 14, 2012, 3:28 p.m.
On 02/14/2012 04:16 PM, Kevin Wolf wrote:
> Juan, Paolo, this is a subsection in a struct array. Does this work
> meanwhile or is it still broken?

Juan fixed it.

Paolo
Kevin Wolf - Feb. 14, 2012, 3:34 p.m.
Am 14.02.2012 16:28, schrieb Paolo Bonzini:
> On 02/14/2012 04:16 PM, Kevin Wolf wrote:
>> Juan, Paolo, this is a subsection in a struct array. Does this work
>> meanwhile or is it still broken?
> 
> Juan fixed it.

Oh, cool. :-)

Then I'll apply the other four patches as well.

Kevin

Patch

diff --git a/hw/fdc.c b/hw/fdc.c
index af007ae..d2a22fa 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 RESET */
 
+typedef struct FDCtrl FDCtrl;
+
 /* Floppy disk drive emulation */
 typedef enum FDiskFlags {
     FDISK_DBL_SIDES  = 0x01,
 } FDiskFlags;
 
 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;
 
 static void fd_init(FDrive *drv)
@@ -195,6 +199,7 @@  static void fd_revalidate(FDrive *drv)
         drv->last_sect = last_sect;
         drv->ro = ro;
         drv->drive = drive;
+        drv->media_rate = rate;
     } else {
         FLOPPY_DPRINTF("No disk in drive\n");
         drv->last_sect = 0;
@@ -206,8 +211,6 @@  static void fd_revalidate(FDrive *drv)
 /********************************************************/
 /* Intel 82078 floppy disk controller emulation          */
 
-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 {
 };
 
 enum {
+    FD_SR1_MA       = 0x01, /* Missing address mark */
     FD_SR1_NW       = 0x02, /* Not writable */
     FD_SR1_EC       = 0x80, /* End of cylinder */
 };
@@ -549,6 +553,24 @@  static const VMStateDescription vmstate_fdrive_media_changed = {
     }
 };
 
+static bool fdrive_media_rate_needed(void *opaque)
+{
+    FDrive *drive = opaque;
+
+    return drive->fdctrl->check_media_rate;
+}
+
+static const VMStateDescription vmstate_fdrive_media_rate = {
+    .name = "fdrive/media_rate",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT8(media_rate, FDrive),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_fdrive = {
     .name = "fdrive",
     .version_id = 1,
@@ -565,6 +587,9 @@  static const VMStateDescription vmstate_fdrive = {
             .vmsd = &vmstate_fdrive_media_changed,
             .needed = &fdrive_media_changed_needed,
         } , {
+            .vmsd = &vmstate_fdrive_media_rate,
+            .needed = &fdrive_media_rate_needed,
+        } , {
             /* empty */
         }
     }
@@ -1078,6 +1103,19 @@  static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
         break;
     }
 
+    /* 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) != cur_drv->media_rate) {
+        FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n",
+                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
+        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
+        fdctrl->fifo[3] = kt;
+        fdctrl->fifo[4] = kh;
+        fdctrl->fifo[5] = ks;
+        return;
+    }
+
     /* Set the FIFO state */
     fdctrl->data_dir = direction;
     fdctrl->data_pos = 0;
@@ -1800,7 +1838,15 @@  static void fdctrl_result_timer(void *opaque)
     if (cur_drv->last_sect != 0) {
         cur_drv->sect = (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) != cur_drv->media_rate) {
+        FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n",
+                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
+        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
+    } else {
+        fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+    }
 }
 
 static void fdctrl_change_cb(void *opaque, bool load)
@@ -1822,6 +1868,7 @@  static int fdctrl_connect_drives(FDCtrl *fdctrl)
 
     for (i = 0; i < MAX_FD; i++) {
         drive = &fdctrl->drives[i];
+        drive->fdctrl = fdctrl;
 
         if (drive->bs) {
             if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {