Lines Matching refs:pAhciPort

930     int (*pfnRead )(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value);
931 int (*pfnWrite)(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value);
938 static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis);
939 static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort);
944 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort, PAHCIREQ pAhciReqExcept);
945 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree);
963 Log(("R3 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
966 do { Log(("R3 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
973 Log(("R0 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
976 do { Log(("R0 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
983 Log(("GC P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
986 do { Log(("GC P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
1066 * @param pAhciPort The port to finish the reset on.
1068 static void ahciPortResetFinish(PAHCIPort pAhciPort)
1071 bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort, NULL);
1075 if (pAhciPort->fATAPI)
1076 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1078 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1081 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
1082 pAhciPort->regSERR |= AHCI_PORT_SERR_X;
1083 pAhciPort->regTFD |= ATA_STAT_BUSY;
1085 if ((pAhciPort->regCMD & AHCI_PORT_CMD_FRE) && (!pAhciPort->fFirstD2HFisSend))
1087 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1088 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
1090 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
1092 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
1097 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1104 switch (AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL))
1107 pAhciPort->regSSTS |= (0x01 << 4); /* Generation 1 (1.5GBps) speed. */
1112 pAhciPort->regSSTS |= (0x02 << 4); /* Generation 2 (3.0GBps) speed. */
1116 ASMAtomicXchgBool(&pAhciPort->fPortReset, false);
1125 * @param pAhciPort The port to kick.
1127 static void ahciIoThreadKick(PAHCI pAhci, PAHCIPort pAhciPort)
1135 pItem->iPort = pAhciPort->iLUN;
1140 int rc = SUPSemEventSignal(pAhci->pSupDrvSession, pAhciPort->hEvtProcess);
1145 static int PortCmdIssue_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1152 uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1153 pAhciPort->regCI &= ~uCIValue;
1155 if ( (pAhciPort->regCMD & AHCI_PORT_CMD_CR)
1162 u32Value &= ~pAhciPort->regCI;
1164 ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value);
1167 if (ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1168 ahciIoThreadKick(ahci, pAhciPort);
1171 pAhciPort->regCI |= u32Value;
1176 static int PortCmdIssue_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1180 uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1182 ahciLog(("%s: read regCI=%#010x uCIValue=%#010x\n", __FUNCTION__, pAhciPort->regCI, uCIValue));
1184 pAhciPort->regCI &= ~uCIValue;
1186 *pu32Value = pAhciPort->regCI;
1191 static int PortSActive_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1195 pAhciPort->regSACT |= u32Value;
1200 static int PortSActive_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1202 uint32_t u32TasksFinished = ASMAtomicXchgU32(&pAhciPort->u32QueuedTasksFinished, 0);
1204 pAhciPort->regSACT &= ~u32TasksFinished;
1207 __FUNCTION__, pAhciPort->regSACT, pAhciPort->regCI, u32TasksFinished));
1209 *pu32Value = pAhciPort->regSACT;
1214 static int PortSError_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1219 && (pAhciPort->regSERR & AHCI_PORT_SERR_X))
1221 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PCS);
1222 pAhciPort->regTFD |= ATA_STAT_ERR;
1223 pAhciPort->regTFD &= ~(ATA_STAT_DRQ | ATA_STAT_BUSY);
1227 && (pAhciPort->regSERR & AHCI_PORT_SERR_N))
1228 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PRCS);
1230 pAhciPort->regSERR &= ~u32Value;
1235 static int PortSError_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1237 ahciLog(("%s: read regSERR=%#010x\n", __FUNCTION__, pAhciPort->regSERR));
1238 *pu32Value = pAhciPort->regSERR;
1242 static int PortSControl_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1253 if (!ASMAtomicXchgBool(&pAhciPort->fPortReset, true))
1255 pAhciPort->iLUN));
1257 pAhciPort->regSSTS = 0;
1258 pAhciPort->regSIG = ~0;
1259 pAhciPort->regTFD = 0x7f;
1260 pAhciPort->fFirstD2HFisSend = false;
1261 pAhciPort->regSCTL = u32Value;
1264 && (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_INIT
1265 && pAhciPort->pDrvBase)
1270 ahciPortResetFinish(pAhciPort);
1271 pAhciPort->regSCTL = u32Value; /* Update after finishing the reset, so the I/O thread doesn't get a chance to do the reset. */
1275 pAhciPort->regSSTS = 0x1; /* Indicate device presence detected but communication not established. */
1276 pAhciPort->regSCTL = u32Value; /* Update before kicking the I/O thread. */
1279 ahciIoThreadKick(ahci, pAhciPort);
1283 pAhciPort->regSCTL = u32Value;
1289 static int PortSControl_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1291 ahciLog(("%s: read regSCTL=%#010x\n", __FUNCTION__, pAhciPort->regSCTL));
1293 AHCI_PORT_SCTL_IPM_GET(pAhciPort->regSCTL), AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL),
1294 AHCI_PORT_SCTL_DET_GET(pAhciPort->regSCTL)));
1296 *pu32Value = pAhciPort->regSCTL;
1300 static int PortSStatus_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1302 ahciLog(("%s: read regSSTS=%#010x\n", __FUNCTION__, pAhciPort->regSSTS));
1304 AHCI_PORT_SSTS_IPM_GET(pAhciPort->regSSTS), AHCI_PORT_SSTS_SPD_GET(pAhciPort->regSSTS),
1305 AHCI_PORT_SSTS_DET_GET(pAhciPort->regSSTS)));
1307 *pu32Value = pAhciPort->regSSTS;
1311 static int PortSignature_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1313 ahciLog(("%s: read regSIG=%#010x\n", __FUNCTION__, pAhciPort->regSIG));
1314 *pu32Value = pAhciPort->regSIG;
1318 static int PortTaskFileData_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1320 ahciLog(("%s: read regTFD=%#010x\n", __FUNCTION__, pAhciPort->regTFD));
1322 (pAhciPort->regTFD >> 8), (pAhciPort->regTFD & AHCI_PORT_TFD_BSY) >> 7,
1323 (pAhciPort->regTFD & AHCI_PORT_TFD_DRQ) >> 3, (pAhciPort->regTFD & AHCI_PORT_TFD_ERR)));
1324 *pu32Value = pAhciPort->regTFD;
1331 static int PortCmd_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1333 ahciLog(("%s: read regCMD=%#010x\n", __FUNCTION__, pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot)));
1335 __FUNCTION__, (pAhciPort->regCMD & AHCI_PORT_CMD_ICC) >> 28, (pAhciPort->regCMD & AHCI_PORT_CMD_ASP) >> 27,
1336 (pAhciPort->regCMD & AHCI_PORT_CMD_ALPE) >> 26, (pAhciPort->regCMD & AHCI_PORT_CMD_DLAE) >> 25,
1337 (pAhciPort->regCMD & AHCI_PORT_CMD_ATAPI) >> 24, (pAhciPort->regCMD & AHCI_PORT_CMD_CPD) >> 20,
1338 (pAhciPort->regCMD & AHCI_PORT_CMD_ISP) >> 19, (pAhciPort->regCMD & AHCI_PORT_CMD_HPCP) >> 18,
1339 (pAhciPort->regCMD & AHCI_PORT_CMD_PMA) >> 17, (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) >> 16,
1340 (pAhciPort->regCMD & AHCI_PORT_CMD_CR) >> 15, (pAhciPort->regCMD & AHCI_PORT_CMD_FR) >> 14,
1341 (pAhciPort->regCMD & AHCI_PORT_CMD_ISS) >> 13, pAhciPort->u32CurrentCommandSlot,
1342 (pAhciPort->regCMD & AHCI_PORT_CMD_FRE) >> 4, (pAhciPort->regCMD & AHCI_PORT_CMD_CLO) >> 3,
1343 (pAhciPort->regCMD & AHCI_PORT_CMD_POD) >> 2, (pAhciPort->regCMD & AHCI_PORT_CMD_SUD) >> 1,
1344 (pAhciPort->regCMD & AHCI_PORT_CMD_ST)));
1345 *pu32Value = pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot);
1353 static int PortCmd_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1371 if (pAhciPort->fPoweredOn && pAhciPort->fSpunUp)
1387 if ( pAhciPort->pDrvBase
1388 && !(pAhciPort->regIS & AHCI_PORT_IS_PCS))
1394 if ( pAhciPort->regCI > 0
1395 && ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1397 ASMAtomicOrU32(&pAhciPort->u32TasksNew, pAhciPort->regCI);
1402 pItem->iPort = pAhciPort->iLUN;
1406 int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
1418 pAhciPort->regCI = 0;
1419 pAhciPort->regSACT = 0;
1421 pAhciPort->u32CurrentCommandSlot = 0;
1425 else if (pAhciPort->pDrvBase)
1427 if ((u32Value & AHCI_PORT_CMD_POD) && (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) && !pAhciPort->fPoweredOn)
1430 pAhciPort->fPoweredOn = true;
1435 if (pAhciPort->fATAPI)
1436 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1438 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1439 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1443 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
1448 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1449 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
1451 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
1453 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
1460 if ((u32Value & AHCI_PORT_CMD_SUD) && pAhciPort->fPoweredOn && !pAhciPort->fSpunUp)
1463 pAhciPort->fSpunUp = true;
1474 if ( !pAhciPort->fFirstD2HFisSend
1475 && pAhciPort->pDrvBase)
1480 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1481 pAhciPort->fFirstD2HFisSend = true;
1491 pAhciPort->regCMD = u32Value;
1499 static int PortIntrEnable_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1501 ahciLog(("%s: read regIE=%#010x\n", __FUNCTION__, pAhciPort->regIE));
1503 __FUNCTION__, (pAhciPort->regIE & AHCI_PORT_IE_CPDE) >> 31, (pAhciPort->regIE & AHCI_PORT_IE_TFEE) >> 30,
1504 (pAhciPort->regIE & AHCI_PORT_IE_HBFE) >> 29, (pAhciPort->regIE & AHCI_PORT_IE_HBDE) >> 28,
1505 (pAhciPort->regIE & AHCI_PORT_IE_IFE) >> 27, (pAhciPort->regIE & AHCI_PORT_IE_INFE) >> 26,
1506 (pAhciPort->regIE & AHCI_PORT_IE_OFE) >> 24, (pAhciPort->regIE & AHCI_PORT_IE_IPME) >> 23,
1507 (pAhciPort->regIE & AHCI_PORT_IE_PRCE) >> 22, (pAhciPort->regIE & AHCI_PORT_IE_DIE) >> 7,
1508 (pAhciPort->regIE & AHCI_PORT_IE_PCE) >> 6, (pAhciPort->regIE & AHCI_PORT_IE_DPE) >> 5,
1509 (pAhciPort->regIE & AHCI_PORT_IE_UFE) >> 4, (pAhciPort->regIE & AHCI_PORT_IE_SDBE) >> 3,
1510 (pAhciPort->regIE & AHCI_PORT_IE_DSE) >> 2, (pAhciPort->regIE & AHCI_PORT_IE_PSE) >> 1,
1511 (pAhciPort->regIE & AHCI_PORT_IE_DHRE)));
1512 *pu32Value = pAhciPort->regIE;
1519 static int PortIntrEnable_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1537 uint32_t u32IntrStatus = ASMAtomicReadU32(&pAhciPort->regIS);
1540 rc = ahciHbaSetInterrupt(ahci, pAhciPort->iLUN, VINF_IOM_R3_MMIO_WRITE);
1543 pAhciPort->regIE = u32Value;
1551 static int PortIntrSts_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1553 ahciLog(("%s: read regIS=%#010x\n", __FUNCTION__, pAhciPort->regIS));
1555 __FUNCTION__, (pAhciPort->regIS & AHCI_PORT_IS_CPDS) >> 31, (pAhciPort->regIS & AHCI_PORT_IS_TFES) >> 30,
1556 (pAhciPort->regIS & AHCI_PORT_IS_HBFS) >> 29, (pAhciPort->regIS & AHCI_PORT_IS_HBDS) >> 28,
1557 (pAhciPort->regIS & AHCI_PORT_IS_IFS) >> 27, (pAhciPort->regIS & AHCI_PORT_IS_INFS) >> 26,
1558 (pAhciPort->regIS & AHCI_PORT_IS_OFS) >> 24, (pAhciPort->regIS & AHCI_PORT_IS_IPMS) >> 23,
1559 (pAhciPort->regIS & AHCI_PORT_IS_PRCS) >> 22, (pAhciPort->regIS & AHCI_PORT_IS_DIS) >> 7,
1560 (pAhciPort->regIS & AHCI_PORT_IS_PCS) >> 6, (pAhciPort->regIS & AHCI_PORT_IS_DPS) >> 5,
1561 (pAhciPort->regIS & AHCI_PORT_IS_UFS) >> 4, (pAhciPort->regIS & AHCI_PORT_IS_SDBS) >> 3,
1562 (pAhciPort->regIS & AHCI_PORT_IS_DSS) >> 2, (pAhciPort->regIS & AHCI_PORT_IS_PSS) >> 1,
1563 (pAhciPort->regIS & AHCI_PORT_IS_DHRS)));
1564 *pu32Value = pAhciPort->regIS;
1571 static int PortIntrSts_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1574 ASMAtomicAndU32(&pAhciPort->regIS, ~(u32Value & AHCI_PORT_IS_READONLY));
1582 static int PortFisAddrUp_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1584 ahciLog(("%s: read regFBU=%#010x\n", __FUNCTION__, pAhciPort->regFBU));
1585 *pu32Value = pAhciPort->regFBU;
1592 static int PortFisAddrUp_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1596 pAhciPort->regFBU = u32Value;
1597 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1605 static int PortFisAddr_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1607 ahciLog(("%s: read regFB=%#010x\n", __FUNCTION__, pAhciPort->regFB));
1608 *pu32Value = pAhciPort->regFB;
1615 static int PortFisAddr_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1621 pAhciPort->regFB = (u32Value & AHCI_PORT_FB_RESERVED);
1622 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1630 static int PortCmdLstAddrUp_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1634 pAhciPort->regCLBU = u32Value;
1635 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1643 static int PortCmdLstAddrUp_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1645 ahciLog(("%s: read regCLBU=%#010x\n", __FUNCTION__, pAhciPort->regCLBU));
1646 *pu32Value = pAhciPort->regCLBU;
1653 static int PortCmdLstAddr_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1655 ahciLog(("%s: read regCLB=%#010x\n", __FUNCTION__, pAhciPort->regCLB));
1656 *pu32Value = pAhciPort->regCLB;
1663 static int PortCmdLstAddr_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1669 pAhciPort->regCLB = (u32Value & AHCI_PORT_CLB_RESERVED);
1670 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1724 PAHCIPort pAhciPort = &ahci->ahciPort[i];
1726 if (pAhciPort->regIE & pAhciPort->regIS)
1951 static int PortInvalid_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1960 static int PortInvalid_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
2007 * @param pAhciPort The port to reset.
2009 static void ahciPortSwReset(PAHCIPort pAhciPort)
2014 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort, NULL);
2017 pAhciPort->regIS = 0;
2018 pAhciPort->regIE = 0;
2019 pAhciPort->regCMD = AHCI_PORT_CMD_CPD | /* Cold presence detection */
2024 if (pAhciPort->fHotpluggable)
2025 pAhciPort->regCMD |= AHCI_PORT_CMD_HPCP;
2027 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
2028 pAhciPort->regSIG = ~0;
2029 pAhciPort->regSSTS = 0;
2030 pAhciPort->regSCTL = 0;
2031 pAhciPort->regSERR = 0;
2032 pAhciPort->regSACT = 0;
2033 pAhciPort->regCI = 0;
2035 pAhciPort->fResetDevice = false;
2036 pAhciPort->fPoweredOn = true;
2037 pAhciPort->fSpunUp = true;
2038 pAhciPort->cMultSectors = ATA_MAX_MULT_SECTORS;
2039 pAhciPort->uATATransferMode = ATA_MODE_UDMA | 6;
2041 pAhciPort->u32TasksNew = 0;
2042 pAhciPort->u32TasksRedo = 0;
2043 pAhciPort->u32TasksFinished = 0;
2044 pAhciPort->u32QueuedTasksFinished = 0;
2045 pAhciPort->u32CurrentCommandSlot = 0;
2047 pAhciPort->cTasksActive = 0;
2049 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
2050 ASMAtomicWriteU32(&pAhciPort->MediaTrackType, ATA_MEDIA_TYPE_UNKNOWN);
2052 if (pAhciPort->pDrvBase)
2054 pAhciPort->regCMD |= AHCI_PORT_CMD_CPS; /* Indicate that there is a device on that port */
2056 if (pAhciPort->fPoweredOn)
2061 if (pAhciPort->fATAPI)
2062 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
2064 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
2065 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
2077 static void ahciPortHwReset(PAHCIPort pAhciPort)
2080 pAhciPort->regCLB = 0;
2081 pAhciPort->regCLBU = 0;
2082 pAhciPort->regFB = 0;
2083 pAhciPort->regFBU = 0;
2086 pAhciPort->GCPhysAddrClb = 0;
2087 pAhciPort->GCPhysAddrFb = 0;
2129 PAHCIPort pAhciPort = &pThis->ahciPort[i];
2131 pAhciPort->iLUN = i;
2132 ahciPortSwReset(pAhciPort);
2650 PAHCIPort pAhciPort = PDMIBASE_2_PAHCIPORT(pInterface);
2651 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pAhciPort->IBase);
2652 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKPORT, &pAhciPort->IPort);
2653 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKASYNCPORT, &pAhciPort->IPortAsync);
2654 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pAhciPort->IMountNotify);
2664 PAHCIPort pAhciPort = PDMIBLOCKPORT_2_PAHCIPORT(pInterface);
2665 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
2673 *piLUN = pAhciPort->iLUN;
2684 * @param pAhciPort The port the command FIS was read from.
2687 static void ahciDumpFisInfo(PAHCIPort pAhciPort, uint8_t *cmdFis)
2766 * @param pAhciPort Pointer to the port the command header was read from.
2769 static void ahciDumpCmdHdrInfo(PAHCIPort pAhciPort, CmdHdr *pCmdHdr)
2800 * @param pAhciPort Pointer to the port which "receives" the FIS.
2802 static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort)
2806 pAhciPort->fFirstD2HFisSend = true;
2816 if (pAhciPort->fATAPI)
2831 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
2832 if (!pAhciPort->fATAPI)
2833 pAhciPort->regTFD |= ATA_STAT_READY;
2835 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
2842 * @param pAhciPort The port which "receives" the FIS.
2846 static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *pCmdFis)
2849 RTGCPHYS GCPhysAddrRecFis = pAhciPort->GCPhysAddrFb;
2852 ahciLog(("%s: pAhciPort=%p uFisType=%u pCmdFis=%p\n", __FUNCTION__, pAhciPort, uFisType, pCmdFis));
2854 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
2895 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrRecFis, pCmdFis, cbFis);
2957 static void atapiCmdOK(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
2964 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
2965 pAhciPort->abATAPISense[0] = 0x70;
2966 pAhciPort->abATAPISense[7] = 10;
2969 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, const uint8_t *pabATAPISense, size_t cbATAPISense)
2977 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
2978 memcpy(pAhciPort->abATAPISense, pabATAPISense, RT_MIN(cbATAPISense, sizeof(pAhciPort->abATAPISense)));
2983 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
2991 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
3029 static int ahciIdentifySS(PAHCIPort pAhciPort, void *pvBuf)
3037 p[1] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
3038 p[3] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
3041 p[6] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
3042 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
3046 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
3047 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
3057 p[54] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
3058 p[55] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
3059 p[56] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
3060 p[57] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors);
3061 p[58] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors >> 16);
3062 if (pAhciPort->cMultSectors)
3063 p[59] = RT_H2LE_U16(0x100 | pAhciPort->cMultSectors);
3064 if (pAhciPort->cTotalSectors <= (1 << 28) - 1)
3066 p[60] = RT_H2LE_U16(pAhciPort->cTotalSectors);
3067 p[61] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
3075 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
3081 if ( pAhciPort->pDrvBlock->pfnDiscard
3082 || ( pAhciPort->fAsyncInterface
3083 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)
3084 || pAhciPort->cbSector != 512
3085 || pAhciPort->fNonRotational)
3101 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
3103 p[100] = RT_H2LE_U16(pAhciPort->cTotalSectors);
3104 p[101] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
3105 p[102] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 32);
3106 p[103] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 48);
3109 if (pAhciPort->cLogSectorsPerPhysicalExp)
3110 p[106] = RT_H2LE_U16(RT_BIT(14) | RT_BIT(13) | pAhciPort->cLogSectorsPerPhysicalExp);
3112 if (pAhciPort->cbSector != 512)
3114 uint32_t cSectorSizeInWords = pAhciPort->cbSector / sizeof(uint16_t);
3121 if (pAhciPort->fNonRotational)
3124 if ( pAhciPort->pDrvBlock->pfnDiscard
3125 || ( pAhciPort->fAsyncInterface
3126 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */
3130 p[75] = RT_H2LE_U16(pAhciPort->CTX_SUFF(pAhci)->cCmdSlotsAvail-1); /* Number of commands we support, 0's based */
3208 static int atapiIdentifySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3215 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
3218 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
3219 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
3225 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
3241 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
3242 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((pAhciPort->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
3249 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&p[0],
3252 atapiCmdOK(pAhciPort, pAhciReq);
3256 static int atapiReadCapacitySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3260 ataH2BE_U32(aBuf, pAhciPort->cTotalSectors - 1);
3264 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3267 atapiCmdOK(pAhciPort, pAhciReq);
3272 static int atapiReadDiscInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3292 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3295 atapiCmdOK(pAhciPort, pAhciReq);
3300 static int atapiReadTrackInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3307 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3318 ataH2BE_U32(aBuf + 24, pAhciPort->cTotalSectors); /* track size */
3323 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3326 atapiCmdOK(pAhciPort, pAhciReq);
3330 static size_t atapiGetConfigurationFillFeatureListProfiles(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3348 static size_t atapiGetConfigurationFillFeatureCore(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3363 static size_t atapiGetConfigurationFillFeatureMorphing(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3377 static size_t atapiGetConfigurationFillFeatureRemovableMedium(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3392 static size_t atapiGetConfigurationFillFeatureRandomReadable(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3408 static size_t atapiGetConfigurationFillFeatureCDRead(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3422 static size_t atapiGetConfigurationFillFeaturePowerManagement(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3434 static size_t atapiGetConfigurationFillFeatureTimeout(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3447 static int atapiGetConfigurationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3457 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3462 if (pAhciPort->cTotalSectors)
3469 cbCopied = atapiGetConfigurationFillFeatureListProfiles(pAhciPort, pbBuf, cbBuf);
3473 cbCopied = atapiGetConfigurationFillFeatureCore(pAhciPort, pbBuf, cbBuf);
3477 cbCopied = atapiGetConfigurationFillFeatureMorphing(pAhciPort, pbBuf, cbBuf);
3481 cbCopied = atapiGetConfigurationFillFeatureRemovableMedium(pAhciPort, pbBuf, cbBuf);
3485 cbCopied = atapiGetConfigurationFillFeatureRandomReadable(pAhciPort, pbBuf, cbBuf);
3489 cbCopied = atapiGetConfigurationFillFeatureCDRead(pAhciPort, pbBuf, cbBuf);
3493 cbCopied = atapiGetConfigurationFillFeaturePowerManagement(pAhciPort, pbBuf, cbBuf);
3497 cbCopied = atapiGetConfigurationFillFeatureTimeout(pAhciPort, pbBuf, cbBuf);
3505 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3508 atapiCmdOK(pAhciPort, pAhciReq);
3513 static int atapiGetEventStatusNotificationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3523 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3530 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus);
3580 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
3582 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&abBuf[0],
3585 atapiCmdOK(pAhciPort, pAhciReq);
3590 static int atapiInquirySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3602 ataSCSIPadStr(aBuf + 8, pAhciPort->szInquiryVendorId, 8);
3603 ataSCSIPadStr(aBuf + 16, pAhciPort->szInquiryProductId, 16);
3604 ataSCSIPadStr(aBuf + 32, pAhciPort->szInquiryRevision, 4);
3607 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3610 atapiCmdOK(pAhciPort, pAhciReq);
3615 static int atapiModeSenseErrorRecoverySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3637 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3640 atapiCmdOK(pAhciPort, pAhciReq);
3645 static int atapiModeSenseCDStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3667 if (pAhciPort->pDrvMount->pfnIsLocked(pAhciPort->pDrvMount))
3688 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3691 atapiCmdOK(pAhciPort, pAhciReq);
3696 static int atapiRequestSenseSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3699 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
3700 pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)));
3702 atapiCmdOK(pAhciPort, pAhciReq);
3707 static int atapiMechanismStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3720 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3723 atapiCmdOK(pAhciPort, pAhciReq);
3728 static int atapiReadTOCNormalSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3738 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3771 ataLBA2MSF(q, pAhciPort->cTotalSectors);
3776 ataH2BE_U32(q, pAhciPort->cTotalSectors);
3783 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3786 atapiCmdOK(pAhciPort, pAhciReq);
3791 static int atapiReadTOCMultiSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3817 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3820 atapiCmdOK(pAhciPort, pAhciReq);
3825 static int atapiReadTOCRawSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3873 ataLBA2MSF(q, pAhciPort->cTotalSectors);
3878 ataH2BE_U32(q, pAhciPort->cTotalSectors);
3906 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3909 atapiCmdOK(pAhciPort, pAhciReq);
3916 static uint32_t ahciMediumTypeSet(PAHCIPort pAhciPort, uint32_t MediaTrackType)
3918 return ASMAtomicXchgU32(&pAhciPort->MediaTrackType, MediaTrackType);
3921 static int atapiPassthroughSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3938 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
3949 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
3951 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
3986 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
3987 LogRel(("AHCI: LUN#%d: CD-ROM passthrough split error\n", pAhciPort->iLUN));
3988 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
4023 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
4052 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
4067 pAhciPort->Led.Actual.s.fReading = 0;
4068 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbTransfer);
4072 pAhciPort->Led.Actual.s.fWriting = 0;
4073 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbTransfer);
4085 if (!pAhciPort->pTrackList)
4086 rc = ATAPIPassthroughTrackListCreateEmpty(&pAhciPort->pTrackList);
4089 rc = ATAPIPassthroughTrackListUpdate(pAhciPort->pTrackList, pAhciReq->aATAPICmd, pvBuf);
4092 && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
4099 if (pAhciPort->pTrackList)
4100 ATAPIPassthroughTrackListClear(pAhciPort->pTrackList);
4127 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf,
4135 atapiCmdOK(pAhciPort, pAhciReq);
4139 if (pAhciPort->cErrors < MAX_LOG_REL_ERRORS)
4151 pAhciPort->cErrors++;
4153 pAhciPort->iLUN, u8Cmd, abATAPISense[2] & 0x0f, abATAPISense[12], abATAPISense[13], rc));
4156 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
4167 static int atapiReadDVDStructureSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
4217 total_sectors = pAhciPort->cTotalSectors;
4297 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, -uASC);
4312 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST,
4318 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
4321 atapiCmdOK(pAhciPort, pAhciReq);
4325 static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbMax, ATAPIFN iSourceSink)
4330 rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciReq, pAhciPort, cbMax,
4339 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
4384 static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
4409 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4422 if (pAhciPort->cNotifiedMediaChange > 0)
4424 if (pAhciPort->cNotifiedMediaChange-- > 2)
4425 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4427 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4429 else if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4430 atapiCmdOK(pAhciPort, pAhciReq);
4432 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4436 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
4450 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
4453 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
4465 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
4472 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_REQUEST_SENSE);
4475 if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4478 pAhciPort->pDrvMount->pfnLock(pAhciPort->pDrvMount);
4480 pAhciPort->pDrvMount->pfnUnlock(pAhciPort->pDrvMount);
4481 atapiCmdOK(pAhciPort, pAhciReq);
4484 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4491 if (pAhciPort->cNotifiedMediaChange > 0)
4493 pAhciPort->cNotifiedMediaChange-- ;
4494 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4497 if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4499 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4509 atapiCmdOK(pAhciPort, pAhciReq);
4512 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
4521 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
4524 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4527 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
4535 if (pAhciPort->cNotifiedMediaChange > 0)
4537 pAhciPort->cNotifiedMediaChange-- ;
4538 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4541 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4543 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4550 atapiCmdOK(pAhciPort, pAhciReq);
4553 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
4562 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
4565 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4572 atapiCmdOK(pAhciPort, pAhciReq);
4576 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
4581 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
4585 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
4586 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4594 if (pAhciPort->cNotifiedMediaChange > 0)
4596 pAhciPort->cNotifiedMediaChange-- ;
4597 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4600 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4602 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4606 if (iATAPILBA > pAhciPort->cTotalSectors)
4615 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
4618 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4621 atapiCmdOK(pAhciPort, pAhciReq);
4636 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
4646 if (pAhciPort->aCachedTasks[i])
4647 ahciReqMemFree(pAhciPort, pAhciPort->aCachedTasks[i], true /* fForceFree */);
4651 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
4652 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
4658 pAhci->pMediaNotify, pAhciPort->iLUN);
4668 atapiCmdOK(pAhciPort, pAhciReq);
4670 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
4676 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
4683 if (pAhciPort->cNotifiedMediaChange > 0)
4685 pAhciPort->cNotifiedMediaChange-- ;
4686 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4689 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4691 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4702 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
4705 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
4708 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
4712 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4718 if (pAhciPort->cNotifiedMediaChange > 0)
4720 pAhciPort->cNotifiedMediaChange-- ;
4721 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4724 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4726 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4729 atapiDoTransfer(pAhciPort, pAhciReq, 8 /* cbMax */, ATAFN_SS_ATAPI_READ_CAPACITY);
4732 if (pAhciPort->cNotifiedMediaChange > 0)
4734 pAhciPort->cNotifiedMediaChange-- ;
4735 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4738 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4740 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4744 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);
4747 if (pAhciPort->cNotifiedMediaChange > 0)
4749 pAhciPort->cNotifiedMediaChange-- ;
4750 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4753 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4755 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4759 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION);
4764 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_CONFIGURATION);
4768 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_INQUIRY);
4772 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DVD_STRUCTURE);
4775 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
4785 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4815 if (ASMAtomicReadU32(&pAhciPort->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
4818 atapiDoTransfer(pAhciPort, pAhciReq, pAhciReq->cbTransfer, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
4899 if (pAhciPort->pTrackList)
4900 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iLbaStart);
4969 if ((pAhciPort->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
4973 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE);
5027 if (pAhciPort->pTrackList)
5028 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
5038 if (pAhciPort->pTrackList)
5039 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
5054 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", pAhciPort->iLUN));
5055 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
5073 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
5076 LogRel(("AHCI: LUN#%d: passthrough unimplemented for command %#x\n", pAhciPort->iLUN, pbPacket[0]));
5077 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
5086 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH);
5092 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5098 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0], SCSICmdText(pbPacket[0])));
5101 if (pAhciPort->fATAPIPassthrough)
5102 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
5104 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
5113 * @param pAhciPort The port the device is attached to.
5116 static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5121 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
5122 pAhciPort->fResetDevice = false;
5123 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5124 ahciPostFirstD2HFisIntoMemory(pAhciPort);
5127 if (pAhciPort->fATAPI)
5128 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
5130 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
5131 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5133 rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
5141 * @param pAhciPort The device to reset.
5144 static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5146 ASMAtomicWriteBool(&pAhciPort->fResetDevice, true);
5153 Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0);
5154 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
5161 * @param pAhciPort The port of the SATA controller.
5166 static void ahciSendPioSetupFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis,
5171 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5179 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5203 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5205 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_PIOSETUP, abPioSetupFis);
5209 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PSS);
5211 if (pAhciPort->regIE & AHCI_PORT_IE_PSE)
5217 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5227 * @param pAhciPort The port of the SATA controller.
5232 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt)
5236 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5240 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5258 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5260 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
5265 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
5266 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
5275 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
5277 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
5281 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5286 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5296 * @param pAhciPort The port for which the SDB Fis is send.
5300 static void ahciSendSDBFis(PAHCIPort pAhciPort, uint32_t uFinishedTasks, bool fInterrupt)
5304 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5305 PAHCIREQ pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ);
5309 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5320 pAhciPort->regTFD = (pTaskErr->uATARegError << 8) | pTaskErr->uATARegStatus;
5326 pAhciPort->regTFD = ATA_STAT_READY | ATA_STAT_SEEK;
5329 sdbFis[1] = pAhciPort->u32QueuedTasksFinished | uFinishedTasks;
5331 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_SETDEVBITS, (uint8_t *)sdbFis);
5336 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
5337 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
5343 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_SDBS);
5345 if (pAhciPort->regIE & AHCI_PORT_IE_SDBE)
5349 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, uFinishedTasks);
5353 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5378 static uint64_t ahciGetSector(PAHCIPort pAhciPort, uint8_t *pCmdFis, bool fLBA48)
5404 iLBA = ((pCmdFis[AHCI_CMDFIS_CYLH] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors +
5405 (pCmdFis[AHCI_CMDFIS_HEAD] & 0x0f) * pAhciPort->PCHSGeometry.cSectors +
5442 * @param pAhciPort The AHCI port.
5446 static void *ahciReqMemAlloc(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cb)
5455 pAhciPort->pDrvBlock->pfnIoBufFree(pAhciPort->pDrvBlock, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5459 int rc = pAhciPort->pDrvBlock->pfnIoBufAlloc(pAhciPort->pDrvBlock, pAhciReq->cbAlloc, &pAhciReq->pvAlloc);
5475 * @param pAhciPort The AHCI port.
5479 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree)
5486 pAhciPort->pDrvBlock->pfnIoBufFree(pAhciPort->pDrvBlock, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5603 * @param pAhciPort The AHCI port.
5607 static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer)
5613 pAhciReq->u.Io.DataSeg.pvSeg = ahciReqMemAlloc(pAhciPort, pAhciReq, cbTransfer);
5620 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq,
5631 * @param pAhciPort The AHCI port.
5636 static void ahciIoBufFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq,
5654 pAhciReq->cbTransfer = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pv, cb);
5659 ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
5664 ahciReqMemFree(pAhciPort, pAhciReq, false /* fForceFree */);
5674 * @param pAhciPort The AHCI port.
5676 static void ahciR3PortCachedReqsFree(PAHCIPort pAhciPort)
5680 if (pAhciPort->aCachedTasks[i])
5682 ahciReqMemFree(pAhciPort, pAhciPort->aCachedTasks[i], true /* fForceFree */);
5683 RTMemFree(pAhciPort->aCachedTasks[i]);
5684 pAhciPort->aCachedTasks[i] = NULL;
5693 * @param pAhciPort The ahci port.
5697 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort, PAHCIREQ pAhciReqExcept)
5699 for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aCachedTasks); i++)
5701 PAHCIREQ pAhciReq = pAhciPort->aCachedTasks[i];
5711 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
5713 ASMAtomicDecU32(&pAhciPort->cTasksActive);
5719 ASMAtomicWriteNullPtr(&pAhciPort->aCachedTasks[i]);
5720 LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
5721 pAhciPort->iLUN, pAhciReq->uTag));
5764 bool ahciIsRedoSetWarning(PAHCIPort pAhciPort, int rc)
5768 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5769 ahciWarningDiskFull(pAhciPort->CTX_SUFF(pDevIns));
5774 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5775 ahciWarningFileTooBig(pAhciPort->CTX_SUFF(pDevIns));
5782 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5783 ahciWarningISCSI(pAhciPort->CTX_SUFF(pDevIns));
5789 ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false);
5800 * @param pAhciPort AHCI port state.
5803 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5811 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
5814 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
5900 pAhciReq->u.Trim.paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;
5901 pAhciReq->u.Trim.paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;
5938 * @param pAhciPort Pointer to the port where to request completed.
5943 static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq, bool fFreeReq)
5951 LogFlowFunc(("pAhciPort=%p pAhciReq=%p rcReq=%d fFreeReq=%RTbool\n",
5952 pAhciPort, pAhciReq, rcReq, fFreeReq));
5985 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, pcszReq, (tsNow - pAhciReq->tsStart) / 1000));
5988 bool fPortReset = ASMAtomicReadBool(&pAhciPort->fPortReset);
5995 ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */);
5996 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
5997 pAhciPort->Led.Actual.s.fReading = 0;
6001 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
6002 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
6003 pAhciPort->Led.Actual.s.fWriting = 0;
6008 pAhciPort->Led.Actual.s.fWriting = 0;
6014 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
6018 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
6021 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
6024 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
6032 fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq);
6038 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
6041 ASMAtomicOrU32(&pAhciPort->u32TasksRedo, RT_BIT_32(pAhciReq->uTag));
6055 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
6064 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
6065 if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
6066 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
6070 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0 ,
6072 ASMAtomicDecU32(&pAhciPort->cTasksActive);
6079 ahciSendPioSetupFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false /* fInterrupt */);
6083 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ))
6084 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(pAhciReq->uTag));
6094 ahciSendSDBFis(pAhciPort, 0, true);
6097 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6116 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0 ,
6118 ASMAtomicDecU32(&pAhciPort->cTasksActive);
6127 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
6130 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
6134 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
6137 pAhciPort->CTX_SUFF(pDevIns)->iInstance,pAhciPort->iLUN, rcReq));
6140 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
6153 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
6154 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
6169 PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);
6175 ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
6186 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
6200 if (pAhciPort->pDrvBlock && !pAhciPort->fATAPI)
6206 ahciIdentifySS(pAhciPort, u16Temp);
6209 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6250 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_MDMA_MODE_MAX);
6253 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_UDMA_MODE_MAX);
6266 if (!pAhciPort->fATAPI)
6274 ahciDeviceReset(pAhciPort, pAhciReq);
6283 if (!pAhciPort->fATAPI)
6289 enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
6292 if (!pAhciPort->fATAPI)
6299 atapiDoTransfer(pAhciPort, pAhciReq, 512, ATAFN_SS_ATAPI_IDENTIFY);
6317 pAhciPort->cMultSectors = pCmdFis[AHCI_CMDFIS_SECTC];
6342 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
6343 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
6351 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
6352 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
6358 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
6359 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
6366 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
6367 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
6392 PAHCIREQ pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIREQ);
6418 ahciIoBufFree(pAhciPort, pTaskErr, false /* fCopyToGuest */);
6430 bool fAbortedAll = ahciCancelActiveTasks(pAhciPort, pAhciReq);
6432 ahciSendSDBFis(pAhciPort, 0xffffffff, true);
6439 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6450 if ( ( !pAhciPort->fAsyncInterface
6451 && pAhciPort->pDrvBlock->pfnDiscard)
6452 || ( pAhciPort->fAsyncInterface
6453 && pAhciPort->pDrvBlockAsync->pfnStartDiscard))
6491 static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
6495 AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb,
6504 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
6507 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
6511 ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr);
6522 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
6535 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE);
6545 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false);
6546 pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY;
6554 ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]);
6565 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysPrdtl, &SGEntry, sizeof(SGLEntry));
6590 PAHCIPort pAhciPort = &pThis->ahciPort[pNotifierItem->iPort];
6595 rc = SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
6604 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
6605 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
6613 ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN));
6624 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true);
6625 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
6628 Assert(ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping));
6629 rc = SUPSemEventWaitNoResume(pAhci->pSupDrvSession, pAhciPort->hEvtProcess, RT_INDEFINITE_WAIT);
6634 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
6637 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false);
6644 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
6658 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
6664 && !pAhciPort->fPortReset)
6678 if (!pAhciPort->aCachedTasks[idx])
6683 pAhciPort->aCachedTasks[idx] = pAhciReq;
6686 pAhciReq = pAhciPort->aCachedTasks[idx];
6698 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
6700 bool fFisRead = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
6719 if (pAhciPort->regSACT & (1 << idx))
6722 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
6731 pAhciPort->fResetDevice = true;
6732 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6734 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
6735 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
6745 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) < AHCI_NR_COMMAND_SLOTS,
6747 ASMAtomicIncU32(&pAhciPort->cTasksActive);
6749 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
6757 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
6759 rc = ahciIoBufAllocate(pAhciPort, pAhciReq, pAhciReq->cbTransfer);
6770 if (pAhciPort->fAsyncInterface)
6776 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
6781 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6784 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6785 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
6791 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
6792 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6799 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6800 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6806 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
6808 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6813 rc = pAhciPort->pDrvBlock->pfnFlush(pAhciPort->pDrvBlock);
6816 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6819 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6820 rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock, pAhciReq->u.Trim.paRanges,
6822 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
6827 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
6828 rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6831 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 0;
6835 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6836 rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6839 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
6841 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6846 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
6861 if ( ASMAtomicReadBool(&pAhciPort->fPortReset)
6862 && (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT)
6863 ahciPortResetFinish(pAhciPort);
6876 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
6879 ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
6893 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
6894 return SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
7327 PAHCIPort pAhciPort = &pThis->ahciPort[i];
7380 uint32_t fTasksOutstanding = pAhciPort->regCI & ~pAhciPort->u32TasksFinished;
7381 uint32_t fQueuedTasksOutstanding = pAhciPort->regSACT & ~pAhciPort->u32QueuedTasksFinished;
7383 pAhciPort->u32TasksNew = fTasksOutstanding | fQueuedTasksOutstanding;
7385 if (pAhciPort->u32TasksNew)
7391 pAhciPort->fRedo = true;
7428 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
7429 pAhciPort->pAhciRC += offDelta;
7430 pAhciPort->pDevInsRC += offDelta;
7438 static void ahciMediumRemoved(PAHCIPort pAhciPort)
7440 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED);
7448 static void ahciMediumInserted(PAHCIPort pAhciPort)
7453 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus);
7465 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
7475 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);
7476 Log(("%s: changing LUN#%d\n", __FUNCTION__, pAhciPort->iLUN));
7479 if (!pAhciPort->pDrvBlock)
7482 if (pAhciPort->fATAPI)
7484 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048;
7486 LogRel(("AHCI: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pAhciPort->iLUN, pAhciPort->cTotalSectors));
7489 if (pAhciPort->cNotifiedMediaChange < 2)
7490 pAhciPort->cNotifiedMediaChange = 2;
7491 ahciMediumInserted(pAhciPort);
7492 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7504 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);
7507 pAhciPort->cTotalSectors = 0;
7509 if (pAhciPort->fATAPI)
7517 pAhciPort->cNotifiedMediaChange = 4;
7518 ahciMediumRemoved(pAhciPort);
7519 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7532 * @param pAhciPort The port for which the device is to be configured.
7534 static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort)
7542 pAhciPort->pDrvBlock = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCK);
7543 if (!pAhciPort->pDrvBlock)
7545 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN));
7548 pAhciPort->pDrvBlockBios = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCKBIOS);
7549 if (!pAhciPort->pDrvBlockBios)
7551 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block BIOS interface!\n", pAhciPort->iLUN));
7555 pAhciPort->pDrvMount = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMOUNT);
7558 pAhciPort->pDrvBlockAsync = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCKASYNC);
7563 enmType = pAhciPort->pDrvBlock->pfnGetType(pAhciPort->pDrvBlock);
7569 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType));
7574 && !pAhciPort->pDrvMount)
7579 pAhciPort->fATAPI = (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD);
7580 pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? (pAhciPort->pDrvBlock->pfnSendCmd != NULL) : false;
7582 if (pAhciPort->fATAPI)
7584 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048;
7585 pAhciPort->PCHSGeometry.cCylinders = 0;
7586 pAhciPort->PCHSGeometry.cHeads = 0;
7587 pAhciPort->PCHSGeometry.cSectors = 0;
7588 LogRel(("AHCI LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pAhciPort->iLUN, pAhciPort->cTotalSectors, (pAhciPort->fATAPIPassthrough ? "enabled" : "disabled")));
7592 pAhciPort->cbSector = pAhciPort->pDrvBlock->pfnGetSectorSize(pAhciPort->pDrvBlock);
7593 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / pAhciPort->cbSector;
7594 rc = pAhciPort->pDrvBlockBios->pfnGetPCHSGeometry(pAhciPort->pDrvBlockBios,
7595 &pAhciPort->PCHSGeometry);
7598 pAhciPort->PCHSGeometry.cCylinders = 0;
7599 pAhciPort->PCHSGeometry.cHeads = 16; /*??*/
7600 pAhciPort->PCHSGeometry.cSectors = 63; /*??*/
7604 pAhciPort->PCHSGeometry.cCylinders = 0; /* autodetect marker */
7609 if ( pAhciPort->PCHSGeometry.cCylinders == 0
7610 || pAhciPort->PCHSGeometry.cHeads == 0
7611 || pAhciPort->PCHSGeometry.cSectors == 0)
7613 uint64_t cCylinders = pAhciPort->cTotalSectors / (16 * 63);
7614 pAhciPort->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
7615 pAhciPort->PCHSGeometry.cHeads = 16;
7616 pAhciPort->PCHSGeometry.cSectors = 63;
7618 pAhciPort->pDrvBlockBios->pfnSetPCHSGeometry(pAhciPort->pDrvBlockBios,
7619 &pAhciPort->PCHSGeometry);
7623 pAhciPort->iLUN, pAhciPort->PCHSGeometry.cCylinders,
7624 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors,
7625 pAhciPort->cTotalSectors));
7626 if (pAhciPort->pDrvBlock->pfnDiscard)
7627 LogRel(("AHCI: LUN#%d: Enabled TRIM support\n", pAhciPort->iLUN));
7703 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
7705 if (pAhciPort->u32TasksRedo)
7710 pAhciPort->u32TasksNew |= pAhciPort->u32TasksRedo;
7711 pAhciPort->u32TasksRedo = 0;
7713 Assert(pAhciPort->fRedo);
7714 pAhciPort->fRedo = false;
7729 * @param pAhciPort The attached device.
7732 static int ahciR3VpdInit(PPDMDEVINS pDevIns, PAHCIPort pAhciPort, const char *pszName)
7741 if (pAhciPort->pDrvBlock)
7742 rc = pAhciPort->pDrvBlock->pfnGetUuid(pAhciPort->pDrvBlock, &Uuid);
7750 pAhciPort->iLUN);
7757 rc = CFGMR3QueryStringDef(pCfgNode, "SerialNumber", pAhciPort->szSerialNumber, sizeof(pAhciPort->szSerialNumber),
7768 rc = CFGMR3QueryStringDef(pCfgNode, "FirmwareRevision", pAhciPort->szFirmwareRevision, sizeof(pAhciPort->szFirmwareRevision),
7779 rc = CFGMR3QueryStringDef(pCfgNode, "ModelNumber", pAhciPort->szModelNumber, sizeof(pAhciPort->szModelNumber),
7780 pAhciPort->fATAPI ? "VBOX CD-ROM" : "VBOX HARDDISK");
7790 rc = CFGMR3QueryBoolDef(pCfgNode, "NonRotationalMedium", &pAhciPort->fNonRotational, false);
7795 rc = CFGMR3QueryU8Def(pCfgNode, "LogicalSectorsPerPhysical", &pAhciPort->cLogSectorsPerPhysicalExp, 0);
7799 if (pAhciPort->cLogSectorsPerPhysicalExp >= 16)
7804 if (pAhciPort->fATAPI)
7806 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIVendorId", pAhciPort->szInquiryVendorId, sizeof(pAhciPort->szInquiryVendorId),
7817 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIProductId", pAhciPort->szInquiryProductId, sizeof(pAhciPort->szInquiryProductId),
7828 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIRevision", pAhciPort->szInquiryRevision, sizeof(pAhciPort->szInquiryRevision),
7857 PAHCIPort pAhciPort = &pAhci->ahciPort[iLUN];
7863 AssertMsgReturnVoid( pAhciPort->fHotpluggable
7865 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN));
7868 if (pAhciPort->pAsyncIOThread)
7872 rc = PDMR3ThreadDestroy(pAhciPort->pAsyncIOThread, &rcThread);
7876 pAhciPort->pAsyncIOThread = NULL;
7877 pAhciPort->fWrkThreadSleeping = true;
7880 if (pAhciPort->fATAPI)
7881 ahciMediumRemoved(pAhciPort);
7884 ahciR3PortCachedReqsFree(pAhciPort);
7891 pAhciPort->regSSTS = 0;
7892 pAhciPort->regSIG = 0;
7897 ASMAtomicAndU32(&pAhciPort->regCMD, ~(AHCI_PORT_CMD_CPS | AHCI_PORT_CMD_CR));
7898 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
7899 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
7900 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
7901 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
7902 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
7903 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
7909 pAhciPort->pDrvBase = NULL;
7910 pAhciPort->pDrvBlock = NULL;
7911 pAhciPort->pDrvBlockAsync = NULL;
7912 pAhciPort->pDrvBlockBios = NULL;
7929 PAHCIPort pAhciPort = &pThis->ahciPort[iLUN];
7936 AssertRelease(!pAhciPort->pDrvBase);
7937 AssertRelease(!pAhciPort->pDrvBlock);
7938 AssertRelease(!pAhciPort->pDrvBlockAsync);
7939 Assert(pAhciPort->iLUN == iLUN);
7941 AssertMsgReturn( pAhciPort->fHotpluggable
7943 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
7950 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, NULL);
7953 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
7958 ahciMediumInserted(pAhciPort);
7959 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7962 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pAhciPort->iLUN, rc));
7966 pAhciPort->pDrvBase = NULL;
7967 pAhciPort->pDrvBlock = NULL;
7974 if ( pAhciPort->pDrvBlockAsync
7975 && !pAhciPort->fATAPI)
7976 pAhciPort->fAsyncInterface = true;
7978 pAhciPort->fAsyncInterface = false;
7980 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
7986 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop, ahciAsyncIOLoopWakeUp, 0,
7995 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
8001 AssertMsgReturn(pAhciPort->fHotpluggable,
8002 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
8008 ASMAtomicOrU32(&pAhciPort->regCMD, AHCI_PORT_CMD_CPS);
8009 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
8010 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
8012 if (pAhciPort->fATAPI)
8013 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
8015 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
8016 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
8020 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
8021 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
8022 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
8023 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
8123 PAHCIPort pAhciPort = &pThis->ahciPort[iActPort];
8125 if (pAhciPort->hEvtProcess != NIL_SUPSEMEVENT)
8127 SUPSemEventClose(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
8128 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
8133 Assert(!pAhciPort->aCachedTasks[i]);
8274 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8275 pAhciPort->pDevInsR3 = pDevIns;
8276 pAhciPort->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
8277 pAhciPort->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
8278 pAhciPort->iLUN = i;
8279 pAhciPort->pAhciR3 = pThis;
8280 pAhciPort->pAhciR0 = PDMINS_2_DATA_R0PTR(pDevIns);
8281 pAhciPort->pAhciRC = PDMINS_2_DATA_RCPTR(pDevIns);
8282 pAhciPort->Led.u32Magic = PDMLED_MAGIC;
8283 pAhciPort->pDrvBase = NULL;
8284 pAhciPort->pAsyncIOThread = NULL;
8285 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
8286 pAhciPort->fHotpluggable = true;
8393 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8395 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatDMA, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
8397 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
8399 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
8401 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatIORequestsPerSecond, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
8404 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileProcessTime, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
8406 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileReadWrite, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
8410 ahciPortHwReset(pAhciPort);
8419 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8423 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface;
8424 pAhciPort->IPortAsync.pfnTransferCompleteNotify = ahciR3TransferCompleteNotify;
8425 pAhciPort->IPort.pfnQueryDeviceLocation = ahciR3PortQueryDeviceLocation;
8426 pAhciPort->IMountNotify.pfnMountNotify = ahciR3MountNotify;
8427 pAhciPort->IMountNotify.pfnUnmountNotify = ahciR3UnmountNotify;
8428 pAhciPort->fWrkThreadSleeping = true;
8434 rc = CFGMR3QueryBoolDef(pCfgPort, "Hotpluggable", &pAhciPort->fHotpluggable, true);
8443 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, szName);
8446 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
8460 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
8469 if (pAhciPort->pDrvBlockAsync && pThis->fUseAsyncInterfaceIfAvailable)
8471 LogRel(("AHCI: LUN#%d: using async I/O\n", pAhciPort->iLUN));
8472 pAhciPort->fAsyncInterface = true;
8476 LogRel(("AHCI: LUN#%d: using normal I/O\n", pAhciPort->iLUN));
8477 pAhciPort->fAsyncInterface = false;
8480 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
8485 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
8493 pAhciPort->pDrvBase = NULL;