Lines Matching defs:pAhciReq

234  * @param   pAhciReq    The task state.
239 typedef DECLCALLBACK(int) FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc);
940 static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
942 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
945 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree);
2957 static void atapiCmdOK(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
2959 pAhciReq->uATARegError = 0;
2960 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
2961 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
2962 | ((pAhciReq->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)
2963 | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
2969 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, const uint8_t *pabATAPISense, size_t cbATAPISense)
2973 pAhciReq->uATARegError = pabATAPISense[2] << 4;
2974 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
2975 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7) |
2983 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
2991 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
3208 static int atapiIdentifySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
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)
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)
3305 if ((pAhciReq->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciReq->aATAPICmd[2]) != 1)
3307 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3323 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3326 atapiCmdOK(pAhciPort, pAhciReq);
3447 static int atapiGetConfigurationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3455 if ((pAhciReq->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciReq->aATAPICmd[2]) != 0)
3457 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
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)
3517 Assert(pAhciReq->enmTxDir == AHCITXDIR_READ);
3518 Assert(pAhciReq->cbTransfer <= 8);
3520 if (!(pAhciReq->aATAPICmd[1] & 1))
3523 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
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)
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)
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,
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)
3734 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
3735 iStartTrack = pAhciReq->aATAPICmd[6];
3738 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
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)
3796 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
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)
3832 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
3833 iStartTrack = pAhciReq->aATAPICmd[6];
3906 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3909 atapiCmdOK(pAhciPort, pAhciReq);
3921 static int atapiPassthroughSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3928 cbTransfer = pAhciReq->cbTransfer;
3936 if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
3938 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
3939 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
3948 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
3963 switch (pAhciReq->aATAPICmd[0])
3968 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3969 cSectors = ataBE2H_U16(pAhciReq->aATAPICmd + 7);
3973 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3974 cSectors = ataBE2H_U32(pAhciReq->aATAPICmd + 6);
3977 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3978 cSectors = ataBE2H_U24(pAhciReq->aATAPICmd + 6);
3981 iATAPILBA = ataMSF2LBA(pAhciReq->aATAPICmd + 3);
3982 cSectors = ataMSF2LBA(pAhciReq->aATAPICmd + 6) - iATAPILBA;
3985 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciReq->aATAPICmd[0]));
3988 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
3992 memcpy(aATAPICmd, pAhciReq->aATAPICmd, ATAPI_PACKET_SIZE);
3996 if (i * pAhciReq->cbATAPISector > SCSI_MAX_BUFFER_SIZE)
3997 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciReq->cbATAPISector;
4000 cbCurrTX = pAhciReq->cbATAPISector * cReqSectors;
4001 switch (pAhciReq->aATAPICmd[0])
4025 pAhciReq->enmTxDir == AHCITXDIR_READ
4036 pbBuf += pAhciReq->cbATAPISector * cReqSectors;
4043 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
4045 else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
4047 else if (pAhciReq->enmTxDir == AHCITXDIR_NONE)
4050 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmTxDir));
4053 pAhciReq->aATAPICmd,
4065 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
4080 switch (pAhciReq->aATAPICmd[0])
4089 rc = ATAPIPassthroughTrackListUpdate(pAhciPort->pTrackList, pAhciReq->aATAPICmd, pvBuf);
4094 rc, pAhciReq->aATAPICmd[0] == SCSI_SEND_CUE_SHEET ? "SEND CUE SHEET" : "READ TOC/PMA/ATIP"));
4105 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
4107 Assert(cbTransfer <= pAhciReq->cbTransfer);
4109 if (pAhciReq->aATAPICmd[0] == SCSI_INQUIRY)
4127 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf,
4135 atapiCmdOK(pAhciPort, pAhciReq);
4141 uint8_t u8Cmd = pAhciReq->aATAPICmd[0];
4156 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
4167 static int atapiReadDVDStructureSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
4171 int media = pAhciReq->aATAPICmd[1];
4172 int format = pAhciReq->aATAPICmd[7];
4174 uint16_t max_len = RT_MIN(ataBE2H_U16(&pAhciReq->aATAPICmd[8]), sizeof(aBuf));
4208 int layer = pAhciReq->aATAPICmd[6];
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,
4333 pAhciReq->cmdHdr.u32PRDBC = cbTransfered;
4334 pAhciReq->cbTransfer = cbTransfered;
4339 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
4344 static int atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc)
4347 uint32_t cSectors = pAhciReq->cbTransfer / 2048;
4348 uint32_t iATAPILBA = pAhciReq->uOffset / 2048;
4350 uint8_t *pbBufSrc = (uint8_t *)pAhciReq->u.Io.DataSeg.pvSeg;
4351 size_t cbAlloc = pAhciReq->cbTransfer + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */
4384 static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
4391 pAhciReq->uOffset = (uint64_t)iATAPILBA * cbSector;
4392 pAhciReq->cbTransfer = cSectors * cbSector;
4396 pAhciReq->u.Io.pfnPostProcess = atapiReadSectors2352PostProcess;
4397 pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048;
4398 pAhciReq->cbTransfer = cSectors * 2048;
4409 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4415 pbPacket = pAhciReq->aATAPICmd;
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 */
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);
4481 atapiCmdOK(pAhciPort, pAhciReq);
4484 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4494 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4499 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4509 atapiCmdOK(pAhciPort, pAhciReq);
4524 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4527 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
4538 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4543 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4550 atapiCmdOK(pAhciPort, pAhciReq);
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);
4586 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4597 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4602 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4618 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4621 atapiCmdOK(pAhciPort, pAhciReq);
4622 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
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);
4686 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
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);
4721 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4726 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4729 atapiDoTransfer(pAhciPort, pAhciReq, 8 /* cbMax */, ATAFN_SS_ATAPI_READ_CAPACITY);
4735 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4740 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4744 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);
4750 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
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)
4792 pbPacket = pAhciReq->aATAPICmd;
4806 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
4817 pAhciReq->cbTransfer = RT_MIN(cbTransfer, 8);
4818 atapiDoTransfer(pAhciPort, pAhciReq, pAhciReq->cbTransfer, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
4824 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
4860 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
4861 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4868 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
4869 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4900 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iLbaStart);
4902 pAhciReq->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
4906 pAhciReq->cbATAPISector = 2352;
4909 pAhciReq->cbATAPISector = 2048;
4912 pAhciReq->cbATAPISector = 2336;
4915 pAhciReq->cbATAPISector = 2048;
4918 pAhciReq->cbATAPISector = 2324;
4922 pAhciReq->cbATAPISector = 0; /** @todo we should probably fail the command here already. */
4926 cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhciReq->cbATAPISector;
4932 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4971 pAhciReq->cbTransfer = cbTransfer;
4972 pAhciReq->enmTxDir = AHCITXDIR_READ;
4973 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE);
5028 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
5030 pAhciReq->cbATAPISector = 2048;
5031 cbTransfer = cSectors * pAhciReq->cbATAPISector;
5039 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
5041 pAhciReq->cbATAPISector = 2048;
5042 cbTransfer = cSectors * pAhciReq->cbATAPISector;
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);
5077 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
5084 pAhciReq->enmTxDir = enmTxDir;
5085 pAhciReq->cbTransfer = cbTransfer;
5086 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH);
5092 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5097 pbPacket = pAhciReq->aATAPICmd;
5099 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8), ATAPI_PACKET_SIZE, pbPacket));
5102 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
5104 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
5114 * @param pAhciReq The state to get the tag number from.
5116 static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5131 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5142 * @param pAhciReq The task state.
5144 static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5154 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
5162 * @param pAhciReq The state of the task.
5166 static void ahciSendPioSetupFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis,
5175 AssertMsg( pAhciReq->cbTransfer > 0
5176 && pAhciReq->cbTransfer <= 65534,
5184 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
5186 abPioSetupFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus;
5187 abPioSetupFis[AHCI_CMDFIS_ERR] = pAhciReq->uATARegError;
5199 abPioSetupFis[16] = (pAhciReq->cbTransfer >> 8) & 0xff;
5200 abPioSetupFis[17] = pAhciReq->cbTransfer & 0xff;
5203 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5228 * @param pAhciReq The state of the task.
5232 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt)
5245 d2hFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus;
5246 d2hFis[AHCI_CMDFIS_ERR] = pAhciReq->uATARegError;
5258 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5262 if (pAhciReq->uATARegStatus & ATA_STAT_ERR)
5281 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5443 * @param pAhciReq The request to allocate memory for.
5446 static void *ahciReqMemAlloc(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cb)
5448 if (pAhciReq->cbAlloc > cb)
5450 pAhciReq->cAllocTooMuch++;
5452 else if (pAhciReq->cbAlloc < cb)
5454 if (pAhciReq->cbAlloc)
5455 pAhciPort->pDrvBlock->pfnIoBufFree(pAhciPort->pDrvBlock, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5457 pAhciReq->pvAlloc = NULL;
5458 pAhciReq->cbAlloc = RT_ALIGN_Z(cb, _4K);
5459 int rc = pAhciPort->pDrvBlock->pfnIoBufAlloc(pAhciPort->pDrvBlock, pAhciReq->cbAlloc, &pAhciReq->pvAlloc);
5461 pAhciReq->pvAlloc = NULL;
5463 pAhciReq->cAllocTooMuch = 0;
5464 if (RT_UNLIKELY(!pAhciReq->pvAlloc))
5465 pAhciReq->cbAlloc = 0;
5468 return pAhciReq->pvAlloc;
5476 * @param pAhciReq The request.
5479 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree)
5481 if ( pAhciReq->cAllocTooMuch >= AHCI_MAX_ALLOC_TOO_MUCH
5484 if (pAhciReq->cbAlloc)
5486 pAhciPort->pDrvBlock->pfnIoBufFree(pAhciPort->pDrvBlock, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5487 pAhciReq->cbAlloc = 0;
5488 pAhciReq->cAllocTooMuch = 0;
5498 * @param pAhciReq AHCI request structure.
5502 static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
5507 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5508 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
5541 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5551 * @param pAhciReq AHCI request structure.
5555 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
5560 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5561 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
5594 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5604 * @param pAhciReq The request state.
5607 static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer)
5609 AssertMsg( pAhciReq->enmTxDir == AHCITXDIR_READ
5610 || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
5613 pAhciReq->u.Io.DataSeg.pvSeg = ahciReqMemAlloc(pAhciPort, pAhciReq, cbTransfer);
5614 if (!pAhciReq->u.Io.DataSeg.pvSeg)
5617 pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer;
5618 if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
5620 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq,
5621 pAhciReq->u.Io.DataSeg.pvSeg,
5632 * @param pAhciReq The request state.
5636 static void ahciIoBufFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq,
5639 AssertMsg( pAhciReq->enmTxDir == AHCITXDIR_READ
5640 || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
5643 if ( pAhciReq->enmTxDir == AHCITXDIR_READ
5646 if (pAhciReq->u.Io.pfnPostProcess)
5650 int rc = pAhciReq->u.Io.pfnPostProcess(pAhciReq, &pv, &cb);
5654 pAhciReq->cbTransfer = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pv, cb);
5659 ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
5660 pAhciReq->u.Io.DataSeg.pvSeg,
5661 pAhciReq->u.Io.DataSeg.cbSeg);
5664 ahciReqMemFree(pAhciPort, pAhciReq, false /* fForceFree */);
5665 pAhciReq->u.Io.DataSeg.pvSeg = NULL;
5666 pAhciReq->u.Io.DataSeg.cbSeg = 0;
5701 PAHCIREQ pAhciReq = pAhciPort->aCachedTasks[i];
5703 if ( VALID_PTR(pAhciReq)
5704 && pAhciReq != pAhciReqExcept)
5706 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE);
5721 pAhciPort->iLUN, pAhciReq->uTag));
5724 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
5801 * @param pAhciReq The request handling the TRIM request.
5803 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5809 uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries;
5810 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5814 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
5816 AssertMsgReturn(pAhciReq->enmTxDir == AHCITXDIR_TRIM, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
5819 if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
5822 cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
5826 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5867 pAhciReq->u.Trim.cRanges = cRanges;
5868 pAhciReq->u.Trim.paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
5869 if (pAhciReq->u.Trim.paRanges)
5873 cPrdtlEntries = pAhciReq->cPrdtlEntries;
5874 GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
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;
5924 * @param pAhciReq The task state.
5926 static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)
5928 AssertReturnVoid(pAhciReq->enmTxDir == AHCITXDIR_TRIM);
5929 RTMemFree(pAhciReq->u.Trim.paRanges);
5939 * @param pAhciReq Pointer to the task which finished.
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));
5954 enmTxState = (AHCITXSTATE)ASMAtomicReadU32((volatile uint32_t *)&pAhciReq->enmTxState);
5955 VBOXDD_AHCI_REQ_COMPLETED(pAhciReq, rcReq, enmTxState, pAhciReq->uOffset, pAhciReq->cbTransfer);
5956 VBOXDD_AHCI_REQ_COMPLETED_TIMESTAMP(pAhciReq, tsNow);
5962 if (tsNow - pAhciReq->tsStart >= 25 * 1000)
5966 switch (pAhciReq->enmTxDir)
5985 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, pcszReq, (tsNow - pAhciReq->tsStart) / 1000));
5989 fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE);
5993 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
5995 ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */);
5996 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
5999 else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
6001 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
6002 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
6005 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6007 ahciTrimRangesDestroy(pAhciReq);
6016 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
6019 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6025 pAhciReq->enmTxDir == AHCITXDIR_READ
6028 pAhciReq->uOffset,
6029 pAhciReq->cbTransfer, rcReq));
6035 pAhciReq->cmdHdr.u32PRDBC = 0;
6036 pAhciReq->uATARegError = ID_ERR;
6037 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6038 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
6041 ASMAtomicOrU32(&pAhciPort->u32TasksRedo, RT_BIT_32(pAhciReq->uTag));
6045 pAhciReq->cmdHdr.u32PRDBC = pAhciReq->cbTransfer;
6048 if (pAhciReq->enmTxDir != AHCITXDIR_NONE)
6050 pAhciReq->uATARegError = 0;
6051 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6055 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
6057 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
6078 if (pAhciReq->fFlags & AHCI_REQ_PIO_DATA)
6079 ahciSendPioSetupFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false /* fInterrupt */);
6081 if (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT)
6084 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(pAhciReq->uTag));
6087 if (pAhciReq->fFlags & AHCI_REQ_IS_QUEUED)
6097 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6106 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_CANCELED || fPortReset,
6122 ASMAtomicXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_FREE);
6124 if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6125 ahciTrimRangesDestroy(pAhciReq);
6126 else if (pAhciReq->enmTxDir != AHCITXDIR_FLUSH)
6127 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
6132 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
6135 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6141 pAhciReq->enmTxDir == AHCITXDIR_READ
6144 pAhciReq->uOffset,
6145 pAhciReq->cbTransfer, rcReq));
6150 RTMemFree(pAhciReq);
6170 PAHCIREQ pAhciReq = (PAHCIREQ)pvUser;
6173 __FUNCTION__, pInterface, pvUser, pAhciReq->uTag));
6175 ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
6186 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
6190 CmdHdr *pCmdHdr = &pAhciReq->cmdHdr;
6194 pAhciReq->cbTransfer = 0;
6209 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6212 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6213 pAhciReq->cbTransfer = cbCopied;
6217 pAhciReq->uATARegError = ABRT_ERR;
6218 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR;
6234 pAhciReq->uATARegError = 0;
6235 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6259 pAhciReq->uATARegError = ABRT_ERR;
6260 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6268 pAhciReq->uATARegError = ABRT_ERR;
6269 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6274 ahciDeviceReset(pAhciPort, pAhciReq);
6285 pAhciReq->uATARegError = ABRT_ERR;
6286 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6289 enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
6294 pAhciReq->uATARegError = ABRT_ERR;
6295 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6299 atapiDoTransfer(pAhciPort, pAhciReq, 512, ATAFN_SS_ATAPI_IDENTIFY);
6301 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6302 pAhciReq->uATARegError = 0;
6303 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6311 pAhciReq->uATARegError = ABRT_ERR;
6312 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6318 pAhciReq->uATARegError = 0;
6319 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6325 pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */
6335 pAhciReq->uATARegError = 0;
6336 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
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;
6360 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
6366 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
6367 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
6368 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
6430 bool fAbortedAll = ahciCancelActiveTasks(pAhciPort, pAhciReq);
6439 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6442 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6443 pAhciReq->cbTransfer = cbCopied;
6456 if ( !(pAhciReq->cmdFis[AHCI_CMDFIS_FET] & UINT16_C(0x01))
6457 || (pAhciReq->cmdFis[AHCI_CMDFIS_FET] & ~UINT16_C(0x1)))
6459 pAhciReq->uATARegError = ABRT_ERR;
6460 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6473 pAhciReq->uATARegError = ABRT_ERR;
6474 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6478 pAhciReq->uATARegError = ABRT_ERR;
6479 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6489 * @param pAhciReq The state of the actual task.
6491 static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
6504 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
6506 pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
6507 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
6511 ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr);
6514 GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);
6516 AssertMsgReturn((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
6522 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
6524 AssertMsgReturn(pAhciReq->cmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D,
6529 pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
6532 if (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A)
6535 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE);
6539 if ((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))
6545 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false);
6549 pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
6550 pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(pAhciReq->cmdHdr.u32DescInf);
6554 ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]);
6557 ahciLog(("PRDT address %RGp number of entries %u\n", pAhciReq->GCPhysPrdtl, pAhciReq->cPrdtlEntries));
6558 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
6560 for (unsigned i = 0; i < pAhciReq->cPrdtlEntries; i++)
6668 PAHCIREQ pAhciReq;
6680 pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
6681 AssertMsg(pAhciReq, ("%s: Cannot allocate task state memory!\n"));
6682 pAhciReq->enmTxState = AHCITXSTATE_FREE;
6683 pAhciPort->aCachedTasks[idx] = pAhciReq;
6686 pAhciReq = pAhciPort->aCachedTasks[idx];
6688 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE);
6691 pAhciReq->tsStart = RTTimeMilliTS();
6692 pAhciReq->uATARegStatus = 0;
6693 pAhciReq->uATARegError = 0;
6694 pAhciReq->fFlags = 0;
6697 pAhciReq->uTag = idx;
6698 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
6700 bool fFisRead = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
6711 fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE);
6721 pAhciReq->fFlags |= AHCI_REQ_CLEAR_SACT;
6722 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
6725 if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
6728 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
6732 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6735 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
6739 fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE);
6749 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
6750 pAhciReq->enmTxDir = enmTxDir;
6759 rc = ahciIoBufAllocate(pAhciPort, pAhciReq, pAhciReq->cbTransfer);
6764 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
6768 if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
6772 VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer);
6773 VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
6777 pAhciReq);
6781 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6785 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
6786 pAhciReq->u.Trim.cRanges, pAhciReq);
6792 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6793 &pAhciReq->u.Io.DataSeg, 1,
6794 pAhciReq->cbTransfer,
6795 pAhciReq);
6800 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6801 &pAhciReq->u.Io.DataSeg, 1,
6802 pAhciReq->cbTransfer,
6803 pAhciReq);
6806 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
6808 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6816 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6820 rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock, pAhciReq->u.Trim.paRanges,
6821 pAhciReq->u.Trim.cRanges);
6828 rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6829 pAhciReq->u.Io.DataSeg.pvSeg,
6830 pAhciReq->cbTransfer);
6836 rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6837 pAhciReq->u.Io.DataSeg.pvSeg,
6838 pAhciReq->cbTransfer);
6841 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6846 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);