VirtualBox

Changeset 63999 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 26, 2016 11:33:48 AM (8 years ago)
Author:
vboxsync
Message:

AHCI: Convert to PDMIMEDIAEX and kick out PDMIMEDIAASYNC. This temporary breaks host CD/DVD support until the driver is cleand up and supports PDMIMEDIAEX

File:
1 edited

Legend:

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

    r63909 r63999  
    2929 * the hard disk and for guests which don't have an AHCI SATA driver.
    3030 *
    31  * The data is transferred in an asynchronous way using one thread per implemented
    32  * port or using the new async completion interface which is still under
    33  * development. [not quite up to date]
     31 * The data is transfered using the extended media interface, asynchronously if
     32 * it is supported by the driver below otherwise it weill be done synchronous.
     33 * Either way a thread is used to process new requests from the guest.
    3434 */
    3535
     
    245245
    246246/**
    247  * Transfer type.
    248  */
    249 typedef enum AHCITXDIR
    250 {
    251     /** Invalid */
    252     AHCITXDIR_INVALID = 0,
    253     /** None */
    254     AHCITXDIR_NONE,
    255     /** Read */
    256     AHCITXDIR_READ,
    257     /** Write */
    258     AHCITXDIR_WRITE,
    259     /** Flush */
    260     AHCITXDIR_FLUSH,
    261     /** Trim */
    262     AHCITXDIR_TRIM
    263 } AHCITXDIR;
    264 
    265 /**
    266247 * Task state.
    267248 */
     
    298279typedef struct AHCIREQ
    299280{
    300     /** List node for the free list if the request is not in use. */
    301     RTLISTNODE                 NodeList;
     281    /** The I/O request handle from the driver below associated with this request. */
     282    PDMMEDIAEXIOREQ            hIoReq;
    302283    /** Task state. */
    303284    volatile AHCITXSTATE       enmTxState;
     
    306287    /** Tag of the task. */
    307288    uint32_t                   uTag;
    308     /** The command header for this task. */
    309     CmdHdr                     cmdHdr;
    310289    /** The command Fis for this task. */
    311290    uint8_t                    cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE];
     
    321300    unsigned                   cPrdtlEntries;
    322301    /** Data direction. */
    323     AHCITXDIR                  enmTxDir;
     302    PDMMEDIAEXIOREQTYPE        enmType;
    324303    /** Start offset. */
    325304    uint64_t                   uOffset;
     
    450429    /** Flag whether this port is in a reset state. */
    451430    volatile bool                   fPortReset;
    452     /** If we use the new async interface. */
    453     bool                            fAsyncInterface;
     431    /** Flag whether TRIM is supported. */
     432    bool                            fTrimEnabled;
    454433    /** Flag if we are in a device reset. */
    455434    bool                            fResetDevice;
     
    507486    /** Pointer to the attached driver's block interface. */
    508487    R3PTRTYPE(PPDMIMEDIA)           pDrvMedia;
    509     /** Pointer to the attached driver's async block interface. */
    510     R3PTRTYPE(PPDMIMEDIAASYNC)      pDrvMediaAsync;
     488    /** Pointer to the attached driver's extended interface. */
     489    R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
    511490    /** Pointer to the attached driver's mount interface. */
    512491    R3PTRTYPE(PPDMIMOUNT)           pDrvMount;
     
    515494    /** The block port interface. */
    516495    PDMIMEDIAPORT                   IPort;
    517     /** The optional block async port interface. */
    518     PDMIMEDIAASYNCPORT              IPortAsync;
     496    /** The extended media port interface. */
     497    PDMIMEDIAEXPORT                 IMediaExPort;
    519498    /** The mount notify interface. */
    520499    PDMIMOUNTNOTIFY                 IMountNotify;
     
    530509    /** Async IO Thread. */
    531510    R3PTRTYPE(PPDMTHREAD)           pAsyncIOThread;
    532     /** Array of active tasks indexed by the tag. */
    533     R3PTRTYPE(volatile PAHCIREQ)    aActiveTasks[AHCI_NR_COMMAND_SLOTS];
    534511    /** First task throwing an error. */
    535512    R3PTRTYPE(volatile PAHCIREQ)    pTaskErr;
     
    572549    uint32_t                        u32Alignment5;
    573550
    574     /** Critical section protecting the global free list. */
    575     RTCRITSECT                      CritSectReqsFree;
    576     /** Head of the global free request list. */
    577     R3PTRTYPE(PRTLISTANCHOR)        pListReqsFree;
    578 
    579551    /** Align to a multiple of 8. */
    580552#if HC_ARCH_BITS == 32
     
    706678    /** R0 enabled. */
    707679    bool                            fR0Enabled;
    708     /** If the new async interface is used if available. */
    709     bool                            fUseAsyncInterfaceIfAvailable;
    710680    /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
    711681     * a port is entering the idle state. */
     
    960930static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, const void *pvBuf, size_t cbBuf);
    961931static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void *pvBuf, size_t cbBuf);
    962 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort, PAHCIREQ pAhciReqExcept);
     932static bool ahciCancelActiveTasks(PAHCIPort pAhciPort);
    963933static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree);
    964 static void ahciR3PortCachedReqsFree(PAHCIPort pAhciPort);
    965934#endif
    966935RT_C_DECLS_END
     
    10901059{
    10911060    /* Cancel all tasks first. */
    1092     bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort, NULL);
     1061    bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
    10931062    Assert(fAllTasksCanceled); NOREF(fAllTasksCanceled);
    10941063
     
    20622031
    20632032    /* Cancel all tasks first. */
    2064     fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort, NULL);
     2033    fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
    20652034    Assert(fAllTasksCanceled);
    20662035
     
    27172686    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pAhciPort->IBase);
    27182687    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pAhciPort->IPort);
    2719     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pAhciPort->IPortAsync);
     2688    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pAhciPort->IMediaExPort);
    27202689    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pAhciPort->IMountNotify);
    27212690    return NULL;
     
    30262995    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    30272996    pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
    3028         | ((pAhciReq->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)
     2997        | ((pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE) ? ATAPI_INT_REASON_IO : 0)
    30292998        | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
    30302999    memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
     
    31423111    p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
    31433112    p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
    3144     if (   pAhciPort->pDrvMedia->pfnDiscard
    3145         || ( pAhciPort->fAsyncInterface
    3146             && pAhciPort->pDrvMediaAsync->pfnStartDiscard)
     3113    if (   pAhciPort->fTrimEnabled
    31473114        || pAhciPort->cbSector != 512
    31483115        || pAhciPort->fNonRotational)
     
    31853152        p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
    31863153
    3187     if (   pAhciPort->pDrvMedia->pfnDiscard
    3188         || (   pAhciPort->fAsyncInterface
    3189             && pAhciPort->pDrvMediaAsync->pfnStartDiscard)) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */
     3154    if (pAhciPort->fTrimEnabled) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */
    31903155        p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */
    31913156
     
    35733538    uint8_t abBuf[8];
    35743539
    3575     Assert(pAhciReq->enmTxDir == AHCITXDIR_READ);
     3540    Assert(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ);
    35763541    Assert(pAhciReq->cbTransfer <= 8);
    35773542
     
    39853950            return VERR_NO_MEMORY;
    39863951
    3987         if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     3952        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    39883953        {
    39893954            ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
     
    39973962    if (cbTransfer >= 2048)
    39983963    {
    3999         if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
     3964        if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE)
    40003965            pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    40013966        else
     
    40744039            rc = pAhciPort->pDrvMedia->pfnSendCmd(pAhciPort->pDrvMedia,
    40754040                                                  aATAPICmd,
    4076                                                   pAhciReq->enmTxDir == AHCITXDIR_READ
     4041                                                  pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    40774042                                                  ? PDMMEDIATXDIR_FROM_DEVICE
    40784043                                                  : PDMMEDIATXDIR_TO_DEVICE,
     
    40924057        PDMMEDIATXDIR enmBlockTxDir = PDMMEDIATXDIR_NONE;
    40934058
    4094         if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     4059        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
    40954060            enmBlockTxDir = PDMMEDIATXDIR_FROM_DEVICE;
    4096         else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     4061        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    40974062            enmBlockTxDir = PDMMEDIATXDIR_TO_DEVICE;
    4098         else if (pAhciReq->enmTxDir == AHCITXDIR_NONE)
     4063        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_INVALID)
    40994064            enmBlockTxDir = PDMMEDIATXDIR_NONE;
    41004065        else
    4101             AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmTxDir));
     4066            AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmType));
    41024067
    41034068        rc = pAhciPort->pDrvMedia->pfnSendCmd(pAhciPort->pDrvMedia,
     
    41144079    if (cbTransfer >= 2048)
    41154080    {
    4116         if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
     4081        if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE)
    41174082        {
    41184083            pAhciPort->Led.Actual.s.fReading = 0;
     
    41544119        }
    41554120
    4156         if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     4121        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
    41574122        {
    41584123           Assert(cbTransfer <= pAhciReq->cbTransfer);
     
    43784343    int rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciReq, pAhciPort, cbMax, &cbTransfered);
    43794344
    4380     pAhciReq->cmdHdr.u32PRDBC = (uint32_t)cbTransfered;
    43814345    pAhciReq->cbTransfer      = (uint32_t)cbTransfered;
    43824346    Assert(pAhciReq->cbTransfer == cbTransfered);
     
    43854349
    43864350    /* Write updated command header into memory of the guest. */
    4387     PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
     4351    uint32_t u32PRDBC = (uint32_t)cbTransfered;
     4352    PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr + RT_OFFSETOF(CmdHdr, u32PRDBC),
     4353                          &u32PRDBC, sizeof(u32PRDBC));
    43884354
    43894355    return rcSourceSink;
     
    44564422}
    44574423
    4458 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    4459 {
    4460     AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     4424static PDMMEDIAEXIOREQTYPE atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     4425{
     4426    PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID;
    44614427    const uint8_t *pbPacket;
    44624428    uint32_t cbMax;
     
    45764542            }
    45774543            atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    4578             enmTxDir = AHCITXDIR_READ;
     4544            enmType = PDMMEDIAEXIOREQTYPE_READ;
    45794545            break;
    45804546        }
     
    46254591                    /* normal read */
    46264592                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    4627                     enmTxDir = AHCITXDIR_READ;
     4593                    enmType = PDMMEDIAEXIOREQTYPE_READ;
    46284594                    break;
    46294595                case 0xf8:
    46304596                    /* read all data */
    46314597                    atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
    4632                     enmTxDir = AHCITXDIR_READ;
     4598                    enmType = PDMMEDIAEXIOREQTYPE_READ;
    46334599                    break;
    46344600                default:
     
    46864652                    PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
    46874653                    PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
    4688 
    4689                     /*
    4690                      * Free the I/O memory of all cached tasks of this port
    4691                      * because the driver providing I/O memory allocation interface
    4692                      * is about to be destroyed.
    4693                      */
    4694                     ahciR3PortCachedReqsFree(pAhciPort);
    46954654
    46964655                    /*
     
    48284787    }
    48294788
    4830     return enmTxDir;
     4789    return enmType;
    48314790}
    48324791
     
    48344793 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
    48354794 */
    4836 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     4795static PDMMEDIAEXIOREQTYPE atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    48374796{
    48384797    const uint8_t *pbPacket;
    48394798    uint32_t cSectors, iATAPILBA;
    48404799    uint32_t cbTransfer = 0;
    4841     AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     4800    PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID;
    48424801    bool fSendCmd = false;
    48434802
     
    48554814            cbTransfer = ataBE2H_U16(pbPacket + 7);
    48564815            Log2(("ATAPI PT: lba %d\n", iATAPILBA));
    4857             enmTxDir = AHCITXDIR_WRITE;
     4816            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    48584817            fSendCmd = true;
    48594818            break;
    48604819        case SCSI_FORMAT_UNIT:
    48614820            cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
    4862             enmTxDir = AHCITXDIR_WRITE;
     4821            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    48634822            fSendCmd = true;
    48644823            break;
    48654824        case SCSI_GET_CONFIGURATION:
    48664825            cbTransfer = ataBE2H_U16(pbPacket + 7);
    4867             enmTxDir = AHCITXDIR_READ;
     4826            enmType = PDMMEDIAEXIOREQTYPE_READ;
    48684827            fSendCmd = true;
    48694828            break;
     
    48764835                break;
    48774836            }
    4878             enmTxDir = AHCITXDIR_READ;
     4837            enmType = PDMMEDIAEXIOREQTYPE_READ;
    48794838            fSendCmd = true;
    48804839            break;
    48814840        case SCSI_GET_PERFORMANCE:
    48824841            cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
    4883             enmTxDir = AHCITXDIR_READ;
     4842            enmType = PDMMEDIAEXIOREQTYPE_READ;
    48844843            fSendCmd = true;
    48854844            break;
    48864845        case SCSI_INQUIRY:
    48874846            cbTransfer = ataBE2H_U16(pbPacket + 3);
    4888             enmTxDir = AHCITXDIR_READ;
     4847            enmType = PDMMEDIAEXIOREQTYPE_READ;
    48894848            fSendCmd = true;
    48904849            break;
     
    48944853        case SCSI_MECHANISM_STATUS:
    48954854            cbTransfer = ataBE2H_U16(pbPacket + 8);
    4896             enmTxDir = AHCITXDIR_READ;
     4855            enmType = PDMMEDIAEXIOREQTYPE_READ;
    48974856            fSendCmd = true;
    48984857            break;
    48994858        case SCSI_MODE_SELECT_10:
    49004859            cbTransfer = ataBE2H_U16(pbPacket + 7);
    4901             enmTxDir = AHCITXDIR_WRITE;
     4860            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    49024861            fSendCmd = true;
    49034862            break;
    49044863        case SCSI_MODE_SENSE_10:
    49054864            cbTransfer = ataBE2H_U16(pbPacket + 7);
    4906             enmTxDir = AHCITXDIR_READ;
     4865            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49074866            fSendCmd = true;
    49084867            break;
     
    49294888            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
    49304889            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    4931             enmTxDir = AHCITXDIR_READ;
     4890            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49324891            fSendCmd = true;
    49334892            break;
     
    49384897            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
    49394898            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    4940             enmTxDir = AHCITXDIR_READ;
     4899            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49414900            fSendCmd = true;
    49424901            break;
    49434902        case SCSI_READ_BUFFER:
    49444903            cbTransfer = ataBE2H_U24(pbPacket + 6);
    4945             enmTxDir = AHCITXDIR_READ;
     4904            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49464905            fSendCmd = true;
    49474906            break;
    49484907        case SCSI_READ_BUFFER_CAPACITY:
    49494908            cbTransfer = ataBE2H_U16(pbPacket + 7);
    4950             enmTxDir = AHCITXDIR_READ;
     4909            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49514910            fSendCmd = true;
    49524911            break;
    49534912        case SCSI_READ_CAPACITY:
    49544913            cbTransfer = 8;
    4955             enmTxDir = AHCITXDIR_READ;
     4914            enmType = PDMMEDIAEXIOREQTYPE_READ;
    49564915            fSendCmd = true;
    49574916            break;
     
    50064965                cbTransfer = cSectors * pAhciReq->cbATAPISector;
    50074966            }
    5008             enmTxDir = AHCITXDIR_READ;
     4967            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50094968            fSendCmd = true;
    50104969            break;
     
    50124971        case SCSI_READ_DISC_INFORMATION:
    50134972            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5014             enmTxDir = AHCITXDIR_READ;
     4973            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50154974            fSendCmd = true;
    50164975            break;
    50174976        case SCSI_READ_DVD_STRUCTURE:
    50184977            cbTransfer = ataBE2H_U16(pbPacket + 8);
    5019             enmTxDir = AHCITXDIR_READ;
     4978            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50204979            fSendCmd = true;
    50214980            break;
    50224981        case SCSI_READ_FORMAT_CAPACITIES:
    50234982            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5024             enmTxDir = AHCITXDIR_READ;
     4983            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50254984            fSendCmd = true;
    50264985            break;
    50274986        case SCSI_READ_SUBCHANNEL:
    50284987            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5029             enmTxDir = AHCITXDIR_READ;
     4988            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50304989            fSendCmd = true;
    50314990            break;
    50324991        case SCSI_READ_TOC_PMA_ATIP:
    50334992            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5034             enmTxDir = AHCITXDIR_READ;
     4993            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50354994            fSendCmd = true;
    50364995            break;
    50374996        case SCSI_READ_TRACK_INFORMATION:
    50384997            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5039             enmTxDir = AHCITXDIR_READ;
     4998            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50404999            fSendCmd = true;
    50415000            break;
     
    50455004        case SCSI_REPORT_KEY:
    50465005            cbTransfer = ataBE2H_U16(pbPacket + 8);
    5047             enmTxDir = AHCITXDIR_READ;
     5006            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50485007            fSendCmd = true;
    50495008            break;
     
    50535012            {
    50545013                pAhciReq->cbTransfer = cbTransfer;
    5055                 pAhciReq->enmTxDir = AHCITXDIR_READ;
     5014                pAhciReq->enmType = PDMMEDIAEXIOREQTYPE_READ;
    50565015                atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE);
    50575016                break;
    50585017            }
    5059             enmTxDir = AHCITXDIR_READ;
     5018            enmType = PDMMEDIAEXIOREQTYPE_READ;
    50605019            fSendCmd = true;
    50615020            break;
     
    50715030        case SCSI_SEND_CUE_SHEET:
    50725031            cbTransfer = ataBE2H_U24(pbPacket + 6);
    5073             enmTxDir = AHCITXDIR_WRITE;
     5032            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    50745033            fSendCmd = true;
    50755034            break;
    50765035        case SCSI_SEND_DVD_STRUCTURE:
    50775036            cbTransfer = ataBE2H_U16(pbPacket + 8);
    5078             enmTxDir = AHCITXDIR_WRITE;
     5037            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    50795038            fSendCmd = true;
    50805039            break;
    50815040        case SCSI_SEND_EVENT:
    50825041            cbTransfer = ataBE2H_U16(pbPacket + 8);
    5083             enmTxDir = AHCITXDIR_WRITE;
     5042            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    50845043            fSendCmd = true;
    50855044            break;
    50865045        case SCSI_SEND_KEY:
    50875046            cbTransfer = ataBE2H_U16(pbPacket + 8);
    5088             enmTxDir = AHCITXDIR_WRITE;
     5047            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    50895048            fSendCmd = true;
    50905049            break;
    50915050        case SCSI_SEND_OPC_INFORMATION:
    50925051            cbTransfer = ataBE2H_U16(pbPacket + 7);
    5093             enmTxDir = AHCITXDIR_WRITE;
     5052            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    50945053            fSendCmd = true;
    50955054            break;
     
    51025061        case SCSI_SET_STREAMING:
    51035062            cbTransfer = ataBE2H_U16(pbPacket + 9);
    5104             enmTxDir = AHCITXDIR_WRITE;
     5063            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    51055064            fSendCmd = true;
    51065065            break;
     
    51305089                pAhciReq->cbATAPISector = 2048;
    51315090            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    5132             enmTxDir = AHCITXDIR_WRITE;
     5091            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    51335092            fSendCmd = true;
    51345093            break;
     
    51425101                pAhciReq->cbATAPISector = 2048;
    51435102            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    5144             enmTxDir = AHCITXDIR_WRITE;
     5103            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    51455104            fSendCmd = true;
    51465105            break;
     
    51595118                default:
    51605119                    cbTransfer = ataBE2H_U16(pbPacket + 6);
    5161                     enmTxDir = AHCITXDIR_WRITE;
     5120                    enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    51625121                    fSendCmd = true;
    51635122                    break;
     
    51665125        case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */
    51675126            cbTransfer = ataBE2H_U32(pbPacket + 6);
    5168             enmTxDir = AHCITXDIR_READ;
     5127            enmType = PDMMEDIAEXIOREQTYPE_READ;
    51695128            fSendCmd = true;
    51705129            break;
     
    51885147        Log2(("ATAPI PT: max size %d\n", cbTransfer));
    51895148        if (cbTransfer == 0)
    5190             enmTxDir = AHCITXDIR_NONE;
    5191         pAhciReq->enmTxDir = enmTxDir;
     5149            enmType = PDMMEDIAEXIOREQTYPE_INVALID;
     5150        pAhciReq->enmType = enmType;
    51925151        pAhciReq->cbTransfer = cbTransfer;
    51935152        atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH);
    51945153    }
    51955154
    5196     return AHCITXDIR_NONE;
    5197 }
    5198 
    5199 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    5200 {
    5201     AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     5155    return PDMMEDIAEXIOREQTYPE_INVALID;
     5156}
     5157
     5158static PDMMEDIAEXIOREQTYPE atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     5159{
     5160    PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID;
    52025161    const uint8_t *pbPacket;
    52035162
     
    52075166
    52085167    if (pAhciPort->fATAPIPassthrough)
    5209         enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
     5168        enmType = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
    52105169    else
    5211         enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
    5212 
    5213     return enmTxDir;
     5170        enmType = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
     5171
     5172    return enmType;
    52145173}
    52155174
     
    52895248        abPioSetupFis[AHCI_CMDFIS_TYPE]  = AHCI_CMDFIS_TYPE_PIOSETUP;
    52905249        abPioSetupFis[AHCI_CMDFIS_BITS]  = (fInterrupt ? AHCI_CMDFIS_I : 0);
    5291         if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     5250        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
    52925251            abPioSetupFis[AHCI_CMDFIS_BITS] |= AHCI_CMDFIS_D;
    52935252        abPioSetupFis[AHCI_CMDFIS_STS]   = pAhciReq->uATARegStatus;
     
    55385497}
    55395498
    5540 #if 0 /* unused */
    5541 DECLINLINE(uint8_t) ahciGetTagQueued(uint8_t *pCmdFis)
    5542 {
    5543     return pCmdFis[AHCI_CMDFIS_SECTC] >> 3;
    5544 }
    5545 #endif /* unused */
    5546 
    55475499/**
    55485500 * Allocates memory for the given request using already allocated memory if possible.
     
    57155667static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer)
    57165668{
    5717     AssertMsg(   pAhciReq->enmTxDir == AHCITXDIR_READ
    5718               || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
     5669    AssertMsg(   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
     5670              || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE,
    57195671              ("Allocating I/O memory for a non I/O request is not allowed\n"));
    57205672
     
    57245676
    57255677    pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer;
    5726     if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     5678    if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    57275679    {
    57285680        ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq,
     
    57455697                          bool fCopyToGuest)
    57465698{
    5747     AssertMsg(   pAhciReq->enmTxDir == AHCITXDIR_READ
    5748               || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
     5699    AssertMsg(   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
     5700              || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE,
    57495701              ("Freeing I/O memory for a non I/O request is not allowed\n"));
    57505702
    5751     if (   pAhciReq->enmTxDir == AHCITXDIR_READ
     5703    if (   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    57525704        && fCopyToGuest)
    57535705    {
     
    57735725}
    57745726
    5775 
    5776 /**
    5777  * Free all cached tasks on the given port.
    5778  *
    5779  * @returns nothing.
    5780  * @param   pAhciPort    The AHCI port.
    5781  */
    5782 static void ahciR3PortCachedReqsFree(PAHCIPort pAhciPort)
    5783 {
    5784     if (pAhciPort->pListReqsFree)
    5785     {
    5786         PAHCIREQ pReq = NULL;
    5787         PAHCIREQ pReqNext = NULL;
    5788 
    5789         RTCritSectEnter(&pAhciPort->CritSectReqsFree);
    5790         RTListForEachSafe(pAhciPort->pListReqsFree, pReq, pReqNext, AHCIREQ, NodeList)
    5791         {
    5792             RTListNodeRemove(&pReq->NodeList);
    5793             ahciReqMemFree(pAhciPort, pReq, true /* fForceFree */);
    5794             RTMemFree(pReq);
    5795         }
    5796         RTCritSectLeave(&pAhciPort->CritSectReqsFree);
    5797     }
    5798 }
    57995727
    58005728/**
     
    58065734 *                           (used for error page reading).
    58075735 */
    5808 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort, PAHCIREQ pAhciReqExcept)
    5809 {
    5810     for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aActiveTasks); i++)
    5811     {
    5812         PAHCIREQ pAhciReq = ASMAtomicReadPtrT(&pAhciPort->aActiveTasks[i], PAHCIREQ);
    5813         if (pAhciReq != pAhciReqExcept)
    5814         {
    5815             pAhciReq = (PAHCIREQ)ASMAtomicXchgPtr((void * volatile *)&pAhciPort->aActiveTasks[i], NULL);
    5816 
    5817             if (VALID_PTR(pAhciReq))
    5818             {
    5819                 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE);
    5820                 if (fXchg)
    5821                 {
    5822                     /* Task is active and was canceled. */
    5823                     AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
    5824                                      ("Task was canceled but none is active\n"));
    5825                     ASMAtomicDecU32(&pAhciPort->cTasksActive);
    5826 
    5827                     /*
    5828                      * Clear the pointer in the cached array. The controller will allocate a
    5829                      * a new task structure for this tag.
    5830                      */
    5831                     ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[i]);
    5832                     LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
    5833                             pAhciPort->iLUN, pAhciReq->uTag));
    5834                 }
    5835                 else
    5836                     AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
    5837                               ("Invalid task state, must be free!\n"));
    5838             }
    5839         }
    5840     }
    5841 
     5736static bool ahciCancelActiveTasks(PAHCIPort pAhciPort)
     5737{
     5738    if (pAhciPort->pDrvMediaEx)
     5739    {
     5740        int rc = pAhciPort->pDrvMediaEx->pfnIoReqCancelAll(pAhciPort->pDrvMediaEx);
     5741        AssertRC(rc);
     5742    }
    58425743    return true; /* always true for now because tasks don't use guest memory as the buffer which makes canceling a task impossible. */
    58435744}
     
    59275828    LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
    59285829
    5929     AssertMsgReturn(pAhciReq->enmTxDir == AHCITXDIR_TRIM, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
     5830    AssertMsgReturn(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
    59305831
    59315832    /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
     
    60395940static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)
    60405941{
    6041     AssertReturnVoid(pAhciReq->enmTxDir == AHCITXDIR_TRIM);
     5942    AssertReturnVoid(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD);
    60425943    RTMemFree(pAhciReq->u.Trim.paRanges);
    60435944}
     
    60485949 * @returns A new AHCI request structure or NULL if out of memory.
    60495950 * @param   pAhciPort    The AHCI port.
    6050  */
    6051 static PAHCIREQ ahciR3ReqAlloc(PAHCIPort pAhciPort)
     5951 * @param   uTag         The tag to assign.
     5952 */
     5953static PAHCIREQ ahciR3ReqAlloc(PAHCIPort pAhciPort, uint32_t uTag)
    60525954{
    60535955    PAHCIREQ pAhciReq = NULL;
    6054 
    6055     /* Check the global free list first. */
    6056     RTCritSectEnter(&pAhciPort->CritSectReqsFree);
    6057     pAhciReq = RTListGetFirst(pAhciPort->pListReqsFree, AHCIREQ, NodeList);
    6058     if (pAhciReq)
    6059     {
    6060         AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE, ("Should be free!\n"));
    6061         RTListNodeRemove(&pAhciReq->NodeList);
    6062     }
    6063     RTCritSectLeave(&pAhciPort->CritSectReqsFree);
    6064 
    6065     if (!pAhciReq)
    6066         pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
    6067 
    6068     pAhciReq->enmTxState = AHCITXSTATE_ACTIVE;
     5956    PDMMEDIAEXIOREQ hIoReq = NULL;
     5957
     5958    int rc = pAhciPort->pDrvMediaEx->pfnIoReqAlloc(pAhciPort->pDrvMediaEx, &hIoReq, (void **)&pAhciReq,
     5959                                                   uTag, 0 /* fFlags */);
     5960    if (RT_SUCCESS(rc))
     5961    {
     5962        pAhciReq->hIoReq     = hIoReq;
     5963        pAhciReq->enmTxState = AHCITXSTATE_ACTIVE;
     5964    }
     5965    else
     5966        pAhciReq = NULL;
    60695967    return pAhciReq;
    60705968}
     
    60815979    pAhciReq->enmTxState = AHCITXSTATE_FREE;
    60825980
    6083     RTCritSectEnter(&pAhciPort->CritSectReqsFree);
    6084     RTListAppend(pAhciPort->pListReqsFree, &pAhciReq->NodeList);
    6085     RTCritSectLeave(&pAhciPort->CritSectReqsFree);
     5981    int rc = pAhciPort->pDrvMediaEx->pfnIoReqFree(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
     5982    AssertRC(rc);
    60865983}
    60875984
     
    61176014     */
    61186015    bool fPortReset = ASMAtomicReadBool(&pAhciPort->fPortReset);
    6119     bool fXchg = ASMAtomicCmpXchgPtr(&pAhciPort->aActiveTasks[pAhciReq->uTag], NULL, pAhciReq);
    61206016    bool fReqErrSaved = false;
    61216017
     
    61286024        const char *pcszReq = NULL;
    61296025
    6130         switch (pAhciReq->enmTxDir)
    6131         {
    6132             case AHCITXDIR_READ:
     6026        switch (pAhciReq->enmType)
     6027        {
     6028            case PDMMEDIAEXIOREQTYPE_READ:
    61336029                pcszReq = "Read";
    61346030                break;
    6135             case AHCITXDIR_WRITE:
     6031            case PDMMEDIAEXIOREQTYPE_WRITE:
    61366032                pcszReq = "Write";
    61376033                break;
    6138             case AHCITXDIR_FLUSH:
     6034            case PDMMEDIAEXIOREQTYPE_FLUSH:
    61396035                pcszReq = "Flush";
    61406036                break;
    6141             case AHCITXDIR_TRIM:
     6037            case PDMMEDIAEXIOREQTYPE_DISCARD:
    61426038                pcszReq = "Trim";
    61436039                break;
     
    61506046    }
    61516047
    6152     if (fXchg && !fPortReset)
    6153     {
    6154         if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     6048    if (rcReq != VERR_PDM_MEDIAEX_IOREQ_CANCELED)
     6049    {
     6050        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
    61556051        {
    61566052            ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */);
     
    61586054            pAhciPort->Led.Actual.s.fReading = 0;
    61596055        }
    6160         else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     6056        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    61616057        {
    61626058            ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
     
    61646060            pAhciPort->Led.Actual.s.fWriting = 0;
    61656061        }
    6166         else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     6062        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    61676063        {
    61686064            ahciTrimRangesDestroy(pAhciReq);
     
    61756071            if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    61766072            {
    6177                 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
     6073                if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
    61786074                    LogRel(("AHCI#%uP%u: Flush returned rc=%Rrc\n",
    61796075                            pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
    6180                 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     6076                else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    61816077                    LogRel(("AHCI#%uP%u: Trim returned rc=%Rrc\n",
    61826078                            pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
     
    61846080                    LogRel(("AHCI#%uP%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    61856081                            pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
    6186                             pAhciReq->enmTxDir == AHCITXDIR_READ
     6082                            pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    61876083                            ? "Read"
    61886084                            : "Write",
     
    61946090            if (!fRedo)
    61956091            {
    6196                 pAhciReq->cmdHdr.u32PRDBC = 0;
    61976092                pAhciReq->uATARegError    = ID_ERR;
    61986093                pAhciReq->uATARegStatus   = ATA_STAT_READY | ATA_STAT_ERR;
     
    62046099        else
    62056100        {
    6206             pAhciReq->cmdHdr.u32PRDBC = pAhciReq->cbTransfer;
    6207 
    62086101            /* Status will be set already for non I/O requests. */
    6209             if (pAhciReq->enmTxDir != AHCITXDIR_NONE)
     6102            if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_INVALID)
    62106103            {
    62116104                pAhciReq->uATARegError = 0;
     
    62146107
    62156108            /* Write updated command header into memory of the guest. */
    6216             PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
     6109            uint32_t u32PRDBC = pAhciReq->cbTransfer;
     6110            PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr + RT_OFFSETOF(CmdHdr, u32PRDBC),
     6111                                  &u32PRDBC, sizeof(u32PRDBC));
    62176112
    62186113            if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
     
    62666161        fCanceled = true;
    62676162
    6268         if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     6163        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    62696164            ahciTrimRangesDestroy(pAhciReq);
    6270         else if (pAhciReq->enmTxDir != AHCITXDIR_FLUSH)
     6165        else if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH)
    62716166            ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
    62726167
     
    62746169        if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    62756170        {
    6276             if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
     6171            if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
    62776172                LogRel(("AHCI#%uP%u: Canceled flush returned rc=%Rrc\n",
    62786173                        pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
    6279             else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     6174            else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
    62806175                LogRel(("AHCI#%uP%u: Canceled trim returned rc=%Rrc\n",
    62816176                        pAhciPort->CTX_SUFF(pDevIns)->iInstance,pAhciPort->iLUN, rcReq));
     
    62836178                LogRel(("AHCI#%uP%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    62846179                        pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
    6285                         pAhciReq->enmTxDir == AHCITXDIR_READ
     6180                        pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    62866181                        ? "read"
    62876182                        : "write",
     
    62996194     * on this thread.
    63006195     */
    6301     if (fXchg)
    6302     {
    6303         AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
    6304                          ("Inconsistent request counter\n"));
    6305         ASMAtomicDecU32(&pAhciPort->cTasksActive);
    6306     }
     6196    ASMAtomicDecU32(&pAhciPort->cTasksActive);
    63076197
    63086198    if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
     
    63186208
    63196209/**
    6320  * Notification callback for a completed transfer.
    6321  *
    6322  * @returns VBox status code.
    6323  * @param   pInterface   Pointer to the interface.
    6324  * @param   pvUser       User data.
    6325  * @param   rcReq        IPRT Status code of the completed request.
    6326  */
    6327 static DECLCALLBACK(int) ahciR3TransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq)
    6328 {
    6329     PAHCIPort pAhciPort = PDMIMEDIAASYNCPORT_2_PAHCIPORT(pInterface);
    6330     PAHCIREQ pAhciReq = (PAHCIREQ)pvUser;
    6331 
    6332     ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
    6333              __FUNCTION__, pInterface, pvUser, pAhciReq->uTag));
    6334 
    6335     ahciTransferComplete(pAhciPort, pAhciReq, rcReq);
     6210 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     6211 */
     6212static DECLCALLBACK(int) ahciR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     6213                                                void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
     6214                                                size_t cbCopy)
     6215{
     6216    RT_NOREF2(pInterface, hIoReq);
     6217    int rc = VINF_SUCCESS;
     6218    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
     6219
     6220    if (offDst + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg)
     6221    {
     6222        void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offDst;
     6223        RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy);
     6224    }
     6225    else
     6226        rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     6227
     6228    return rc;
     6229}
     6230
     6231/**
     6232 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     6233 */
     6234static DECLCALLBACK(int) ahciR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     6235                                              void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
     6236                                              size_t cbCopy)
     6237{
     6238    RT_NOREF2(pInterface, hIoReq);
     6239    int rc = VINF_SUCCESS;
     6240    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
     6241
     6242    if (offSrc + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg)
     6243    {
     6244        void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offSrc;
     6245        RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy);
     6246    }
     6247    else
     6248        rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     6249
     6250    return rc;
     6251}
     6252
     6253/**
     6254 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqQueryDiscardRanges}
     6255 */
     6256static DECLCALLBACK(int) ahciR3IoReqQueryDiscardRanges(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     6257                                                       void *pvIoReqAlloc, uint32_t idxRangeStart,
     6258                                                       uint32_t cRanges, PRTRANGE paRanges,
     6259                                                       uint32_t *pcRanges)
     6260{
     6261    RT_NOREF2(pInterface, hIoReq);
     6262    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
     6263    uint32_t cRangesCopy = RT_MIN(pIoReq->u.Trim.cRanges - idxRangeStart, cRanges);
     6264    Assert(   idxRangeStart < pIoReq->u.Trim.cRanges
     6265           && (idxRangeStart + cRanges) <= pIoReq->u.Trim.cRanges);
     6266
     6267    memcpy(paRanges, &pIoReq->u.Trim.paRanges[idxRangeStart], cRangesCopy * sizeof(RTRANGE));
     6268    *pcRanges = cRangesCopy;
    63366269
    63376270    return VINF_SUCCESS;
    63386271}
     6272
     6273/**
     6274 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     6275 */
     6276static DECLCALLBACK(int) ahciR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     6277                                                   void *pvIoReqAlloc, int rcReq)
     6278{
     6279    RT_NOREF(hIoReq);
     6280    PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
     6281    ahciTransferComplete(pAhciPort, (PAHCIREQ)pvIoReqAlloc, rcReq);
     6282    return VINF_SUCCESS;
     6283}
     6284
     6285/**
     6286 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     6287 */
     6288static DECLCALLBACK(void) ahciR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     6289                                                  void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     6290{
     6291    RT_NOREF(hIoReq);
     6292    PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
     6293    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
     6294
     6295    RT_NOREF3(pAhciPort, pIoReq, enmState);
     6296    AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n"));
     6297}
     6298
    63396299
    63406300/**
     
    63446304 * @param   pCmdHdr Pointer to the command header.
    63456305 */
    6346 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
    6347 {
    6348     AHCITXDIR enmTxDir = AHCITXDIR_NONE;
     6306static PDMMEDIAEXIOREQTYPE ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
     6307{
     6308    PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID;
    63496309    bool fLBA48 = false;
    63506310
     
    63936353                    break;
    63946354                case 0x82: /* write cache disable */
    6395                     enmTxDir = AHCITXDIR_FLUSH;
     6355                    enmType = PDMMEDIAEXIOREQTYPE_FLUSH;
    63966356                    break;
    63976357                case 0x03:
     
    64356395        case ATA_FLUSH_CACHE_EXT:
    64366396        case ATA_FLUSH_CACHE:
    6437             enmTxDir = AHCITXDIR_FLUSH;
     6397            enmType = PDMMEDIAEXIOREQTYPE_FLUSH;
    64386398            break;
    64396399        case ATA_PACKET:
     
    64446404            }
    64456405            else
    6446                 enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
     6406                enmType = atapiParseCmd(pAhciPort, pAhciReq);
    64476407            break;
    64486408        case ATA_IDENTIFY_PACKET_DEVICE:
     
    64996459            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
    65006460            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
    6501             enmTxDir = AHCITXDIR_READ;
     6461            enmType = PDMMEDIAEXIOREQTYPE_READ;
    65026462            break;
    65036463        }
     
    65086468            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
    65096469            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
    6510             enmTxDir = AHCITXDIR_WRITE;
     6470            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    65116471            break;
    65126472        }
     
    65166476            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
    65176477            pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
    6518             enmTxDir = AHCITXDIR_READ;
     6478            enmType = PDMMEDIAEXIOREQTYPE_READ;
    65196479            break;
    65206480        }
     
    65246484            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
    65256485            pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
    6526             enmTxDir = AHCITXDIR_WRITE;
     6486            enmType = PDMMEDIAEXIOREQTYPE_WRITE;
    65276487            break;
    65286488        }
     
    65696529                            aBuf[511] = (uint8_t)-(int8_t)uChkSum;
    65706530
    6571                             if (pTaskErr->enmTxDir == AHCITXDIR_TRIM)
    6572                                 ahciTrimRangesDestroy(pTaskErr);
    6573                             else if (pTaskErr->enmTxDir != AHCITXDIR_FLUSH)
    6574                                 ahciReqMemFree(pAhciPort, pTaskErr, true /* fForceFree */);
    6575 
    65766531                            /* Finally free the error task state structure because it is completely unused now. */
    65776532                            RTMemFree(pTaskErr);
     
    65846539                         * See SATA2 1.2 spec chapter 4.2.3.4
    65856540                         */
    6586                         bool fAbortedAll = ahciCancelActiveTasks(pAhciPort, pAhciReq);
     6541                        bool fAbortedAll = ahciCancelActiveTasks(pAhciPort);
    65876542                        Assert(fAbortedAll); NOREF(fAbortedAll);
    65886543                        ahciSendSDBFis(pAhciPort, 0xffffffff, true);
     
    66036558        case ATA_DATA_SET_MANAGEMENT:
    66046559        {
    6605             if (   (   !pAhciPort->fAsyncInterface
    6606                     && pAhciPort->pDrvMedia->pfnDiscard)
    6607                 || (   pAhciPort->fAsyncInterface
    6608                     && pAhciPort->pDrvMediaAsync->pfnStartDiscard))
     6560            if (pAhciPort->fTrimEnabled)
    66096561            {
    66106562                /* Check that the trim bit is set and all other bits are 0. */
     
    66166568                }
    66176569                else
    6618                     enmTxDir = AHCITXDIR_TRIM;
     6570                    enmType = PDMMEDIAEXIOREQTYPE_DISCARD;
    66196571                break;
    66206572            }
     
    66366588    }
    66376589
    6638     return enmTxDir;
     6590    return enmType;
    66396591}
    66406592
     
    66476599static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    66486600{
    6649     RTGCPHYS  GCPhysAddrCmdTbl;
    6650 
    66516601    AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb,
    66526602                    ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__),
     
    66586608     * We can process the Command FIS afterwards.
    66596609     */
     6610    CmdHdr cmdHdr;
    66606611    pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
    66616612    LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__,
    66626613             pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
    6663     PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
     6614    PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &cmdHdr, sizeof(CmdHdr));
    66646615
    66656616#ifdef LOG_ENABLED
    66666617    /* Print some infos about the command header. */
    6667     ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr);
     6618    ahciDumpCmdHdrInfo(pAhciPort, &cmdHdr);
    66686619#endif
    66696620
    6670     GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);
    6671 
    6672     AssertMsgReturn((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
     6621    RTGCPHYS GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr);
     6622
     6623    AssertMsgReturn((cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
    66736624                    ("This is not a command FIS!!\n"),
    66746625                    false);
     
    66836634
    66846635    /* Set transfer direction. */
    6685     pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
     6636    pAhciReq->enmType = (cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? PDMMEDIAEXIOREQTYPE_WRITE : PDMMEDIAEXIOREQTYPE_READ;
    66866637
    66876638    /* If this is an ATAPI command read the atapi command. */
    6688     if (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A)
     6639    if (cmdHdr.u32DescInf & AHCI_CMDHDR_A)
    66896640    {
    66906641        GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET;
     
    66936644
    66946645    /* We "received" the FIS. Clear the BSY bit in regTFD. */
    6695     if ((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))
     6646    if ((cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))
    66966647    {
    66976648        /*
     
    67036654    }
    67046655
    6705     pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
    6706     pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(pAhciReq->cmdHdr.u32DescInf);
     6656    pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
     6657    pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(cmdHdr.u32DescInf);
    67076658
    67086659#ifdef LOG_ENABLED
     
    67376688 * @param   pAhciPort    The port the request is for.
    67386689 * @param   pAhciReq     The request to submit.
    6739  * @param   enmTxDir     The request type.
    6740  */
    6741 static bool ahciR3ReqSubmit(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, AHCITXDIR enmTxDir)
     6690 * @param   enmType     The request type.
     6691 */
     6692static bool ahciR3ReqSubmit(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, PDMMEDIAEXIOREQTYPE enmType)
    67426693{
    67436694    int rc = VINF_SUCCESS;
    67446695    bool fReqCanceled = false;
    67456696
    6746     if (pAhciPort->fAsyncInterface)
    6747     {
    6748         VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, pAhciReq->enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer);
    6749         VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
    6750         if (enmTxDir == AHCITXDIR_FLUSH)
    6751         {
    6752             rc = pAhciPort->pDrvMediaAsync->pfnStartFlush(pAhciPort->pDrvMediaAsync,
    6753                                                           pAhciReq);
    6754         }
    6755         else if (enmTxDir == AHCITXDIR_TRIM)
    6756         {
    6757             rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    6758             if (RT_SUCCESS(rc))
    6759             {
    6760                 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6761                 rc = pAhciPort->pDrvMediaAsync->pfnStartDiscard(pAhciPort->pDrvMediaAsync, pAhciReq->u.Trim.paRanges,
    6762                                                                 pAhciReq->u.Trim.cRanges, pAhciReq);
    6763             }
    6764         }
    6765         else if (enmTxDir == AHCITXDIR_READ)
    6766         {
    6767             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6768             rc = pAhciPort->pDrvMediaAsync->pfnStartRead(pAhciPort->pDrvMediaAsync, pAhciReq->uOffset,
    6769                                                          &pAhciReq->u.Io.DataSeg, 1,
    6770                                                          pAhciReq->cbTransfer,
    6771                                                          pAhciReq);
    6772         }
    6773         else
     6697    VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, pAhciReq->enmType, pAhciReq->uOffset, pAhciReq->cbTransfer);
     6698    VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
     6699
     6700    if (enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
     6701        rc = pAhciPort->pDrvMediaEx->pfnIoReqFlush(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
     6702    else if (enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
     6703    {
     6704        rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
     6705        if (RT_SUCCESS(rc))
    67746706        {
    67756707            pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6776             rc = pAhciPort->pDrvMediaAsync->pfnStartWrite(pAhciPort->pDrvMediaAsync, pAhciReq->uOffset,
    6777                                                           &pAhciReq->u.Io.DataSeg, 1,
    6778                                                           pAhciReq->cbTransfer,
    6779                                                           pAhciReq);
    6780         }
    6781         if (rc == VINF_VD_ASYNC_IO_FINISHED)
    6782             fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
    6783         else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    6784             fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc);
     6708            rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
     6709                                                         pAhciReq->u.Trim.cRanges);
     6710        }
     6711    }
     6712    else if (enmType == PDMMEDIAEXIOREQTYPE_READ)
     6713    {
     6714        pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     6715        rc = pAhciPort->pDrvMediaEx->pfnIoReqRead(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
     6716                                                  pAhciReq->uOffset, pAhciReq->cbTransfer);
    67856717    }
    67866718    else
    67876719    {
    6788         if (enmTxDir == AHCITXDIR_FLUSH)
    6789             rc = pAhciPort->pDrvMedia->pfnFlush(pAhciPort->pDrvMedia);
    6790         else if (enmTxDir == AHCITXDIR_TRIM)
    6791         {
    6792             rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    6793             if (RT_SUCCESS(rc))
    6794             {
    6795                 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6796                 rc = pAhciPort->pDrvMedia->pfnDiscard(pAhciPort->pDrvMedia, pAhciReq->u.Trim.paRanges,
    6797                                                       pAhciReq->u.Trim.cRanges);
    6798                 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
    6799             }
    6800         }
    6801         else if (enmTxDir == AHCITXDIR_READ)
    6802         {
    6803             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6804             rc = pAhciPort->pDrvMedia->pfnRead(pAhciPort->pDrvMedia, pAhciReq->uOffset,
    6805                                                pAhciReq->u.Io.DataSeg.pvSeg,
    6806                                                pAhciReq->cbTransfer);
    6807             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 0;
    6808         }
    6809         else
    6810         {
    6811             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6812             rc = pAhciPort->pDrvMedia->pfnWrite(pAhciPort->pDrvMedia, pAhciReq->uOffset,
    6813                                                 pAhciReq->u.Io.DataSeg.pvSeg,
    6814                                                 pAhciReq->cbTransfer);
    6815             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
    6816         }
     6720        pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6721        rc = pAhciPort->pDrvMediaEx->pfnIoReqWrite(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
     6722                                                   pAhciReq->uOffset, pAhciReq->cbTransfer);
     6723    }
     6724
     6725    if (rc == VINF_SUCCESS)
     6726        fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
     6727    else if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
    68176728        fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc);
    6818     }
    68196729
    68206730    return fReqCanceled;
     
    68386748    /* Set current command slot */
    68396749    ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
    6840     ASMAtomicWritePtr(&pAhciPort->aActiveTasks[pAhciReq->uTag], pAhciReq);
    68416750
    68426751    bool fContinue = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
     
    69846893        {
    69856894            bool fReqCanceled = false;
    6986             AHCITXDIR enmTxDir;
    6987             PAHCIREQ pAhciReq;
    69886895
    69896896            /* Decrement to get the slot number. */
     
    69916898            ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, idx));
    69926899
    6993             /* Check whether the request is already active and ignore. */
    6994             if (ASMAtomicReadPtr((void * volatile *)&pAhciPort->aActiveTasks[idx]))
    6995             {
    6996                 ahciLog(("%s: Ignoring command at slot %d because it is already active\n", __FUNCTION__, idx));
    6997                 continue;
    6998             }
    6999 
    7000             pAhciReq = ahciR3ReqAlloc(pAhciPort);
     6900            PAHCIREQ pAhciReq = ahciR3ReqAlloc(pAhciPort, idx);
    70016901            if (RT_LIKELY(pAhciReq))
    70026902            {
     
    70076907                if (fContinue)
    70086908                {
    7009                     enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
    7010                     pAhciReq->enmTxDir = enmTxDir;
    7011 
    7012                     if (enmTxDir != AHCITXDIR_NONE)
     6909                    PDMMEDIAEXIOREQTYPE enmType = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
     6910                    pAhciReq->enmType = enmType;
     6911
     6912                    if (enmType != PDMMEDIAEXIOREQTYPE_INVALID)
    70136913                    {
    7014                         if (   enmTxDir != AHCITXDIR_FLUSH
    7015                             && enmTxDir != AHCITXDIR_TRIM)
     6914                        if (   enmType != PDMMEDIAEXIOREQTYPE_FLUSH
     6915                            && enmType != PDMMEDIAEXIOREQTYPE_DISCARD)
    70166916                        {
    70176917                            STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
     
    70276927
    70286928                        if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    7029                             fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmTxDir);
     6929                            fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType);
    70306930                        else /* Overflow is handled in completion routine. */
    70316931                            fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
     
    70356935                } /* Command */
    70366936                else
    7037                 {
    7038                     ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[pAhciReq->uTag]);
    70396937                    ahciR3ReqFree(pAhciPort, pAhciReq);
    7040                 }
    70416938            }
    70426939            else /* !Request allocated, use on stack variant to signal the error. */
     
    71447041        PAHCIPort pThisPort = &pThis->ahciPort[i];
    71457042
    7146         pHlp->pfnPrintf(pHlp, "Port %d: async=%RTbool device-attached=%RTbool\n",
    7147                         pThisPort->iLUN, pThisPort->fAsyncInterface, pThisPort->pDrvBase != NULL);
     7043        pHlp->pfnPrintf(pHlp, "Port %d: device-attached=%RTbool\n",
     7044                        pThisPort->iLUN, pThisPort->pDrvBase != NULL);
    71487045        pHlp->pfnPrintf(pHlp, "PortClb=%#x\n", pThisPort->regCLB);
    71497046        pHlp->pfnPrintf(pHlp, "PortClbU=%#x\n", pThisPort->regCLBU);
     
    77077604    Log(("%s:\n", __FUNCTION__));
    77087605
    7709     /* Free all cached I/O tasks. */
    7710     ahciR3PortCachedReqsFree(pAhciPort);
    7711 
    77127606    pAhciPort->cTotalSectors = 0;
    77137607
     
    77397633static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort)
    77407634{
    7741     int          rc = VINF_SUCCESS;
    7742     PDMMEDIATYPE enmType;
    7743 
    7744     /*
    7745      * Query the block and blockbios interfaces.
    7746      */
     7635    /* Query the media interface. */
    77477636    pAhciPort->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIA);
    7748     if (!pAhciPort->pDrvMedia)
    7749     {
    7750         AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN));
    7751         return VERR_PDM_MISSING_INTERFACE;
    7752     }
     7637    AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMedia),
     7638                    ("AHCI configuration error: LUN#%d misses the basic media interface!\n", pAhciPort->iLUN),
     7639                    VERR_PDM_MISSING_INTERFACE);
     7640
     7641    /* Get the extended media interface. */
     7642    pAhciPort->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIAEX);
     7643    AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMediaEx),
     7644                    ("AHCI configuration error: LUN#%d misses the extended media interface!\n", pAhciPort->iLUN),
     7645                    VERR_PDM_MISSING_INTERFACE);
    77537646
    77547647    pAhciPort->pDrvMount = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMOUNT);
    7755 
    7756     /* Try to get the optional async block interface. */
    7757     pAhciPort->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIAASYNC);
    77587648
    77597649    /*
    77607650     * Validate type.
    77617651     */
    7762     enmType = pAhciPort->pDrvMedia->pfnGetType(pAhciPort->pDrvMedia);
    7763 
    7764     if (   enmType != PDMMEDIATYPE_HARD_DISK
    7765         && enmType != PDMMEDIATYPE_CDROM
    7766         && enmType != PDMMEDIATYPE_DVD)
    7767     {
    7768         AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType));
    7769         return VERR_PDM_UNSUPPORTED_BLOCK_TYPE;
    7770     }
    7771 
    7772     if (   (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD)
    7773         && !pAhciPort->pDrvMount)
    7774     {
    7775         AssertMsgFailed(("Internal error: CD/DVD-ROM without a mountable interface\n"));
    7776         return VERR_INTERNAL_ERROR;
    7777     }
    7778     pAhciPort->fATAPI = (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD);
    7779     pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? (pAhciPort->pDrvMedia->pfnSendCmd != NULL) : false;
    7780 
    7781     rc = RTCritSectInit(&pAhciPort->CritSectReqsFree);
     7652    PDMMEDIATYPE enmType = pAhciPort->pDrvMedia->pfnGetType(pAhciPort->pDrvMedia);
     7653    AssertMsgReturn(enmType == PDMMEDIATYPE_HARD_DISK || enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD,
     7654                    ("AHCI configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%u\n", pAhciPort->iLUN, enmType),
     7655                    VERR_PDM_UNSUPPORTED_BLOCK_TYPE);
     7656    AssertMsgReturn(enmType == PDMMEDIATYPE_HARD_DISK || pAhciPort->pDrvMount,
     7657                    ("AHCI configuration error: LUN#%d is CD/DVD-ROM without a mountable interface\n", pAhciPort->iLUN),
     7658                    VERR_INTERNAL_ERROR);
     7659
     7660    int rc = pAhciPort->pDrvMediaEx->pfnIoReqAllocSizeSet(pAhciPort->pDrvMediaEx, sizeof(AHCIREQ));
    77827661    if (RT_FAILURE(rc))
    77837662        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
    7784                                    N_("AHCI initialisation error: Failed to create critical section for free request list"));
    7785 
    7786     pAhciPort->pListReqsFree = (PRTLISTANCHOR)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(RTLISTANCHOR));
    7787     if (!pAhciPort->pListReqsFree)
    7788         return PDMDevHlpVMSetError(pDevIns, VERR_NO_MEMORY, RT_SRC_POS,
    7789                                    N_("AHCI initialisation error: Failed to allocate memory for free request list"));
    7790 
    7791     RTListInit(pAhciPort->pListReqsFree);
    7792 
     7663                                   N_("AHCI configuration error: LUN#%u: Failed to set I/O request size!"),
     7664                                   pAhciPort->iLUN);
     7665
     7666    uint32_t fFeatures = 0;
     7667    rc = pAhciPort->pDrvMediaEx->pfnQueryFeatures(pAhciPort->pDrvMediaEx, &fFeatures);
     7668    if (RT_FAILURE(rc))
     7669        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     7670                                   N_("AHCI configuration error: LUN#%u: Failed to query features of device"),
     7671                                   pAhciPort->iLUN);
     7672
     7673    if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD)
     7674        pAhciPort->fTrimEnabled = true;
     7675
     7676    pAhciPort->fATAPI = (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD);
     7677    pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? !!(fFeatures & PDMIMEDIAEX_FEATURE_F_RAWSCSICMD) : false;
    77937678    if (pAhciPort->fATAPI)
    77947679    {
     
    78347719                 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors,
    78357720                 pAhciPort->cTotalSectors));
    7836         if (pAhciPort->pDrvMedia->pfnDiscard)
     7721        if (pAhciPort->fTrimEnabled)
    78377722            LogRel(("AHCI: LUN#%d: Enabled TRIM support\n", pAhciPort->iLUN));
    78387723    }
     
    78537738    PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
    78547739    ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    7855     /*
    7856      * Free all cached tasks here, not possible on destruct because the driver
    7857      * is destroyed before us.
    7858      */
    7859     for (unsigned iPort = 0; iPort < pThis->cPortsImpl; iPort++)
    7860         ahciR3PortCachedReqsFree(&pThis->ahciPort[iPort]);
    78617740    return true;
    78627741}
     
    78737752        PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone);
    78747753    else
    7875     {
    7876         /*
    7877          * Free all cached tasks here, not possible on destruct because the driver
    7878          * is destroyed before us.
    7879          */
    7880         for (unsigned iPort = 0; iPort < pThis->cPortsImpl; iPort++)
    7881             ahciR3PortCachedReqsFree(&pThis->ahciPort[iPort]);
    7882 
    78837754        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    7884     }
    78857755}
    78867756
     
    80897959    if (pAhciPort->fATAPI)
    80907960        ahciMediumRemoved(pAhciPort);
    8091 
    8092     /* Free all cached I/O tasks. */
    8093     ahciR3PortCachedReqsFree(pAhciPort);
    8094 
    8095     if (RTCritSectIsInitialized(&pAhciPort->CritSectReqsFree))
    8096         RTCritSectDelete(&pAhciPort->CritSectReqsFree);
    8097 
    8098     if (pAhciPort->pListReqsFree)
    8099         MMR3HeapFree(pAhciPort->pListReqsFree);
    8100 
    8101     pAhciPort->pListReqsFree = NULL;
    81027961
    81037962    if (!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG))
     
    81267985    pAhciPort->pDrvBase = NULL;
    81277986    pAhciPort->pDrvMedia = NULL;
    8128     pAhciPort->pDrvMediaAsync = NULL;
     7987    pAhciPort->pDrvMediaEx = NULL;
    81297988}
    81307989
     
    81528011    AssertRelease(!pAhciPort->pDrvBase);
    81538012    AssertRelease(!pAhciPort->pDrvMedia);
    8154     AssertRelease(!pAhciPort->pDrvMediaAsync);
     8013    AssertRelease(!pAhciPort->pDrvMediaEx);
    81558014    Assert(pAhciPort->iLUN == iLUN);
    81568015
     
    81878046        char szName[24];
    81888047        RTStrPrintf(szName, sizeof(szName), "Port%d", iLUN);
    8189 
    8190         if (   pAhciPort->pDrvMediaAsync
    8191             && !pAhciPort->fATAPI)
    8192             pAhciPort->fAsyncInterface = true;
    8193         else
    8194             pAhciPort->fAsyncInterface = false;
    81958048
    81968049        rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
     
    83458198                pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
    83468199            }
    8347 
    8348             if (RTCritSectIsInitialized(&pAhciPort->CritSectReqsFree))
    8349                 RTCritSectDelete(&pAhciPort->CritSectReqsFree);
    8350 
    8351 #ifdef VBOX_STRICT
    8352             for (uint32_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++)
    8353                 Assert(!pAhciPort->aActiveTasks[i]);
    8354 #endif
    83558200        }
    83568201
     
    83878232                                    "SecondarySlave\0"
    83888233                                    "PortCount\0"
    8389                                     "UseAsyncInterfaceIfAvailable\0"
    83908234                                    "Bootable\0"
    83918235                                    "CmdSlotsAvail\0"))
     
    84188262                                   N_("AHCI configuration error: PortCount=%u should be at least 1"),
    84198263                                   pThis->cPortsImpl);
    8420 
    8421     rc = CFGMR3QueryBoolDef(pCfg, "UseAsyncInterfaceIfAvailable", &pThis->fUseAsyncInterfaceIfAvailable, true);
    8422     if (RT_FAILURE(rc))
    8423         return PDMDEV_SET_ERROR(pDevIns, rc,
    8424                                 N_("AHCI configuration error: failed to read UseAsyncInterfaceIfAvailable as boolean"));
    84258264
    84268265    rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &pThis->fBootable, true);
     
    86418480         * Init interfaces.
    86428481         */
    8643         pAhciPort->IBase.pfnQueryInterface              = ahciR3PortQueryInterface;
    8644         pAhciPort->IPortAsync.pfnTransferCompleteNotify = ahciR3TransferCompleteNotify;
    8645         pAhciPort->IPort.pfnQueryDeviceLocation         = ahciR3PortQueryDeviceLocation;
    8646         pAhciPort->IMountNotify.pfnMountNotify          = ahciR3MountNotify;
    8647         pAhciPort->IMountNotify.pfnUnmountNotify        = ahciR3UnmountNotify;
    8648         pAhciPort->fWrkThreadSleeping                   = true;
     8482        pAhciPort->IBase.pfnQueryInterface                 = ahciR3PortQueryInterface;
     8483        pAhciPort->IMediaExPort.pfnIoReqCompleteNotify     = ahciR3IoReqCompleteNotify;
     8484        pAhciPort->IMediaExPort.pfnIoReqCopyFromBuf        = ahciR3IoReqCopyFromBuf;
     8485        pAhciPort->IMediaExPort.pfnIoReqCopyToBuf          = ahciR3IoReqCopyToBuf;
     8486        pAhciPort->IMediaExPort.pfnIoReqQueryDiscardRanges = ahciR3IoReqQueryDiscardRanges;
     8487        pAhciPort->IMediaExPort.pfnIoReqStateChanged       = ahciR3IoReqStateChanged;
     8488        pAhciPort->IPort.pfnQueryDeviceLocation            = ahciR3PortQueryDeviceLocation;
     8489        pAhciPort->IMountNotify.pfnMountNotify             = ahciR3MountNotify;
     8490        pAhciPort->IMountNotify.pfnUnmountNotify           = ahciR3UnmountNotify;
     8491        pAhciPort->fWrkThreadSleeping                      = true;
    86498492
    86508493        /* Query per port configuration options if available. */
     
    86818524            if (RT_FAILURE(rc))
    86828525                return rc;
    8683 
    8684             /*
    8685              * If the new async interface is available we use a PDMQueue to transmit
    8686              * the requests into R3.
    8687              * Otherwise we use a event semaphore and a async I/O thread which processes them.
    8688              */
    8689             if (pAhciPort->pDrvMediaAsync && pThis->fUseAsyncInterfaceIfAvailable)
    8690             {
    8691                 LogRel(("AHCI: LUN#%d: using async I/O\n", pAhciPort->iLUN));
    8692                 pAhciPort->fAsyncInterface = true;
    8693             }
    8694             else
    8695             {
    8696                 LogRel(("AHCI: LUN#%d: using normal I/O\n", pAhciPort->iLUN));
    8697                 pAhciPort->fAsyncInterface = false;
    8698             }
    86998526
    87008527            rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
Note: See TracChangeset for help on using the changeset viewer.

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