- Timestamp:
- Jan 30, 2007 9:39:09 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r332 r427 77 77 * The SSM saved state version. 78 78 */ 79 #define ATA_SAVED_STATE_VERSION 1 479 #define ATA_SAVED_STATE_VERSION 15 80 80 81 81 /** The maximum number of release log entries per device. */ … … 146 146 /** Elementary ATA/ATAPI transfer size, shared PIO/DMA. */ 147 147 uint32_t cbElementaryTransfer; 148 /** Current read/write buffer position, shared PIO/DMA. */ 149 uint32_t iIOBufferCur; 148 150 /** First element beyond end of valid buffer content, shared PIO/DMA. */ 149 151 uint32_t iIOBufferEnd; 150 152 151 /** ATA/ATAPI current PIO read/write buffer position. Not shared with DMA for safety reasons. */152 uint32_t iIOBufferPIO;153 153 /** ATA/ATAPI current PIO read/write transfer position. Not shared with DMA for safety reasons. */ 154 154 uint32_t iIOBufferPIODataStart; … … 295 295 bool fChainedTransfer; 296 296 /** 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; 298 304 /** The BusMaster DMA state. */ 299 305 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; 300 314 301 315 /** The ATA/ATAPI interfaces of this controller. */ … … 321 335 /** The mutex protecting the request queue. */ 322 336 RTSEMMUTEX AsyncIORequestMutex; 337 /** The event semaphore the thread is waiting on during suspended I/O. */ 338 RTSEMEVENT SuspendIOSem; 323 339 /** Magic delay before triggering interrupts in DMA mode. */ 324 340 uint32_t DelayIRQMillies; … … 422 438 423 439 typedef void (*PBeginTransferFunc)(ATADevState *); 424 typedef void(*PSourceSinkFunc)(ATADevState *);440 typedef bool (*PSourceSinkFunc)(ATADevState *); 425 441 426 442 static void ataReadWriteSectorsBT(ATADevState *); … … 429 445 static void atapiPassthroughCmdBT(ATADevState *); 430 446 431 static voidataIdentifySS(ATADevState *);432 static voidataFlushSS(ATADevState *);433 static voidataReadSectorsSS(ATADevState *);434 static voidataWriteSectorsSS(ATADevState *);435 static voidataExecuteDeviceDiagnosticSS(ATADevState *);436 static voidataPacketSS(ATADevState *);437 static voidatapiGetConfigurationSS(ATADevState *);438 static voidatapiIdentifySS(ATADevState *);439 static voidatapiInquirySS(ATADevState *);440 static voidatapiMechanismStatusSS(ATADevState *);441 static voidatapiModeSenseErrorRecoverySS(ATADevState *);442 static voidatapiModeSenseCDStatusSS(ATADevState *);443 static voidatapiReadSS(ATADevState *);444 static voidatapiReadCapacitySS(ATADevState *);445 static voidatapiReadDiscInformationSS(ATADevState *);446 static voidatapiReadTOCNormalSS(ATADevState *);447 static voidatapiReadTOCMultiSS(ATADevState *);448 static voidatapiReadTOCRawSS(ATADevState *);449 static voidatapiReadTrackInformationSS(ATADevState *);450 static voidatapiRequestSenseSS(ATADevState *);451 static voidatapiPassthroughSS(ATADevState *);447 static bool ataIdentifySS(ATADevState *); 448 static bool ataFlushSS(ATADevState *); 449 static bool ataReadSectorsSS(ATADevState *); 450 static bool ataWriteSectorsSS(ATADevState *); 451 static bool ataExecuteDeviceDiagnosticSS(ATADevState *); 452 static bool ataPacketSS(ATADevState *); 453 static bool atapiGetConfigurationSS(ATADevState *); 454 static bool atapiIdentifySS(ATADevState *); 455 static bool atapiInquirySS(ATADevState *); 456 static bool atapiMechanismStatusSS(ATADevState *); 457 static bool atapiModeSenseErrorRecoverySS(ATADevState *); 458 static bool atapiModeSenseCDStatusSS(ATADevState *); 459 static bool atapiReadSS(ATADevState *); 460 static bool atapiReadCapacitySS(ATADevState *); 461 static bool atapiReadDiscInformationSS(ATADevState *); 462 static bool atapiReadTOCNormalSS(ATADevState *); 463 static bool atapiReadTOCMultiSS(ATADevState *); 464 static bool atapiReadTOCRawSS(ATADevState *); 465 static bool atapiReadTrackInformationSS(ATADevState *); 466 static bool atapiRequestSenseSS(ATADevState *); 467 static bool atapiPassthroughSS(ATADevState *); 452 468 453 469 /** … … 686 702 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); 687 703 AssertRC(rc); 688 fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail); 704 fIdle = pCtl->fRedoIdle; 705 if (!fIdle) 706 fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail); 689 707 if (fStrict) 690 708 fIdle &= (pCtl->uAsyncIOState == ATA_AIO_NEW); … … 991 1009 s->cbTotalTransfer = 0; 992 1010 s->cbElementaryTransfer = 0; 993 s->iIOBuffer PIO= 0;1011 s->iIOBufferCur = 0; 994 1012 s->iIOBufferEnd = 0; 995 1013 s->uTxDir = PDMBLOCKTXDIR_NONE; … … 999 1017 1000 1018 1001 static voidataIdentifySS(ATADevState *s)1019 static bool ataIdentifySS(ATADevState *s) 1002 1020 { 1003 1021 uint16_t *p; … … 1092 1110 s->iSourceSink = ATAFN_SS_NULL; 1093 1111 ataCmdOK(s, ATA_STAT_SEEK); 1094 } 1095 1096 1097 static void ataFlushSS(ATADevState *s) 1112 return false; 1113 } 1114 1115 1116 static bool ataFlushSS(ATADevState *s) 1098 1117 { 1099 1118 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); … … 1114 1133 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 1115 1134 ataCmdOK(s, 0); 1116 } 1117 1118 1119 static void atapiIdentifySS(ATADevState *s) 1135 return false; 1136 } 1137 1138 1139 static bool atapiIdentifySS(ATADevState *s) 1120 1140 { 1121 1141 uint16_t *p; … … 1173 1193 s->iSourceSink = ATAFN_SS_NULL; 1174 1194 ataCmdOK(s, ATA_STAT_SEEK); 1195 return false; 1175 1196 } 1176 1197 … … 1328 1349 } 1329 1350 1330 static void ataReadSectorsSS(ATADevState *s) 1351 1352 static 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 1363 static bool ataReadSectorsSS(ATADevState *s) 1331 1364 { 1332 1365 int rc; … … 1348 1381 else 1349 1382 { 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) 1352 1389 LogRel(("PIIX3 ATA: LUN#%d: disk read error (rc=%Vrc iSector=%#RX64 cSectors=%#RX32)\n", 1353 1390 s->iLUN, rc, iLBA, cSectors)); 1354 1391 ataCmdError(s, ID_ERR); 1355 1392 } 1356 } 1357 1358 1359 static void ataWriteSectorsSS(ATADevState *s) 1393 /** @todo implement redo for iSCSI */ 1394 return false; 1395 } 1396 1397 1398 static bool ataWriteSectorsSS(ATADevState *s) 1360 1399 { 1361 1400 int rc; … … 1377 1416 else 1378 1417 { 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) 1381 1424 LogRel(("PIIX3 ATA: LUN#%d: disk write error (rc=%Vrc iSector=%#RX64 cSectors=%#RX32)\n", 1382 1425 s->iLUN, rc, iLBA, cSectors)); 1383 if (rc == VERR_DISK_FULL)1384 AssertReleaseMsgFailed(("Host disk full\n"));1385 1426 ataCmdError(s, ID_ERR); 1386 1427 } 1428 /** @todo implement redo for iSCSI */ 1429 return false; 1387 1430 } 1388 1431 … … 1412 1455 s->cbTotalTransfer = 0; 1413 1456 s->cbElementaryTransfer = 0; 1457 s->iIOBufferCur = 0; 1414 1458 s->iIOBufferEnd = 0; 1415 s->iIOBufferPIO = 0;1416 1459 s->uTxDir = PDMBLOCKTXDIR_NONE; 1417 1460 s->iBeginTransfer = ATAFN_BT_NULL; … … 1507 1550 1508 1551 1509 static voidatapiReadSS(ATADevState *s)1552 static bool atapiReadSS(ATADevState *s) 1510 1553 { 1511 1554 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); … … 1577 1620 atapiCmdError(s, SCSI_SENSE_MEDIUM_ERROR, SCSI_ASC_READ_ERROR); 1578 1621 } 1579 } 1580 1581 1582 static void atapiPassthroughSS(ATADevState *s) 1622 return false; 1623 } 1624 1625 1626 static bool atapiPassthroughSS(ATADevState *s) 1583 1627 { 1584 1628 PATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s); … … 1653 1697 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 1654 1698 } 1655 return ;1699 return false; 1656 1700 } 1657 1701 memcpy(aATAPICmd, s->aATAPICmd, ATAPI_PACKET_SIZE); … … 1752 1796 s->uATAPIASC = SCSI_ASC_NONE; 1753 1797 } 1754 } 1755 1756 1757 static void atapiReadSectors(ATADevState *s, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector) 1798 return false; 1799 } 1800 1801 1802 static bool atapiReadSectors(ATADevState *s, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector) 1758 1803 { 1759 1804 Assert(cSectors > 0); … … 1761 1806 s->cbATAPISector = cbSector; 1762 1807 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 1812 static bool atapiReadCapacitySS(ATADevState *s) 1767 1813 { 1768 1814 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1774 1820 s->iSourceSink = ATAFN_SS_NULL; 1775 1821 atapiCmdOK(s); 1776 } 1777 1778 1779 static void atapiReadDiscInformationSS(ATADevState *s) 1822 return false; 1823 } 1824 1825 1826 static bool atapiReadDiscInformationSS(ATADevState *s) 1780 1827 { 1781 1828 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1799 1846 s->iSourceSink = ATAFN_SS_NULL; 1800 1847 atapiCmdOK(s); 1801 } 1802 1803 1804 static void atapiReadTrackInformationSS(ATADevState *s) 1848 return false; 1849 } 1850 1851 1852 static bool atapiReadTrackInformationSS(ATADevState *s) 1805 1853 { 1806 1854 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1812 1860 { 1813 1861 atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 1814 return ;1862 return false; 1815 1863 } 1816 1864 memset(pbBuf, '\0', 36); … … 1827 1875 s->iSourceSink = ATAFN_SS_NULL; 1828 1876 atapiCmdOK(s); 1829 } 1830 1831 1832 static void atapiGetConfigurationSS(ATADevState *s) 1877 return false; 1878 } 1879 1880 1881 static bool atapiGetConfigurationSS(ATADevState *s) 1833 1882 { 1834 1883 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1840 1889 { 1841 1890 atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 1842 return ;1891 return false; 1843 1892 } 1844 1893 memset(pbBuf, '\0', 32); … … 1853 1902 s->iSourceSink = ATAFN_SS_NULL; 1854 1903 atapiCmdOK(s); 1855 } 1856 1857 1858 static void atapiInquirySS(ATADevState *s) 1904 return false; 1905 } 1906 1907 1908 static bool atapiInquirySS(ATADevState *s) 1859 1909 { 1860 1910 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1880 1930 s->iSourceSink = ATAFN_SS_NULL; 1881 1931 atapiCmdOK(s); 1882 } 1883 1884 1885 static void atapiModeSenseErrorRecoverySS(ATADevState *s) 1932 return false; 1933 } 1934 1935 1936 static bool atapiModeSenseErrorRecoverySS(ATADevState *s) 1886 1937 { 1887 1938 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1907 1958 s->iSourceSink = ATAFN_SS_NULL; 1908 1959 atapiCmdOK(s); 1909 } 1910 1911 1912 static void atapiModeSenseCDStatusSS(ATADevState *s) 1960 return false; 1961 } 1962 1963 1964 static bool atapiModeSenseCDStatusSS(ATADevState *s) 1913 1965 { 1914 1966 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1954 2006 s->iSourceSink = ATAFN_SS_NULL; 1955 2007 atapiCmdOK(s); 1956 } 1957 1958 1959 static void atapiRequestSenseSS(ATADevState *s) 2008 return false; 2009 } 2010 2011 2012 static bool atapiRequestSenseSS(ATADevState *s) 1960 2013 { 1961 2014 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1970 2023 s->iSourceSink = ATAFN_SS_NULL; 1971 2024 atapiCmdOK(s); 1972 } 1973 1974 1975 static void atapiMechanismStatusSS(ATADevState *s) 2025 return false; 2026 } 2027 2028 2029 static bool atapiMechanismStatusSS(ATADevState *s) 1976 2030 { 1977 2031 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 1988 2042 s->iSourceSink = ATAFN_SS_NULL; 1989 2043 atapiCmdOK(s); 1990 } 1991 1992 1993 static void atapiReadTOCNormalSS(ATADevState *s) 2044 return false; 2045 } 2046 2047 2048 static bool atapiReadTOCNormalSS(ATADevState *s) 1994 2049 { 1995 2050 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer), *q, iStartTrack; … … 2003 2058 { 2004 2059 atapiCmdError(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 2005 return ;2060 return false; 2006 2061 } 2007 2062 q = pbBuf + 2; … … 2049 2104 s->iSourceSink = ATAFN_SS_NULL; 2050 2105 atapiCmdOK(s); 2051 } 2052 2053 2054 static void atapiReadTOCMultiSS(ATADevState *s) 2106 return false; 2107 } 2108 2109 2110 static bool atapiReadTOCMultiSS(ATADevState *s) 2055 2111 { 2056 2112 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer); … … 2080 2136 s->iSourceSink = ATAFN_SS_NULL; 2081 2137 atapiCmdOK(s); 2082 } 2083 2084 2085 static void atapiReadTOCRawSS(ATADevState *s) 2138 return false; 2139 } 2140 2141 2142 static bool atapiReadTOCRawSS(ATADevState *s) 2086 2143 { 2087 2144 uint8_t *pbBuf = s->CTXSUFF(pbIOBuffer), *q, iStartTrack; … … 2166 2223 s->iSourceSink = ATAFN_SS_NULL; 2167 2224 atapiCmdOK(s); 2225 return false; 2168 2226 } 2169 2227 … … 2385 2443 break; 2386 2444 case 2: /* 10 - Eject media */ 2387 #if 0 2388 rc = s->pDrvMount->pfnUnmount(s->pDrvMount); 2389 #else 2445 /* This must be done from EMT. */ 2390 2446 { 2391 2447 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s); … … 2396 2452 VMR3ReqFree(pReq); 2397 2453 } 2398 #endif2399 2454 break; 2400 2455 case 3: /* 11 - Load media */ … … 2820 2875 2821 2876 2822 static voidataPacketSS(ATADevState *s)2877 static bool ataPacketSS(ATADevState *s) 2823 2878 { 2824 2879 s->fDMA = !!(s->uATARegFeature & 1); … … 2828 2883 s->cbElementaryTransfer = 0; 2829 2884 atapiParseCmd(s); 2885 return false; 2830 2886 } 2831 2887 … … 2906 2962 2907 2963 2908 static voidataExecuteDeviceDiagnosticSS(ATADevState *s)2964 static bool ataExecuteDeviceDiagnosticSS(ATADevState *s) 2909 2965 { 2910 2966 ataSetSignature(s); 2911 2967 ataSetStatusValue(s, 0); /* NOTE: READY is _not_ set */ 2912 2968 s->uATARegError = 0x01; 2969 return false; 2913 2970 } 2914 2971 … … 3590 3647 3591 3648 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 */ 3592 3656 static void ataDMATransfer(PATACONTROLLER pCtl) 3593 3657 { 3594 BMDMAState *bm = &pCtl->BmDma;3595 3658 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; 3603 3662 uint32_t cbTotalTransfer, cbElementaryTransfer; 3604 uint32_t iIOBuffer DMA, iIOBufferEnd;3663 uint32_t iIOBufferCur, iIOBufferEnd; 3605 3664 uint32_t dmalen; 3606 3665 PDMBLOCKTXDIR uTxDir; 3607 bool fLast PRD= 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); 3614 3673 uTxDir = (PDMBLOCKTXDIR)s->uTxDir; 3615 3674 cbTotalTransfer = s->cbTotalTransfer; 3616 3675 cbElementaryTransfer = s->cbElementaryTransfer; 3617 iIOBuffer DMA = 0;3676 iIOBufferCur = s->iIOBufferCur; 3618 3677 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 else3624 AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));3625 3678 3626 3679 /* The DMA loop is designed to hold the lock only when absolutely … … 3632 3685 __FUNCTION__, uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T", 3633 3686 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 3662 3730 && (uTxDir == PDMBLOCKTXDIR_TO_DEVICE || cbTotalTransfer)) 3663 3731 { … … 3677 3745 if (s->iSourceSink != ATAFN_SS_NULL) 3678 3746 { 3747 s->iIOBufferCur = iIOBufferCur; 3679 3748 s->iIOBufferEnd = iIOBufferEnd; 3680 3749 s->cbElementaryTransfer = cbElementaryTransfer; 3681 3750 s->cbTotalTransfer = cbTotalTransfer; 3682 3751 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; 3686 3771 } 3687 3772 else 3688 3773 { 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; 3692 3776 } 3693 cbTotalTransfer = s->cbTotalTransfer;3694 cbElementaryTransfer = s->cbElementaryTransfer;3695 3777 3696 3778 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; 3702 3781 } 3703 3782 } 3704 3783 3784 if (RT_UNLIKELY(fRedo)) 3785 break; 3786 3705 3787 /* end of transfer */ 3706 if (!cbTotalTransfer || fLast PRD)3788 if (!cbTotalTransfer || fLastDesc) 3707 3789 break; 3708 3790 … … 3713 3795 } 3714 3796 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); 3719 3802 /* This forces the loop to exit immediately. */ 3720 cur_addr = bm->pvAddr + _4K;3803 pDesc = pCtl->pLastDMADesc + 1; 3721 3804 } 3722 3805 … … 3730 3813 } 3731 3814 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; 3734 3820 s->cbTotalTransfer = cbTotalTransfer; 3735 3821 s->cbElementaryTransfer = cbElementaryTransfer; 3822 s->iIOBufferCur = iIOBufferCur; 3736 3823 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 installation3742 * work reliably (otherwise it crashes, usually during component3743 * 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 }3749 3824 } 3750 3825 … … 3757 3832 Log3(("%s: if=%p\n", __FUNCTION__, s)); 3758 3833 3759 if (s->cbTotalTransfer && s->iIOBuffer PIO> s->iIOBufferEnd)3834 if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd) 3760 3835 { 3761 3836 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")); … … 3766 3841 if (s->iSourceSink != ATAFN_SS_NULL) 3767 3842 { 3843 bool fRedo; 3768 3844 uint8_t status = s->uATARegStatus; 3769 3845 ataSetStatusValue(s, ATA_STAT_BUSY); 3770 3846 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; 3772 3851 ataSetStatusValue(s, status); 3773 s->iIOBuffer PIO= 0;3852 s->iIOBufferCur = 0; 3774 3853 s->iIOBufferEnd = s->cbElementaryTransfer; 3775 3854 } … … 3786 3865 __FUNCTION__, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T", 3787 3866 s->cbTotalTransfer, s->cbElementaryTransfer, 3788 s->iIOBuffer PIO, s->iIOBufferEnd));3789 ataPIOTransferStart(s, s->iIOBuffer PIO, s->cbElementaryTransfer);3867 s->iIOBufferCur, s->iIOBufferEnd)); 3868 ataPIOTransferStart(s, s->iIOBufferCur, s->cbElementaryTransfer); 3790 3869 s->cbTotalTransfer -= s->cbElementaryTransfer; 3791 s->iIOBuffer PIO+= s->cbElementaryTransfer;3870 s->iIOBufferCur += s->cbElementaryTransfer; 3792 3871 3793 3872 if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer) … … 3798 3877 } 3799 3878 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 */ 3888 static 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 } 3800 3900 3801 3901 /** Asynch I/O thread for an interface. Once upon a time this was readable … … 3816 3916 while (!pCtl->fShutdown) 3817 3917 { 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 3818 3928 /* Wait for work. */ 3819 3929 if (pReq == NULL) … … 3888 3998 s->iIOBufferEnd = s->cbTotalTransfer; 3889 3999 } 3890 s->iIOBuffer PIO= 0;4000 s->iIOBufferCur = 0; 3891 4001 3892 4002 if (s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE) … … 3894 4004 if (s->iSourceSink != ATAFN_SS_NULL) 3895 4005 { 4006 bool fRedo; 3896 4007 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 } 3898 4020 } 3899 4021 else … … 3938 4060 { 3939 4061 ataPIOTransfer(pCtl); 4062 Assert(!pCtl->fRedo); 3940 4063 if (s->fATAPITransfer || s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE) 3941 4064 ataSetIRQ(s); … … 3948 4071 /* Finish PIO transfer. */ 3949 4072 ataPIOTransfer(pCtl); 4073 Assert(!pCtl->fRedo); 3950 4074 if (!s->fATAPITransfer) 3951 4075 ataSetIRQ(s); … … 3956 4080 3957 4081 case ATA_AIO_DMA: 4082 { 4083 BMDMAState *bm = &pCtl->BmDma; 3958 4084 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 } 3960 4099 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 } 3961 4123 3962 4124 ataUnsetStatus(s, ATA_STAT_DRQ); … … 3972 4134 pCtl->uAsyncIOState = ATA_AIO_NEW; 3973 4135 break; 4136 } 3974 4137 3975 4138 case ATA_AIO_PIO: … … 3978 4141 if (s->iSourceSink != ATAFN_SS_NULL) 3979 4142 { 4143 bool fRedo; 3980 4144 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; 3983 4155 s->iIOBufferEnd = s->cbElementaryTransfer; 3984 4156 } … … 4134 4306 pCtl->AsyncIOSem = NIL_RTSEMEVENT; 4135 4307 } 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. */ 4136 4314 pCtl->fShutdown = false; 4137 4315 /* This must be last, as it also signals thread exit to EMT. */ … … 4376 4554 4377 4555 pData->aCts[i].fReset = true; 4556 pData->aCts[i].fRedo = false; 4557 pData->aCts[i].fRedoIdle = false; 4378 4558 ataAsyncIOClearRequests(&pData->aCts[i]); 4379 4559 Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i)); … … 4775 4955 PCIATAState *pData = PDMINS2DATA(pDevIns, PCIATAState *); 4776 4956 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 } 4791 4967 } 4792 4968 … … 4803 4979 { 4804 4980 PCIATAState *pData = PDMINS2DATA(pDevIns, PCIATAState *); 4981 int rc; 4805 4982 4806 4983 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));4811 4984 4812 4985 /* … … 4818 4991 { 4819 4992 ASMAtomicXchgU32(&pData->aCts[i].fShutdown, true); 4820 RTSemEventSignal(pData->aCts[i].AsyncIOSem); 4993 rc = RTSemEventSignal(pData->aCts[i].AsyncIOSem); 4994 AssertRC(rc); 4821 4995 } 4822 4996 } … … 4848 5022 else 4849 5023 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 } 4850 5036 return VINF_SUCCESS; 4851 5037 } … … 5092 5278 5093 5279 /** 5280 * Resume notification. 5281 * 5282 * @returns VBox status. 5283 * @param pDrvIns The driver instance data. 5284 */ 5285 static 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 /** 5094 5304 * Power Off notification. 5095 5305 * … … 5118 5328 5119 5329 /* 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 } 5126 5336 return VINF_SUCCESS; 5127 5337 } … … 5139 5349 PCIATAState *pData = PDMINS2DATA(pDevIns, PCIATAState *); 5140 5350 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 5145 5351 for (uint32_t i = 0; i < RT_ELEMENTS(pData->aCts); i++) 5146 5352 { … … 5150 5356 SSMR3PutBool(pSSMHandle, pData->aCts[i].fChainedTransfer); 5151 5357 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); 5152 5361 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); 5153 5366 5154 5367 for (uint32_t j = 0; j < RT_ELEMENTS(pData->aCts[i].aIfs); j++) … … 5186 5399 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].cbTotalTransfer); 5187 5400 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].cbElementaryTransfer); 5401 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferCur); 5188 5402 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferEnd); 5189 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIO);5190 5403 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIODataStart); 5191 5404 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].iIOBufferPIODataEnd); … … 5235 5448 { 5236 5449 /* 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)) 5239 5451 { 5240 5452 AssertMsgFailed(("Async I/O for controller %d is active\n", i)); … … 5248 5460 SSMR3GetBool(pSSMHandle, &pData->aCts[i].fChainedTransfer); 5249 5461 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); 5250 5465 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); 5251 5470 5252 5471 for (uint32_t j = 0; j < RT_ELEMENTS(pData->aCts[i].aIfs); j++) … … 5284 5503 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].cbTotalTransfer); 5285 5504 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].cbElementaryTransfer); 5505 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferCur); 5286 5506 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferEnd); 5287 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIO);5288 5507 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIODataStart); 5289 5508 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].iIOBufferPIODataEnd); … … 5541 5760 rc = RTSemEventCreate(&pCtl->AsyncIOSem); 5542 5761 AssertRC(rc); 5762 rc = RTSemEventCreate(&pCtl->SuspendIOSem); 5763 AssertRC(rc); 5543 5764 rc = RTSemMutexCreate(&pCtl->AsyncIORequestMutex); 5544 5765 AssertRC(rc); … … 5546 5767 rc = RTThreadCreate(&pCtl->AsyncIOThread, ataAsyncIOLoop, (void *)pCtl, 128*1024, RTTHREADTYPE_IO, 0, "ATA"); 5547 5768 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)); 5550 5771 5551 5772 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++) … … 5651 5872 ataSuspend, 5652 5873 /* pfnResume */ 5653 NULL,5874 ataResume, 5654 5875 /* pfnAttach */ 5655 5876 ataAttach,
Note:
See TracChangeset
for help on using the changeset viewer.