VirtualBox

Changeset 427 in vbox for trunk/src


Ignore:
Timestamp:
Jan 30, 2007 9:39:09 AM (18 years ago)
Author:
vboxsync
Message:

Suspend (and later redo) I/O operations and EMT if the VDI layer reports
disk full condition. Provide a warning message in this case.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r332 r427  
    7777 * The SSM saved state version.
    7878 */
    79 #define ATA_SAVED_STATE_VERSION 14
     79#define ATA_SAVED_STATE_VERSION 15
    8080
    8181/** The maximum number of release log entries per device. */
     
    146146    /** Elementary ATA/ATAPI transfer size, shared PIO/DMA. */
    147147    uint32_t cbElementaryTransfer;
     148    /** Current read/write buffer position, shared PIO/DMA. */
     149    uint32_t iIOBufferCur;
    148150    /** First element beyond end of valid buffer content, shared PIO/DMA. */
    149151    uint32_t iIOBufferEnd;
    150152
    151     /** ATA/ATAPI current PIO read/write buffer position. Not shared with DMA for safety reasons. */
    152     uint32_t iIOBufferPIO;
    153153    /** ATA/ATAPI current PIO read/write transfer position. Not shared with DMA for safety reasons. */
    154154    uint32_t iIOBufferPIODataStart;
     
    295295    bool        fChainedTransfer;
    296296    /** Set when the reset processing is currently active on this controller. */
    297     bool volatile fReset;
     297    bool        fReset;
     298    /** Flag whether the current transfer needs to be redone. */
     299    bool        fRedo;
     300    /** Flag whether the redo suspend has been finished. */
     301    bool        fRedoIdle;
     302    /** Flag whether the DMA operation to be redone is the final transfer. */
     303    bool        fRedoDMALastDesc;
    298304    /** The BusMaster DMA state. */
    299305    BMDMAState  BmDma;
     306    /** Pointer to first DMA descriptor. */
     307    RTGCPHYS    pFirstDMADesc;
     308    /** Pointer to last DMA descriptor. */
     309    RTGCPHYS    pLastDMADesc;
     310    /** Pointer to current DMA buffer (for redo operations). */
     311    RTGCPHYS    pRedoDMABuffer;
     312    /** Size of current DMA buffer (for redo operations). */
     313    uint32_t    cbRedoDMABuffer;
    300314
    301315    /** The ATA/ATAPI interfaces of this controller. */
     
    321335    /** The mutex protecting the request queue. */
    322336    RTSEMMUTEX          AsyncIORequestMutex;
     337    /** The event semaphore the thread is waiting on during suspended I/O. */
     338    RTSEMEVENT          SuspendIOSem;
    323339    /** Magic delay before triggering interrupts in DMA mode. */
    324340    uint32_t            DelayIRQMillies;
     
    422438
    423439typedef void (*PBeginTransferFunc)(ATADevState *);
    424 typedef void (*PSourceSinkFunc)(ATADevState *);
     440typedef bool (*PSourceSinkFunc)(ATADevState *);
    425441
    426442static void ataReadWriteSectorsBT(ATADevState *);
     
    429445static void atapiPassthroughCmdBT(ATADevState *);
    430446
    431 static void ataIdentifySS(ATADevState *);
    432 static void ataFlushSS(ATADevState *);
    433 static void ataReadSectorsSS(ATADevState *);
    434 static void ataWriteSectorsSS(ATADevState *);
    435 static void ataExecuteDeviceDiagnosticSS(ATADevState *);
    436 static void ataPacketSS(ATADevState *);
    437 static void atapiGetConfigurationSS(ATADevState *);
    438 static void atapiIdentifySS(ATADevState *);
    439 static void atapiInquirySS(ATADevState *);
    440 static void atapiMechanismStatusSS(ATADevState *);
    441 static void atapiModeSenseErrorRecoverySS(ATADevState *);
    442 static void atapiModeSenseCDStatusSS(ATADevState *);
    443 static void atapiReadSS(ATADevState *);
    444 static void atapiReadCapacitySS(ATADevState *);
    445 static void atapiReadDiscInformationSS(ATADevState *);
    446 static void atapiReadTOCNormalSS(ATADevState *);
    447 static void atapiReadTOCMultiSS(ATADevState *);
    448 static void atapiReadTOCRawSS(ATADevState *);
    449 static void atapiReadTrackInformationSS(ATADevState *);
    450 static void atapiRequestSenseSS(ATADevState *);
    451 static void atapiPassthroughSS(ATADevState *);
     447static bool ataIdentifySS(ATADevState *);
     448static bool ataFlushSS(ATADevState *);
     449static bool ataReadSectorsSS(ATADevState *);
     450static bool ataWriteSectorsSS(ATADevState *);
     451static bool ataExecuteDeviceDiagnosticSS(ATADevState *);
     452static bool ataPacketSS(ATADevState *);
     453static bool atapiGetConfigurationSS(ATADevState *);
     454static bool atapiIdentifySS(ATADevState *);
     455static bool atapiInquirySS(ATADevState *);
     456static bool atapiMechanismStatusSS(ATADevState *);
     457static bool atapiModeSenseErrorRecoverySS(ATADevState *);
     458static bool atapiModeSenseCDStatusSS(ATADevState *);
     459static bool atapiReadSS(ATADevState *);
     460static bool atapiReadCapacitySS(ATADevState *);
     461static bool atapiReadDiscInformationSS(ATADevState *);
     462static bool atapiReadTOCNormalSS(ATADevState *);
     463static bool atapiReadTOCMultiSS(ATADevState *);
     464static bool atapiReadTOCRawSS(ATADevState *);
     465static bool atapiReadTrackInformationSS(ATADevState *);
     466static bool atapiRequestSenseSS(ATADevState *);
     467static bool atapiPassthroughSS(ATADevState *);
    452468
    453469/**
     
    686702    rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
    687703    AssertRC(rc);
    688     fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail);
     704    fIdle = pCtl->fRedoIdle;
     705    if (!fIdle)
     706        fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail);
    689707    if (fStrict)
    690708        fIdle &= (pCtl->uAsyncIOState == ATA_AIO_NEW);
     
    9911009    s->cbTotalTransfer = 0;
    9921010    s->cbElementaryTransfer = 0;
    993     s->iIOBufferPIO = 0;
     1011    s->iIOBufferCur = 0;
    9941012    s->iIOBufferEnd = 0;
    9951013    s->uTxDir = PDMBLOCKTXDIR_NONE;
     
    9991017
    10001018
    1001 static void ataIdentifySS(ATADevState *s)
     1019static bool ataIdentifySS(ATADevState *s)
    10021020{
    10031021    uint16_t *p;
     
    10921110    s->iSourceSink = ATAFN_SS_NULL;
    10931111    ataCmdOK(s, ATA_STAT_SEEK);
    1094 }
    1095 
    1096 
    1097 static void ataFlushSS(ATADevState *s)
     1112    return false;
     1113}
     1114
     1115
     1116static bool ataFlushSS(ATADevState *s)
    10981117{
    10991118    PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     
    11141133    STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
    11151134    ataCmdOK(s, 0);
    1116 }
    1117 
    1118 
    1119 static void atapiIdentifySS(ATADevState *s)
     1135    return false;
     1136}
     1137
     1138
     1139static bool atapiIdentifySS(ATADevState *s)
    11201140{
    11211141    uint16_t *p;
     
    11731193    s->iSourceSink = ATAFN_SS_NULL;
    11741194    ataCmdOK(s, ATA_STAT_SEEK);
     1195    return false;
    11751196}
    11761197
     
    13281349}
    13291350
    1330 static void ataReadSectorsSS(ATADevState *s)
     1351
     1352static void ataDiskFull(PPDMDEVINS pDevIns)
     1353{
     1354    int rc;
     1355    LogRel(("PIIX3 ATA: Host disk full\n"));
     1356    rc = VMSetRuntimeError(PDMDevHlpGetVM(ATADEVSTATE_2_DEVINS(s)),
     1357                           false, "DevATA_DISKFULL",
     1358                           N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
     1359    AssertRC(rc);
     1360}
     1361
     1362
     1363static bool ataReadSectorsSS(ATADevState *s)
    13311364{
    13321365    int rc;
     
    13481381    else
    13491382    {
    1350         if (    rc == VERR_DISK_FULL
    1351             ||  s->cErrors++ < MAX_LOG_REL_ERRORS)
     1383        if (rc == VERR_DISK_FULL)
     1384        {
     1385            ataDiskFull(ATADEVSTATE_2_DEVINS(s));
     1386            return true;
     1387        }
     1388        if (s->cErrors++ < MAX_LOG_REL_ERRORS)
    13521389            LogRel(("PIIX3 ATA: LUN#%d: disk read error (rc=%Vrc iSector=%#RX64 cSectors=%#RX32)\n",
    13531390                    s->iLUN, rc, iLBA, cSectors));
    13541391        ataCmdError(s, ID_ERR);
    13551392    }
    1356 }
    1357 
    1358 
    1359 static void ataWriteSectorsSS(ATADevState *s)
     1393    /** @todo implement redo for iSCSI */
     1394    return false;
     1395}
     1396
     1397
     1398static bool ataWriteSectorsSS(ATADevState *s)
    13601399{
    13611400    int rc;
     
    13771416    else
    13781417    {
    1379         if (    rc == VERR_DISK_FULL
    1380             ||  s->cErrors++ < MAX_LOG_REL_ERRORS)
     1418        if (rc == VERR_DISK_FULL)
     1419        {
     1420            ataDiskFull(ATADEVSTATE_2_DEVINS(s));
     1421            return true;
     1422        }
     1423        if (s->cErrors++ < MAX_LOG_REL_ERRORS)
    13811424            LogRel(("PIIX3 ATA: LUN#%d: disk write error (rc=%Vrc iSector=%#RX64 cSectors=%#RX32)\n",
    13821425                    s->iLUN, rc, iLBA, cSectors));
    1383         if (rc == VERR_DISK_FULL)
    1384             AssertReleaseMsgFailed(("Host disk full\n"));
    13851426        ataCmdError(s, ID_ERR);
    13861427    }
     1428    /** @todo implement redo for iSCSI */
     1429    return false;
    13871430}
    13881431
     
    14121455    s->cbTotalTransfer = 0;
    14131456    s->cbElementaryTransfer = 0;
     1457    s->iIOBufferCur = 0;
    14141458    s->iIOBufferEnd = 0;
    1415     s->iIOBufferPIO = 0;
    14161459    s->uTxDir = PDMBLOCKTXDIR_NONE;
    14171460    s->iBeginTransfer = ATAFN_BT_NULL;
     
    15071550
    15081551
    1509 static void atapiReadSS(ATADevState *s)
     1552static bool atapiReadSS(ATADevState *s)
    15101553{
    15111554    PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     
    15771620        atapiCmdError(s, SCSI_SENSE_MEDIUM_ERROR, SCSI_ASC_READ_ERROR);
    15781621    }
    1579 }
    1580 
    1581 
    1582 static void atapiPassthroughSS(ATADevState *s)
     1622    return false;
     1623}
     1624
     1625
     1626static bool atapiPassthroughSS(ATADevState *s)
    15831627{
    15841628    PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
     
    16531697                STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
    16541698                }
    1655                 return;
     1699                return false;
    16561700        }
    16571701        memcpy(aATAPICmd, s->aATAPICmd, ATAPI_PACKET_SIZE);
     
    17521796        s->uATAPIASC = SCSI_ASC_NONE;
    17531797    }
    1754 }
    1755 
    1756 
    1757 static void atapiReadSectors(ATADevState *s, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
     1798    return false;
     1799}
     1800
     1801
     1802static bool atapiReadSectors(ATADevState *s, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
    17581803{
    17591804    Assert(cSectors > 0);
     
    17611806    s->cbATAPISector = cbSector;
    17621807    ataStartTransfer(s, cSectors * cbSector, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ, true);
    1763 }
    1764 
    1765 
    1766 static void atapiReadCapacitySS(ATADevState *s)
     1808    return false;
     1809}
     1810
     1811
     1812static bool atapiReadCapacitySS(ATADevState *s)
    17671813{
    17681814    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    17741820    s->iSourceSink = ATAFN_SS_NULL;
    17751821    atapiCmdOK(s);
    1776 }
    1777 
    1778 
    1779 static void atapiReadDiscInformationSS(ATADevState *s)
     1822    return false;
     1823}
     1824
     1825
     1826static bool atapiReadDiscInformationSS(ATADevState *s)
    17801827{
    17811828    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    17991846    s->iSourceSink = ATAFN_SS_NULL;
    18001847    atapiCmdOK(s);
    1801 }
    1802 
    1803 
    1804 static void atapiReadTrackInformationSS(ATADevState *s)
     1848    return false;
     1849}
     1850
     1851
     1852static bool atapiReadTrackInformationSS(ATADevState *s)
    18051853{
    18061854    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    18121860    {
    18131861        atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    1814         return;
     1862        return false;
    18151863    }
    18161864    memset(pbBuf, '\0', 36);
     
    18271875    s->iSourceSink = ATAFN_SS_NULL;
    18281876    atapiCmdOK(s);
    1829 }
    1830 
    1831 
    1832 static void atapiGetConfigurationSS(ATADevState *s)
     1877    return false;
     1878}
     1879
     1880
     1881static bool atapiGetConfigurationSS(ATADevState *s)
    18331882{
    18341883    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    18401889    {
    18411890        atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    1842         return;
     1891        return false;
    18431892    }
    18441893    memset(pbBuf, '\0', 32);
     
    18531902    s->iSourceSink = ATAFN_SS_NULL;
    18541903    atapiCmdOK(s);
    1855 }
    1856 
    1857 
    1858 static void atapiInquirySS(ATADevState *s)
     1904    return false;
     1905}
     1906
     1907
     1908static bool atapiInquirySS(ATADevState *s)
    18591909{
    18601910    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    18801930    s->iSourceSink = ATAFN_SS_NULL;
    18811931    atapiCmdOK(s);
    1882 }
    1883 
    1884 
    1885 static void atapiModeSenseErrorRecoverySS(ATADevState *s)
     1932    return false;
     1933}
     1934
     1935
     1936static bool atapiModeSenseErrorRecoverySS(ATADevState *s)
    18861937{
    18871938    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    19071958    s->iSourceSink = ATAFN_SS_NULL;
    19081959    atapiCmdOK(s);
    1909 }
    1910 
    1911 
    1912 static void atapiModeSenseCDStatusSS(ATADevState *s)
     1960    return false;
     1961}
     1962
     1963
     1964static bool atapiModeSenseCDStatusSS(ATADevState *s)
    19131965{
    19141966    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    19542006    s->iSourceSink = ATAFN_SS_NULL;
    19552007    atapiCmdOK(s);
    1956 }
    1957 
    1958 
    1959 static void atapiRequestSenseSS(ATADevState *s)
     2008    return false;
     2009}
     2010
     2011
     2012static bool atapiRequestSenseSS(ATADevState *s)
    19602013{
    19612014    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    19702023    s->iSourceSink = ATAFN_SS_NULL;
    19712024    atapiCmdOK(s);
    1972 }
    1973 
    1974 
    1975 static void atapiMechanismStatusSS(ATADevState *s)
     2025    return false;
     2026}
     2027
     2028
     2029static bool atapiMechanismStatusSS(ATADevState *s)
    19762030{
    19772031    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    19882042    s->iSourceSink = ATAFN_SS_NULL;
    19892043    atapiCmdOK(s);
    1990 }
    1991 
    1992 
    1993 static void atapiReadTOCNormalSS(ATADevState *s)
     2044    return false;
     2045}
     2046
     2047
     2048static bool atapiReadTOCNormalSS(ATADevState *s)
    19942049{
    19952050    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer), *q, iStartTrack;
     
    20032058    {
    20042059        atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    2005         return;
     2060        return false;
    20062061    }
    20072062    q = pbBuf + 2;
     
    20492104    s->iSourceSink = ATAFN_SS_NULL;
    20502105    atapiCmdOK(s);
    2051 }
    2052 
    2053 
    2054 static void atapiReadTOCMultiSS(ATADevState *s)
     2106    return false;
     2107}
     2108
     2109
     2110static bool atapiReadTOCMultiSS(ATADevState *s)
    20552111{
    20562112    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer);
     
    20802136    s->iSourceSink = ATAFN_SS_NULL;
    20812137    atapiCmdOK(s);
    2082 }
    2083 
    2084 
    2085 static void atapiReadTOCRawSS(ATADevState *s)
     2138    return false;
     2139}
     2140
     2141
     2142static bool atapiReadTOCRawSS(ATADevState *s)
    20862143{
    20872144    uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer), *q, iStartTrack;
     
    21662223    s->iSourceSink = ATAFN_SS_NULL;
    21672224    atapiCmdOK(s);
     2225    return false;
    21682226}
    21692227
     
    23852443                        break;
    23862444                    case 2: /* 10 - Eject media */
    2387 #if 0
    2388                         rc = s->pDrvMount->pfnUnmount(s->pDrvMount);
    2389 #else
     2445                        /* This must be done from EMT. */
    23902446                        {
    23912447                        PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
     
    23962452                        VMR3ReqFree(pReq);
    23972453                        }
    2398 #endif
    23992454                        break;
    24002455                    case 3: /* 11 - Load media */
     
    28202875
    28212876
    2822 static void ataPacketSS(ATADevState *s)
     2877static bool ataPacketSS(ATADevState *s)
    28232878{
    28242879    s->fDMA = !!(s->uATARegFeature & 1);
     
    28282883    s->cbElementaryTransfer = 0;
    28292884    atapiParseCmd(s);
     2885    return false;
    28302886}
    28312887
     
    29062962
    29072963
    2908 static void ataExecuteDeviceDiagnosticSS(ATADevState *s)
     2964static bool ataExecuteDeviceDiagnosticSS(ATADevState *s)
    29092965{
    29102966    ataSetSignature(s);
    29112967    ataSetStatusValue(s, 0); /* NOTE: READY is _not_ set */
    29122968    s->uATARegError = 0x01;
     2969    return false;
    29132970}
    29142971
     
    35903647
    35913648
     3649/**
     3650 * Perform the entire DMA transfer in one go (unless a source/sink operation
     3651 * has to be redone or a RESET comes in between). Unlike the PIO counterpart
     3652 * this function cannot handle empty transfers.
     3653 *
     3654 * @param pCtl      Controller for which to perform the transfer.
     3655 */
    35923656static void ataDMATransfer(PATACONTROLLER pCtl)
    35933657{
    3594     BMDMAState *bm = &pCtl->BmDma;
    35953658    PPDMDEVINS pDevIns = CONTROLLER_2_DEVINS(pCtl);
    3596     ATADevState *s;
    3597     ATAFNSS iOriginalSourceSink;
    3598     struct {
    3599         uint32_t addr;
    3600         uint32_t size;
    3601     } prd;
    3602     RTGCPHYS cur_addr;
     3659    ATADevState *s = &pCtl->aIfs[pCtl->iAIOIf];
     3660    bool fRedo;
     3661    RTGCPHYS pDesc;
    36033662    uint32_t cbTotalTransfer, cbElementaryTransfer;
    3604     uint32_t iIOBufferDMA, iIOBufferEnd;
     3663    uint32_t iIOBufferCur, iIOBufferEnd;
    36053664    uint32_t dmalen;
    36063665    PDMBLOCKTXDIR uTxDir;
    3607     bool fLastPRD = false;
    3608 
    3609     Assert(sizeof(prd) == 8);
    3610 
    3611     s = &pCtl->aIfs[pCtl->iAIOIf];
    3612     Assert(s->cbTotalTransfer);
    3613     iOriginalSourceSink = (ATAFNSS)s->iSourceSink; /* Used by the hack below, but gets reset by then. */
     3666    bool fLastDesc = false;
     3667
     3668    Assert(sizeof(BMDMADesc) == 8);
     3669
     3670    fRedo = pCtl->fRedo;
     3671    if (RT_LIKELY(!fRedo))
     3672        Assert(s->cbTotalTransfer);
    36143673    uTxDir = (PDMBLOCKTXDIR)s->uTxDir;
    36153674    cbTotalTransfer = s->cbTotalTransfer;
    36163675    cbElementaryTransfer = s->cbElementaryTransfer;
    3617     iIOBufferDMA = 0;
     3676    iIOBufferCur = s->iIOBufferCur;
    36183677    iIOBufferEnd = s->iIOBufferEnd;
    3619 
    3620     Log3(("%s: bm=%p if=%p\n", __FUNCTION__, bm, s));
    3621     if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
    3622         AssertRelease(bm->u8Cmd & BM_CMD_WRITE);
    3623     else
    3624         AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));
    36253678
    36263679    /* The DMA loop is designed to hold the lock only when absolutely
     
    36323685         __FUNCTION__, uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
    36333686         cbTotalTransfer, cbElementaryTransfer,
    3634          iIOBufferDMA, iIOBufferEnd));
    3635     /* The specs say that the descriptor table must not cross a 4K boundary. */
    3636     for (cur_addr = bm->pvAddr; cur_addr + sizeof(prd) <= RT_ALIGN_32(bm->pvAddr + 1, _4K); cur_addr += sizeof(prd))
    3637     {
    3638         PDMDevHlpPhysRead(pDevIns, cur_addr, &prd, sizeof(prd));
    3639         prd.addr = RT_LE2H_U32(prd.addr);
    3640         prd.size = RT_LE2H_U32(prd.size);
    3641         fLastPRD = !!(prd.size & 0x80000000);
    3642         prd.size &= 0xfffe;
    3643         if (prd.size == 0)
    3644             prd.size = 0x10000;
    3645         if (prd.size > cbTotalTransfer)
    3646             prd.size = cbTotalTransfer;
    3647 
    3648         while (prd.size && cbTotalTransfer)
    3649         {
    3650             dmalen = RT_MIN(prd.size, iIOBufferEnd - iIOBufferDMA);
    3651             Log2(("%s: prd %#010x: addr=%#010x size=%#010x\n", __FUNCTION__,
    3652                    (int)cur_addr, prd.addr, prd.size));
    3653             if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
    3654                 PDMDevHlpPhysWrite(pDevIns, prd.addr, s->CTXSUFF(pbIOBuffer) + iIOBufferDMA, dmalen);
    3655             else
    3656                 PDMDevHlpPhysRead(pDevIns, prd.addr, s->CTXSUFF(pbIOBuffer) + iIOBufferDMA, dmalen);
    3657             iIOBufferDMA += dmalen;
    3658             cbTotalTransfer -= dmalen;
    3659             prd.size -= dmalen;
    3660             prd.addr += dmalen;
    3661             if (    iIOBufferDMA == iIOBufferEnd
     3687         iIOBufferCur, iIOBufferEnd));
     3688    for (pDesc = pCtl->pFirstDMADesc; pDesc <= pCtl->pLastDMADesc; pDesc += sizeof(BMDMADesc))
     3689    {
     3690        BMDMADesc DMADesc;
     3691        RTGCPHYS pBuffer;
     3692        uint32_t cbBuffer;
     3693
     3694        if (RT_UNLIKELY(fRedo))
     3695        {
     3696            pBuffer = pCtl->pRedoDMABuffer;
     3697            cbBuffer = pCtl->cbRedoDMABuffer;
     3698            fLastDesc = pCtl->fRedoDMALastDesc;
     3699        }
     3700        else
     3701        {
     3702            PDMDevHlpPhysRead(pDevIns, pDesc, &DMADesc, sizeof(BMDMADesc));
     3703            pBuffer = RT_LE2H_U32(DMADesc.pBuffer);
     3704            cbBuffer = RT_LE2H_U32(DMADesc.cbBuffer);
     3705            fLastDesc = !!(cbBuffer & 0x80000000);
     3706            cbBuffer &= 0xfffe;
     3707            if (cbBuffer == 0)
     3708                cbBuffer = 0x10000;
     3709            if (cbBuffer > cbTotalTransfer)
     3710                cbBuffer = cbTotalTransfer;
     3711        }
     3712
     3713        while (RT_UNLIKELY(fRedo) || (cbBuffer && cbTotalTransfer))
     3714        {
     3715            if (RT_LIKELY(!fRedo))
     3716            {
     3717                dmalen = RT_MIN(cbBuffer, iIOBufferEnd - iIOBufferCur);
     3718                Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x\n", __FUNCTION__,
     3719                       (int)pDesc, pBuffer, cbBuffer));
     3720                if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
     3721                    PDMDevHlpPhysWrite(pDevIns, pBuffer, s->CTXSUFF(pbIOBuffer) + iIOBufferCur, dmalen);
     3722                else
     3723                    PDMDevHlpPhysRead(pDevIns, pBuffer, s->CTXSUFF(pbIOBuffer) + iIOBufferCur, dmalen);
     3724                iIOBufferCur += dmalen;
     3725                cbTotalTransfer -= dmalen;
     3726                cbBuffer -= dmalen;
     3727                pBuffer += dmalen;
     3728            }
     3729            if (    iIOBufferCur == iIOBufferEnd
    36623730                &&  (uTxDir == PDMBLOCKTXDIR_TO_DEVICE || cbTotalTransfer))
    36633731            {
     
    36773745                if (s->iSourceSink != ATAFN_SS_NULL)
    36783746                {
     3747                    s->iIOBufferCur = iIOBufferCur;
    36793748                    s->iIOBufferEnd = iIOBufferEnd;
    36803749                    s->cbElementaryTransfer = cbElementaryTransfer;
    36813750                    s->cbTotalTransfer = cbTotalTransfer;
    36823751                    Log2(("%s: calling source/sink function\n", __FUNCTION__));
    3683                     g_apfnSourceSinkFuncs[s->iSourceSink](s);
    3684                     cbTotalTransfer = s->cbTotalTransfer;
    3685                     cbElementaryTransfer = s->cbElementaryTransfer;
     3752                    fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
     3753                    if (RT_UNLIKELY(fRedo))
     3754                    {
     3755                        pCtl->pFirstDMADesc = pDesc;
     3756                        pCtl->pRedoDMABuffer = pBuffer;
     3757                        pCtl->cbRedoDMABuffer = cbBuffer;
     3758                        pCtl->fRedoDMALastDesc = fLastDesc;
     3759                    }
     3760                    else
     3761                    {
     3762                        cbTotalTransfer = s->cbTotalTransfer;
     3763                        cbElementaryTransfer = s->cbElementaryTransfer;
     3764
     3765                        if (uTxDir == PDMBLOCKTXDIR_TO_DEVICE && cbElementaryTransfer > cbTotalTransfer)
     3766                            cbElementaryTransfer = cbTotalTransfer;
     3767                        iIOBufferCur = 0;
     3768                        iIOBufferEnd = cbElementaryTransfer;
     3769                    }
     3770                    pCtl->fRedo = fRedo;
    36863771                }
    36873772                else
    36883773                {
    3689                     /* This forces the loop to exit immediately. Just to be
    3690                      * on the safe side. */
    3691                     cur_addr = bm->pvAddr + _4K;
     3774                    /* This forces the loop to exit immediately. */
     3775                    pDesc = pCtl->pLastDMADesc + 1;
    36923776                }
    3693                 cbTotalTransfer = s->cbTotalTransfer;
    3694                 cbElementaryTransfer = s->cbElementaryTransfer;
    36953777
    36963778                PDMCritSectLeave(&pCtl->lock);
    3697 
    3698                 if (uTxDir == PDMBLOCKTXDIR_TO_DEVICE && cbElementaryTransfer > cbTotalTransfer)
    3699                     cbElementaryTransfer = cbTotalTransfer;
    3700                 iIOBufferDMA = 0;
    3701                 iIOBufferEnd = cbElementaryTransfer;
     3779                if (RT_UNLIKELY(fRedo))
     3780                    break;
    37023781            }
    37033782        }
    37043783
     3784        if (RT_UNLIKELY(fRedo))
     3785            break;
     3786
    37053787        /* end of transfer */
    3706         if (!cbTotalTransfer || fLastPRD)
     3788        if (!cbTotalTransfer || fLastDesc)
    37073789            break;
    37083790
     
    37133795        }
    37143796
    3715         if (!(pCtl->BmDma.u8Cmd & BM_CMD_START))
    3716         {
    3717             LogRel(("PIIX3 ATA: Ctl#%d: ABORT DMA\n", ATACONTROLLER_IDX(pCtl)));
    3718             ataDMATransferStop(s);
     3797        if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
     3798        {
     3799            LogRel(("PIIX3 ATA: Ctl#%d: ABORT DMA%s\n", ATACONTROLLER_IDX(pCtl), pCtl->fReset ? " due to RESET" : ""));
     3800            if (!pCtl->fReset)
     3801                ataDMATransferStop(s);
    37193802            /* This forces the loop to exit immediately. */
    3720             cur_addr = bm->pvAddr + _4K;
     3803            pDesc = pCtl->pLastDMADesc + 1;
    37213804        }
    37223805
     
    37303813    }
    37313814
    3732     if (fLastPRD)
    3733         bm->u8Status &= ~BM_STATUS_DMAING;
     3815    if (RT_UNLIKELY(fRedo))
     3816        return;
     3817
     3818    if (fLastDesc)
     3819        pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
    37343820    s->cbTotalTransfer = cbTotalTransfer;
    37353821    s->cbElementaryTransfer = cbElementaryTransfer;
     3822    s->iIOBufferCur = iIOBufferCur;
    37363823    s->iIOBufferEnd = iIOBufferEnd;
    3737 
    3738     /* The infamous delay IRQ hack. */
    3739     if (iOriginalSourceSink == ATAFN_SS_WRITE_SECTORS && pCtl->DelayIRQMillies)
    3740     {
    3741         /* Delay IRQ for writing. Required to get the Win2K installation
    3742          * work reliably (otherwise it crashes, usually during component
    3743          * install). So far no better solution has been found. */
    3744         Log(("%s: delay IRQ hack\n", __FUNCTION__));
    3745         PDMCritSectLeave(&pCtl->lock);
    3746         RTThreadSleep(pCtl->DelayIRQMillies);
    3747         PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
    3748     }
    37493824}
    37503825
     
    37573832    Log3(("%s: if=%p\n", __FUNCTION__, s));
    37583833
    3759     if (s->cbTotalTransfer && s->iIOBufferPIO > s->iIOBufferEnd)
     3834    if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
    37603835    {
    37613836        LogRel(("PIIX3 ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n", s->iLUN, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "storing" : "loading"));
     
    37663841        if (s->iSourceSink != ATAFN_SS_NULL)
    37673842        {
     3843            bool fRedo;
    37683844            uint8_t status = s->uATARegStatus;
    37693845            ataSetStatusValue(s, ATA_STAT_BUSY);
    37703846            Log2(("%s: calling source/sink function\n", __FUNCTION__));
    3771             g_apfnSourceSinkFuncs[s->iSourceSink](s);
     3847            fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
     3848            pCtl->fRedo = fRedo;
     3849            if (RT_UNLIKELY(fRedo))
     3850                return;
    37723851            ataSetStatusValue(s, status);
    3773             s->iIOBufferPIO = 0;
     3852            s->iIOBufferCur = 0;
    37743853            s->iIOBufferEnd = s->cbElementaryTransfer;
    37753854        }
     
    37863865             __FUNCTION__, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
    37873866             s->cbTotalTransfer, s->cbElementaryTransfer,
    3788              s->iIOBufferPIO, s->iIOBufferEnd));
    3789         ataPIOTransferStart(s, s->iIOBufferPIO, s->cbElementaryTransfer);
     3867             s->iIOBufferCur, s->iIOBufferEnd));
     3868        ataPIOTransferStart(s, s->iIOBufferCur, s->cbElementaryTransfer);
    37903869        s->cbTotalTransfer -= s->cbElementaryTransfer;
    3791         s->iIOBufferPIO += s->cbElementaryTransfer;
     3870        s->iIOBufferCur += s->cbElementaryTransfer;
    37923871
    37933872        if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
     
    37983877}
    37993878
     3879
     3880/**
     3881 * Suspend I/O operations on a controller. Also suspends EMT, because it's
     3882 * waiting for I/O to make progress. The next attempt to perform an I/O
     3883 * operation will be made when EMT is resumed up again (as the resume
     3884 * callback below restarts I/O).
     3885 *
     3886 * @param pCtl      Controller for which to suspend I/O.
     3887 */
     3888static void ataSuspendRedo(PATACONTROLLER pCtl)
     3889{
     3890    PPDMDEVINS  pDevIns = CONTROLLER_2_DEVINS(pCtl);
     3891    PVMREQ      pReq;
     3892    int         rc;
     3893
     3894    pCtl->fRedoIdle = true;
     3895    rc = VMR3ReqCall(PDMDevHlpGetVM(pDevIns), &pReq, RT_INDEFINITE_WAIT,
     3896                     (PFNRT)pDevIns->pDevHlp->pfnVMSuspend, 1, pDevIns);
     3897    AssertReleaseRC(rc);
     3898    VMR3ReqFree(pReq);
     3899}
    38003900
    38013901/** Asynch I/O thread for an interface. Once upon a time this was readable
     
    38163916    while (!pCtl->fShutdown)
    38173917    {
     3918        /* Keep this thread from doing anything as long as EMT is suspended. */
     3919        while (pCtl->fRedoIdle)
     3920        {
     3921            rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT);
     3922            if (VBOX_FAILURE(rc) || pCtl->fShutdown)
     3923                break;
     3924
     3925            pCtl->fRedoIdle = false;
     3926        }
     3927
    38183928        /* Wait for work.  */
    38193929        if (pReq == NULL)
     
    38883998                    s->iIOBufferEnd = s->cbTotalTransfer;
    38893999                }
    3890                 s->iIOBufferPIO = 0;
     4000                s->iIOBufferCur = 0;
    38914001
    38924002                if (s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
     
    38944004                    if (s->iSourceSink != ATAFN_SS_NULL)
    38954005                    {
     4006                        bool fRedo;
    38964007                        Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
    3897                         g_apfnSourceSinkFuncs[s->iSourceSink](s);
     4008                        fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
     4009                        pCtl->fRedo = fRedo;
     4010                        if (RT_UNLIKELY(fRedo))
     4011                        {
     4012                            /* Operation failed at the initial transfer, restart
     4013                             * everything from scratch by resending the current
     4014                             * request. Occurs very rarely, not worth optimizing. */
     4015                            LogRel(("%s: Ctl#%d: redo entire operation\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
     4016                            ataAsyncIOPutRequest(pCtl, pReq);
     4017                            ataSuspendRedo(pCtl);
     4018                            break;
     4019                        }
    38984020                    }
    38994021                    else
     
    39384060                    {
    39394061                        ataPIOTransfer(pCtl);
     4062                        Assert(!pCtl->fRedo);
    39404063                        if (s->fATAPITransfer || s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
    39414064                            ataSetIRQ(s);
     
    39484071                        /* Finish PIO transfer. */
    39494072                        ataPIOTransfer(pCtl);
     4073                        Assert(!pCtl->fRedo);
    39504074                        if (!s->fATAPITransfer)
    39514075                            ataSetIRQ(s);
     
    39564080
    39574081            case ATA_AIO_DMA:
     4082            {
     4083                BMDMAState *bm = &pCtl->BmDma;
    39584084                s = &pCtl->aIfs[pCtl->iAIOIf]; /* Do not remove or there's an instant crash after loading the saved state */
    3959 
     4085                ATAFNSS iOriginalSourceSink = (ATAFNSS)s->iSourceSink; /* Used by the hack below, but gets reset by then. */
     4086
     4087                if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
     4088                    AssertRelease(bm->u8Cmd & BM_CMD_WRITE);
     4089                else
     4090                    AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));
     4091
     4092                if (RT_LIKELY(!pCtl->fRedo))
     4093                {
     4094                    /* The specs say that the descriptor table must not cross a
     4095                     * 4K boundary. */
     4096                    pCtl->pFirstDMADesc = bm->pvAddr;
     4097                    pCtl->pLastDMADesc = RT_ALIGN_32(bm->pvAddr + 1, _4K) - sizeof(BMDMADesc);
     4098                }
    39604099                ataDMATransfer(pCtl);
     4100
     4101                if (RT_UNLIKELY(pCtl->fRedo))
     4102                {
     4103                    LogRel(("PIIX3 ATA: Ctl#%d: redo DMA operation\n", ATACONTROLLER_IDX(pCtl)));
     4104                    ataAsyncIOPutRequest(pCtl, &ataDMARequest);
     4105                    ataSuspendRedo(pCtl);
     4106                    break;
     4107                }
     4108
     4109                /* The infamous delay IRQ hack. */
     4110                if (   iOriginalSourceSink == ATAFN_SS_WRITE_SECTORS
     4111                    && s->cbTotalTransfer == 0
     4112                    && pCtl->DelayIRQMillies)
     4113                {
     4114                    /* Delay IRQ for writing. Required to get the Win2K
     4115                     * installation work reliably (otherwise it crashes,
     4116                     * usually during component install). So far no better
     4117                     * solution has been found. */
     4118                    Log(("%s: delay IRQ hack\n", __FUNCTION__));
     4119                    PDMCritSectLeave(&pCtl->lock);
     4120                    RTThreadSleep(pCtl->DelayIRQMillies);
     4121                    PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
     4122                }
    39614123
    39624124                ataUnsetStatus(s, ATA_STAT_DRQ);
     
    39724134                pCtl->uAsyncIOState = ATA_AIO_NEW;
    39734135                break;
     4136            }
    39744137
    39754138            case ATA_AIO_PIO:
     
    39784141                if (s->iSourceSink != ATAFN_SS_NULL)
    39794142                {
     4143                    bool fRedo;
    39804144                    Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
    3981                     g_apfnSourceSinkFuncs[s->iSourceSink](s);
    3982                     s->iIOBufferPIO = 0;
     4145                    fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
     4146                    pCtl->fRedo = fRedo;
     4147                    if (RT_UNLIKELY(fRedo))
     4148                    {
     4149                        LogRel(("PIIX3 ATA: Ctl#%d: redo PIO operation\n", ATACONTROLLER_IDX(pCtl)));
     4150                        ataAsyncIOPutRequest(pCtl, &ataPIORequest);
     4151                        ataSuspendRedo(pCtl);
     4152                        break;
     4153                    }
     4154                    s->iIOBufferCur = 0;
    39834155                    s->iIOBufferEnd = s->cbElementaryTransfer;
    39844156                }
     
    41344306        pCtl->AsyncIOSem = NIL_RTSEMEVENT;
    41354307    }
     4308    if (pCtl->SuspendIOSem)
     4309    {
     4310        RTSemEventDestroy(pCtl->SuspendIOSem);
     4311        pCtl->SuspendIOSem = NIL_RTSEMEVENT;
     4312    }
     4313    /* Do not destroy request mutex yet, still needed for proper shutdown. */
    41364314    pCtl->fShutdown = false;
    41374315    /* This must be last, as it also signals thread exit to EMT. */
     
    43764554
    43774555        pData->aCts[i].fReset = true;
     4556        pData->aCts[i].fRedo = false;
     4557        pData->aCts[i].fRedoIdle = false;
    43784558        ataAsyncIOClearRequests(&pData->aCts[i]);
    43794559        Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i));
     
    47754955    PCIATAState *pData = PDMINS2DATA(pDevIns, PCIATAState *);
    47764956
    4777     pData->aCts[0].pDevInsGC += offDelta;
    4778     pData->aCts[1].pDevInsGC += offDelta;
    4779     pData->aCts[0].aIfs[0].pDevInsGC += offDelta;
    4780     pData->aCts[0].aIfs[0].pControllerGC += offDelta;
    4781     ataRelocBuffer(pDevIns, &pData->aCts[0].aIfs[0]);
    4782     pData->aCts[0].aIfs[1].pDevInsGC += offDelta;
    4783     pData->aCts[0].aIfs[1].pControllerGC += offDelta;
    4784     ataRelocBuffer(pDevIns, &pData->aCts[0].aIfs[1]);
    4785     pData->aCts[1].aIfs[0].pDevInsGC += offDelta;
    4786     pData->aCts[1].aIfs[0].pControllerGC += offDelta;
    4787     ataRelocBuffer(pDevIns, &pData->aCts[1].aIfs[0]);
    4788     pData->aCts[1].aIfs[1].pDevInsGC += offDelta;
    4789     pData->aCts[1].aIfs[1].pControllerGC += offDelta;
    4790     ataRelocBuffer(pDevIns, &pData->aCts[1].aIfs[1]);
     4957    for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++)
     4958    {
     4959        pData->aCts[i].pDevInsGC += offDelta;
     4960        pData->aCts[i].aIfs[0].pDevInsGC += offDelta;
     4961        pData->aCts[i].aIfs[0].pControllerGC += offDelta;
     4962        ataRelocBuffer(pDevIns, &pData->aCts[i].aIfs[0]);
     4963        pData->aCts[i].aIfs[1].pDevInsGC += offDelta;
     4964        pData->aCts[i].aIfs[1].pControllerGC += offDelta;
     4965        ataRelocBuffer(pDevIns, &pData->aCts[i].aIfs[1]);
     4966    }
    47914967}
    47924968
     
    48034979{
    48044980    PCIATAState    *pData = PDMINS2DATA(pDevIns, PCIATAState *);
     4981    int             rc;
    48054982
    48064983    Log(("%s:\n", __FUNCTION__));
    4807 
    4808     /* sanity - power off will have made sure they are all idle. */
    4809     Assert(!(pData->aCts[0].BmDma.u8Status & BM_STATUS_DMAING));
    4810     Assert(!(pData->aCts[1].BmDma.u8Status & BM_STATUS_DMAING));
    48114984
    48124985    /*
     
    48184991        {
    48194992            ASMAtomicXchgU32(&pData->aCts[i].fShutdown, true);
    4820             RTSemEventSignal(pData->aCts[i].AsyncIOSem);
     4993            rc = RTSemEventSignal(pData->aCts[i].AsyncIOSem);
     4994            AssertRC(rc);
    48214995        }
    48224996    }
     
    48485022    else
    48495023        AssertMsgFailed(("Async I/O is still busy!\n"));
     5024
     5025    /*
     5026     * Now the request mutexes are no longer needed. Free resources.
     5027     */
     5028    for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++)
     5029    {
     5030        if (pData->aCts[i].AsyncIORequestMutex)
     5031        {
     5032            RTSemMutexDestroy(pData->aCts[i].AsyncIORequestMutex);
     5033            pData->aCts[i].AsyncIORequestMutex = NIL_RTSEMEVENT;
     5034        }
     5035    }
    48505036    return VINF_SUCCESS;
    48515037}
     
    50925278
    50935279/**
     5280 * Resume notification.
     5281 *
     5282 * @returns VBox status.
     5283 * @param   pDrvIns     The driver instance data.
     5284 */
     5285static DECLCALLBACK(void) ataResume(PPDMDEVINS pDevIns)
     5286{
     5287    PCIATAState    *pData = PDMINS2DATA(pDevIns, PCIATAState *);
     5288    int             rc;
     5289
     5290    Log(("%s:\n", __FUNCTION__));
     5291    for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++)
     5292    {
     5293        if (pData->aCts[i].fRedo && pData->aCts[i].fRedoIdle)
     5294        {
     5295            rc = RTSemEventSignal(pData->aCts[i].SuspendIOSem);
     5296            AssertRC(rc);
     5297        }
     5298    }
     5299    return;
     5300}
     5301
     5302
     5303/**
    50945304 * Power Off notification.
    50955305 *
     
    51185328
    51195329    /* sanity - the suspend notification will wait on the async stuff. */
    5120     Assert(ataAsyncIOIsIdle(&pData->aCts[0], false));
    5121     Assert(ataAsyncIOIsIdle(&pData->aCts[1], false));
    5122 
    5123     if (    !ataAsyncIOIsIdle(&pData->aCts[0], false)
    5124         ||  !ataAsyncIOIsIdle(&pData->aCts[1], false))
    5125         return VERR_SSM_IDE_ASYNC_TIMEOUT;
     5330    for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++)
     5331    {
     5332        Assert(ataAsyncIOIsIdle(&pData->aCts[i], false));
     5333        if (!ataAsyncIOIsIdle(&pData->aCts[i], false))
     5334            return VERR_SSM_IDE_ASYNC_TIMEOUT;
     5335    }
    51265336    return VINF_SUCCESS;
    51275337}
     
    51395349    PCIATAState    *pData = PDMINS2DATA(pDevIns, PCIATAState *);
    51405350
    5141     /* No dmaing now. */
    5142     Assert(!(pData->aCts[0].BmDma.u8Status & BM_STATUS_DMAING));
    5143     Assert(!(pData->aCts[1].BmDma.u8Status & BM_STATUS_DMAING));
    5144 
    51455351    for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++)
    51465352    {
     
    51505356        SSMR3PutBool(pSSMHandle, pData->aCts[i].fChainedTransfer);
    51515357        SSMR3PutBool(pSSMHandle, pData->aCts[i].fReset);
     5358        SSMR3PutBool(pSSMHandle, pData->aCts[i].fRedo);
     5359        SSMR3PutBool(pSSMHandle, pData->aCts[i].fRedoIdle);
     5360        SSMR3PutBool(pSSMHandle, pData->aCts[i].fRedoDMALastDesc);
    51525361        SSMR3PutMem(pSSMHandle, &pData->aCts[i].BmDma, sizeof(pData->aCts[i].BmDma));
     5362        SSMR3PutGCPhys(pSSMHandle, pData->aCts[i].pFirstDMADesc);
     5363        SSMR3PutGCPhys(pSSMHandle, pData->aCts[i].pLastDMADesc);
     5364        SSMR3PutGCPhys(pSSMHandle, pData->aCts[i].pRedoDMABuffer);
     5365        SSMR3PutU32(pSSMHandle, pData->aCts[i].cbRedoDMABuffer);
    51535366
    51545367        for (uint32_t j = 0; j < RT_ELEMENTS(pData->aCts[i].aIfs); j++)
     
    51865399            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].cbTotalTransfer);
    51875400            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].cbElementaryTransfer);
     5401            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferCur);
    51885402            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferEnd);
    5189             SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIO);
    51905403            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIODataStart);
    51915404            SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIODataEnd);
     
    52355448    {
    52365449        /* integrity check */
    5237         if (    (pData->aCts[i].BmDma.u8Status & BM_STATUS_DMAING)
    5238             ||  !ataAsyncIOIsIdle(&pData->aCts[i], false))
     5450        if (!ataAsyncIOIsIdle(&pData->aCts[i], false))
    52395451        {
    52405452            AssertMsgFailed(("Async I/O for controller %d is active\n", i));
     
    52485460        SSMR3GetBool(pSSMHandle, &pData->aCts[i].fChainedTransfer);
    52495461        SSMR3GetBool(pSSMHandle, (bool *)&pData->aCts[i].fReset);
     5462        SSMR3GetBool(pSSMHandle, (bool *)&pData->aCts[i].fRedo);
     5463        SSMR3GetBool(pSSMHandle, (bool *)&pData->aCts[i].fRedoIdle);
     5464        SSMR3GetBool(pSSMHandle, (bool *)&pData->aCts[i].fRedoDMALastDesc);
    52505465        SSMR3GetMem(pSSMHandle, &pData->aCts[i].BmDma, sizeof(pData->aCts[i].BmDma));
     5466        SSMR3GetGCPhys(pSSMHandle, &pData->aCts[i].pFirstDMADesc);
     5467        SSMR3GetGCPhys(pSSMHandle, &pData->aCts[i].pLastDMADesc);
     5468        SSMR3GetGCPhys(pSSMHandle, &pData->aCts[i].pRedoDMABuffer);
     5469        SSMR3GetU32(pSSMHandle, &pData->aCts[i].cbRedoDMABuffer);
    52515470
    52525471        for (uint32_t j = 0; j < RT_ELEMENTS(pData->aCts[i].aIfs); j++)
     
    52845503            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].cbTotalTransfer);
    52855504            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].cbElementaryTransfer);
     5505            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferCur);
    52865506            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferEnd);
    5287             SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIO);
    52885507            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIODataStart);
    52895508            SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIODataEnd);
     
    55415760        rc = RTSemEventCreate(&pCtl->AsyncIOSem);
    55425761        AssertRC(rc);
     5762        rc = RTSemEventCreate(&pCtl->SuspendIOSem);
     5763        AssertRC(rc);
    55435764        rc = RTSemMutexCreate(&pCtl->AsyncIORequestMutex);
    55445765        AssertRC(rc);
     
    55465767        rc = RTThreadCreate(&pCtl->AsyncIOThread, ataAsyncIOLoop, (void *)pCtl, 128*1024, RTTHREADTYPE_IO, 0, "ATA");
    55475768        AssertRC(rc);
    5548         Assert(pCtl->AsyncIOThread != NIL_RTTHREAD && pCtl->AsyncIOSem != NIL_RTSEMEVENT);
    5549         Log(("%s: controller %d AIO thread id %#x; sem %p mutex %p\n", __FUNCTION__, i, pCtl->AsyncIOThread, pCtl->AsyncIOSem, pCtl->AsyncIORequestMutex));
     5769        Assert(pCtl->AsyncIOThread != NIL_RTTHREAD && pCtl->AsyncIOSem != NIL_RTSEMEVENT && pCtl->SuspendIOSem != NIL_RTSEMEVENT && pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX);
     5770        Log(("%s: controller %d AIO thread id %#x; sem %p susp_sem %p mutex %p\n", __FUNCTION__, i, pCtl->AsyncIOThread, pCtl->AsyncIOSem, pCtl->SuspendIOSem, pCtl->AsyncIORequestMutex));
    55505771
    55515772        for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
     
    56515872    ataSuspend,
    56525873    /* pfnResume */
    5653     NULL,
     5874    ataResume,
    56545875    /* pfnAttach */
    56555876    ataAttach,
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