VirtualBox

Changeset 64222 in vbox


Ignore:
Timestamp:
Oct 12, 2016 12:40:16 PM (8 years ago)
Author:
vboxsync
Message:

UsbMsd: Convert device emulation to use PDMIMEDIAEX and friends

File:
1 edited

Legend:

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

    r63482 r64222  
    5353
    5454/** Saved state version. */
    55 #define USB_MSD_SAVED_STATE_VERSION 1
     55#define USB_MSD_SAVED_STATE_VERSION             2
     56/** Saved state vesion before the cleanup. */
     57#define USB_MSD_SAVED_STATE_VERSION_PRE_CLEANUP 1
    5658
    5759
     
    145147    /** The state of the request. */
    146148    USBMSDREQSTATE      enmState;
     149    /** The I/O requesthandle .*/
     150    PDMMEDIAEXIOREQ     hIoReq;
    147151    /** The size of the data buffer. */
    148152    uint32_t            cbBuf;
     
    153157    /** The current Cbw when we're in the pending state. */
    154158    USBCBW              Cbw;
    155     /** The current SCSI request. */
    156     PDMSCSIREQUEST      ScsiReq;
    157     /** The scatter-gather segment used by ScsiReq for describing pbBuf. */
    158     RTSGSEG             ScsiReqSeg;
    159     /** The sense buffer for the current SCSI request. */
    160     uint8_t             ScsiReqSense[64];
    161159    /** The status of a completed SCSI request. */
    162     int                 iScsiReqStatus;
    163     /** Pointer to the USB device instance owning it. */
    164     PPDMUSBINS          pUsbIns;
     160    uint8_t             iScsiReqStatus;
    165161} USBMSDREQ;
    166162/** Pointer to a USB MSD request. */
     
    208204     * (0 - default, 1 - the only, i.e configured.) */
    209205    uint8_t             bConfigurationValue;
    210 #if 0
    211     /** The state of the MSD (state machine).*/
    212     USBMSDSTATE         enmState;
    213 #endif
    214206    /** Endpoint 0 is the default control pipe, 1 is the host->dev bulk pipe and 2
    215207     * is the dev->host one. */
     
    255247        /** The base interface for LUN\#0. */
    256248        PDMIBASE            IBase;
    257         /** The SCSI port interface for LUN\#0  */
    258         PDMISCSIPORT        IScsiPort;
     249        /** The media port interface fo LUN\#0. */
     250        PDMIMEDIAPORT       IMediaPort;
     251        /** The extended media port interface for LUN\#0  */
     252        PDMIMEDIAEXPORT     IMediaExPort;
    259253
    260254        /** The base interface for the SCSI driver connected to LUN\#0. */
    261255        PPDMIBASE           pIBase;
    262         /** The SCSI connector interface for the SCSI driver connected to LUN\#0. */
    263         PPDMISCSICONNECTOR  pIScsiConnector;
     256        /** The media interface for th SCSI drver conected to LUN\#0. */
     257        PPDMIMEDIA          pIMedia;
     258        /** The extended media inerface for the SCSI driver connected to LUN\#0. */
     259        PPDMIMEDIAEX        pIMediaEx;
    264260    } Lun0;
    265261
     
    818814 *
    819815 * @returns Pointer to the new request.  NULL if we're out of memory.
    820  * @param   pUsbIns             The instance allocating it.
    821  */
    822 static PUSBMSDREQ usbMsdReqAlloc(PPDMUSBINS pUsbIns)
    823 {
    824     PUSBMSDREQ pReq = (PUSBMSDREQ)PDMUsbHlpMMHeapAllocZ(pUsbIns, sizeof(*pReq));
    825     if (pReq)
    826     {
    827         pReq->enmState          = USBMSDREQSTATE_READY;
    828         pReq->iScsiReqStatus    = -1;
    829         pReq->pUsbIns           = pUsbIns;
     816 * @param   pThis               The MSD instance.
     817 */
     818static PUSBMSDREQ usbMsdReqAlloc(PUSBMSD pThis)
     819{
     820    PUSBMSDREQ pReq = NULL;
     821    PDMMEDIAEXIOREQ hIoReq = NULL;
     822
     823    int rc = pThis->Lun0.pIMediaEx->pfnIoReqAlloc(pThis->Lun0.pIMediaEx, &hIoReq, (void **)&pReq,
     824                                                  0 /* uTag */, PDMIMEDIAEX_F_DEFAULT);
     825    if (RT_SUCCESS(rc))
     826    {
     827        pReq->hIoReq         = hIoReq;
     828        pReq->enmState       = USBMSDREQSTATE_READY;
     829        pReq->iScsiReqStatus = 0xff;
    830830    }
    831831    else
    832         LogRel(("usbMsdReqAlloc: Out of memory\n"));
     832        LogRel(("usbMsdReqAlloc: Out of memory (%Rrc)\n", rc));
     833
    833834    return pReq;
    834835}
     
    838839 * Frees a request.
    839840 *
     841 * @param   pThis               The MSD instance.
    840842 * @param   pReq                The request.
    841843 */
    842 static void usbMsdReqFree(PUSBMSDREQ pReq)
     844static void usbMsdReqFree(PUSBMSD pThis, PUSBMSDREQ pReq)
    843845{
    844846    /*
     
    848850                     &&  pReq->enmState != USBMSDREQSTATE_EXECUTING
    849851                     &&  pReq->enmState < USBMSDREQSTATE_END);
    850     PPDMUSBINS pUsbIns = pReq->pUsbIns;
     852    PPDMUSBINS pUsbIns = pThis->pUsbIns;
    851853    AssertPtrReturnVoid(pUsbIns);
    852854    AssertReturnVoid(PDM_VERSION_ARE_COMPATIBLE(pUsbIns->u32Version, PDM_USBINS_VERSION));
     
    855857     * Invalidate it and free the associated resources.
    856858     */
    857     pReq->enmState                      = USBMSDREQSTATE_INVALID;
    858     pReq->cbBuf                         = 0;
    859     pReq->offBuf                        = 0;
    860     pReq->ScsiReq.pbCDB                 = NULL;
    861     pReq->ScsiReq.paScatterGatherHead   = NULL;
    862     pReq->ScsiReq.pbSenseBuffer         = NULL;
    863     pReq->ScsiReq.pvUser                = NULL;
    864     pReq->ScsiReqSeg.cbSeg              = 0;
    865     pReq->ScsiReqSeg.pvSeg              = NULL;
     859    pReq->enmState = USBMSDREQSTATE_INVALID;
     860    pReq->cbBuf    = 0;
     861    pReq->offBuf   = 0;
    866862
    867863    if (pReq->pbBuf)
     
    871867    }
    872868
    873     PDMUsbHlpMMHeapFree(pUsbIns, pReq);
     869    int rc = pThis->Lun0.pIMediaEx->pfnIoReqFree(pThis->Lun0.pIMediaEx, pReq->hIoReq);
     870    AssertRC(rc);
    874871}
    875872
     
    889886
    890887    /* Setup the SCSI request. */
    891     pReq->ScsiReq.uLogicalUnit      = pReq->Cbw.bCBWLun;
    892     pReq->ScsiReq.uDataDirection    = (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT
    893                                     ? PDMSCSIREQUESTTXDIR_TO_DEVICE
    894                                     : PDMSCSIREQUESTTXDIR_FROM_DEVICE;
    895     pReq->ScsiReq.cbCDB             = pReq->Cbw.bCBWCBLength;
    896 
    897     pReq->ScsiReq.pbCDB             = &pReq->Cbw.CBWCB[0];
    898     pReq->offBuf                    = 0;
    899     pReq->ScsiReqSeg.pvSeg          = pReq->pbBuf;
    900     pReq->ScsiReqSeg.cbSeg          = pReq->Cbw.dCBWDataTransferLength;
    901     pReq->ScsiReq.cbScatterGather   = pReq->Cbw.dCBWDataTransferLength;
    902     pReq->ScsiReq.cScatterGatherEntries = 1;
    903     pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg;
    904     pReq->ScsiReq.cbSenseBuffer     = sizeof(pReq->ScsiReqSense);
    905     pReq->ScsiReq.pbSenseBuffer     = &pReq->ScsiReqSense[0];
    906     pReq->ScsiReq.pvUser            = NULL;
    907     RT_ZERO(pReq->ScsiReqSense);
    908     pReq->iScsiReqStatus            = -1;
     888    pReq->offBuf         = 0;
     889    pReq->iScsiReqStatus = 0xff;
    909890}
    910891
     
    914895 *
    915896 * @returns Success indicator (true/false)
    916  * @param   pReq
    917  * @param   cbBuf       The required buffer space.
    918  */
    919 static int usbMsdReqEnsureBuffer(PUSBMSDREQ pReq, uint32_t cbBuf)
     897 * @param   pThis               The MSD instance.
     898 * @param   pReq                The request.
     899 * @param   cbBuf               The required buffer space.
     900 */
     901static int usbMsdReqEnsureBuffer(PUSBMSD pThis, PUSBMSDREQ pReq, uint32_t cbBuf)
    920902{
    921903    if (RT_LIKELY(pReq->cbBuf >= cbBuf))
     
    923905    else
    924906    {
    925         PDMUsbHlpMMHeapFree(pReq->pUsbIns, pReq->pbBuf);
     907        PDMUsbHlpMMHeapFree(pThis->pUsbIns, pReq->pbBuf);
    926908        pReq->cbBuf = 0;
    927909
    928910        cbBuf = RT_ALIGN_Z(cbBuf, 0x1000);
    929         pReq->pbBuf = (uint8_t *)PDMUsbHlpMMHeapAllocZ(pReq->pUsbIns, cbBuf);
     911        pReq->pbBuf = (uint8_t *)PDMUsbHlpMMHeapAllocZ(pThis->pUsbIns, cbBuf);
    930912        if (!pReq->pbBuf)
    931913            return false;
     
    1015997
    1016998        /* Device reset: Wait for up to 10 ms.  If it doesn't work, ditch
    1017            whoe the request structure.  We'll allocate a new one when needed. */
     999           whole the request structure.  We'll allocate a new one when needed. */
    10181000        Log(("usbMsdResetWorker: Waiting for completion...\n"));
    10191001        Assert(!pThis->fSignalResetSem);
     
    10431025    {
    10441026        pReq->enmState       = USBMSDREQSTATE_READY;
    1045         pReq->iScsiReqStatus = -1;
     1027        pReq->iScsiReqStatus = 0xff;
    10461028    }
    10471029
     
    10771059
    10781060/**
    1079  * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
    1080  */
    1081 static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
    1082                                                         int rcCompletion, bool fRedo, int rcReq)
    1083 {
    1084     RT_NOREF(fRedo, rcReq);
    1085     PUSBMSD     pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
    1086     PUSBMSDREQ  pReq  = RT_FROM_MEMBER(pSCSIRequest, USBMSDREQ, ScsiReq);
    1087 
    1088     Log(("usbMsdLun0ScsiRequestCompleted: pReq=%p dCBWTag=%#x iScsiReqStatus=%u \n", pReq, pReq->Cbw.dCBWTag, rcCompletion));
     1061 * Process a completed request.
     1062 *
     1063 * @returns nothing.
     1064 * @param   pThis               The MSD instance.
     1065 * @param   pReq                The request.
     1066 * @param   rcReq               The completion status.
     1067 */
     1068static void usbMsdReqComplete(PUSBMSD pThis, PUSBMSDREQ pReq, int rcReq)
     1069{
     1070    RT_NOREF1(rcReq);
     1071
     1072    Log(("usbMsdLun0IoReqCompleteNotify: pReq=%p dCBWTag=%#x iScsiReqStatus=%u \n", pReq, pReq->Cbw.dCBWTag, pReq->iScsiReqStatus));
    10891073    RTCritSectEnter(&pThis->CritSect);
    10901074
     
    10931077        Assert(pReq->enmState == USBMSDREQSTATE_EXECUTING);
    10941078        Assert(pThis->pReq == pReq);
    1095         pReq->iScsiReqStatus = rcCompletion;
    10961079
    10971080        /*
     
    11021085        {
    11031086            pReq->enmState = USBMSDREQSTATE_STATUS;
    1104             Log(("usbMsdLun0ScsiRequestCompleted: Entering STATUS\n"));
     1087            Log(("usbMsdLun0IoReqCompleteNotify: Entering STATUS\n"));
    11051088        }
    11061089        else
    11071090        {
    11081091            pReq->enmState = USBMSDREQSTATE_DATA_TO_HOST;
    1109             Log(("usbMsdLun0ScsiRequestCompleted: Entering DATA_TO_HOST\n"));
     1092            Log(("usbMsdLun0IoReqCompleteNotify: Entering DATA_TO_HOST\n"));
    11101093        }
    11111094
     
    11251108    else
    11261109    {
    1127         Log(("usbMsdLun0ScsiRequestCompleted: freeing %p\n", pReq));
    1128         usbMsdReqFree(pReq);
     1110        Log(("usbMsdLun0IoReqCompleteNotify: freeing %p\n", pReq));
     1111        usbMsdReqFree(pThis, pReq);
    11291112    }
    11301113
     
    11391122
    11401123    RTCritSectLeave(&pThis->CritSect);
     1124}
     1125
     1126
     1127/**
     1128 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     1129 */
     1130static DECLCALLBACK(int) usbMsdLun0IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1131                                                    void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
     1132                                                    size_t cbCopy)
     1133{
     1134    RT_NOREF2(pInterface, hIoReq);
     1135    int rc = VINF_SUCCESS;
     1136    PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc;
     1137
     1138    if (RT_UNLIKELY(offDst + cbCopy > pReq->cbBuf))
     1139        rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     1140    else
     1141    {
     1142        size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, pReq->pbBuf + offDst, cbCopy);
     1143        Assert(cbCopied == cbCopy);
     1144    }
     1145
     1146    return rc;
     1147}
     1148
     1149
     1150/**
     1151 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     1152 */
     1153static DECLCALLBACK(int) usbMsdLun0IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1154                                                  void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
     1155                                                  size_t cbCopy)
     1156{
     1157    RT_NOREF2(pInterface, hIoReq);
     1158    int rc = VINF_SUCCESS;
     1159    PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc;
     1160
     1161    if (RT_UNLIKELY(offSrc + cbCopy > pReq->cbBuf))
     1162        rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     1163    else
     1164    {
     1165        size_t cbCopied = RTSgBufCopyFromBuf(pSgBuf, pReq->pbBuf + offSrc, cbCopy);
     1166        Assert(cbCopied == cbCopy);
     1167    }
     1168
     1169    return rc;
     1170}
     1171
     1172
     1173/**
     1174 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     1175 */
     1176static DECLCALLBACK(int) usbMsdLun0IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1177                                                       void *pvIoReqAlloc, int rcReq)
     1178{
     1179    RT_NOREF1(hIoReq);
     1180    PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IMediaExPort);
     1181    PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc;
     1182
     1183    usbMsdReqComplete(pThis, pReq, rcReq);
    11411184    return VINF_SUCCESS;
    11421185}
     
    11441187
    11451188/**
     1189 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     1190 */
     1191static DECLCALLBACK(void) usbMsdLun0IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1192                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     1193{
     1194    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
     1195    AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n"));
     1196}
     1197
     1198
     1199/**
     1200 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     1201 */
     1202static DECLCALLBACK(void) usbMsdLun0MediumEjected(PPDMIMEDIAEXPORT pInterface)
     1203{
     1204    RT_NOREF1(pInterface); /** @todo */
     1205}
     1206
     1207
     1208/**
    11461209 * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation}
    11471210 */
    1148 static DECLCALLBACK(int) usbMsdLun0QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
     1211static DECLCALLBACK(int) usbMsdLun0QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    11491212                                                       uint32_t *piInstance, uint32_t *piLUN)
    11501213{
    1151     PUSBMSD    pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
     1214    PUSBMSD    pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IMediaPort);
    11521215    PPDMUSBINS pUsbIns = pThis->pUsbIns;
    11531216
     
    11711234    PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IBase);
    11721235    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
    1173     PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pThis->Lun0.IScsiPort);
     1236    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->Lun0.IMediaPort);
     1237    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pThis->Lun0.IMediaExPort);
    11741238    return NULL;
    11751239}
     
    12201284        PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncSuspendOrPowerOffDone);
    12211285    else
     1286    {
    12221287        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     1288
     1289        if (pThis->pReq)
     1290        {
     1291            usbMsdReqFree(pThis, pThis->pReq);
     1292            pThis->pReq = NULL;
     1293        }
     1294    }
    12231295}
    12241296
     
    13051377        SSMR3PutU32(pSSM, pReq->offBuf);
    13061378        SSMR3PutMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw));
    1307         SSMR3PutU32(pSSM, pReq->ScsiReq.uLogicalUnit);
    1308         SSMR3PutU32(pSSM, pReq->ScsiReq.uDataDirection);
    1309         SSMR3PutU32(pSSM, pReq->ScsiReq.cbCDB);
    1310         SSMR3PutU32(pSSM, pReq->ScsiReq.cbScatterGather);
    1311         SSMR3PutMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense));
    1312         SSMR3PutS32(pSSM, pReq->iScsiReqStatus);
     1379        SSMR3PutU8(pSSM, pReq->iScsiReqStatus);
    13131380    }
    13141381
     
    13511418        if (fReqAlloc)
    13521419        {
    1353             PUSBMSDREQ pReq = usbMsdReqAlloc(pUsbIns);
     1420            PUSBMSDREQ pReq = usbMsdReqAlloc(pThis);
    13541421            AssertReturn(pReq, VERR_NO_MEMORY);
    13551422            pThis->pReq = pReq;
     
    13611428            if (cbBuf)
    13621429            {
    1363                 if (usbMsdReqEnsureBuffer(pReq, cbBuf))
     1430                if (usbMsdReqEnsureBuffer(pThis, pReq, cbBuf))
    13641431                {
    13651432                    AssertPtr(pReq->pbBuf);
     
    13731440            SSMR3GetU32(pSSM, &pReq->offBuf);
    13741441            SSMR3GetMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw));
    1375             SSMR3GetU32(pSSM, &pReq->ScsiReq.uLogicalUnit);
    1376             SSMR3GetU32(pSSM, (uint32_t *)&pReq->ScsiReq.uDataDirection);
    1377             SSMR3GetU32(pSSM, &pReq->ScsiReq.cbCDB);
    1378             SSMR3GetU32(pSSM, &pReq->ScsiReq.cbScatterGather);
    1379             SSMR3GetMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense));
    1380             rc = SSMR3GetS32(pSSM, &pReq->iScsiReqStatus);
     1442
     1443            if (uVersion >= USB_MSD_SAVED_STATE_VERSION_PRE_CLEANUP)
     1444                rc = SSMR3GetU8(pSSM, &pReq->iScsiReqStatus);
     1445            else
     1446            {
     1447                int32_t iScsiReqStatus;
     1448
     1449                /* Skip old fields which are unused now or can be determined from the CBW. */
     1450                SSMR3Skip(pSSM, 4 * 4 + 64);
     1451                rc = SSMR3GetS32(pSSM, &iScsiReqStatus);
     1452                pReq->iScsiReqStatus = (uint8_t)iScsiReqStatus;
     1453            }
    13811454            AssertRCReturn(rc, rc);
    1382 
    1383             /* Setup the rest of the SCSI request. */
    1384             pReq->ScsiReq.cbCDB             = pReq->Cbw.bCBWCBLength;
    1385             pReq->ScsiReq.pbCDB             = &pReq->Cbw.CBWCB[0];
    1386             pReq->ScsiReqSeg.pvSeg          = pReq->pbBuf;
    1387             pReq->ScsiReqSeg.cbSeg          = pReq->ScsiReq.cbScatterGather;
    1388             pReq->ScsiReq.cScatterGatherEntries = 1;
    1389             pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg;
    1390             pReq->ScsiReq.cbSenseBuffer     = sizeof(pReq->ScsiReqSense);
    1391             pReq->ScsiReq.pbSenseBuffer     = &pReq->ScsiReqSense[0];
    1392             pReq->ScsiReq.pvUser            = NULL;
    13931455        }
    13941456
     
    14631525
    14641526    RTCritSectLeave(&pThis->CritSect);
    1465     return VINF_SUCCESS;
    1466 }
    1467 
    1468 
    1469 /**
    1470  * Fails an illegal SCSI request.
    1471  *
    1472  * @returns VBox status code.
    1473  * @param   pThis               The MSD instance data.
    1474  * @param   pReq                The MSD request.
    1475  * @param   bAsc                The ASC for the SCSI_SENSE_ILLEGAL_REQUEST.
    1476  * @param   bAscq               The ASC qualifier.
    1477  * @param   pszWhy              For logging why.
    1478  */
    1479 static int usbMsdScsiIllegalRequest(PUSBMSD pThis, PUSBMSDREQ pReq, uint8_t bAsc, uint8_t bAscq, const char *pszWhy)
    1480 {
    1481     RT_NOREF(bAsc, bAscq, pszWhy);
    1482     Log(("usbMsdScsiIllegalRequest: bAsc=%#x bAscq=%#x %s\n", bAsc, bAscq, pszWhy));
    1483 
    1484     RT_ZERO(pReq->ScsiReqSense);
    1485     pReq->ScsiReqSense[0]  = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
    1486     pReq->ScsiReqSense[2]  = SCSI_SENSE_ILLEGAL_REQUEST;
    1487     pReq->ScsiReqSense[7]  = 10;
    1488     pReq->ScsiReqSense[12] = SCSI_ASC_INVALID_MESSAGE;
    1489     pReq->ScsiReqSense[13] = 0; /* Should be ASCQ but it has the same value for success. */
    1490 
    1491     usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
    1492     return VINF_SUCCESS;
    1493 }
    1494 
    1495 
    1496 /**
    1497  * The SCSI driver doesn't handle SCSI_REQUEST_SENSE but instead
    1498  * returns the sense info with the request.
    1499  *
    1500  */
    1501 static int usbMsdHandleScsiReqestSense(PUSBMSD pThis, PUSBMSDREQ pReq, PCUSBCBW pCbw)
    1502 {
    1503     Log(("usbMsdHandleScsiReqestSense: Entering EXECUTING (dCBWTag=%#x).\n", pReq->Cbw.dCBWTag));
    1504     Assert(pReq == pThis->pReq);
    1505     pReq->enmState = USBMSDREQSTATE_EXECUTING;
    1506 
    1507     /* validation */
    1508     if ((pCbw->bmCBWFlags & USBCBW_DIR_MASK) != USBCBW_DIR_IN)
    1509         return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "direction");
    1510     if (pCbw->bCBWCBLength < 6)
    1511         return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "length");
    1512     if ((pCbw->CBWCB[1] >> 5) != pCbw->bCBWLun)
    1513         return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "lun");
    1514     if (pCbw->bCBWLun != 0)
    1515         return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "lun0");
    1516     if (pCbw->CBWCB[4] < 6)
    1517         return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "out length");
    1518 
    1519     /* If the previous command succeeded successfully, whip up some sense data. */
    1520     if (   pReq->iScsiReqStatus == SCSI_STATUS_OK
    1521         && pReq->ScsiReqSense[0] == 0)
    1522     {
    1523         RT_ZERO(pReq->ScsiReqSense);
    1524 #if 0  /** @todo something upsets linux about this stuff. Needs investigation. */
    1525         pReq->ScsiReqSense[0]  = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
    1526         pReq->ScsiReqSense[0]  = SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;
    1527         pReq->ScsiReqSense[2]  = SCSI_SENSE_NONE;
    1528         pReq->ScsiReqSense[7]  = 10;
    1529         pReq->ScsiReqSense[12] = SCSI_ASC_NONE;
    1530         pReq->ScsiReqSense[13] = SCSI_ASC_NONE; /* Should be ASCQ but it has the same value for success. */
    1531 #endif
    1532     }
    1533 
    1534     /* Copy the data into the result buffer. */
    1535     size_t cbCopy = RT_MIN(pCbw->dCBWDataTransferLength, sizeof(pReq->ScsiReqSense));
    1536     Log(("usbMsd: SCSI_REQUEST_SENSE - CBWCB[4]=%#x iOldState=%d, %u bytes, raw: %.*Rhxs\n",
    1537          pCbw->CBWCB[4], pReq->iScsiReqStatus, pCbw->dCBWDataTransferLength, RT_MAX(1, cbCopy), pReq->ScsiReqSense));
    1538     memcpy(pReq->pbBuf, &pReq->ScsiReqSense[0], cbCopy);
    1539 
    1540     usbMsdReqPrepare(pReq, pCbw);
    1541 
    1542     /* Do normal completion.  */
    1543     usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
    15441527    return VINF_SUCCESS;
    15451528}
     
    15621545    pReq->enmState = USBMSDREQSTATE_EXECUTING;
    15631546
    1564     switch (pReq->ScsiReq.pbCDB[0])
    1565     {
    1566         case SCSI_REQUEST_SENSE:
    1567         {
    1568         }
    1569 
    1570         default:
    1571             return pThis->Lun0.pIScsiConnector->pfnSCSIRequestSend(pThis->Lun0.pIScsiConnector, &pReq->ScsiReq);
    1572     }
    1573 }
    1574 
    1575 /**
    1576  * Validates a SCSI request before passing it down to the SCSI driver.
    1577  *
    1578  * @returns true / false.  The request will be completed on failure.
    1579  * @param   pThis               The MSD instance data.
    1580  * @param   pCbw                The USB command block wrapper.
    1581  * @param   pUrb                The URB.
    1582  */
    1583 static bool usbMsdIsValidCommand(PUSBMSD pThis, PCUSBCBW pCbw, PVUSBURB pUrb)
    1584 {
    1585     RT_NOREF(pThis, pUrb);
    1586     switch (pCbw->CBWCB[0])
    1587     {
    1588         case SCSI_REQUEST_SENSE:
    1589             /** @todo validate this. */
    1590             return true;
    1591 
    1592         default:
    1593             return true;
    1594     }
     1547    PDMMEDIAEXIOREQSCSITXDIR enmTxDir = pReq->Cbw.dCBWDataTransferLength == 0
     1548                                      ? PDMMEDIAEXIOREQSCSITXDIR_NONE
     1549                                      :   (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT
     1550                                        ? PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE
     1551                                        : PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE;
     1552
     1553    return pThis->Lun0.pIMediaEx->pfnIoReqSendScsiCmd(pThis->Lun0.pIMediaEx, pReq->hIoReq, pReq->Cbw.bCBWLun,
     1554                                                      &pReq->Cbw.CBWCB[0], pReq->Cbw.bCBWCBLength, enmTxDir,
     1555                                                      pReq->Cbw.dCBWDataTransferLength, NULL, 0,
     1556                                                      &pReq->iScsiReqStatus, 20 * RT_MS_1SEC);
    15951557}
    15961558
     
    16671629            }
    16681630
    1669             if (!usbMsdIsValidCommand(pThis, pCbw, pUrb))
    1670                 return VINF_SUCCESS;
    1671 
    16721631            /*
    16731632             * Make sure we've got a request and a sufficient buffer space.
     
    16791638            if (!pReq)
    16801639            {
    1681                 pReq = usbMsdReqAlloc(pThis->pUsbIns);
     1640                pReq = usbMsdReqAlloc(pThis);
    16821641                if (!pReq)
    16831642                    return usbMsdCompleteStall(pThis, NULL, pUrb, "Request allocation failure");
    16841643                pThis->pReq = pReq;
    16851644            }
    1686             if (!usbMsdReqEnsureBuffer(pReq, pCbw->dCBWDataTransferLength))
     1645            if (!usbMsdReqEnsureBuffer(pThis, pReq, pCbw->dCBWDataTransferLength))
    16871646                return usbMsdCompleteStall(pThis, NULL, pUrb, "Buffer allocation failure");
    16881647
    16891648            /*
    1690              * Special case REQUEST SENSE requests, usbMsdReqPrepare will
    1691              * trash the sense data otherwise.
     1649             * Prepare the request.  Kick it off right away if possible.
    16921650             */
    1693             if (pCbw->CBWCB[0] == SCSI_REQUEST_SENSE)
    1694                 usbMsdHandleScsiReqestSense(pThis, pReq, pCbw);
     1651            usbMsdReqPrepare(pReq, pCbw);
     1652
     1653            if (   pReq->Cbw.dCBWDataTransferLength == 0
     1654                || (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_IN)
     1655            {
     1656                int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev");
     1657                if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     1658                    usbMsdReqComplete(pThis, pReq, rc);
     1659                else if (RT_FAILURE(rc))
     1660                {
     1661                    Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
     1662                    return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #1");
     1663                }
     1664            }
    16951665            else
    16961666            {
    1697                 /*
    1698                  * Prepare the request.  Kick it off right away if possible.
    1699                  */
    1700                 usbMsdReqPrepare(pReq, pCbw);
    1701 
    1702                 if (   pReq->Cbw.dCBWDataTransferLength == 0
    1703                     || (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_IN)
    1704                 {
    1705                     int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev");
    1706                     if (RT_FAILURE(rc))
    1707                     {
    1708                         Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
    1709                         return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #1");
    1710                     }
    1711                 }
    1712                 else
    1713                 {
    1714                     Log(("usbMsdHandleBulkHostToDev: Entering DATA_FROM_HOST.\n"));
    1715                     pReq->enmState = USBMSDREQSTATE_DATA_FROM_HOST;
    1716                 }
     1667                Log(("usbMsdHandleBulkHostToDev: Entering DATA_FROM_HOST.\n"));
     1668                pReq->enmState = USBMSDREQSTATE_DATA_FROM_HOST;
    17171669            }
    17181670
     
    17391691            {
    17401692                int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev");
    1741                 if (RT_FAILURE(rc))
     1693                if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     1694                    usbMsdReqComplete(pThis, pReq, rc);
     1695                else if (RT_FAILURE(rc))
    17421696                {
    17431697                    Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
     
    18251779            pCsw->bCSWStatus    = pReq->iScsiReqStatus == SCSI_STATUS_OK
    18261780                                ? USBCSW_STATUS_OK
    1827                                 : pReq->iScsiReqStatus >= 0
     1781                                : pReq->iScsiReqStatus < 0xff
    18281782                                ? USBCSW_STATUS_FAILED
    18291783                                : USBCSW_STATUS_PHASE_ERROR;
     
    18321786            if ((pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT)
    18331787                pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK
    1834                                       ? pReq->Cbw.dCBWDataTransferLength - pReq->ScsiReq.cbScatterGather
     1788                                      ? 0
    18351789                                      : pReq->Cbw.dCBWDataTransferLength;
    18361790            else
    18371791                pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK
    18381792                                      ? 0
    1839                                       : pReq->ScsiReq.cbScatterGather;
     1793                                      : pReq->Cbw.dCBWDataTransferLength;
    18401794            Log(("usbMsd: CSW: dCSWTag=%#x bCSWStatus=%d dCSWDataResidue=%#x\n",
    18411795                 pCsw->dCSWTag, pCsw->bCSWStatus, pCsw->dCSWDataResidue));
     
    18601814            }
    18611815
    1862             /* Adjust the request and kick it off.  Special case the no-data
    1863                case since the SCSI driver doesn't like that. */
    1864             pReq->ScsiReq.cbScatterGather = pReq->offBuf;
    1865             pReq->ScsiReqSeg.cbSeg        = pReq->offBuf;
    1866             if (!pReq->offBuf)
    1867             {
    1868                 Log(("usbMsdHandleBulkDevToHost: Entering EXECUTING (offBuf=0x0).\n"));
    1869                 pReq->enmState = USBMSDREQSTATE_EXECUTING;
    1870 
    1871                 usbMsdQueueAddTail(&pThis->ToHostQueue, pUrb);
    1872                 LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
    1873 
    1874                 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
    1875                 return VINF_SUCCESS;
    1876             }
    1877 
    18781816            int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkDevToHost");
    1879             if (RT_FAILURE(rc))
     1817            if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     1818                usbMsdReqComplete(pThis, pReq, rc);
     1819            else if (RT_FAILURE(rc))
    18801820            {
    18811821                Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc));
     
    21542094    PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
    21552095
    2156     LogFlow(("usbMsdDetach/#%u:\n", pUsbIns->iInstance));
     2096    LogFlow(("usbMsdDriverAttach/#%u:\n", pUsbIns->iInstance));
    21572097
    21582098    AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n"));
     
    21622102    /* the usual paranoia */
    21632103    AssertRelease(!pThis->Lun0.pIBase);
    2164     AssertRelease(!pThis->Lun0.pIScsiConnector);
     2104    AssertRelease(!pThis->Lun0.pIMedia);
     2105    AssertRelease(!pThis->Lun0.pIMediaEx);
    21652106
    21662107    /*
     
    21712112    if (RT_SUCCESS(rc))
    21722113    {
    2173         /* Get SCSI connector interface. */
    2174         pThis->Lun0.pIScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR);
    2175         AssertMsgReturn(pThis->Lun0.pIScsiConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
     2114        /* Get media and extended media interface. */
     2115        pThis->Lun0.pIMedia = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIA);
     2116        AssertMsgReturn(pThis->Lun0.pIMedia, ("Missing media interface below\n"), VERR_PDM_MISSING_INTERFACE);
     2117        pThis->Lun0.pIMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIAEX);
     2118        AssertMsgReturn(pThis->Lun0.pIMediaEx, ("Missing extended media interface below\n"), VERR_PDM_MISSING_INTERFACE);
     2119
     2120        rc = pThis->Lun0.pIMediaEx->pfnIoReqAllocSizeSet(pThis->Lun0.pIMediaEx, sizeof(USBMSDREQ));
     2121        AssertMsgRCReturn(rc, ("MSD failed to set I/O request size!\n"), VERR_PDM_MISSING_INTERFACE);
    21762122    }
    21772123    else
     
    21812127    {
    21822128        pThis->Lun0.pIBase = NULL;
    2183         pThis->Lun0.pIScsiConnector = NULL;
    2184     }
    2185 
    2186     /*
    2187      * Find out what kind of device we are.
    2188      */
    2189     PDMSCSILUNTYPE enmLunType;
     2129        pThis->Lun0.pIMedia = NULL;
     2130        pThis->Lun0.pIMediaEx = NULL;
     2131    }
     2132
    21902133    pThis->fIsCdrom = false;
    2191     rc = pThis->Lun0.pIScsiConnector->pfnQueryLUNType(pThis->Lun0.pIScsiConnector, 0 /*iLun*/, &enmLunType);
    2192     if (RT_SUCCESS(rc))
    2193     {
    2194         /* Anything else will be reported as a hard disk. */
    2195         if (enmLunType == PDMSCSILUNTYPE_MMC)
    2196             pThis->fIsCdrom = true;
    2197     }
     2134    PDMMEDIATYPE enmType = pThis->Lun0.pIMedia->pfnGetType(pThis->Lun0.pIMedia);
     2135    /* Anything else will be reported as a hard disk. */
     2136    if (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD)
     2137        pThis->fIsCdrom = true;
    21982138
    21992139    return rc;
     
    22092149    PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);
    22102150
    2211     LogFlow(("usbMsdDetach/#%u:\n", pUsbIns->iInstance));
     2151    LogFlow(("usbMsdDriverDetach/#%u:\n", pUsbIns->iInstance));
    22122152
    22132153    AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n"));
    22142154    AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
    22152155              ("UsbMsd: Device does not support hotplugging\n"));
     2156
     2157    if (pThis->pReq)
     2158    {
     2159        usbMsdReqFree(pThis, pThis->pReq);
     2160        pThis->pReq = NULL;
     2161    }
    22162162
    22172163    /*
     
    22192165     */
    22202166    pThis->Lun0.pIBase = NULL;
    2221     pThis->Lun0.pIScsiConnector = NULL;
     2167    pThis->Lun0.pIMedia = NULL;
     2168    pThis->Lun0.pIMediaEx = NULL;
    22222169}
    22232170
     
    22752222    }
    22762223
    2277     if (pThis->pReq)
    2278     {
    2279         usbMsdReqFree(pThis->pReq);
    2280         pThis->pReq = NULL;
    2281     }
    2282 
    22832224    if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
    22842225    {
     
    23092250     * will not misbehave.
    23102251     */
    2311     pThis->pUsbIns                                  = pUsbIns;
    2312     pThis->hEvtDoneQueue                            = NIL_RTSEMEVENT;
    2313     pThis->hEvtReset                                = NIL_RTSEMEVENTMULTI;
    2314     pThis->Lun0.IBase.pfnQueryInterface             = usbMsdLun0QueryInterface;
    2315     pThis->Lun0.IScsiPort.pfnSCSIRequestCompleted   = usbMsdLun0ScsiRequestCompleted;
    2316     pThis->Lun0.IScsiPort.pfnQueryDeviceLocation    = usbMsdLun0QueryDeviceLocation;
     2252    pThis->pUsbIns                                      = pUsbIns;
     2253    pThis->hEvtDoneQueue                                = NIL_RTSEMEVENT;
     2254    pThis->hEvtReset                                    = NIL_RTSEMEVENTMULTI;
     2255    pThis->Lun0.IBase.pfnQueryInterface                 = usbMsdLun0QueryInterface;
     2256    pThis->Lun0.IMediaPort.pfnQueryDeviceLocation       = usbMsdLun0QueryDeviceLocation;
     2257    pThis->Lun0.IMediaExPort.pfnIoReqCompleteNotify     = usbMsdLun0IoReqCompleteNotify;
     2258    pThis->Lun0.IMediaExPort.pfnIoReqCopyFromBuf        = usbMsdLun0IoReqCopyFromBuf;
     2259    pThis->Lun0.IMediaExPort.pfnIoReqCopyToBuf          = usbMsdLun0IoReqCopyToBuf;
     2260    pThis->Lun0.IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
     2261    pThis->Lun0.IMediaExPort.pfnIoReqStateChanged       = usbMsdLun0IoReqStateChanged;
     2262    pThis->Lun0.IMediaExPort.pfnMediumEjected           = usbMsdLun0MediumEjected;
    23172263    usbMsdQueueInit(&pThis->ToHostQueue);
    23182264    usbMsdQueueInit(&pThis->DoneQueue);
     
    23402286    if (RT_FAILURE(rc))
    23412287        return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("MSD failed to attach SCSI driver"));
    2342     pThis->Lun0.pIScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR);
    2343     if (!pThis->Lun0.pIScsiConnector)
     2288    pThis->Lun0.pIMedia = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIA);
     2289    if (!pThis->Lun0.pIMedia)
    23442290        return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
    2345                                    N_("MSD failed to query the PDMISCSICONNECTOR from the driver below it"));
     2291                                   N_("MSD failed to query the PDMIMEDIA from the driver below it"));
     2292    pThis->Lun0.pIMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIAEX);
     2293    if (!pThis->Lun0.pIMediaEx)
     2294        return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
     2295                                   N_("MSD failed to query the PDMIMEDIAEX from the driver below it"));
    23462296
    23472297    /*
    23482298     * Find out what kind of device we are.
    23492299     */
    2350     PDMSCSILUNTYPE enmLunType;
    23512300    pThis->fIsCdrom = false;
    2352     rc = pThis->Lun0.pIScsiConnector->pfnQueryLUNType(pThis->Lun0.pIScsiConnector, 0 /*iLun*/, &enmLunType);
    2353     if (RT_SUCCESS(rc))
    2354     {
    2355         /* Anything else will be reported as a hard disk. */
    2356         if (enmLunType == PDMSCSILUNTYPE_MMC)
    2357             pThis->fIsCdrom = true;
    2358     }
     2301    PDMMEDIATYPE enmType = pThis->Lun0.pIMedia->pfnGetType(pThis->Lun0.pIMedia);
     2302    /* Anything else will be reported as a hard disk. */
     2303    if (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD)
     2304        pThis->fIsCdrom = true;
     2305
     2306    rc = pThis->Lun0.pIMediaEx->pfnIoReqAllocSizeSet(pThis->Lun0.pIMediaEx, sizeof(USBMSDREQ));
     2307    if (RT_FAILURE(rc))
     2308        return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("MSD failed to set I/O request size!"));
    23592309
    23602310    /*
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