Revision 844f65d6 hw/fdc.c

b/hw/fdc.c
62 62
#define FD_SECTOR_SC           2   /* Sector size code */
63 63
#define FD_RESET_SENSEI_COUNT  4   /* Number of sense interrupts on RESET */
64 64

  
65
typedef struct FDCtrl FDCtrl;
66

  
65 67
/* Floppy disk drive emulation */
66 68
typedef enum FDiskFlags {
67 69
    FDISK_DBL_SIDES  = 0x01,
68 70
} FDiskFlags;
69 71

  
70 72
typedef struct FDrive {
73
    FDCtrl *fdctrl;
71 74
    BlockDriverState *bs;
72 75
    /* Drive status */
73 76
    FDriveType drive;
......
83 86
    uint16_t bps;             /* Bytes per sector       */
84 87
    uint8_t ro;               /* Is read-only           */
85 88
    uint8_t media_changed;    /* Is media changed       */
89
    uint8_t media_rate;       /* Data rate of medium    */
86 90
} FDrive;
87 91

  
88 92
static void fd_init(FDrive *drv)
......
195 199
        drv->last_sect = last_sect;
196 200
        drv->ro = ro;
197 201
        drv->drive = drive;
202
        drv->media_rate = rate;
198 203
    } else {
199 204
        FLOPPY_DPRINTF("No disk in drive\n");
200 205
        drv->last_sect = 0;
......
206 211
/********************************************************/
207 212
/* Intel 82078 floppy disk controller emulation          */
208 213

  
209
typedef struct FDCtrl FDCtrl;
210

  
211 214
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
212 215
static void fdctrl_reset_fifo(FDCtrl *fdctrl);
213 216
static int fdctrl_transfer_handler (void *opaque, int nchan,
......
303 306
};
304 307

  
305 308
enum {
309
    FD_SR1_MA       = 0x01, /* Missing address mark */
306 310
    FD_SR1_NW       = 0x02, /* Not writable */
307 311
    FD_SR1_EC       = 0x80, /* End of cylinder */
308 312
};
......
549 553
    }
550 554
};
551 555

  
556
static bool fdrive_media_rate_needed(void *opaque)
557
{
558
    FDrive *drive = opaque;
559

  
560
    return drive->fdctrl->check_media_rate;
561
}
562

  
563
static const VMStateDescription vmstate_fdrive_media_rate = {
564
    .name = "fdrive/media_rate",
565
    .version_id = 1,
566
    .minimum_version_id = 1,
567
    .minimum_version_id_old = 1,
568
    .fields      = (VMStateField[]) {
569
        VMSTATE_UINT8(media_rate, FDrive),
570
        VMSTATE_END_OF_LIST()
571
    }
572
};
573

  
552 574
static const VMStateDescription vmstate_fdrive = {
553 575
    .name = "fdrive",
554 576
    .version_id = 1,
......
565 587
            .vmsd = &vmstate_fdrive_media_changed,
566 588
            .needed = &fdrive_media_changed_needed,
567 589
        } , {
590
            .vmsd = &vmstate_fdrive_media_rate,
591
            .needed = &fdrive_media_rate_needed,
592
        } , {
568 593
            /* empty */
569 594
        }
570 595
    }
......
1078 1103
        break;
1079 1104
    }
1080 1105

  
1106
    /* Check the data rate. If the programmed data rate does not match
1107
     * the currently inserted medium, the operation has to fail. */
1108
    if (fdctrl->check_media_rate &&
1109
        (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
1110
        FLOPPY_DPRINTF("data rate mismatch (fdc=%d, media=%d)\n",
1111
                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
1112
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
1113
        fdctrl->fifo[3] = kt;
1114
        fdctrl->fifo[4] = kh;
1115
        fdctrl->fifo[5] = ks;
1116
        return;
1117
    }
1118

  
1081 1119
    /* Set the FIFO state */
1082 1120
    fdctrl->data_dir = direction;
1083 1121
    fdctrl->data_pos = 0;
......
1800 1838
    if (cur_drv->last_sect != 0) {
1801 1839
        cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
1802 1840
    }
1803
    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1841
    /* READ_ID can't automatically succeed! */
1842
    if (fdctrl->check_media_rate &&
1843
        (fdctrl->dsr & FD_DSR_DRATEMASK) != cur_drv->media_rate) {
1844
        FLOPPY_DPRINTF("read id rate mismatch (fdc=%d, media=%d)\n",
1845
                       fdctrl->dsr & FD_DSR_DRATEMASK, cur_drv->media_rate);
1846
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_MA, 0x00);
1847
    } else {
1848
        fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1849
    }
1804 1850
}
1805 1851

  
1806 1852
static void fdctrl_change_cb(void *opaque, bool load)
......
1822 1868

  
1823 1869
    for (i = 0; i < MAX_FD; i++) {
1824 1870
        drive = &fdctrl->drives[i];
1871
        drive->fdctrl = fdctrl;
1825 1872

  
1826 1873
        if (drive->bs) {
1827 1874
            if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {

Also available in: Unified diff