VirtualBox

Changeset 34294 in vbox for trunk


Ignore:
Timestamp:
Nov 23, 2010 4:11:48 PM (14 years ago)
Author:
vboxsync
Message:

fdc: Synced code, now easier to follow and fix.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/fdc.c

    r33540 r34294  
    1 #ifdef VBOX
    21/* $Id$ */
    32/** @file
     
    5655#include "../vl_vbox.h"
    5756
     57#define FDC_SAVESTATE_CURRENT   2       /* The new and improved saved state. */
     58#define FDC_SAVESTATE_OLD       1       /* The original saved state. */
     59
    5860#define MAX_FD 2
    5961
     
    6466    ((fdrive_t *)((uintptr_t)(p) - RT_OFFSETOF(fdrive_t, IMountNotify)))
    6567
    66 #endif /* VBOX */
    67 
    68 #ifndef VBOX
    69 #include "vl.h"
    70 #endif /* !VBOX */
    7168
    7269/********************************************************/
     
    109106/* Floppy drive emulation                               */
    110107
     108#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
     109#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
     110
    111111/* Will always be a fixed parameter for us */
    112 #define FD_SECTOR_LEN 512
    113 #define FD_SECTOR_SC  2   /* Sector size code */
     112#define FD_SECTOR_LEN          512
     113#define FD_SECTOR_SC           2   /* Sector size code */
     114#define FD_RESET_SENSEI_COUNT  4   /* Number of sense interrupts on RESET */
    114115
    115116/* Floppy disk drive emulation */
     
    127128    FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */
    128129    FDRIVE_DRV_NONE = 0x03    /* No drive connected     */
    129 #ifdef VBOX
    130     , FDRIVE_DRV_DUMMY = INT32_MAX
    131 #endif
    132130} fdrive_type_t;
    133131
    134132typedef enum fdrive_flags_t {
    135     FDRIVE_MOTOR_ON   = 0x01, /* motor on/off           */
    136     FDRIVE_REVALIDATE = 0x02  /* Revalidated            */
    137 #ifdef VBOX
    138     , FDRIVE_DUMMY = INT32_MAX
    139 #endif
     133    FDISK_DBL_SIDES  = 0x01
    140134} fdrive_flags_t;
    141135
    142 typedef enum fdisk_flags_t {
    143     FDISK_DBL_SIDES  = 0x01
    144 #ifdef VBOX
    145     , FDDISK_DUMMY = INT32_MAX
    146 #endif
    147 } fdisk_flags_t;
    148 
    149 #ifdef VBOX
    150136/**
    151137 * The status for one drive.
     
    155141 * @implements  PDMIMOUNTNOTIFY
    156142 */
    157 #endif
    158143typedef struct fdrive_t {
    159144#ifndef VBOX
     
    179164    /** The LED for this LUN. */
    180165    PDMLED                          Led;
    181     /** The Diskette present/missing flag. */
    182     bool                            fMediaPresent;
     166    /** Media change flag. */
     167    bool                            fMediaChanged;
    183168#endif
    184169    /* Drive status */
    185170    fdrive_type_t drive;
    186     fdrive_flags_t drflags;
    187171    uint8_t perpendicular;    /* 2.88 MB access mode    */
     172    uint8_t dsk_chg;          /* Disk change line       */
    188173    /* Position */
    189174    uint8_t head;
    190175    uint8_t track;
    191176    uint8_t sect;
    192     /* Last operation status */
    193     uint8_t dir;              /* Direction              */
    194     uint8_t rw;               /* Read/write             */
    195177    /* Media */
    196     fdisk_flags_t flags;
     178    fdrive_flags_t flags;
    197179    uint8_t last_sect;        /* Nb sector per track    */
    198180    uint8_t max_track;        /* Nb of tracks           */
     
    201183} fdrive_t;
    202184
    203 #ifndef VBOX
    204 static void fd_init (fdrive_t *drv, BlockDriverState *bs)
     185static void fd_init(fdrive_t *drv)
    205186{
    206187    /* Drive */
    207     drv->bs = bs;
    208188    drv->drive = FDRIVE_DRV_NONE;
    209     drv->drflags = 0;
    210189    drv->perpendicular = 0;
    211190    /* Disk */
    212191    drv->last_sect = 0;
    213192    drv->max_track = 0;
    214 }
    215 #endif
    216 
    217 static unsigned _fd_sector (uint8_t head, uint8_t track,
    218                         uint8_t sect, uint8_t last_sect)
     193    drv->fMediaChanged = true;
     194}
     195
     196static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect,
     197                          uint8_t last_sect)
    219198{
    220199    return (((track * 2) + head) * last_sect) + sect - 1; /* sect >= 1 */
     
    222201
    223202/* Returns current position, in sectors, for given drive */
    224 static unsigned fd_sector (fdrive_t *drv)
    225 {
    226     return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect);
    227 }
    228 
    229 static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
    230                     int enable_seek)
    231 {
    232     uint32_t sector;
     203static int fd_sector(fdrive_t *drv)
     204{
     205    return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect);
     206}
     207
     208/* Seek to a new position:
     209 * returns 0 if already on right track
     210 * returns 1 if track changed
     211 * returns 2 if track is invalid
     212 * returns 3 if sector is invalid
     213 * returns 4 if seek is disabled
     214 */
     215static int fd_seek(fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
     216                   int enable_seek)
     217{
     218    int sector;
    233219    int ret;
    234220
     
    248234        return 3;
    249235    }
    250     sector = _fd_sector(head, track, sect, drv->last_sect);
     236    sector = fd_sector_calc(head, track, sect, drv->last_sect);
    251237    ret = 0;
    252238    if (sector != fd_sector(drv)) {
     
    269255
    270256/* Set drive back to track 0 */
    271 static void fd_recalibrate (fdrive_t *drv)
     257static void fd_recalibrate(fdrive_t *drv)
    272258{
    273259    FLOPPY_DPRINTF("recalibrate\n");
     
    275261    drv->track = 0;
    276262    drv->sect = 1;
    277     drv->dir = 1;
    278     drv->rw = 0;
    279263}
    280264
     
    289273} fd_format_t;
    290274
    291 static fd_format_t fd_formats[] = {
     275static const fd_format_t fd_formats[] = {
    292276    /* First entry is default format */
    293277    /* 1.44 MB 3"1/2 floppy disks */
     
    337321
    338322/* Revalidate a disk drive after a disk change */
    339 static void fd_revalidate (fdrive_t *drv)
    340 {
    341     fd_format_t *parse;
    342     int64_t nb_sectors, size;
     323static void fd_revalidate(fdrive_t *drv)
     324{
     325    const fd_format_t *parse;
     326    uint64_t nb_sectors, size;
    343327    int i, first_match, match;
    344328    int nb_heads, max_track, last_sect, ro;
    345329
    346330    FLOPPY_DPRINTF("revalidate\n");
    347     drv->drflags &= ~FDRIVE_REVALIDATE;
    348331#ifndef VBOX
    349332    if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
     
    351334        bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
    352335#else /* VBOX */
    353         /** @todo */ /** @todo r=bird: todo what exactly? */
    354336    if (drv->pDrvBlock
    355337        && drv->pDrvMount
    356338        && drv->pDrvMount->pfnIsMounted (drv->pDrvMount)) {
    357339        ro = drv->pDrvBlock->pfnIsReadOnly (drv->pDrvBlock);
    358         nb_heads = 0;
    359         max_track = 0;
    360         last_sect = 0;
     340        nb_heads = max_track = last_sect = 0;
    361341#endif /* VBOX */
    362342        if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
     
    367347            bdrv_get_geometry(drv->bs, &nb_sectors);
    368348#else /* VBOX */
    369             /* @todo */ /** @todo r=bird: todo what exactly?!?!? */
    370349            {
    371350                uint64_t size2 = drv->pDrvBlock->pfnGetSize (drv->pDrvBlock);
    372                 nb_sectors = size2 / 512;
     351                nb_sectors = size2 / FD_SECTOR_LEN;
    373352            }
    374353#endif /* VBOX */
     
    413392        drv->last_sect = last_sect;
    414393        drv->ro = ro;
    415 #ifdef VBOX
    416         drv->fMediaPresent = true;
    417 #endif
    418394    } else {
    419395        FLOPPY_DPRINTF("No disk in drive\n");
     
    421397        drv->max_track = 0;
    422398        drv->flags &= ~FDISK_DBL_SIDES;
    423 #ifdef VBOX
    424         drv->fMediaPresent = false;
    425 #endif
    426     }
    427     drv->drflags |= FDRIVE_REVALIDATE;
    428 }
    429 
    430 /* Motor control */
    431 static void fd_start (fdrive_t *drv)
    432 {
    433     drv->drflags |= FDRIVE_MOTOR_ON;
    434 }
    435 
    436 static void fd_stop (fdrive_t *drv)
    437 {
    438     drv->drflags &= ~FDRIVE_MOTOR_ON;
    439 }
    440 
    441 /* Re-initialise a drives (motor off, repositioned) */
    442 static void fd_reset (fdrive_t *drv)
    443 {
    444     fd_stop(drv);
    445     fd_recalibrate(drv);
     399    }
    446400}
    447401
     
    449403/* Intel 82078 floppy disk controller emulation          */
    450404
    451 #define target_ulong uint32_t
    452 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
    453 static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
     405static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq);
     406static void fdctrl_reset_fifo(fdctrl_t *fdctrl);
    454407#ifndef VBOX
    455 static int fdctrl_transfer_handler (void *opaque, int nchan, int dma_pos, int dma_len);
     408static int fdctrl_transfer_handler (void *opaque, int nchan,
     409                                    int dma_pos, int dma_len);
    456410#else /* VBOX: */
    457411static DECLCALLBACK(uint32_t) fdctrl_transfer_handler (PPDMDEVINS pDevIns,
     
    461415                                                       uint32_t dma_len);
    462416#endif /* VBOX */
    463 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
     417static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0);
     418
    464419static void fdctrl_result_timer(void *opaque);
    465 
    466 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
    467 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
    468 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
    469 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl);
    470 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value);
    471 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl);
    472 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value);
    473 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl);
    474 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
    475 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
    476 
    477 enum {
    478     FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
    479     FD_CTRL_RESET  = 0x02,
    480     FD_CTRL_SLEEP  = 0x04, /* XXX: suppress that */
    481     FD_CTRL_BUSY   = 0x08, /* dma transfer in progress */
    482     FD_CTRL_INTR   = 0x10
    483 };
     420static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl);
     421static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl);
     422static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl);
     423static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value);
     424static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl);
     425static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value);
     426static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl);
     427static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value);
     428static uint32_t fdctrl_read_data(fdctrl_t *fdctrl);
     429static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value);
     430static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl);
    484431
    485432enum {
     
    492439
    493440enum {
    494     FD_STATE_CMD    = 0x00,
    495     FD_STATE_STATUS = 0x01,
    496     FD_STATE_DATA   = 0x02,
    497     FD_STATE_STATE  = 0x03,
    498     FD_STATE_MULTI  = 0x10,
    499     FD_STATE_SEEK   = 0x20,
    500     FD_STATE_FORMAT = 0x40
     441    FD_STATE_MULTI  = 0x01,     /* multi track flag */
     442    FD_STATE_FORMAT = 0x02,     /* format flag */
     443    FD_STATE_SEEK   = 0x04      /* seek flag */
    501444};
    502445
    503 #define FD_STATE(state) ((state) & FD_STATE_STATE)
    504 #define FD_SET_STATE(state, new_state) \
    505 do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0)
     446enum {
     447    FD_REG_SRA = 0x00,
     448    FD_REG_SRB = 0x01,
     449    FD_REG_DOR = 0x02,
     450    FD_REG_TDR = 0x03,
     451    FD_REG_MSR = 0x04,
     452    FD_REG_DSR = 0x04,
     453    FD_REG_FIFO = 0x05,
     454    FD_REG_DIR = 0x07
     455};
     456
     457enum {
     458    FD_CMD_READ_TRACK = 0x02,
     459    FD_CMD_SPECIFY = 0x03,
     460    FD_CMD_SENSE_DRIVE_STATUS = 0x04,
     461    FD_CMD_WRITE = 0x05,
     462    FD_CMD_READ = 0x06,
     463    FD_CMD_RECALIBRATE = 0x07,
     464    FD_CMD_SENSE_INTERRUPT_STATUS = 0x08,
     465    FD_CMD_WRITE_DELETED = 0x09,
     466    FD_CMD_READ_ID = 0x0a,
     467    FD_CMD_READ_DELETED = 0x0c,
     468    FD_CMD_FORMAT_TRACK = 0x0d,
     469    FD_CMD_DUMPREG = 0x0e,
     470    FD_CMD_SEEK = 0x0f,
     471    FD_CMD_VERSION = 0x10,
     472    FD_CMD_SCAN_EQUAL = 0x11,
     473    FD_CMD_PERPENDICULAR_MODE = 0x12,
     474    FD_CMD_CONFIGURE = 0x13,
     475    FD_CMD_LOCK = 0x14,
     476    FD_CMD_VERIFY = 0x16,
     477    FD_CMD_POWERDOWN_MODE = 0x17,
     478    FD_CMD_PART_ID = 0x18,
     479    FD_CMD_SCAN_LOW_OR_EQUAL = 0x19,
     480    FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d,
     481    FD_CMD_SAVE = 0x2e,
     482    FD_CMD_OPTION = 0x33,
     483    FD_CMD_RESTORE = 0x4e,
     484    FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e,
     485    FD_CMD_RELATIVE_SEEK_OUT = 0x8f,
     486    FD_CMD_FORMAT_AND_WRITE = 0xcd,
     487    FD_CMD_RELATIVE_SEEK_IN = 0xcf
     488};
     489
     490enum {
     491    FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */
     492    FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */
     493    FD_CONFIG_POLL  = 0x10, /* Poll enabled */
     494    FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */
     495    FD_CONFIG_EIS   = 0x40  /* No implied seeks */
     496};
     497
     498enum {
     499    FD_SR0_EQPMT    = 0x10,
     500    FD_SR0_SEEK     = 0x20,
     501    FD_SR0_ABNTERM  = 0x40,
     502    FD_SR0_INVCMD   = 0x80,
     503    FD_SR0_RDYCHG   = 0xc0
     504};
     505
     506enum {
     507    FD_SR1_EC       = 0x80  /* End of cylinder */
     508};
     509
     510enum {
     511    FD_SR2_SNS      = 0x04, /* Scan not satisfied */
     512    FD_SR2_SEH      = 0x08  /* Scan equal hit */
     513};
     514
     515enum {
     516    FD_SRA_DIR      = 0x01,
     517    FD_SRA_nWP      = 0x02,
     518    FD_SRA_nINDX    = 0x04,
     519    FD_SRA_HDSEL    = 0x08,
     520    FD_SRA_nTRK0    = 0x10,
     521    FD_SRA_STEP     = 0x20,
     522    FD_SRA_nDRV2    = 0x40,
     523    FD_SRA_INTPEND  = 0x80
     524};
     525
     526enum {
     527    FD_SRB_MTR0     = 0x01,
     528    FD_SRB_MTR1     = 0x02,
     529    FD_SRB_WGATE    = 0x04,
     530    FD_SRB_RDATA    = 0x08,
     531    FD_SRB_WDATA    = 0x10,
     532    FD_SRB_DR0      = 0x20
     533};
     534
     535enum {
     536#if MAX_FD == 4
     537    FD_DOR_SELMASK  = 0x03,
     538#else
     539    FD_DOR_SELMASK  = 0x01,
     540#endif
     541    FD_DOR_nRESET   = 0x04,
     542    FD_DOR_DMAEN    = 0x08,
     543    FD_DOR_MOTEN0   = 0x10,
     544    FD_DOR_MOTEN1   = 0x20,
     545    FD_DOR_MOTEN2   = 0x40,
     546    FD_DOR_MOTEN3   = 0x80
     547};
     548
     549enum {
     550#if MAX_FD == 4
     551    FD_TDR_BOOTSEL  = 0x0c
     552#else
     553    FD_TDR_BOOTSEL  = 0x04
     554#endif
     555};
     556
     557enum {
     558    FD_DSR_DRATEMASK= 0x03,
     559    FD_DSR_PWRDOWN  = 0x40,
     560    FD_DSR_SWRESET  = 0x80
     561};
     562
     563enum {
     564    FD_MSR_DRV0BUSY = 0x01,
     565    FD_MSR_DRV1BUSY = 0x02,
     566    FD_MSR_DRV2BUSY = 0x04,
     567    FD_MSR_DRV3BUSY = 0x08,
     568    FD_MSR_CMDBUSY  = 0x10,
     569    FD_MSR_NONDMA   = 0x20,
     570    FD_MSR_DIO      = 0x40,
     571    FD_MSR_RQM      = 0x80
     572};
     573
     574enum {
     575    FD_DIR_DSKCHG   = 0x80
     576};
     577
    506578#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
    507579#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
     
    523595    /* HW */
    524596#ifndef VBOX
    525     int irq_lvl;
     597    int irq;
    526598    int dma_chann;
    527599#else
     
    532604    /* Controller state */
    533605    QEMUTimer *result_timer;
    534     uint8_t state;
    535     uint8_t dma_en;
     606    uint8_t sra;
     607    uint8_t srb;
     608    uint8_t dor;
     609    uint8_t tdr;
     610    uint8_t dsr;
     611    uint8_t msr;
    536612    uint8_t cur_drv;
    537     uint8_t bootsel;
     613    uint8_t status0;
     614    uint8_t status1;
     615    uint8_t status2;
    538616    /* Command FIFO */
    539617    uint8_t fifo[FD_SECTOR_LEN];
     
    542620    uint8_t data_state;
    543621    uint8_t data_dir;
    544     uint8_t int_status;
    545622    uint8_t eot; /* last wanted sector */
    546623    /* States kept only to be returned back */
     
    555632    uint8_t pwrd;
    556633    /* Floppy drives */
    557     fdrive_t drives[2];
     634    uint8_t num_floppies;
     635    fdrive_t drives[MAX_FD];
     636    uint8_t reset_sensei;
    558637#ifdef VBOX
    559638    /** Pointer to device instance. */
     
    574653    uint32_t retval;
    575654
    576     switch (reg & 0x07) {
    577     case 0x01:
     655    switch (reg) {
     656    case FD_REG_SRA:
     657        retval = fdctrl_read_statusA(fdctrl);
     658        break;
     659    case FD_REG_SRB:
    578660        retval = fdctrl_read_statusB(fdctrl);
    579661        break;
    580     case 0x02:
     662    case FD_REG_DOR:
    581663        retval = fdctrl_read_dor(fdctrl);
    582664        break;
    583     case 0x03:
     665    case FD_REG_TDR:
    584666        retval = fdctrl_read_tape(fdctrl);
    585667        break;
    586     case 0x04:
     668    case FD_REG_MSR:
    587669        retval = fdctrl_read_main_status(fdctrl);
    588670        break;
    589     case 0x05:
     671    case FD_REG_FIFO:
    590672        retval = fdctrl_read_data(fdctrl);
    591673        break;
    592     case 0x07:
     674    case FD_REG_DIR:
    593675        retval = fdctrl_read_dir(fdctrl);
    594676        break;
     
    608690    FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
    609691
    610     switch (reg & 0x07) {
    611     case 0x02:
     692    switch (reg) {
     693    case FD_REG_DOR:
    612694        fdctrl_write_dor(fdctrl, value);
    613695        break;
    614     case 0x03:
     696    case FD_REG_TDR:
    615697        fdctrl_write_tape(fdctrl, value);
    616698        break;
    617     case 0x04:
     699    case FD_REG_DSR:
    618700        fdctrl_write_rate(fdctrl, value);
    619701        break;
    620     case 0x05:
     702    case FD_REG_FIFO:
    621703        fdctrl_write_data(fdctrl, value);
    622704        break;
     
    626708}
    627709
    628 #ifndef VBOX
    629 static void fd_change_cb (void *opaque)
    630 {
    631     fdrive_t *drv = opaque;
    632 
    633     FLOPPY_DPRINTF("disk change\n");
    634     fd_revalidate(drv);
    635 #if 0
    636     fd_recalibrate(drv);
    637     fdctrl_reset_fifo(drv->fdctrl);
    638     fdctrl_raise_irq(drv->fdctrl, 0x20);
    639 #endif
    640 }
    641 
    642 #else  /* VBOX */
     710#ifdef VBOX
    643711/**
    644  * Called when a media is mounted.
     712 * Called when a medium is mounted.
    645713 *
    646714 * @param   pInterface      Pointer to the interface structure
     
    651719    fdrive_t *drv = PDMIMOUNTNOTIFY_2_FDRIVE (pInterface);
    652720    LogFlow(("fdMountNotify:\n"));
    653     fd_revalidate (drv);
     721    drv->fMediaChanged = true;
    654722}
    655723
    656724/**
    657  * Called when a media is unmounted
    658  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     725 * Called when a medium is unmounted.
     726 * @param   pInterface      Pointer to the interface structure
     727 *                          containing the called function pointer.
    659728 */
    660729static DECLCALLBACK(void) fdUnmountNotify(PPDMIMOUNTNOTIFY pInterface)
     
    662731    fdrive_t *drv = PDMIMOUNTNOTIFY_2_FDRIVE (pInterface);
    663732    LogFlow(("fdUnmountNotify:\n"));
    664     fd_revalidate (drv);
    665 }
    666 #endif
    667 
    668 #ifndef VBOX
    669 fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
    670                        uint32_t io_base,
    671                        BlockDriverState **fds)
    672 {
    673     fdctrl_t *fdctrl;
    674 /* //    int io_mem; */
    675     int i;
    676 
    677     FLOPPY_DPRINTF("init controller\n");
    678     fdctrl = qemu_mallocz(sizeof(fdctrl_t));
    679     if (!fdctrl)
    680         return NULL;
    681     fdctrl->result_timer = qemu_new_timer(vm_clock,
    682                                           fdctrl_result_timer, fdctrl);
    683 
    684     fdctrl->version = 0x90; /* Intel 82078 controller */
    685     fdctrl->irq_lvl = irq_lvl;
    686     fdctrl->dma_chann = dma_chann;
    687     fdctrl->io_base = io_base;
    688     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
    689     if (fdctrl->dma_chann != -1) {
    690         fdctrl->dma_en = 1;
    691         DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
    692     } else {
    693         fdctrl->dma_en = 0;
    694     }
    695     for (i = 0; i < 2; i++) {
    696         fd_init(&fdctrl->drives[i], fds[i]);
    697         if (fds[i]) {
    698             bdrv_set_change_cb(fds[i],
    699                                &fd_change_cb, &fdctrl->drives[i]);
    700         }
    701     }
    702     fdctrl_reset(fdctrl, 0);
    703     fdctrl->state = FD_CTRL_ACTIVE;
    704     if (mem_mapped) {
    705         FLOPPY_ERROR("memory mapped floppy not supported by now !\n");
    706 #if 0
    707         io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write);
    708         cpu_register_physical_memory(base, 0x08, io_mem);
    709 #endif
    710     } else {
    711         register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
    712         register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
    713         register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
    714         register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
    715     }
    716     for (i = 0; i < 2; i++) {
    717         fd_revalidate(&fdctrl->drives[i]);
    718     }
    719 
    720     return fdctrl;
    721 }
    722 
    723 /* XXX: may change if moved to bdrv */
    724 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
    725 {
    726     return fdctrl->drives[drive_num].drive;
     733    drv->fMediaChanged = true;
    727734}
    728735#endif
    729736
    730737/* Change IRQ state */
    731 static void fdctrl_reset_irq (fdctrl_t *fdctrl)
    732 {
     738static void fdctrl_reset_irq(fdctrl_t *fdctrl)
     739{
     740    if (!(fdctrl->sra & FD_SRA_INTPEND))
     741        return;
    733742    FLOPPY_DPRINTF("Reset interrupt\n");
    734743#ifdef VBOX
    735744    PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 0);
    736745#else
    737     pic_set_irq(fdctrl->irq_lvl, 0);
    738 #endif
    739     fdctrl->state &= ~FD_CTRL_INTR;
    740 }
    741 
    742 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
    743 {
    744     if (~(fdctrl->state & FD_CTRL_INTR)) {
     746    qemu_set_irq(fdctrl->irq, 0);
     747#endif
     748    fdctrl->sra &= ~FD_SRA_INTPEND;
     749}
     750
     751static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0)
     752{
     753    if (!(fdctrl->sra & FD_SRA_INTPEND)) {
    745754#ifdef VBOX
    746755        PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 1);
    747756#else
    748         pic_set_irq(fdctrl->irq_lvl, 1);
    749 #endif
    750         fdctrl->state |= FD_CTRL_INTR;
    751     }
    752     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
    753     fdctrl->int_status = status;
     757        qemu_set_irq(fdctrl->irq, 1);
     758#endif
     759        fdctrl->sra |= FD_SRA_INTPEND;
     760    }
     761    fdctrl->reset_sensei = 0;
     762    fdctrl->status0 = status0;
     763    FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
    754764}
    755765
    756766/* Reset controller */
    757 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
     767static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq)
    758768{
    759769    int i;
     
    762772    fdctrl_reset_irq(fdctrl);
    763773    /* Initialise controller */
     774    fdctrl->sra = 0;
     775    fdctrl->srb = 0xc0;
     776#ifdef VBOX
     777    if (!fdctrl->drives[1].pDrvBlock)
     778#else
     779    if (!fdctrl->drives[1].bs)
     780#endif
     781        fdctrl->sra |= FD_SRA_nDRV2;
    764782    fdctrl->cur_drv = 0;
     783    fdctrl->dor = FD_DOR_nRESET;
     784    fdctrl->dor |= (fdctrl->dma_chann != 0xff) ? FD_DOR_DMAEN : 0;
     785    fdctrl->msr = FD_MSR_RQM;
    765786    /* FIFO state */
    766787    fdctrl->data_pos = 0;
    767788    fdctrl->data_len = 0;
    768     fdctrl->data_state = FD_STATE_CMD;
     789    fdctrl->data_state = 0;
    769790    fdctrl->data_dir = FD_DIR_WRITE;
    770791    for (i = 0; i < MAX_FD; i++)
    771         fd_reset(&fdctrl->drives[i]);
     792        fd_recalibrate(&fdctrl->drives[i]);
    772793    fdctrl_reset_fifo(fdctrl);
    773     if (do_irq)
    774         fdctrl_raise_irq(fdctrl, 0xc0);
    775 }
    776 
    777 static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
    778 {
    779     return &fdctrl->drives[fdctrl->bootsel];
    780 }
    781 
    782 static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
    783 {
    784     return &fdctrl->drives[1 - fdctrl->bootsel];
    785 }
    786 
    787 static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
    788 {
    789     return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
     794    if (do_irq) {
     795        fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
     796        fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
     797    }
     798}
     799
     800static inline fdrive_t *drv0(fdctrl_t *fdctrl)
     801{
     802    return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
     803}
     804
     805static inline fdrive_t *drv1(fdctrl_t *fdctrl)
     806{
     807    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
     808        return &fdctrl->drives[1];
     809    else
     810        return &fdctrl->drives[0];
     811}
     812
     813#if MAX_FD == 4
     814static inline fdrive_t *drv2(fdctrl_t *fdctrl)
     815{
     816    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
     817        return &fdctrl->drives[2];
     818    else
     819        return &fdctrl->drives[1];
     820}
     821
     822static inline fdrive_t *drv3(fdctrl_t *fdctrl)
     823{
     824    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
     825        return &fdctrl->drives[3];
     826    else
     827        return &fdctrl->drives[2];
     828}
     829#endif
     830
     831static fdrive_t *get_cur_drv(fdctrl_t *fdctrl)
     832{
     833    switch (fdctrl->cur_drv) {
     834        case 0: return drv0(fdctrl);
     835        case 1: return drv1(fdctrl);
     836#if MAX_FD == 4
     837        case 2: return drv2(fdctrl);
     838        case 3: return drv3(fdctrl);
     839#endif
     840        default: return NULL;
     841    }
     842}
     843
     844/* Status A register : 0x00 (read-only) */
     845static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl)
     846{
     847    uint32_t retval = fdctrl->sra;
     848
     849    FLOPPY_DPRINTF("status register A: 0x%02x\n", retval);
     850
     851    return retval;
    790852}
    791853
    792854/* Status B register : 0x01 (read-only) */
    793 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
    794 {
    795     FLOPPY_DPRINTF("status register: 0x00\n");
    796     return 0;
     855static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl)
     856{
     857    uint32_t retval = fdctrl->srb;
     858
     859    FLOPPY_DPRINTF("status register B: 0x%02x\n", retval);
     860
     861    return retval;
    797862}
    798863
    799864/* Digital output register : 0x02 */
    800 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
    801 {
    802     uint32_t retval = 0;
    803 
    804     /* Drive motors state indicators */
    805 #ifndef VBOX
    806     if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
    807         retval |= 1 << 5;
    808     if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
    809         retval |= 1 << 4;
    810 #else
    811     /* bit4: 0 = drive 0 motor off/1 = on */
    812     if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
    813         retval |= RT_BIT(4);
    814     /* bit5: 0 = drive 1 motor off/1 = on */
    815     if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
    816         retval |= RT_BIT(5);
    817 #endif
    818     /* DMA enable */
    819     retval |= fdctrl->dma_en << 3;
    820     /* Reset indicator */
    821     retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0;
     865static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl)
     866{
     867    uint32_t retval = fdctrl->dor;
     868
    822869    /* Selected drive */
    823870    retval |= fdctrl->cur_drv;
     
    827874}
    828875
    829 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
    830 {
    831     /* Reset mode */
    832     if (fdctrl->state & FD_CTRL_RESET) {
    833         if (!(value & 0x04)) {
    834             FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
    835             return;
    836         }
    837     }
     876static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value)
     877{
    838878    FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
    839     /* Drive motors state indicators */
    840     if (value & 0x20)
    841         fd_start(drv1(fdctrl));
     879
     880    /* Motors */
     881    if (value & FD_DOR_MOTEN0)
     882        fdctrl->srb |= FD_SRB_MTR0;
    842883    else
    843         fd_stop(drv1(fdctrl));
    844     if (value & 0x10)
    845         fd_start(drv0(fdctrl));
     884        fdctrl->srb &= ~FD_SRB_MTR0;
     885    if (value & FD_DOR_MOTEN1)
     886        fdctrl->srb |= FD_SRB_MTR1;
    846887    else
    847         fd_stop(drv0(fdctrl));
    848     /* DMA enable */
    849 #if 0
    850     if (fdctrl->dma_chann != -1)
    851         fdctrl->dma_en = 1 - ((value >> 3) & 1);
    852 #endif
     888        fdctrl->srb &= ~FD_SRB_MTR1;
     889
     890    /* Drive */
     891    if (value & 1)
     892        fdctrl->srb |= FD_SRB_DR0;
     893    else
     894        fdctrl->srb &= ~FD_SRB_DR0;
     895
    853896    /* Reset */
    854     if (!(value & 0x04)) {
    855         if (!(fdctrl->state & FD_CTRL_RESET)) {
     897    if (!(value & FD_DOR_nRESET)) {
     898        if (fdctrl->dor & FD_DOR_nRESET) {
    856899            FLOPPY_DPRINTF("controller enter RESET state\n");
    857             fdctrl->state |= FD_CTRL_RESET;
    858900        }
    859901    } else {
    860         if (fdctrl->state & FD_CTRL_RESET) {
     902        if (!(fdctrl->dor & FD_DOR_nRESET)) {
    861903            FLOPPY_DPRINTF("controller out of RESET state\n");
    862904            fdctrl_reset(fdctrl, 1);
    863             fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);
     905            fdctrl->dsr &= ~FD_DSR_PWRDOWN;
    864906        }
    865907    }
    866908    /* Selected drive */
    867     fdctrl->cur_drv = value & 1;
     909    fdctrl->cur_drv = value & FD_DOR_SELMASK;
     910
     911    fdctrl->dor = value;
    868912}
    869913
    870914/* Tape drive register : 0x03 */
    871 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
    872 {
    873     uint32_t retval = 0;
    874 
    875     /* Disk boot selection indicator */
    876     retval |= fdctrl->bootsel << 2;
    877     /* Tape indicators: never allowed */
     915static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl)
     916{
     917    uint32_t retval = fdctrl->tdr;
     918
    878919    FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
    879920
     
    881922}
    882923
    883 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
     924static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value)
    884925{
    885926    /* Reset mode */
    886     if (fdctrl->state & FD_CTRL_RESET) {
     927    if (!(fdctrl->dor & FD_DOR_nRESET)) {
    887928        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
    888929        return;
     
    890931    FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
    891932    /* Disk boot selection indicator */
    892     fdctrl->bootsel = (value >> 2) & 1;
     933    fdctrl->tdr = value & FD_TDR_BOOTSEL;
    893934    /* Tape indicators: never allow */
    894935}
    895936
    896937/* Main status register : 0x04 (read) */
    897 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
    898 {
    899     uint32_t retval = 0;
    900 
    901     fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
    902     if (!(fdctrl->state & FD_CTRL_BUSY)) {
    903         /* Data transfer allowed */
    904         retval |= 0x80;
    905         /* Data transfer direction indicator */
    906         if (fdctrl->data_dir == FD_DIR_READ)
    907             retval |= 0x40;
    908     }
    909     /* Should handle 0x20 for SPECIFY command */
    910     /* Command busy indicator */
    911     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||
    912         FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)
    913         retval |= 0x10;
     938static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl)
     939{
     940    uint32_t retval = fdctrl->msr;
     941
     942    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
     943    fdctrl->dor |= FD_DOR_nRESET;
     944
    914945    FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
    915946
     
    918949
    919950/* Data select rate register : 0x04 (write) */
    920 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
     951static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value)
    921952{
    922953    /* Reset mode */
    923     if (fdctrl->state & FD_CTRL_RESET) {
    924             FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
    925             return;
    926         }
     954    if (!(fdctrl->dor & FD_DOR_nRESET)) {
     955        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
     956        return;
     957    }
    927958    FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
    928959    /* Reset: autoclear */
    929     if (value & 0x80) {
    930         fdctrl->state |= FD_CTRL_RESET;
     960    if (value & FD_DSR_SWRESET) {
     961        fdctrl->dor &= ~FD_DOR_nRESET;
    931962        fdctrl_reset(fdctrl, 1);
    932         fdctrl->state &= ~FD_CTRL_RESET;
    933     }
    934     if (value & 0x40) {
    935         fdctrl->state |= FD_CTRL_SLEEP;
     963        fdctrl->dor |= FD_DOR_nRESET;
     964    }
     965    if (value & FD_DSR_PWRDOWN) {
    936966        fdctrl_reset(fdctrl, 1);
    937967    }
    938 /* //        fdctrl.precomp = (value >> 2) & 0x07; */
     968    fdctrl->dsr = value;
     969}
     970
     971static int fdctrl_media_changed(fdrive_t *drv)
     972{
     973    int ret;
     974
     975#ifdef VBOX
     976    if (!drv->pDrvBlock)
     977        return 0;
     978    ret = drv->fMediaChanged;
     979    drv->fMediaChanged = false;
     980#else
     981    if (!drv->bs)
     982        return 0;
     983    ret = bdrv_media_changed(drv->bs);
     984#endif
     985    if (ret) {
     986        fd_revalidate(drv);
     987    }
     988    return ret;
    939989}
    940990
    941991/* Digital input register : 0x07 (read-only) */
    942 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
     992static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl)
    943993{
    944994    uint32_t retval = 0;
    945995
    946 #ifndef VBOX
    947     if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
    948         drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
    949 #else
    950     fdrive_t *cur_drv = get_cur_drv(fdctrl);
    951     if (    drv0(fdctrl)->drflags & FDRIVE_REVALIDATE
    952         ||  drv1(fdctrl)->drflags & FDRIVE_REVALIDATE
    953         ||  !cur_drv->fMediaPresent)
    954 #endif
    955         retval |= 0x80;
     996    if (fdctrl_media_changed(drv0(fdctrl))
     997     || fdctrl_media_changed(drv1(fdctrl))
     998#if MAX_FD == 4
     999     || fdctrl_media_changed(drv2(fdctrl))
     1000     || fdctrl_media_changed(drv3(fdctrl))
     1001#endif
     1002        )
     1003        retval |= FD_DIR_DSKCHG;
    9561004    if (retval != 0)
    9571005        FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
    958     drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
    959     drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
    9601006
    9611007    return retval;
     
    9631009
    9641010/* FIFO state control */
    965 static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
     1011static void fdctrl_reset_fifo(fdctrl_t *fdctrl)
    9661012{
    9671013    fdctrl->data_dir = FD_DIR_WRITE;
    9681014    fdctrl->data_pos = 0;
    969     FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);
     1015    fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
    9701016}
    9711017
    9721018/* Set FIFO status for the host to read */
    973 static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
     1019static void fdctrl_set_fifo(fdctrl_t *fdctrl, int fifo_len, int do_irq)
    9741020{
    9751021    fdctrl->data_dir = FD_DIR_READ;
    9761022    fdctrl->data_len = fifo_len;
    9771023    fdctrl->data_pos = 0;
    978     FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);
     1024    fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
    9791025    if (do_irq)
    9801026        fdctrl_raise_irq(fdctrl, 0x00);
     
    9821028
    9831029/* Set an error: unimplemented/unknown command */
    984 static void fdctrl_unimplemented (fdctrl_t *fdctrl)
    985 {
    986 #if 0
    987     fdrive_t *cur_drv;
    988 
    989     cur_drv = get_cur_drv(fdctrl);
    990     fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;
    991     fdctrl->fifo[1] = 0x00;
    992     fdctrl->fifo[2] = 0x00;
    993     fdctrl_set_fifo(fdctrl, 3, 1);
    994 #else
    995     /* //    fdctrl_reset_fifo(fdctrl); */
    996     fdctrl->fifo[0] = 0x80;
     1030static void fdctrl_unimplemented(fdctrl_t *fdctrl, int direction)
     1031{
     1032    FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]);
     1033    fdctrl->fifo[0] = FD_SR0_INVCMD;
    9971034    fdctrl_set_fifo(fdctrl, 1, 0);
    998 #endif
     1035}
     1036
     1037/* Seek to next sector */
     1038static int fdctrl_seek_to_next_sect(fdctrl_t *fdctrl, fdrive_t *cur_drv)
     1039{
     1040    FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n",
     1041                   cur_drv->head, cur_drv->track, cur_drv->sect,
     1042                   fd_sector(cur_drv));
     1043    /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
     1044       error in fact */
     1045    if (cur_drv->sect >= cur_drv->last_sect ||
     1046        cur_drv->sect == fdctrl->eot) {
     1047        cur_drv->sect = 1;
     1048        if (FD_MULTI_TRACK(fdctrl->data_state)) {
     1049            if (cur_drv->head == 0 &&
     1050                (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
     1051                cur_drv->head = 1;
     1052            } else {
     1053                cur_drv->head = 0;
     1054                cur_drv->track++;
     1055                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
     1056                    return 0;
     1057            }
     1058        } else {
     1059            cur_drv->track++;
     1060            return 0;
     1061        }
     1062        FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
     1063                       cur_drv->head, cur_drv->track,
     1064                       cur_drv->sect, fd_sector(cur_drv));
     1065    } else {
     1066        cur_drv->sect++;
     1067    }
     1068    return 1;
    9991069}
    10001070
    10011071/* Callback for transfer end (stop or abort) */
    1002 static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
    1003                                   uint8_t status1, uint8_t status2)
     1072static void fdctrl_stop_transfer(fdctrl_t *fdctrl, uint8_t status0,
     1073                                 uint8_t status1, uint8_t status2)
    10041074{
    10051075    fdrive_t *cur_drv;
     
    10081078    FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
    10091079                   status0, status1, status2,
    1010                    status0 | (cur_drv->head << 2) | fdctrl->cur_drv);
    1011     fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;
     1080                   status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl));
     1081    fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
    10121082    fdctrl->fifo[1] = status1;
    10131083    fdctrl->fifo[2] = status2;
     
    10171087    fdctrl->fifo[6] = FD_SECTOR_SC;
    10181088    fdctrl->data_dir = FD_DIR_READ;
    1019     if (fdctrl->state & FD_CTRL_BUSY) {
     1089    if (!(fdctrl->msr & FD_MSR_NONDMA)) {
    10201090#ifdef VBOX
    10211091        PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 0);
     
    10231093        DMA_release_DREQ(fdctrl->dma_chann);
    10241094#endif
    1025         fdctrl->state &= ~FD_CTRL_BUSY;
    1026     }
     1095    }
     1096    fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
     1097    fdctrl->msr &= ~FD_MSR_NONDMA;
    10271098    fdctrl_set_fifo(fdctrl, 7, 1);
    10281099}
    10291100
    10301101/* Prepare a data transfer (either DMA or FIFO) */
    1031 static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
     1102static void fdctrl_start_transfer(fdctrl_t *fdctrl, int direction)
    10321103{
    10331104    fdrive_t *cur_drv;
    10341105    uint8_t kh, kt, ks;
    1035     int did_seek;
    1036 
    1037     fdctrl->cur_drv = fdctrl->fifo[1] & 1;
     1106    int did_seek = 0;
     1107
     1108    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
    10381109    cur_drv = get_cur_drv(fdctrl);
    10391110    kt = fdctrl->fifo[2];
     
    10411112    ks = fdctrl->fifo[4];
    10421113    FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
    1043                    fdctrl->cur_drv, kh, kt, ks,
    1044                    _fd_sector(kh, kt, ks, cur_drv->last_sect));
    1045     did_seek = 0;
    1046     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
     1114                   GET_CUR_DRV(fdctrl), kh, kt, ks,
     1115                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
     1116    switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
    10471117    case 2:
    10481118        /* sect too big */
    1049         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
     1119        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
    10501120        fdctrl->fifo[3] = kt;
    10511121        fdctrl->fifo[4] = kh;
     
    10541124    case 3:
    10551125        /* track too big */
    1056         fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
     1126        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
    10571127        fdctrl->fifo[3] = kt;
    10581128        fdctrl->fifo[4] = kh;
     
    10611131    case 4:
    10621132        /* No seek enabled */
    1063         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
     1133        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
    10641134        fdctrl->fifo[3] = kt;
    10651135        fdctrl->fifo[4] = kh;
     
    10721142        break;
    10731143    }
     1144
    10741145    /* Set the FIFO state */
    10751146    fdctrl->data_dir = direction;
    10761147    fdctrl->data_pos = 0;
    1077     FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */
     1148    fdctrl->msr |= FD_MSR_CMDBUSY;
    10781149    if (fdctrl->fifo[0] & 0x80)
    10791150        fdctrl->data_state |= FD_STATE_MULTI;
     
    10881159    } else {
    10891160        int tmp;
    1090         fdctrl->data_len = 128 << fdctrl->fifo[5];
    1091         tmp = (cur_drv->last_sect - ks + 1);
     1161        fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
     1162        tmp = (fdctrl->fifo[6] - ks + 1);
    10921163        if (fdctrl->fifo[0] & 0x80)
    1093             tmp += cur_drv->last_sect;
     1164            tmp += fdctrl->fifo[6];
    10941165        fdctrl->data_len *= tmp;
    10951166    }
    10961167    fdctrl->eot = fdctrl->fifo[6];
    1097     if (fdctrl->dma_en) {
     1168    if (fdctrl->dor & FD_DOR_DMAEN) {
    10981169        int dma_mode;
    10991170        /* DMA transfer are enabled. Check if DMA channel is well programmed */
     
    11131184            (direction == FD_DIR_READ && dma_mode == 1)) {
    11141185            /* No access is allowed until DMA transfer has completed */
    1115             fdctrl->state |= FD_CTRL_BUSY;
     1186            fdctrl->msr &= ~FD_MSR_RQM;
    11161187            /* Now, we just have to wait for the DMA controller to
    11171188             * recall us...
     
    11301201    }
    11311202    FLOPPY_DPRINTF("start non-DMA transfer\n");
     1203    fdctrl->msr |= FD_MSR_NONDMA;
     1204    if (direction != FD_DIR_WRITE)
     1205        fdctrl->msr |= FD_MSR_DIO;
    11321206    /* IO based transfer: calculate len */
    11331207    fdctrl_raise_irq(fdctrl, 0x00);
     
    11371211
    11381212/* Prepare a transfer of deleted data */
    1139 static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
    1140 {
     1213static void fdctrl_start_transfer_del(fdctrl_t *fdctrl, int direction)
     1214{
     1215    FLOPPY_ERROR("fdctrl_start_transfer_del() unimplemented\n");
     1216
    11411217    /* We don't handle deleted data,
    11421218     * so we don't return *ANYTHING*
    11431219     */
    1144     fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
    1145 }
    1146 
    1147 #if 0
    1148 #include <stdio.h>
    1149 #include <stdlib.h>
    1150 
    1151 static FILE * f;
    1152 static void dump (void *p, size_t len)
    1153 {
    1154     size_t n;
    1155 
    1156     if (!f) {
    1157         f = fopen ("dump", "wb");
    1158         if (!f)
    1159             exit (0);
    1160     }
    1161 
    1162     n = fwrite (p, len, 1, f);
    1163     if (n != 1) {
    1164         AssertMsgFailed (("failed to dump\n"));
    1165         exit (0);
    1166     }
    1167 }
    1168 #else
    1169 #define dump(a,b) do { } while (0)
     1220    fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
     1221}
     1222
     1223#ifdef VBOX
     1224/* Block driver read/write wrappers. */
     1225
     1226static int blk_write(fdrive_t *drv, int64_t sector_num, const uint8_t *buf, int nb_sectors)
     1227{
     1228    int     rc;
     1229
     1230    drv->Led.Asserted.s.fWriting = drv->Led.Actual.s.fWriting = 1;
     1231
     1232    rc = drv->pDrvBlock->pfnWrite(drv->pDrvBlock, sector_num * FD_SECTOR_LEN,
     1233                                  buf, nb_sectors * FD_SECTOR_LEN);
     1234
     1235    drv->Led.Actual.s.fWriting = 0;
     1236    if (RT_FAILURE(rc))
     1237        AssertMsgFailed(("Floppy: Failure to read sector %d. rc=%Rrc", sector_num, rc));
     1238
     1239    return rc;
     1240}
     1241
     1242static int blk_read(fdrive_t *drv, int64_t sector_num, uint8_t *buf, int nb_sectors)
     1243{
     1244    int     rc;
     1245
     1246    drv->Led.Asserted.s.fReading = drv->Led.Actual.s.fReading = 1;
     1247
     1248    rc = drv->pDrvBlock->pfnRead(drv->pDrvBlock, sector_num * FD_SECTOR_LEN,
     1249                                 buf, nb_sectors * FD_SECTOR_LEN);
     1250
     1251    drv->Led.Actual.s.fReading = 0;
     1252
     1253    if (RT_FAILURE(rc))
     1254        AssertMsgFailed(("Floppy: Failure to read sector %d. rc=%Rrc", sector_num, rc));
     1255
     1256    return rc;
     1257}
     1258
    11701259#endif
    11711260
     
    11931282
    11941283    fdctrl = opaque;
    1195     if (!(fdctrl->state & FD_CTRL_BUSY)) {
     1284    if (fdctrl->msr & FD_MSR_RQM) {
    11961285        FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
    11971286        return 0;
     
    12001289    if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
    12011290        fdctrl->data_dir == FD_DIR_SCANH)
    1202         status2 = 0x04;
     1291        status2 = FD_SR2_SNS;
    12031292    if (dma_len > fdctrl->data_len)
    12041293        dma_len = fdctrl->data_len;
    12051294#ifndef VBOX
    1206     if (cur_drv->bs == NULL) {
     1295    if (cur_drv->bs == NULL)
    12071296#else  /* !VBOX */
    1208     if (cur_drv->pDrvBlock == NULL) {
    1209 #endif
     1297    if (cur_drv->pDrvBlock == NULL)
     1298#endif
     1299    {
    12101300        if (fdctrl->data_dir == FD_DIR_WRITE)
    1211             fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
     1301            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
    12121302        else
    1213             fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
     1303            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
    12141304        len = 0;
    12151305        goto transfer_error;
     
    12221312        FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
    12231313                       "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
    1224                        fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
     1314                       fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head,
    12251315                       cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
    1226                        fd_sector(cur_drv) * 512);
     1316                       fd_sector(cur_drv) * FD_SECTOR_LEN);
    12271317        if (fdctrl->data_dir != FD_DIR_WRITE ||
    12281318            len < FD_SECTOR_LEN || rel_pos != 0) {
    12291319            /* READ & SCAN commands and realign to a sector for WRITE */
    1230 #ifndef VBOX
     1320#ifdef VBOX
     1321            rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
     1322            if (RT_FAILURE(rc))
     1323#else
    12311324            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
    1232                           fdctrl->fifo, 1) < 0) {
     1325                          fdctrl->fifo, 1) < 0)
     1326#endif
     1327            {
    12331328                FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
    12341329                               fd_sector(cur_drv));
     
    12361331                memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
    12371332            }
    1238 #else
    1239             cur_drv->Led.Asserted.s.fReading
    1240                 = cur_drv->Led.Actual.s.fReading = 1;
    1241 
    1242             rc = cur_drv->pDrvBlock->pfnRead (
    1243                 cur_drv->pDrvBlock,
    1244                 fd_sector (cur_drv) * 512,
    1245                 fdctrl->fifo,
    1246                 1 * 512
    1247                 );
    1248 
    1249             cur_drv->Led.Actual.s.fReading = 0;
    1250 
    1251             if (RT_FAILURE (rc)) {
    1252                 AssertMsgFailed (
    1253                     ("Floppy: error getting sector %d, rc = %Rrc",
    1254                      fd_sector (cur_drv), rc));
    1255                 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
    1256             }
    1257 #endif
    12581333        }
    12591334        switch (fdctrl->data_dir) {
     
    12671342                                                  fdctrl->data_pos,
    12681343                                                  len, &read);
    1269                 dump (fdctrl->fifo + rel_pos, len);
    12701344                AssertMsgRC (rc2, ("DMAWriteMemory -> %Rrc\n", rc2));
    12711345            }
     
    12851359                 * LED or attempt any writes. A real floppy doesn't attempt
    12861360                 * to write to readonly media either. */
    1287                 fdctrl_stop_transfer (fdctrl, 0x60, 0x00 | (cur_drv->ro << 1),
    1288                                       0x00);
     1361                fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, cur_drv->ro << 1,
     1362                                     0x00);
    12891363                goto transfer_error;
    12901364            }
     
    12991373            }
    13001374
    1301             cur_drv->Led.Asserted.s.fWriting
    1302                 = cur_drv->Led.Actual.s.fWriting = 1;
    1303 
    1304             rc = cur_drv->pDrvBlock->pfnWrite (
    1305                 cur_drv->pDrvBlock,
    1306                 fd_sector (cur_drv) * 512,
    1307                 fdctrl->fifo,
    1308                 1 * 512
    1309                 );
    1310 
    1311             cur_drv->Led.Actual.s.fWriting = 0;
    1312 
    1313             if (RT_FAILURE (rc)) {
    1314                 AssertMsgFailed(("Floppy: error writing sector %d. rc=%Rrc",
    1315                                  fd_sector (cur_drv), rc));
    1316                 fdctrl_stop_transfer (fdctrl, 0x60, 0x00 | (cur_drv->ro << 1),
    1317                                       0x00);
    1318                 goto transfer_error;
    1319             }
     1375            rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
     1376            if (RT_FAILURE(rc))
    13201377#else
    13211378            DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
    13221379                             fdctrl->data_pos, len);
    1323 /*             cpu_physical_memory_read(addr + fdctrl->data_pos, */
    1324 /*                                   fdctrl->fifo + rel_pos, len); */
    13251380            if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
    1326                            fdctrl->fifo, 1) < 0) {
    1327                 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
    1328                 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
     1381                           fdctrl->fifo, 1) < 0)
     1382#endif
     1383            {
     1384                FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
     1385                fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
    13291386                goto transfer_error;
    13301387            }
    1331 #endif
    13321388            break;
    13331389        default:
     
    13441400                DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
    13451401#endif
    1346 /*                 cpu_physical_memory_read(addr + fdctrl->data_pos, */
    1347 /*                                          tmpbuf, len); */
    13481402                ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
    13491403                if (ret == 0) {
    1350                     status2 = 0x08;
     1404                    status2 = FD_SR2_SEH;
    13511405                    goto end_transfer;
    13521406                }
     
    13631417        if (rel_pos == 0) {
    13641418            /* Seek to next sector */
    1365             FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
    1366                            cur_drv->head, cur_drv->track, cur_drv->sect,
    1367                            fd_sector(cur_drv),
    1368                            fdctrl->data_pos - len);
    1369             /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
    1370                error in fact */
    1371             if (cur_drv->sect >= cur_drv->last_sect ||
    1372                 cur_drv->sect == fdctrl->eot) {
    1373                 cur_drv->sect = 1;
    1374                 if (FD_MULTI_TRACK(fdctrl->data_state)) {
    1375                     if (cur_drv->head == 0 &&
    1376                         (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
    1377                         cur_drv->head = 1;
    1378                     } else {
    1379                         cur_drv->head = 0;
    1380                         cur_drv->track++;
    1381                         if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
    1382                             break;
    1383                     }
    1384                 } else {
    1385                     cur_drv->track++;
    1386                     break;
    1387                 }
    1388                 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
    1389                                cur_drv->head, cur_drv->track,
    1390                                cur_drv->sect, fd_sector(cur_drv));
    1391             } else {
    1392                 cur_drv->sect++;
    1393             }
     1419            if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
     1420                break;
    13941421        }
    13951422    }
     
    14011428        fdctrl->data_dir == FD_DIR_SCANL ||
    14021429        fdctrl->data_dir == FD_DIR_SCANH)
    1403         status2 = 0x08;
     1430        status2 = FD_SR2_SEH;
    14041431    if (FD_DID_SEEK(fdctrl->data_state))
    1405         status0 |= 0x20;
     1432        status0 |= FD_SR0_SEEK;
    14061433    fdctrl->data_len -= len;
    1407     /* if (fdctrl->data_len == 0) */
    14081434    fdctrl_stop_transfer(fdctrl, status0, status1, status2);
    14091435transfer_error:
     
    14121438}
    14131439
    1414 #if 0
    1415 {
    1416     fdctrl_t *fdctrl;
     1440/* Data register : 0x05 */
     1441static uint32_t fdctrl_read_data(fdctrl_t *fdctrl)
     1442{
    14171443    fdrive_t *cur_drv;
    1418     int len, start_pos, rel_pos;
    1419     uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
    1420 
    1421     fdctrl = opaque;
    1422     if (!(fdctrl->state & FD_CTRL_BUSY)) {
    1423         FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
     1444    uint32_t retval = 0;
     1445    unsigned pos;
     1446#ifdef VBOX
     1447    int rc;
     1448#endif
     1449
     1450    cur_drv = get_cur_drv(fdctrl);
     1451    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
     1452    if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) {
     1453        FLOPPY_ERROR("controller not ready for reading\n");
    14241454        return 0;
    14251455    }
    1426     cur_drv = get_cur_drv(fdctrl);
    1427     if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
    1428         fdctrl->data_dir == FD_DIR_SCANH)
    1429         status2 = 0x04;
    1430     if (size > fdctrl->data_len)
    1431         size = fdctrl->data_len;
    1432 #ifndef VBOX
    1433     if (cur_drv->bs == NULL) {
     1456    pos = fdctrl->data_pos;
     1457    if (fdctrl->msr & FD_MSR_NONDMA) {
     1458        pos %= FD_SECTOR_LEN;
     1459        if (pos == 0) {
     1460            if (fdctrl->data_pos != 0)
     1461                if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
     1462                    FLOPPY_DPRINTF("error seeking to next sector %d\n",
     1463                                   fd_sector(cur_drv));
     1464                    return 0;
     1465                }
     1466#ifdef VBOX
     1467            rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
     1468            if (RT_FAILURE(rc))
    14341469#else
    1435     if (cur_drv->pDrvBase == NULL) {
    1436 #endif
    1437         if (fdctrl->data_dir == FD_DIR_WRITE)
    1438             fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
    1439         else
    1440             fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
    1441         len = 0;
    1442         goto transfer_error;
    1443     }
    1444     rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
    1445     for (start_pos = fdctrl->data_pos; fdctrl->data_pos < size;) {
    1446         len = size - fdctrl->data_pos;
    1447         if (len + rel_pos > FD_SECTOR_LEN)
    1448             len = FD_SECTOR_LEN - rel_pos;
    1449         FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x "
    1450                        "(%d-0x%08x 0x%08x)\n", len, size, fdctrl->data_pos,
    1451                        fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
    1452                        cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
    1453                        fd_sector(cur_drv) * 512, addr);
    1454         if (fdctrl->data_dir != FD_DIR_WRITE ||
    1455             len < FD_SECTOR_LEN || rel_pos != 0) {
    1456             /* READ & SCAN commands and realign to a sector for WRITE */
    1457 #ifndef VBOX
    1458             if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
    1459                           fdctrl->fifo, 1) < 0) {
    1460                 FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
     1470            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0)
     1471#endif
     1472            {
     1473                FLOPPY_DPRINTF("error getting sector %d\n",
    14611474                               fd_sector(cur_drv));
    14621475                /* Sure, image size is too small... */
    14631476                memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
    14641477            }
    1465 #else
    1466             int rc;
    1467 
    1468             cur_drv->Led.Asserted.s.fReading
    1469                 = cur_drv->Led.Actual.s.fReading = 1;
    1470 
    1471             rc = cur_drv->pDrvBlock->pfnRead (
    1472                 cur_drv->pDrvBlock,
    1473                 fd_sector (cur_drv) * 512,
    1474                 fdctrl->fifo,
    1475                 1 * 512
    1476                 );
    1477 
    1478             cur_drv->Led.Actual.s.fReading = 0;
    1479 
    1480             if (RT_FAILURE (rc)) {
    1481                 AssertMsgFailed (
    1482                     ("Floppy: error getting sector %d. rc=%Rrc\n",
    1483                      fd_sector(cur_drv), rc));
    1484                 /* Sure, image size is too small... */
    1485                 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
    1486             }
    1487             /* *p_fd_activity = 1; */
    1488 #endif
    1489         }
    1490         switch (fdctrl->data_dir) {
    1491         case FD_DIR_READ:
    1492             /* READ commands */
    1493 #ifdef VBOX
    1494             PDMDevHlpPhysWrite (fdctrl->pDevIns, addr + fdctrl->data_pos,
    1495                                 fdctrl->fifo + rel_pos, len);
    1496 #else
    1497             cpu_physical_memory_write(addr + fdctrl->data_pos,
    1498                                       fdctrl->fifo + rel_pos, len);
    1499 #endif
    1500             break;
    1501         case FD_DIR_WRITE:
    1502             /* WRITE commands */
    1503 #ifdef VBOX
    1504             {
    1505                 int rc;
    1506 
    1507                 PDMDevHlpPhysRead (fdctrl->pDevIns, addr + fdctrl->data_pos,
    1508                                    fdctrl->fifo + rel_pos, len);
    1509 
    1510                 cur_drv->Led.Asserted.s.fWriting
    1511                     = cur_drv->Led.Actual.s.fWriting = 1;
    1512 
    1513                 rc = cur_drv->pDrvBlock->pfnWrite (
    1514                     cur_drv->pDrvBlock,
    1515                     fd_sector (cur_drv) * 512,
    1516                     fdctrl->fifo,
    1517                     1 * 512
    1518                     );
    1519 
    1520                 cur_drv->Led.Actual.s.fWriting = 0;
    1521 
    1522                 if (RT_FAILURE (rc)) {
    1523                     AssertMsgFailed (
    1524                         ("Floppy: error writting sector %d. rc=%Rrc\n",
    1525                          fd_sector(cur_drv), rc));
    1526                     fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
    1527                     goto transfer_error;
    1528                 }
    1529             }
    1530             /* *p_fd_activity = 2; */
    1531 #else  /* !VBOX */
    1532             cpu_physical_memory_read(addr + fdctrl->data_pos,
    1533                                      fdctrl->fifo + rel_pos, len);
    1534             if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
    1535                            fdctrl->fifo, 1) < 0) {
    1536                 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
    1537                 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
    1538                 goto transfer_error;
    1539             }
    1540 #endif
    1541             break;
    1542         default:
    1543             /* SCAN commands */
    1544             {
    1545                 uint8_t tmpbuf[FD_SECTOR_LEN];
    1546                 int ret;
    1547 #ifdef VBOX
    1548                 PDMDevHlpPhysRead (fdctrl->pDevIns, addr + fdctrl->data_pos,
    1549                                    tmpbuf, len);
    1550 #else
    1551                 cpu_physical_memory_read(addr + fdctrl->data_pos,
    1552                                          tmpbuf, len);
    1553 #endif
    1554                 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
    1555                 if (ret == 0) {
    1556                     status2 = 0x08;
    1557                     goto end_transfer;
    1558                 }
    1559                 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
    1560                     (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
    1561                     status2 = 0x00;
    1562                     goto end_transfer;
    1563                 }
    1564             }
    1565             break;
    1566         }
    1567         fdctrl->data_pos += len;
    1568         rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
    1569         if (rel_pos == 0) {
    1570             /* Seek to next sector */
    1571             FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
    1572                            cur_drv->head, cur_drv->track, cur_drv->sect,
    1573                            fd_sector(cur_drv),
    1574                            fdctrl->data_pos - size);
    1575             /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
    1576                error in fact */
    1577             if (cur_drv->sect >= cur_drv->last_sect ||
    1578                 cur_drv->sect == fdctrl->eot) {
    1579                 cur_drv->sect = 1;
    1580                 if (FD_MULTI_TRACK(fdctrl->data_state)) {
    1581                     if (cur_drv->head == 0 &&
    1582                         (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
    1583                         cur_drv->head = 1;
    1584                     } else {
    1585                         cur_drv->head = 0;
    1586                         cur_drv->track++;
    1587                         if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
    1588                             break;
    1589                     }
    1590                 } else {
    1591                     cur_drv->track++;
    1592                     break;
    1593                 }
    1594                 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
    1595                                cur_drv->head, cur_drv->track,
    1596                                cur_drv->sect, fd_sector(cur_drv));
    1597             } else {
    1598                 cur_drv->sect++;
    1599             }
    1600         }
    1601     }
    1602 end_transfer:
    1603     len = fdctrl->data_pos - start_pos;
    1604     FLOPPY_DPRINTF("end transfer %d %d %d\n",
    1605                    fdctrl->data_pos, len, fdctrl->data_len);
    1606     if (fdctrl->data_dir == FD_DIR_SCANE ||
    1607         fdctrl->data_dir == FD_DIR_SCANL ||
    1608         fdctrl->data_dir == FD_DIR_SCANH)
    1609         status2 = 0x08;
    1610     if (FD_DID_SEEK(fdctrl->data_state))
    1611         status0 |= 0x20;
    1612     fdctrl->data_len -= len;
    1613     /* //    if (fdctrl->data_len == 0) */
    1614     fdctrl_stop_transfer(fdctrl, status0, status1, status2);
    1615 transfer_error:
    1616 
    1617     return len;
    1618 }
    1619 #endif
    1620 
    1621 /* Data register : 0x05 */
    1622 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
    1623 {
    1624     fdrive_t *cur_drv;
    1625     uint32_t retval = 0;
    1626     unsigned pos, len;
    1627 #ifdef VBOX
    1628     int rc;
    1629 #endif
    1630 
    1631     cur_drv = get_cur_drv(fdctrl);
    1632     fdctrl->state &= ~FD_CTRL_SLEEP;
    1633     if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {
    1634         FLOPPY_ERROR("can't read data in CMD state\n");
    1635         return 0;
    1636     }
    1637     pos = fdctrl->data_pos;
    1638     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
    1639         pos %= FD_SECTOR_LEN;
    1640         if (pos == 0) {
    1641             len = fdctrl->data_len - fdctrl->data_pos;
    1642             if (len > FD_SECTOR_LEN)
    1643                 len = FD_SECTOR_LEN;
    1644 #ifdef VBOX
    1645             cur_drv->Led.Asserted.s.fReading
    1646                 = cur_drv->Led.Actual.s.fReading = 1;
    1647 
    1648             Assert(len <= sizeof(fdctrl->fifo));
    1649             rc = cur_drv->pDrvBlock->pfnRead (
    1650                 cur_drv->pDrvBlock,
    1651                 fd_sector (cur_drv) * 512,
    1652                 fdctrl->fifo,
    1653                 len
    1654                 );
    1655 
    1656             cur_drv->Led.Actual.s.fReading = 0;
    1657 
    1658             if (RT_FAILURE (rc)) {
    1659                 AssertMsgFailed (
    1660                     ("Floppy: Failure to read sector %d. rc=%Rrc",
    1661                      fd_sector (cur_drv), rc));
    1662             }
    1663 #else
    1664             bdrv_read(cur_drv->bs, fd_sector(cur_drv),
    1665                       fdctrl->fifo, len);
    1666 #endif
    16671478        }
    16681479    }
     
    16731484         * then from status mode to command mode
    16741485         */
    1675         if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
    1676             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
     1486        if (fdctrl->msr & FD_MSR_NONDMA) {
     1487            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
    16771488        } else {
    16781489            fdctrl_reset_fifo(fdctrl);
     
    16851496}
    16861497
    1687 static void fdctrl_format_sector (fdctrl_t *fdctrl)
     1498static void fdctrl_format_sector(fdctrl_t *fdctrl)
    16881499{
    16891500    fdrive_t *cur_drv;
    16901501    uint8_t kh, kt, ks;
    1691     int did_seek;
    16921502#ifdef VBOX
    16931503    int ok = 0, rc;
    16941504#endif
    16951505
    1696     fdctrl->cur_drv = fdctrl->fifo[1] & 1;
     1506    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
    16971507    cur_drv = get_cur_drv(fdctrl);
    16981508    kt = fdctrl->fifo[6];
     
    17001510    ks = fdctrl->fifo[8];
    17011511    FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
    1702                    fdctrl->cur_drv, kh, kt, ks,
    1703                    _fd_sector(kh, kt, ks, cur_drv->last_sect));
    1704     did_seek = 0;
    1705     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
     1512                   GET_CUR_DRV(fdctrl), kh, kt, ks,
     1513                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
     1514    switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
    17061515    case 2:
    17071516        /* sect too big */
    1708         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
     1517        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
    17091518        fdctrl->fifo[3] = kt;
    17101519        fdctrl->fifo[4] = kh;
     
    17131522    case 3:
    17141523        /* track too big */
    1715         fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
     1524        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
    17161525        fdctrl->fifo[3] = kt;
    17171526        fdctrl->fifo[4] = kh;
     
    17201529    case 4:
    17211530        /* No seek enabled */
    1722         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
     1531        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
    17231532        fdctrl->fifo[3] = kt;
    17241533        fdctrl->fifo[4] = kh;
     
    17261535        return;
    17271536    case 1:
    1728         did_seek = 1;
    17291537        fdctrl->data_state |= FD_STATE_SEEK;
    17301538        break;
     
    17341542    memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
    17351543#ifdef VBOX
    1736     /* *p_fd_activity = 2; */
    17371544    if (cur_drv->pDrvBlock) {
    1738         cur_drv->Led.Asserted.s.fWriting = cur_drv->Led.Actual.s.fWriting = 1;
    1739 
    1740         rc = cur_drv->pDrvBlock->pfnWrite (
    1741             cur_drv->pDrvBlock,
    1742             fd_sector (cur_drv) * 512,
    1743             fdctrl->fifo,
    1744             1 * 512
    1745             );
    1746 
    1747         cur_drv->Led.Actual.s.fWriting = 0;
    1748 
     1545        rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
    17491546        if (RT_FAILURE (rc)) {
    1750             AssertMsgFailed (("Floppy: error formating sector %d. rc=%Rrc\n",
    1751                               fd_sector (cur_drv), rc));
    1752             fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
    1753         }
    1754         else {
     1547            FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
     1548            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
     1549        } else {
    17551550            ok = 1;
    17561551        }
     
    17601555    if (cur_drv->bs == NULL ||
    17611556        bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
    1762         FLOPPY_ERROR("formating sector %d\n", fd_sector(cur_drv));
    1763         fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
     1557        FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
     1558        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
    17641559    } else {
    17651560#endif
     
    17681563            /* Last sector done */
    17691564            if (FD_DID_SEEK(fdctrl->data_state))
    1770                 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
     1565                fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
    17711566            else
    17721567                fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
     
    17791574}
    17801575
    1781 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
     1576static void fdctrl_handle_lock(fdctrl_t *fdctrl, int direction)
     1577{
     1578    fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
     1579    fdctrl->fifo[0] = fdctrl->lock << 4;
     1580    fdctrl_set_fifo(fdctrl, 1, fdctrl->lock);
     1581}
     1582
     1583static void fdctrl_handle_dumpreg(fdctrl_t *fdctrl, int direction)
     1584{
     1585    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1586
     1587    /* Drives position */
     1588    fdctrl->fifo[0] = drv0(fdctrl)->track;
     1589    fdctrl->fifo[1] = drv1(fdctrl)->track;
     1590#if MAX_FD == 4
     1591    fdctrl->fifo[2] = drv2(fdctrl)->track;
     1592    fdctrl->fifo[3] = drv3(fdctrl)->track;
     1593#else
     1594    fdctrl->fifo[2] = 0;
     1595    fdctrl->fifo[3] = 0;
     1596#endif
     1597    /* timers */
     1598    fdctrl->fifo[4] = fdctrl->timer0;
     1599    fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
     1600    fdctrl->fifo[6] = cur_drv->last_sect;
     1601    fdctrl->fifo[7] = (fdctrl->lock << 7) |
     1602        (cur_drv->perpendicular << 2);
     1603    fdctrl->fifo[8] = fdctrl->config;
     1604    fdctrl->fifo[9] = fdctrl->precomp_trk;
     1605    fdctrl_set_fifo(fdctrl, 10, 0);
     1606}
     1607
     1608static void fdctrl_handle_version(fdctrl_t *fdctrl, int direction)
     1609{
     1610    /* Controller's version */
     1611    fdctrl->fifo[0] = fdctrl->version;
     1612    fdctrl_set_fifo(fdctrl, 1, 1);
     1613}
     1614
     1615static void fdctrl_handle_partid(fdctrl_t *fdctrl, int direction)
     1616{
     1617    fdctrl->fifo[0] = 0x41; /* Stepping 1 */
     1618    fdctrl_set_fifo(fdctrl, 1, 0);
     1619}
     1620
     1621static void fdctrl_handle_restore(fdctrl_t *fdctrl, int direction)
     1622{
     1623    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1624
     1625    /* Drives position */
     1626    drv0(fdctrl)->track = fdctrl->fifo[3];
     1627    drv1(fdctrl)->track = fdctrl->fifo[4];
     1628#if MAX_FD == 4
     1629    drv2(fdctrl)->track = fdctrl->fifo[5];
     1630    drv3(fdctrl)->track = fdctrl->fifo[6];
     1631#endif
     1632    /* timers */
     1633    fdctrl->timer0 = fdctrl->fifo[7];
     1634    fdctrl->timer1 = fdctrl->fifo[8];
     1635    cur_drv->last_sect = fdctrl->fifo[9];
     1636    fdctrl->lock = fdctrl->fifo[10] >> 7;
     1637    cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
     1638    fdctrl->config = fdctrl->fifo[11];
     1639    fdctrl->precomp_trk = fdctrl->fifo[12];
     1640    fdctrl->pwrd = fdctrl->fifo[13];
     1641    fdctrl_reset_fifo(fdctrl);
     1642}
     1643
     1644static void fdctrl_handle_save(fdctrl_t *fdctrl, int direction)
     1645{
     1646    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1647
     1648    fdctrl->fifo[0] = 0;
     1649    fdctrl->fifo[1] = 0;
     1650    /* Drives position */
     1651    fdctrl->fifo[2] = drv0(fdctrl)->track;
     1652    fdctrl->fifo[3] = drv1(fdctrl)->track;
     1653#if MAX_FD == 4
     1654    fdctrl->fifo[4] = drv2(fdctrl)->track;
     1655    fdctrl->fifo[5] = drv3(fdctrl)->track;
     1656#else
     1657    fdctrl->fifo[4] = 0;
     1658    fdctrl->fifo[5] = 0;
     1659#endif
     1660    /* timers */
     1661    fdctrl->fifo[6] = fdctrl->timer0;
     1662    fdctrl->fifo[7] = fdctrl->timer1;
     1663    fdctrl->fifo[8] = cur_drv->last_sect;
     1664    fdctrl->fifo[9] = (fdctrl->lock << 7) |
     1665        (cur_drv->perpendicular << 2);
     1666    fdctrl->fifo[10] = fdctrl->config;
     1667    fdctrl->fifo[11] = fdctrl->precomp_trk;
     1668    fdctrl->fifo[12] = fdctrl->pwrd;
     1669    fdctrl->fifo[13] = 0;
     1670    fdctrl->fifo[14] = 0;
     1671    fdctrl_set_fifo(fdctrl, 15, 1);
     1672}
     1673
     1674static void fdctrl_handle_readid(fdctrl_t *fdctrl, int direction)
     1675{
     1676    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1677
     1678    /* XXX: should set main status register to busy */
     1679    cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
     1680#ifdef VBOX
     1681    TMTimerSetMillies(fdctrl->result_timer, 1000 / 50);
     1682#else
     1683    qemu_mod_timer(fdctrl->result_timer,
     1684                   qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 50));
     1685#endif
     1686}
     1687
     1688static void fdctrl_handle_format_track(fdctrl_t *fdctrl, int direction)
    17821689{
    17831690    fdrive_t *cur_drv;
     1691
     1692    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1693    cur_drv = get_cur_drv(fdctrl);
     1694    fdctrl->data_state |= FD_STATE_FORMAT;
     1695    if (fdctrl->fifo[0] & 0x80)
     1696        fdctrl->data_state |= FD_STATE_MULTI;
     1697    else
     1698        fdctrl->data_state &= ~FD_STATE_MULTI;
     1699    fdctrl->data_state &= ~FD_STATE_SEEK;
     1700    cur_drv->bps =
     1701        fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
     1702#if 0
     1703    cur_drv->last_sect =
     1704        cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
     1705        fdctrl->fifo[3] / 2;
     1706#else
     1707    cur_drv->last_sect = fdctrl->fifo[3];
     1708#endif
     1709    /* TODO: implement format using DMA expected by the Bochs BIOS
     1710     * and Linux fdformat (read 3 bytes per sector via DMA and fill
     1711     * the sector with the specified fill byte
     1712     */
     1713    fdctrl->data_state &= ~FD_STATE_FORMAT;
     1714    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
     1715}
     1716
     1717static void fdctrl_handle_specify(fdctrl_t *fdctrl, int direction)
     1718{
     1719    fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
     1720    fdctrl->timer1 = fdctrl->fifo[2] >> 1;
     1721    if (fdctrl->fifo[2] & 1)
     1722        fdctrl->dor &= ~FD_DOR_DMAEN;
     1723    else
     1724        fdctrl->dor |= FD_DOR_DMAEN;
     1725    /* No result back */
     1726    fdctrl_reset_fifo(fdctrl);
     1727}
     1728
     1729static void fdctrl_handle_sense_drive_status(fdctrl_t *fdctrl, int direction)
     1730{
     1731    fdrive_t *cur_drv;
     1732
     1733    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1734    cur_drv = get_cur_drv(fdctrl);
     1735    cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
     1736    /* 1 Byte status back */
     1737    fdctrl->fifo[0] = (cur_drv->ro << 6) |
     1738        (cur_drv->track == 0 ? 0x10 : 0x00) |
     1739        (cur_drv->head << 2) |
     1740        GET_CUR_DRV(fdctrl) |
     1741        0x28;
     1742    fdctrl_set_fifo(fdctrl, 1, 0);
     1743}
     1744
     1745static void fdctrl_handle_recalibrate(fdctrl_t *fdctrl, int direction)
     1746{
     1747    fdrive_t *cur_drv;
     1748
     1749    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1750    cur_drv = get_cur_drv(fdctrl);
     1751    fd_recalibrate(cur_drv);
     1752    fdctrl_reset_fifo(fdctrl);
     1753    /* Raise Interrupt */
     1754    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
     1755}
     1756
     1757static void fdctrl_handle_sense_interrupt_status(fdctrl_t *fdctrl, int direction)
     1758{
     1759    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1760
     1761    if(fdctrl->reset_sensei > 0) {
     1762        fdctrl->fifo[0] =
     1763            FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
     1764        fdctrl->reset_sensei--;
     1765    } else {
     1766        /* XXX: status0 handling is broken for read/write
     1767           commands, so we do this hack. It should be suppressed
     1768           ASAP */
     1769        fdctrl->fifo[0] =
     1770            FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
     1771    }
     1772
     1773    fdctrl->fifo[1] = cur_drv->track;
     1774    fdctrl_set_fifo(fdctrl, 2, 0);
     1775    fdctrl_reset_irq(fdctrl);
     1776    fdctrl->status0 = FD_SR0_RDYCHG;
     1777}
     1778
     1779static void fdctrl_handle_seek(fdctrl_t *fdctrl, int direction)
     1780{
     1781    fdrive_t *cur_drv;
     1782
     1783    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1784    cur_drv = get_cur_drv(fdctrl);
     1785    fdctrl_reset_fifo(fdctrl);
     1786    if (cur_drv->max_track && fdctrl->fifo[2] > cur_drv->max_track) {
     1787        fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
     1788    } else {
     1789        cur_drv->track = fdctrl->fifo[2];
     1790        /* Raise Interrupt */
     1791        fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
     1792    }
     1793}
     1794
     1795static void fdctrl_handle_perpendicular_mode(fdctrl_t *fdctrl, int direction)
     1796{
     1797    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1798
     1799    if (fdctrl->fifo[1] & 0x80)
     1800        cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
     1801    /* No result back */
     1802    fdctrl_reset_fifo(fdctrl);
     1803}
     1804
     1805static void fdctrl_handle_configure(fdctrl_t *fdctrl, int direction)
     1806{
     1807    fdctrl->config = fdctrl->fifo[2];
     1808    fdctrl->precomp_trk =  fdctrl->fifo[3];
     1809    /* No result back */
     1810    fdctrl_reset_fifo(fdctrl);
     1811}
     1812
     1813static void fdctrl_handle_powerdown_mode(fdctrl_t *fdctrl, int direction)
     1814{
     1815    fdctrl->pwrd = fdctrl->fifo[1];
     1816    fdctrl->fifo[0] = fdctrl->fifo[1];
     1817    fdctrl_set_fifo(fdctrl, 1, 1);
     1818}
     1819
     1820static void fdctrl_handle_option(fdctrl_t *fdctrl, int direction)
     1821{
     1822    /* No result back */
     1823    fdctrl_reset_fifo(fdctrl);
     1824}
     1825
     1826static void fdctrl_handle_drive_specification_command(fdctrl_t *fdctrl, int direction)
     1827{
     1828    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1829
     1830    if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
     1831        /* Command parameters done */
     1832        if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
     1833            fdctrl->fifo[0] = fdctrl->fifo[1];
     1834            fdctrl->fifo[2] = 0;
     1835            fdctrl->fifo[3] = 0;
     1836            fdctrl_set_fifo(fdctrl, 4, 1);
     1837        } else {
     1838            fdctrl_reset_fifo(fdctrl);
     1839        }
     1840    } else if (fdctrl->data_len > 7) {
     1841        /* ERROR */
     1842        fdctrl->fifo[0] = 0x80 |
     1843            (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
     1844        fdctrl_set_fifo(fdctrl, 1, 1);
     1845    }
     1846}
     1847
     1848static void fdctrl_handle_relative_seek_out(fdctrl_t *fdctrl, int direction)
     1849{
     1850    fdrive_t *cur_drv;
     1851
     1852    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1853    cur_drv = get_cur_drv(fdctrl);
     1854    if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
     1855        cur_drv->track = cur_drv->max_track - 1;
     1856    } else {
     1857        cur_drv->track += fdctrl->fifo[2];
     1858    }
     1859    fdctrl_reset_fifo(fdctrl);
     1860    /* Raise Interrupt */
     1861    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
     1862}
     1863
     1864static void fdctrl_handle_relative_seek_in(fdctrl_t *fdctrl, int direction)
     1865{
     1866    fdrive_t *cur_drv;
     1867
     1868    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
     1869    cur_drv = get_cur_drv(fdctrl);
     1870    if (fdctrl->fifo[2] > cur_drv->track) {
     1871        cur_drv->track = 0;
     1872    } else {
     1873        cur_drv->track -= fdctrl->fifo[2];
     1874    }
     1875    fdctrl_reset_fifo(fdctrl);
     1876    /* Raise Interrupt */
     1877    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
     1878}
     1879
     1880static const struct {
     1881    uint8_t value;
     1882    uint8_t mask;
     1883    const char* name;
     1884    int parameters;
     1885    void (*handler)(fdctrl_t *fdctrl, int direction);
     1886    int direction;
     1887} handlers[] = {
     1888    { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ },
     1889    { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE },
     1890    { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek },
     1891    { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status },
     1892    { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate },
     1893    { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track },
     1894    { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ },
     1895    { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */
     1896    { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
     1897    { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
     1898    { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
     1899    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented },
     1900    { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
     1901    { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
     1902    { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
     1903    { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid },
     1904    { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify },
     1905    { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status },
     1906    { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode },
     1907    { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure },
     1908    { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode },
     1909    { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option },
     1910    { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command },
     1911    { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out },
     1912    { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented },
     1913    { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in },
     1914    { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock },
     1915    { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg },
     1916    { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version },
     1917    { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid },
     1918    { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */
     1919    { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */
     1920};
     1921/* Associate command to an index in the 'handlers' array */
     1922static uint8_t command_to_handler[256];
     1923
     1924static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value)
     1925{
     1926    fdrive_t *cur_drv;
     1927    int pos;
    17841928
    17851929    cur_drv = get_cur_drv(fdctrl);
    17861930    /* Reset mode */
    1787     if (fdctrl->state & FD_CTRL_RESET) {
     1931    if (!(fdctrl->dor & FD_DOR_nRESET)) {
    17881932        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
    17891933        return;
    17901934    }
    1791     fdctrl->state &= ~FD_CTRL_SLEEP;
    1792     if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) {
    1793         FLOPPY_ERROR("can't write data in status mode\n");
     1935    if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) {
     1936        FLOPPY_ERROR("controller not ready for writing\n");
    17941937        return;
    17951938    }
     1939    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
    17961940    /* Is it write command time ? */
    1797     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
     1941    if (fdctrl->msr & FD_MSR_NONDMA) {
    17981942        /* FIFO data write */
    1799         fdctrl->fifo[fdctrl->data_pos++] = value;
    1800         if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
     1943        pos = fdctrl->data_pos++;
     1944        pos %= FD_SECTOR_LEN;
     1945        fdctrl->fifo[pos] = value;
     1946        if (pos == FD_SECTOR_LEN - 1 ||
    18011947            fdctrl->data_pos == fdctrl->data_len) {
    18021948#ifdef VBOX
    1803             int rc;
    1804             /* *p_fd_activity = 2; */
    1805             cur_drv->Led.Asserted.s.fWriting
    1806                 = cur_drv->Led.Actual.s.fWriting = 1;
    1807 
    1808             rc = cur_drv->pDrvBlock->pfnWrite (
    1809                 cur_drv->pDrvBlock,
    1810                 fd_sector (cur_drv) * 512,
    1811                 fdctrl->fifo,
    1812                 FD_SECTOR_LEN
    1813                 );
    1814 
    1815             cur_drv->Led.Actual.s.fWriting = 0;
    1816 
    1817             if (RT_FAILURE (rc)) {
    1818                 AssertMsgFailed (
    1819                     ("Floppy: failed to write sector %d. rc=%Rrc\n",
    1820                      fd_sector (cur_drv), rc));
    1821             }
     1949            blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1);
    18221950#else
    18231951            bdrv_write(cur_drv->bs, fd_sector(cur_drv),
    1824                        fdctrl->fifo, FD_SECTOR_LEN);
     1952                       fdctrl->fifo, 1);
    18251953#endif
    18261954        }
     
    18281956         * then from status mode to command mode
    18291957         */
    1830         if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
    1831             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
     1958        if (fdctrl->data_pos == fdctrl->data_len)
     1959            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
    18321960        return;
    18331961    }
    18341962    if (fdctrl->data_pos == 0) {
    18351963        /* Command */
    1836         switch (value & 0x5F) {
    1837         case 0x46:
    1838             /* READ variants */
    1839             FLOPPY_DPRINTF("READ command\n");
    1840             /* 8 parameters cmd */
    1841             fdctrl->data_len = 9;
    1842             goto enqueue;
    1843         case 0x4C:
    1844             /* READ_DELETED variants */
    1845             FLOPPY_DPRINTF("READ_DELETED command\n");
    1846             /* 8 parameters cmd */
    1847             fdctrl->data_len = 9;
    1848             goto enqueue;
    1849         case 0x50:
    1850             /* SCAN_EQUAL variants */
    1851             FLOPPY_DPRINTF("SCAN_EQUAL command\n");
    1852             /* 8 parameters cmd */
    1853             fdctrl->data_len = 9;
    1854             goto enqueue;
    1855         case 0x56:
    1856             /* VERIFY variants */
    1857             FLOPPY_DPRINTF("VERIFY command\n");
    1858             /* 8 parameters cmd */
    1859             fdctrl->data_len = 9;
    1860             goto enqueue;
    1861         case 0x59:
    1862             /* SCAN_LOW_OR_EQUAL variants */
    1863             FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n");
    1864             /* 8 parameters cmd */
    1865             fdctrl->data_len = 9;
    1866             goto enqueue;
    1867         case 0x5D:
    1868             /* SCAN_HIGH_OR_EQUAL variants */
    1869             FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n");
    1870             /* 8 parameters cmd */
    1871             fdctrl->data_len = 9;
    1872             goto enqueue;
    1873         default:
    1874             break;
    1875         }
    1876         switch (value & 0x7F) {
    1877         case 0x45:
    1878             /* WRITE variants */
    1879             FLOPPY_DPRINTF("WRITE command\n");
    1880             /* 8 parameters cmd */
    1881             fdctrl->data_len = 9;
    1882             goto enqueue;
    1883         case 0x49:
    1884             /* WRITE_DELETED variants */
    1885             FLOPPY_DPRINTF("WRITE_DELETED command\n");
    1886             /* 8 parameters cmd */
    1887             fdctrl->data_len = 9;
    1888             goto enqueue;
    1889         default:
    1890             break;
    1891         }
    1892         switch (value) {
    1893         case 0x03:
    1894             /* SPECIFY */
    1895             FLOPPY_DPRINTF("SPECIFY command\n");
    1896             /* 1 parameter cmd */
    1897             fdctrl->data_len = 3;
    1898             goto enqueue;
    1899         case 0x04:
    1900             /* SENSE_DRIVE_STATUS */
    1901             FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n");
    1902             /* 1 parameter cmd */
    1903             fdctrl->data_len = 2;
    1904             goto enqueue;
    1905         case 0x07:
    1906             /* RECALIBRATE */
    1907             FLOPPY_DPRINTF("RECALIBRATE command\n");
    1908             /* 1 parameter cmd */
    1909             fdctrl->data_len = 2;
    1910             goto enqueue;
    1911         case 0x08:
    1912             /* SENSE_INTERRUPT_STATUS */
    1913             FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n",
    1914                            fdctrl->int_status);
    1915             /* No parameters cmd: returns status if no interrupt */
    1916 #if 0
    1917             fdctrl->fifo[0] =
    1918                 fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv;
    1919 #else
    1920             /* XXX: int_status handling is broken for read/write
    1921                commands, so we do this hack. It should be suppressed
    1922                ASAP */
    1923             fdctrl->fifo[0] =
    1924                 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv;
    1925 #endif
    1926             fdctrl->fifo[1] = cur_drv->track;
    1927             fdctrl_set_fifo(fdctrl, 2, 0);
    1928             fdctrl_reset_irq(fdctrl);
    1929             fdctrl->int_status = 0xC0;
    1930             return;
    1931         case 0x0E:
    1932             /* DUMPREG */
    1933             FLOPPY_DPRINTF("DUMPREG command\n");
    1934             /* Drives position */
    1935             fdctrl->fifo[0] = drv0(fdctrl)->track;
    1936             fdctrl->fifo[1] = drv1(fdctrl)->track;
    1937             fdctrl->fifo[2] = 0;
    1938             fdctrl->fifo[3] = 0;
    1939             /* timers */
    1940             fdctrl->fifo[4] = fdctrl->timer0;
    1941             fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
    1942             fdctrl->fifo[6] = cur_drv->last_sect;
    1943             fdctrl->fifo[7] = (fdctrl->lock << 7) |
    1944                     (cur_drv->perpendicular << 2);
    1945             fdctrl->fifo[8] = fdctrl->config;
    1946             fdctrl->fifo[9] = fdctrl->precomp_trk;
    1947             fdctrl_set_fifo(fdctrl, 10, 0);
    1948             return;
    1949         case 0x0F:
    1950             /* SEEK */
    1951             FLOPPY_DPRINTF("SEEK command\n");
    1952             /* 2 parameters cmd */
    1953             fdctrl->data_len = 3;
    1954             goto enqueue;
    1955         case 0x10:
    1956             /* VERSION */
    1957             FLOPPY_DPRINTF("VERSION command\n");
    1958             /* No parameters cmd */
    1959             /* Controller's version */
    1960             fdctrl->fifo[0] = fdctrl->version;
    1961             fdctrl_set_fifo(fdctrl, 1, 1);
    1962             return;
    1963         case 0x12:
    1964             /* PERPENDICULAR_MODE */
    1965             FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n");
    1966             /* 1 parameter cmd */
    1967             fdctrl->data_len = 2;
    1968             goto enqueue;
    1969         case 0x13:
    1970             /* CONFIGURE */
    1971             FLOPPY_DPRINTF("CONFIGURE command\n");
    1972             /* 3 parameters cmd */
    1973             fdctrl->data_len = 4;
    1974             goto enqueue;
    1975         case 0x14:
    1976             /* UNLOCK */
    1977             FLOPPY_DPRINTF("UNLOCK command\n");
    1978             /* No parameters cmd */
    1979             fdctrl->lock = 0;
    1980             fdctrl->fifo[0] = 0;
    1981             fdctrl_set_fifo(fdctrl, 1, 0);
    1982             return;
    1983         case 0x17:
    1984             /* POWERDOWN_MODE */
    1985             FLOPPY_DPRINTF("POWERDOWN_MODE command\n");
    1986             /* 2 parameters cmd */
    1987             fdctrl->data_len = 3;
    1988             goto enqueue;
    1989         case 0x18:
    1990             /* PART_ID */
    1991             FLOPPY_DPRINTF("PART_ID command\n");
    1992             /* No parameters cmd */
    1993             fdctrl->fifo[0] = 0x41; /* Stepping 1 */
    1994             fdctrl_set_fifo(fdctrl, 1, 0);
    1995             return;
    1996         case 0x2C:
    1997             /* SAVE */
    1998             FLOPPY_DPRINTF("SAVE command\n");
    1999             /* No parameters cmd */
    2000             fdctrl->fifo[0] = 0;
    2001             fdctrl->fifo[1] = 0;
    2002             /* Drives position */
    2003             fdctrl->fifo[2] = drv0(fdctrl)->track;
    2004             fdctrl->fifo[3] = drv1(fdctrl)->track;
    2005             fdctrl->fifo[4] = 0;
    2006             fdctrl->fifo[5] = 0;
    2007             /* timers */
    2008             fdctrl->fifo[6] = fdctrl->timer0;
    2009             fdctrl->fifo[7] = fdctrl->timer1;
    2010             fdctrl->fifo[8] = cur_drv->last_sect;
    2011             fdctrl->fifo[9] = (fdctrl->lock << 7) |
    2012                     (cur_drv->perpendicular << 2);
    2013             fdctrl->fifo[10] = fdctrl->config;
    2014             fdctrl->fifo[11] = fdctrl->precomp_trk;
    2015             fdctrl->fifo[12] = fdctrl->pwrd;
    2016             fdctrl->fifo[13] = 0;
    2017             fdctrl->fifo[14] = 0;
    2018             fdctrl_set_fifo(fdctrl, 15, 1);
    2019             return;
    2020         case 0x33:
    2021             /* OPTION */
    2022             FLOPPY_DPRINTF("OPTION command\n");
    2023             /* 1 parameter cmd */
    2024             fdctrl->data_len = 2;
    2025             goto enqueue;
    2026         case 0x42:
    2027             /* READ_TRACK */
    2028             FLOPPY_DPRINTF("READ_TRACK command\n");
    2029             /* 8 parameters cmd */
    2030             fdctrl->data_len = 9;
    2031             goto enqueue;
    2032         case 0x4A:
    2033             /* READ_ID */
    2034             FLOPPY_DPRINTF("READ_ID command\n");
    2035             /* 1 parameter cmd */
    2036             fdctrl->data_len = 2;
    2037             goto enqueue;
    2038         case 0x4C:
    2039             /* RESTORE */
    2040             FLOPPY_DPRINTF("RESTORE command\n");
    2041             /* 17 parameters cmd */
    2042             fdctrl->data_len = 18;
    2043             goto enqueue;
    2044         case 0x4D:
    2045             /* FORMAT_TRACK */
    2046             FLOPPY_DPRINTF("FORMAT_TRACK command\n");
    2047             /* 5 parameters cmd */
    2048             fdctrl->data_len = 6;
    2049             goto enqueue;
    2050         case 0x8E:
    2051             /* DRIVE_SPECIFICATION_COMMAND */
    2052             FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n");
    2053             /* 5 parameters cmd */
    2054             fdctrl->data_len = 6;
    2055             goto enqueue;
    2056         case 0x8F:
    2057             /* RELATIVE_SEEK_OUT */
    2058             FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n");
    2059             /* 2 parameters cmd */
    2060             fdctrl->data_len = 3;
    2061             goto enqueue;
    2062         case 0x94:
    2063             /* LOCK */
    2064             FLOPPY_DPRINTF("LOCK command\n");
    2065             /* No parameters cmd */
    2066             fdctrl->lock = 1;
    2067             fdctrl->fifo[0] = 0x10;
    2068             fdctrl_set_fifo(fdctrl, 1, 1);
    2069             return;
    2070         case 0xCD:
    2071             /* FORMAT_AND_WRITE */
    2072             FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n");
    2073             /* 10 parameters cmd */
    2074             fdctrl->data_len = 11;
    2075             goto enqueue;
    2076         case 0xCF:
    2077             /* RELATIVE_SEEK_IN */
    2078             FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n");
    2079             /* 2 parameters cmd */
    2080             fdctrl->data_len = 3;
    2081             goto enqueue;
    2082         default:
    2083             /* Unknown command */
    2084             FLOPPY_ERROR("unknown command: 0x%02x\n", value);
    2085             fdctrl_unimplemented(fdctrl);
    2086             return;
    2087         }
    2088     }
    2089 enqueue:
     1964        pos = command_to_handler[value & 0xff];
     1965        FLOPPY_DPRINTF("%s command\n", handlers[pos].name);
     1966        fdctrl->data_len = handlers[pos].parameters + 1;
     1967    }
     1968
    20901969    FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
    2091     fdctrl->fifo[fdctrl->data_pos] = value;
    2092     if (++fdctrl->data_pos == fdctrl->data_len) {
     1970    fdctrl->fifo[fdctrl->data_pos++] = value;
     1971    if (fdctrl->data_pos == fdctrl->data_len) {
    20931972        /* We now have all parameters
    20941973         * and will be able to treat the command
     
    20981977            return;
    20991978        }
    2100         switch (fdctrl->fifo[0] & 0x1F) {
    2101         case 0x06:
    2102         {
    2103             /* READ variants */
    2104             FLOPPY_DPRINTF("treat READ command\n");
    2105             fdctrl_start_transfer(fdctrl, FD_DIR_READ);
    2106             return;
    2107         }
    2108         case 0x0C:
    2109             /* READ_DELETED variants */
    2110 /* //            FLOPPY_DPRINTF("treat READ_DELETED command\n"); */
    2111             FLOPPY_ERROR("treat READ_DELETED command\n");
    2112             fdctrl_start_transfer_del(fdctrl, FD_DIR_READ);
    2113             return;
    2114         case 0x16:
    2115             /* VERIFY variants */
    2116 /* //            FLOPPY_DPRINTF("treat VERIFY command\n"); */
    2117             FLOPPY_ERROR("treat VERIFY command\n");
    2118             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
    2119             return;
    2120         case 0x10:
    2121             /* SCAN_EQUAL variants */
    2122 /* //            FLOPPY_DPRINTF("treat SCAN_EQUAL command\n"); */
    2123             FLOPPY_ERROR("treat SCAN_EQUAL command\n");
    2124             fdctrl_start_transfer(fdctrl, FD_DIR_SCANE);
    2125             return;
    2126         case 0x19:
    2127             /* SCAN_LOW_OR_EQUAL variants */
    2128 /* //            FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n"); */
    2129             FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n");
    2130             fdctrl_start_transfer(fdctrl, FD_DIR_SCANL);
    2131             return;
    2132         case 0x1D:
    2133             /* SCAN_HIGH_OR_EQUAL variants */
    2134 /* //            FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n"); */
    2135             FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n");
    2136             fdctrl_start_transfer(fdctrl, FD_DIR_SCANH);
    2137             return;
    2138         default:
    2139             break;
    2140         }
    2141         switch (fdctrl->fifo[0] & 0x3F) {
    2142         case 0x05:
    2143             /* WRITE variants */
    2144             FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]);
    2145             fdctrl_start_transfer(fdctrl, FD_DIR_WRITE);
    2146             return;
    2147         case 0x09:
    2148             /* WRITE_DELETED variants */
    2149 /* //            FLOPPY_DPRINTF("treat WRITE_DELETED command\n"); */
    2150             FLOPPY_ERROR("treat WRITE_DELETED command\n");
    2151             fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE);
    2152             return;
    2153         default:
    2154             break;
    2155         }
    2156         switch (fdctrl->fifo[0]) {
    2157         case 0x03:
    2158             /* SPECIFY */
    2159             FLOPPY_DPRINTF("treat SPECIFY command\n");
    2160             fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
    2161             fdctrl->timer1 = fdctrl->fifo[2] >> 1;
    2162             fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
    2163             /* No result back */
    2164             fdctrl_reset_fifo(fdctrl);
    2165             break;
    2166         case 0x04:
    2167             /* SENSE_DRIVE_STATUS */
    2168             FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n");
    2169             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2170             cur_drv = get_cur_drv(fdctrl);
    2171             cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
    2172             /* 1 Byte status back */
    2173             fdctrl->fifo[0] = (cur_drv->ro << 6) |
    2174                 (cur_drv->track == 0 ? 0x10 : 0x00) |
    2175                 (cur_drv->head << 2) |
    2176                 fdctrl->cur_drv |
    2177                 0x28;
    2178             fdctrl_set_fifo(fdctrl, 1, 0);
    2179             break;
    2180         case 0x07:
    2181             /* RECALIBRATE */
    2182             FLOPPY_DPRINTF("treat RECALIBRATE command\n");
    2183             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2184             cur_drv = get_cur_drv(fdctrl);
    2185             fd_recalibrate(cur_drv);
    2186             fdctrl_reset_fifo(fdctrl);
    2187             /* Raise Interrupt */
    2188             fdctrl_raise_irq(fdctrl, 0x20);
    2189             break;
    2190         case 0x0F:
    2191             /* SEEK */
    2192             FLOPPY_DPRINTF("treat SEEK command\n");
    2193             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2194             cur_drv = get_cur_drv(fdctrl);
    2195             fd_start(cur_drv);
    2196             if (fdctrl->fifo[2] <= cur_drv->track)
    2197                 cur_drv->dir = 1;
    2198             else
    2199                 cur_drv->dir = 0;
    2200             fdctrl_reset_fifo(fdctrl);
    2201 #ifndef VBOX
    2202             if (fdctrl->fifo[2] > cur_drv->max_track) {
    2203 #else
    2204             if (    fdctrl->fifo[2] > cur_drv->max_track
    2205                 &&  cur_drv->fMediaPresent) {
    2206 #endif
    2207                 fdctrl_raise_irq(fdctrl, 0x60);
    2208             } else {
    2209                 cur_drv->track = fdctrl->fifo[2];
    2210                 /* Raise Interrupt */
    2211                 fdctrl_raise_irq(fdctrl, 0x20);
    2212             }
    2213             break;
    2214         case 0x12:
    2215             /* PERPENDICULAR_MODE */
    2216             FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n");
    2217             if (fdctrl->fifo[1] & 0x80)
    2218                 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
    2219             /* No result back */
    2220             fdctrl_reset_fifo(fdctrl);
    2221             break;
    2222         case 0x13:
    2223             /* CONFIGURE */
    2224             FLOPPY_DPRINTF("treat CONFIGURE command\n");
    2225             fdctrl->config = fdctrl->fifo[2];
    2226             fdctrl->precomp_trk =  fdctrl->fifo[3];
    2227             /* No result back */
    2228             fdctrl_reset_fifo(fdctrl);
    2229             break;
    2230         case 0x17:
    2231             /* POWERDOWN_MODE */
    2232             FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n");
    2233             fdctrl->pwrd = fdctrl->fifo[1];
    2234             fdctrl->fifo[0] = fdctrl->fifo[1];
    2235             fdctrl_set_fifo(fdctrl, 1, 1);
    2236             break;
    2237         case 0x33:
    2238             /* OPTION */
    2239             FLOPPY_DPRINTF("treat OPTION command\n");
    2240             /* No result back */
    2241             fdctrl_reset_fifo(fdctrl);
    2242             break;
    2243         case 0x42:
    2244             /* READ_TRACK */
    2245 /* //            FLOPPY_DPRINTF("treat READ_TRACK command\n"); */
    2246             FLOPPY_ERROR("treat READ_TRACK command\n");
    2247             fdctrl_start_transfer(fdctrl, FD_DIR_READ);
    2248             break;
    2249         case 0x4A:
    2250                 /* READ_ID */
    2251             FLOPPY_DPRINTF("treat READ_ID command\n");
    2252             /* XXX: should set main status register to busy */
    2253             cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
    2254 #ifdef VBOX
    2255             TMTimerSetMillies(fdctrl->result_timer, 1000 / 50);
    2256 #else
    2257             qemu_mod_timer(fdctrl->result_timer,
    2258                            qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
    2259 #endif
    2260             break;
    2261         case 0x4C:
    2262             /* RESTORE */
    2263             FLOPPY_DPRINTF("treat RESTORE command\n");
    2264             /* Drives position */
    2265             drv0(fdctrl)->track = fdctrl->fifo[3];
    2266             drv1(fdctrl)->track = fdctrl->fifo[4];
    2267             /* timers */
    2268             fdctrl->timer0 = fdctrl->fifo[7];
    2269             fdctrl->timer1 = fdctrl->fifo[8];
    2270             cur_drv->last_sect = fdctrl->fifo[9];
    2271             fdctrl->lock = fdctrl->fifo[10] >> 7;
    2272             cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
    2273             fdctrl->config = fdctrl->fifo[11];
    2274             fdctrl->precomp_trk = fdctrl->fifo[12];
    2275             fdctrl->pwrd = fdctrl->fifo[13];
    2276             fdctrl_reset_fifo(fdctrl);
    2277             break;
    2278         case 0x4D:
    2279             /* FORMAT_TRACK */
    2280             FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
    2281             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2282             cur_drv = get_cur_drv(fdctrl);
    2283             fdctrl->data_state |= FD_STATE_FORMAT;
    2284             if (fdctrl->fifo[0] & 0x80)
    2285                 fdctrl->data_state |= FD_STATE_MULTI;
    2286             else
    2287                 fdctrl->data_state &= ~FD_STATE_MULTI;
    2288             fdctrl->data_state &= ~FD_STATE_SEEK;
    2289             cur_drv->bps =
    2290                 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
    2291 #if 0
    2292             cur_drv->last_sect =
    2293                 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
    2294                 fdctrl->fifo[3] / 2;
    2295 #else
    2296             cur_drv->last_sect = fdctrl->fifo[3];
    2297 #endif
    2298             /* Bochs BIOS is buggy and don't send format information
    2299              * for each sector. So, pretend all's done right now...
    2300              */
    2301             fdctrl->data_state &= ~FD_STATE_FORMAT;
    2302             fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
    2303             break;
    2304         case 0x8E:
    2305             /* DRIVE_SPECIFICATION_COMMAND */
    2306             FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n");
    2307             if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
    2308                 /* Command parameters done */
    2309                 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
    2310                     fdctrl->fifo[0] = fdctrl->fifo[1];
    2311                     fdctrl->fifo[2] = 0;
    2312                     fdctrl->fifo[3] = 0;
    2313                     fdctrl_set_fifo(fdctrl, 4, 1);
    2314                 } else {
    2315                     fdctrl_reset_fifo(fdctrl);
    2316                 }
    2317             } else if (fdctrl->data_len > 7) {
    2318                 /* ERROR */
    2319                 fdctrl->fifo[0] = 0x80 |
    2320                     (cur_drv->head << 2) | fdctrl->cur_drv;
    2321                 fdctrl_set_fifo(fdctrl, 1, 1);
    2322             }
    2323             break;
    2324         case 0x8F:
    2325             /* RELATIVE_SEEK_OUT */
    2326             FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n");
    2327             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2328             cur_drv = get_cur_drv(fdctrl);
    2329             fd_start(cur_drv);
    2330                 cur_drv->dir = 0;
    2331             if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
    2332                 cur_drv->track = cur_drv->max_track - 1;
    2333             } else {
    2334                 cur_drv->track += fdctrl->fifo[2];
    2335             }
    2336             fdctrl_reset_fifo(fdctrl);
    2337             fdctrl_raise_irq(fdctrl, 0x20);
    2338             break;
    2339         case 0xCD:
    2340             /* FORMAT_AND_WRITE */
    2341 /* //                FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n"); */
    2342             FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n");
    2343             fdctrl_unimplemented(fdctrl);
    2344             break;
    2345         case 0xCF:
    2346                 /* RELATIVE_SEEK_IN */
    2347             FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n");
    2348             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
    2349             cur_drv = get_cur_drv(fdctrl);
    2350             fd_start(cur_drv);
    2351                 cur_drv->dir = 1;
    2352             if (fdctrl->fifo[2] > cur_drv->track) {
    2353                 cur_drv->track = 0;
    2354             } else {
    2355                 cur_drv->track -= fdctrl->fifo[2];
    2356             }
    2357             fdctrl_reset_fifo(fdctrl);
    2358             /* Raise Interrupt */
    2359             fdctrl_raise_irq(fdctrl, 0x20);
    2360             break;
    2361         }
     1979
     1980        pos = command_to_handler[fdctrl->fifo[0] & 0xff];
     1981        FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name);
     1982        (*handlers[pos].handler)(fdctrl, handlers[pos].direction);
    23621983    }
    23631984}
     
    23661987{
    23671988    fdctrl_t *fdctrl = opaque;
     1989    fdrive_t *cur_drv = get_cur_drv(fdctrl);
     1990
     1991    /* Pretend we are spinning.
     1992     * This is needed for Coherent, which uses READ ID to check for
     1993     * sector interleaving.
     1994     */
     1995    if (cur_drv->last_sect != 0) {
     1996        cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
     1997    }
    23681998    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
    23691999}
    2370 
    23712000
    23722001#ifdef VBOX
     
    23842013{
    23852014    if (cb == 1) {
    2386         fdctrl_write (pvUser, Port, u32);
     2015        fdctrl_write (pvUser, Port & 7, u32);
    23872016    }
    23882017    else {
     
    23992028{
    24002029    if (cb == 1) {
    2401         *pu32 = fdctrl_read (pvUser, Port);
     2030        *pu32 = fdctrl_read (pvUser, Port & 7);
    24022031        return VINF_SUCCESS;
    24032032    }
     
    24132042    unsigned int i;
    24142043
    2415     qemu_put_8s (f, &s->version);
    2416     qemu_put_8s (f, &s->irq_lvl);
    2417     qemu_put_8s (f, &s->dma_chann);
    2418     qemu_put_be32s (f, &s->io_base);
    2419     qemu_put_8s (f, &s->state);
    2420     qemu_put_8s (f, &s->dma_en);
    2421     qemu_put_8s (f, &s->cur_drv);
    2422     qemu_put_8s (f, &s->bootsel);
    2423     qemu_put_buffer (f, s->fifo, FD_SECTOR_LEN);
    2424     qemu_put_be32s (f, &s->data_pos);
    2425     qemu_put_be32s (f, &s->data_len);
    2426     qemu_put_8s (f, &s->data_state);
    2427     qemu_put_8s (f, &s->data_dir);
    2428     qemu_put_8s (f, &s->int_status);
    2429     qemu_put_8s (f, &s->eot);
    2430     qemu_put_8s (f, &s->timer0);
    2431     qemu_put_8s (f, &s->timer1);
    2432     qemu_put_8s (f, &s->precomp_trk);
    2433     qemu_put_8s (f, &s->config);
    2434     qemu_put_8s (f, &s->lock);
    2435     qemu_put_8s (f, &s->pwrd);
    2436 
    2437     for (i = 0; i < sizeof (s->drives) / sizeof (s->drives[0]); ++i) {
     2044    /* Save the FDC I/O registers... */
     2045    SSMR3PutU8(pSSMHandle, s->sra);
     2046    SSMR3PutU8(pSSMHandle, s->srb);
     2047    SSMR3PutU8(pSSMHandle, s->dor);
     2048    SSMR3PutU8(pSSMHandle, s->tdr);
     2049    SSMR3PutU8(pSSMHandle, s->dsr);
     2050    SSMR3PutU8(pSSMHandle, s->msr);
     2051    /* ...the status registers... */
     2052    SSMR3PutU8(pSSMHandle, s->status0);
     2053    SSMR3PutU8(pSSMHandle, s->status1);
     2054    SSMR3PutU8(pSSMHandle, s->status2);
     2055    /* ...the command FIFO... */
     2056    SSMR3PutU32(pSSMHandle, sizeof(s->fifo));
     2057    SSMR3PutMem(pSSMHandle, &s->fifo, sizeof(s->fifo));
     2058    SSMR3PutU32(pSSMHandle, s->data_pos);
     2059    SSMR3PutU32(pSSMHandle, s->data_len);
     2060    SSMR3PutU8(pSSMHandle, s->data_state);
     2061    SSMR3PutU8(pSSMHandle, s->data_dir);
     2062    /* ...and miscellaneous internal FDC state. */
     2063    SSMR3PutU8(pSSMHandle, s->reset_sensei);
     2064    SSMR3PutU8(pSSMHandle, s->eot);
     2065    SSMR3PutU8(pSSMHandle, s->timer0);
     2066    SSMR3PutU8(pSSMHandle, s->timer1);
     2067    SSMR3PutU8(pSSMHandle, s->precomp_trk);
     2068    SSMR3PutU8(pSSMHandle, s->config);
     2069    SSMR3PutU8(pSSMHandle, s->lock);
     2070    SSMR3PutU8(pSSMHandle, s->pwrd);
     2071    SSMR3PutU8(pSSMHandle, s->version);
     2072
     2073    /* Save the number of drives and per-drive state. Note that the media
     2074     * states will be updated in fd_revalidate() and need not be saved.
     2075     */
     2076    SSMR3PutU8(pSSMHandle, s->num_floppies);
     2077    Assert(RT_ELEMENTS(s->drives) == s->num_floppies);
     2078    for (i = 0; i < s->num_floppies; ++i) {
    24382079        fdrive_t *d = &s->drives[i];
    24392080
    2440         SSMR3PutMem (pSSMHandle, &d->Led, sizeof (d->Led));
    2441         qemu_put_be32s (f, &d->drive);
    2442         qemu_put_be32s (f, &d->drflags);
    2443         qemu_put_8s (f, &d->perpendicular);
    2444         qemu_put_8s (f, &d->head);
    2445         qemu_put_8s (f, &d->track);
    2446         qemu_put_8s (f, &d->sect);
    2447         qemu_put_8s (f, &d->dir);
    2448         qemu_put_8s (f, &d->rw);
    2449         qemu_put_be32s (f, &d->flags);
    2450         qemu_put_8s (f, &d->last_sect);
    2451         qemu_put_8s (f, &d->max_track);
    2452         qemu_put_be16s (f, &d->bps);
    2453         qemu_put_8s (f, &d->ro);
     2081        SSMR3PutMem(pSSMHandle, &d->Led, sizeof(d->Led));
     2082        SSMR3PutU32(pSSMHandle, d->drive);
     2083        SSMR3PutU8(pSSMHandle, d->dsk_chg);
     2084        SSMR3PutU8(pSSMHandle, d->perpendicular);
     2085        SSMR3PutU8(pSSMHandle, d->head);
     2086        SSMR3PutU8(pSSMHandle, d->track);
     2087        SSMR3PutU8(pSSMHandle, d->sect);
    24542088    }
    24552089    return TMR3TimerSave (s->result_timer, pSSMHandle);
     
    24642098    QEMUFile *f = pSSMHandle;
    24652099    unsigned int i;
    2466 
    2467     AssertMsgReturn(uVersion == 1, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
     2100    uint32_t val32;
     2101    uint8_t val8;
     2102
     2103    if (uVersion > FDC_SAVESTATE_CURRENT)
     2104        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    24682105    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    24692106
    2470     qemu_get_8s (f, &s->version);
    2471     qemu_get_8s (f, &s->irq_lvl);
    2472     qemu_get_8s (f, &s->dma_chann);
    2473     qemu_get_be32s (f, &s->io_base);
    2474     qemu_get_8s (f, &s->state);
    2475     qemu_get_8s (f, &s->dma_en);
    2476     qemu_get_8s (f, &s->cur_drv);
    2477     qemu_get_8s (f, &s->bootsel);
    2478     qemu_get_buffer (f, s->fifo, FD_SECTOR_LEN);
    2479     qemu_get_be32s (f, &s->data_pos);
    2480     qemu_get_be32s (f, &s->data_len);
    2481     qemu_get_8s (f, &s->data_state);
    2482     qemu_get_8s (f, &s->data_dir);
    2483     qemu_get_8s (f, &s->int_status);
    2484     qemu_get_8s (f, &s->eot);
    2485     qemu_get_8s (f, &s->timer0);
    2486     qemu_get_8s (f, &s->timer1);
    2487     qemu_get_8s (f, &s->precomp_trk);
    2488     qemu_get_8s (f, &s->config);
    2489     qemu_get_8s (f, &s->lock);
    2490     qemu_get_8s (f, &s->pwrd);
    2491 
    2492     for (i = 0; i < sizeof (s->drives) / sizeof (s->drives[0]); ++i) {
    2493         fdrive_t *d = &s->drives[i];
    2494 
    2495         SSMR3GetMem (pSSMHandle, &d->Led, sizeof (d->Led));
    2496         qemu_get_be32s (f, &d->drive);
    2497         qemu_get_be32s (f, &d->drflags);
    2498         qemu_get_8s (f, &d->perpendicular);
    2499         qemu_get_8s (f, &d->head);
    2500         qemu_get_8s (f, &d->track);
    2501         qemu_get_8s (f, &d->sect);
    2502         qemu_get_8s (f, &d->dir);
    2503         qemu_get_8s (f, &d->rw);
    2504         qemu_get_be32s (f, &d->flags);
    2505         qemu_get_8s (f, &d->last_sect);
    2506         qemu_get_8s (f, &d->max_track);
    2507         qemu_get_be16s (f, &d->bps);
    2508         qemu_get_8s (f, &d->ro);
     2107    /* The old saved state was significantly different. However, we can get
     2108     * back most of the controller state and fix the rest by pretending the
     2109     * disk in the drive (if any) has been replaced. At any rate there should
     2110     * be no difficulty unless the state was saved during a floppy operation.
     2111     */
     2112    if (uVersion == FDC_SAVESTATE_OLD)
     2113    {
     2114        /* First verify a few assumptions. */
     2115        AssertMsgReturn(sizeof(s->fifo) == FD_SECTOR_LEN,
     2116                        ("The size of FIFO in saved state doesn't match!\n"),
     2117                        VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2118        AssertMsgReturn(RT_ELEMENTS(s->drives) == 2,
     2119                        ("The number of drives in old saved state doesn't match!\n"),
     2120                        VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2121        /* Now load the old state. */
     2122        SSMR3GetU8(pSSMHandle, &s->version);
     2123        /* Toss IRQ level, DMA channel, I/O base, and state. */
     2124        SSMR3GetU8(pSSMHandle, &val8);
     2125        SSMR3GetU8(pSSMHandle, &val8);
     2126        SSMR3GetU32(pSSMHandle, &val32);
     2127        SSMR3GetU8(pSSMHandle, &val8);
     2128        /* Translate dma_en. */
     2129        SSMR3GetU8(pSSMHandle, &val8);
     2130        if (val8)
     2131            s->dor |= FD_DOR_DMAEN;
     2132        SSMR3GetU8(pSSMHandle, &s->cur_drv);
     2133        /* Translate bootsel. */
     2134        SSMR3GetU8(pSSMHandle, &val8);
     2135        s->tdr |= val8 << 2;
     2136        SSMR3GetMem(pSSMHandle, &s->fifo, FD_SECTOR_LEN);
     2137        SSMR3GetU32(pSSMHandle, &s->data_pos);
     2138        SSMR3GetU32(pSSMHandle, &s->data_len);
     2139        SSMR3GetU8(pSSMHandle, &s->data_state);
     2140        SSMR3GetU8(pSSMHandle, &s->data_dir);
     2141        SSMR3GetU8(pSSMHandle, &s->status0);
     2142        SSMR3GetU8(pSSMHandle, &s->eot);
     2143        SSMR3GetU8(pSSMHandle, &s->timer0);
     2144        SSMR3GetU8(pSSMHandle, &s->timer1);
     2145        SSMR3GetU8(pSSMHandle, &s->precomp_trk);
     2146        SSMR3GetU8(pSSMHandle, &s->config);
     2147        SSMR3GetU8(pSSMHandle, &s->lock);
     2148        SSMR3GetU8(pSSMHandle, &s->pwrd);
     2149
     2150        for (i = 0; i < 2; ++i) {
     2151            fdrive_t *d = &s->drives[i];
     2152
     2153            SSMR3GetMem (pSSMHandle, &d->Led, sizeof (d->Led));
     2154            SSMR3GetU32(pSSMHandle, &val32);
     2155            d->drive = val32;
     2156            SSMR3GetU32(pSSMHandle, &val32);    /* Toss drflags */
     2157            SSMR3GetU8(pSSMHandle, &d->perpendicular);
     2158            SSMR3GetU8(pSSMHandle, &d->head);
     2159            SSMR3GetU8(pSSMHandle, &d->track);
     2160            SSMR3GetU8(pSSMHandle, &d->sect);
     2161            SSMR3GetU8(pSSMHandle, &val8);      /* Toss dir, rw */
     2162            SSMR3GetU8(pSSMHandle, &val8);
     2163            SSMR3GetU32(pSSMHandle, &val32);
     2164            d->flags = val32;
     2165            SSMR3GetU8(pSSMHandle, &d->last_sect);
     2166            SSMR3GetU8(pSSMHandle, &d->max_track);
     2167            SSMR3GetU16(pSSMHandle, &d->bps);
     2168            SSMR3GetU8(pSSMHandle, &d->ro);
     2169        }
     2170    }
     2171    else    /* New state - straightforward. */
     2172    {       
     2173        Assert(uVersion == FDC_SAVESTATE_CURRENT);
     2174        /* Load the FDC I/O registers... */
     2175        SSMR3GetU8(pSSMHandle, &s->sra);
     2176        SSMR3GetU8(pSSMHandle, &s->srb);
     2177        SSMR3GetU8(pSSMHandle, &s->dor);
     2178        SSMR3GetU8(pSSMHandle, &s->tdr);
     2179        SSMR3GetU8(pSSMHandle, &s->dsr);
     2180        SSMR3GetU8(pSSMHandle, &s->msr);
     2181        /* ...the status registers... */
     2182        SSMR3GetU8(pSSMHandle, &s->status0);
     2183        SSMR3GetU8(pSSMHandle, &s->status1);
     2184        SSMR3GetU8(pSSMHandle, &s->status2);
     2185        /* ...the command FIFO, if the size matches... */
     2186        SSMR3GetU32(pSSMHandle, &val32);
     2187        AssertMsgReturn(sizeof(s->fifo) == val32,
     2188                        ("The size of FIFO in saved state doesn't match!\n"),
     2189                        VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2190        SSMR3GetMem(pSSMHandle, &s->fifo, sizeof(s->fifo));
     2191        SSMR3GetU32(pSSMHandle, &s->data_pos);
     2192        SSMR3GetU32(pSSMHandle, &s->data_len);
     2193        SSMR3GetU8(pSSMHandle, &s->data_state);
     2194        SSMR3GetU8(pSSMHandle, &s->data_dir);
     2195        /* ...and miscellaneous internal FDC state. */
     2196        SSMR3GetU8(pSSMHandle, &s->reset_sensei);
     2197        SSMR3GetU8(pSSMHandle, &s->eot);
     2198        SSMR3GetU8(pSSMHandle, &s->timer0);
     2199        SSMR3GetU8(pSSMHandle, &s->timer1);
     2200        SSMR3GetU8(pSSMHandle, &s->precomp_trk);
     2201        SSMR3GetU8(pSSMHandle, &s->config);
     2202        SSMR3GetU8(pSSMHandle, &s->lock);
     2203        SSMR3GetU8(pSSMHandle, &s->pwrd);
     2204        SSMR3GetU8(pSSMHandle, &s->version);
     2205
     2206        /* Validate the number of drives. */
     2207        SSMR3GetU8(pSSMHandle, &s->num_floppies);
     2208        AssertMsgReturn(RT_ELEMENTS(s->drives) == s->num_floppies,
     2209                        ("The number of drives in saved state doesn't match!\n"),
     2210                        VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2211
     2212        /* Load the per-drive state. */
     2213        for (i = 0; i < s->num_floppies; ++i) {
     2214            fdrive_t *d = &s->drives[i];
     2215
     2216            SSMR3GetMem(pSSMHandle, &d->Led, sizeof(d->Led));
     2217            SSMR3GetU32(pSSMHandle, &val32);
     2218            d->drive = val32;
     2219            SSMR3GetU8(pSSMHandle, &d->dsk_chg);
     2220            SSMR3GetU8(pSSMHandle, &d->perpendicular);
     2221            SSMR3GetU8(pSSMHandle, &d->head);
     2222            SSMR3GetU8(pSSMHandle, &d->track);
     2223            SSMR3GetU8(pSSMHandle, &d->sect);
     2224        }
    25092225    }
    25102226    return TMR3TimerLoad (s->result_timer, pSSMHandle);
     
    25912307                drv->pDrvMount = PDMIBASE_QUERY_INTERFACE(drv->pDrvBase, PDMIMOUNT);
    25922308                if (drv->pDrvMount) {
    2593                     /*
    2594                      * Init the state.
    2595                      */
    2596                     drv->drive = FDRIVE_DRV_NONE;
    2597                     drv->drflags = 0;
    2598                     drv->perpendicular = 0;
    2599                     /* Disk */
    2600                     drv->last_sect = 0;
    2601                     drv->max_track = 0;
    2602                     drv->fMediaPresent = false;
     2309                    fd_init(drv);
    26032310                } else {
    26042311                    AssertMsgFailed (("Configuration error: LUN#%d without mountable interface!\n", drv->iLUN));
     
    27442451
    27452452    fdctrl_reset(fdctrl, 0);
    2746     fdctrl->state = FD_CTRL_ACTIVE;
    27472453
    27482454    for (i = 0; i < RT_ELEMENTS(fdctrl->drives); i++) {
     
    27612467    int            rc;
    27622468    fdctrl_t       *fdctrl = PDMINS_2_DATA(pDevIns, fdctrl_t*);
    2763     unsigned       i;
     2469    unsigned       i, j;
     2470    int            ii;
    27642471    bool           mem_mapped;
    27652472    uint16_t       io_base;
     
    28202527    fdctrl->dma_chann = dma_chann;
    28212528    fdctrl->io_base   = io_base;
    2822     fdctrl->config    = 0x60;   /* Implicit seek, polling & FIFO enabled */
     2529    fdctrl->config    = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
     2530    fdctrl->num_floppies = MAX_FD;
     2531
     2532    /* Fill 'command_to_handler' lookup table */
     2533    for (ii = RT_ELEMENTS(handlers) - 1; ii >= 0; ii--) {
     2534        for (j = 0; j < sizeof(command_to_handler); j++) {
     2535            if ((j & handlers[ii].mask) == handlers[ii].value) {
     2536                command_to_handler[j] = ii;
     2537            }
     2538        }
     2539    }
    28232540
    28242541    fdctrl->IBaseStatus.pfnQueryInterface = fdcStatusQueryInterface;
     
    28492566     */
    28502567    if (fdctrl->dma_chann != 0xff) {
    2851         fdctrl->dma_en = 1;
    28522568        rc = PDMDevHlpDMARegister (pDevIns, dma_chann, &fdctrl_transfer_handler, fdctrl);
    28532569        if (RT_FAILURE (rc))
    28542570            return rc;
    2855     } else
    2856         fdctrl->dma_en = 0;
     2571    }
    28572572
    28582573    /*
     
    28822597     * Register the saved state data unit.
    28832598     */
    2884     rc = PDMDevHlpSSMRegister (pDevIns, 1 /*uVersion*/, sizeof(*fdctrl), fdcSaveExec, fdcLoadExec);
     2599    rc = PDMDevHlpSSMRegister (pDevIns, FDC_SAVESTATE_CURRENT, sizeof(*fdctrl), fdcSaveExec, fdcLoadExec);
    28852600    if (RT_FAILURE(rc))
    28862601        return rc;
     
    29122627
    29132628    fdctrl_reset(fdctrl, 0);
    2914     fdctrl->state = FD_CTRL_ACTIVE;
    29152629
    29162630    for (i = 0; i < RT_ELEMENTS(fdctrl->drives); i++)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette