VirtualBox

Changeset 64320 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 19, 2016 2:55:59 PM (8 years ago)
Author:
vboxsync
Message:

Devices/Storage/DrvHost*: Start working on implementing PDMIMEDIAEX and SCSI command passthrough (wip)

Location:
trunk/src/VBox/Devices/Storage
Files:
3 edited

Legend:

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

    r64316 r64320  
    6868        }
    6969        else
    70             Log(("%s-%d: drvHostBaseReadOs: drvHostBaseReadOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
     70            Log(("%s-%d: drvHostBaseRead: drvHostBaseReadOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
    7171                 pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
    7272                 off, pvBuf, cbRead, rc, pThis->pszDevice));
     
    217217    RTCritSectLeave(&pThis->CritSect);
    218218    LogFlow(("%s-%d: %s: returns %Rrc CHS={%d,%d,%d}\n",
    219              pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
     219             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc,
     220             pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
    220221    return rc;
    221222}
     
    227228    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
    228229    LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n",
    229              pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     230             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__,
     231             pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    230232    RTCritSectEnter(&pThis->CritSect);
    231233
     
    269271    RTCritSectLeave(&pThis->CritSect);
    270272    LogFlow(("%s-%d: %s: returns %Rrc CHS={%d,%d,%d}\n",
    271              pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
     273             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc,
     274             pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
    272275    return rc;
    273276}
     
    279282    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
    280283    LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n",
    281              pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     284             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__,
     285             pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    282286    RTCritSectEnter(&pThis->CritSect);
    283287
     
    303307    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
    304308    return pThis->fBiosVisible;
     309}
     310
     311
     312
     313/* -=-=-=-=- IMediaEx -=-=-=-=- */
     314
     315DECLHIDDEN(int) drvHostBaseBufferRetain(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void **ppvBuf)
     316{
     317    int rc = VINF_SUCCESS;
     318
     319    if (pThis->cbBuf < cbBuf)
     320    {
     321        RTMemFree(pThis->pvBuf);
     322        pThis->cbBuf = 0;
     323        pThis->pvBuf = RTMemAlloc(cbBuf);
     324        if (pThis->pvBuf)
     325            pThis->cbBuf = cbBuf;
     326        else
     327            rc = VERR_NO_MEMORY;
     328    }
     329
     330    if (RT_SUCCESS(rc) && fWrite)
     331    {
     332        RTSGSEG Seg;
     333        RTSGBUF SgBuf;
     334
     335        Seg.pvSeg = pThis->pvBuf;
     336        Seg.cbSeg = cbBuf;
     337        RTSgBufInit(&SgBuf, &Seg, 1);
     338        rc = pThis->pDrvMediaExPort->pfnIoReqCopyToBuf(pThis->pDrvMediaExPort, (PDMMEDIAEXIOREQ)pReq,
     339                                                       &pReq->abAlloc[0], 0, &SgBuf, cbBuf);
     340    }
     341
     342    if (RT_SUCCESS(rc))
     343        *ppvBuf = pThis->pvBuf;
     344
     345    return rc;
     346}
     347
     348DECLHIDDEN(int) drvHostBaseBufferRelease(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void *pvBuf)
     349{
     350    int rc = VINF_SUCCESS;
     351
     352    if (!fWrite)
     353    {
     354        RTSGSEG Seg;
     355        RTSGBUF SgBuf;
     356
     357        Seg.pvSeg = pvBuf;
     358        Seg.cbSeg = cbBuf;
     359        RTSgBufInit(&SgBuf, &Seg, 1);
     360        rc = pThis->pDrvMediaExPort->pfnIoReqCopyFromBuf(pThis->pDrvMediaExPort, (PDMMEDIAEXIOREQ)pReq,
     361                                                         &pReq->abAlloc[0], 0, &SgBuf, cbBuf);
     362    }
     363
     364    return rc;
     365}
     366
     367/** @interface_method_impl{PDMIMEDIAEX,pfnQueryFeatures} */
     368static DECLCALLBACK(int) drvHostBaseQueryFeatures(PPDMIMEDIAEX pInterface, uint32_t *pfFeatures)
     369{
     370    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     371
     372    *pfFeatures = pThis->IMediaEx.pfnIoReqSendScsiCmd ? PDMIMEDIAEX_FEATURE_F_RAWSCSICMD : 0;
     373    return VINF_SUCCESS;
     374}
     375
     376/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet} */
     377static DECLCALLBACK(int) drvHostBaseIoReqAllocSizeSet(PPDMIMEDIAEX pInterface, size_t cbIoReqAlloc)
     378{
     379    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     380
     381    pThis->cbIoReqAlloc = RT_OFFSETOF(DRVHOSTBASEREQ, abAlloc[cbIoReqAlloc]);
     382    return VINF_SUCCESS;
     383}
     384
     385/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAlloc} */
     386static DECLCALLBACK(int) drvHostBaseIoReqAlloc(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc,
     387                                               PDMMEDIAEXIOREQID uIoReqId, uint32_t fFlags)
     388{
     389    RT_NOREF2(uIoReqId, fFlags);
     390
     391    int rc = VINF_SUCCESS;
     392    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     393    PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)RTMemAllocZ(pThis->cbIoReqAlloc);
     394    if (RT_LIKELY(pReq))
     395    {
     396        *phIoReq = (PDMMEDIAEXIOREQ)pReq;
     397        *ppvIoReqAlloc = &pReq->abAlloc[0];
     398    }
     399    else
     400        rc = VERR_NO_MEMORY;
     401
     402    return rc;
     403}
     404
     405/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFree} */
     406static DECLCALLBACK(int) drvHostBaseIoReqFree(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
     407{
     408    RT_NOREF1(pInterface);
     409    PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
     410
     411    RTMemFree(pReq);
     412    return VINF_SUCCESS;
     413}
     414
     415/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQueryResidual} */
     416static DECLCALLBACK(int) drvHostBaseIoReqQueryResidual(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbResidual)
     417{
     418    RT_NOREF2(pInterface, hIoReq);
     419
     420    *pcbResidual = 0; /** @todo: Implement. */
     421    return VINF_SUCCESS;
     422}
     423
     424/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancelAll} */
     425static DECLCALLBACK(int) drvHostBaseIoReqCancelAll(PPDMIMEDIAEX pInterface)
     426{
     427    RT_NOREF1(pInterface);
     428    return VINF_SUCCESS;
     429}
     430
     431/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancel} */
     432static DECLCALLBACK(int) drvHostBaseIoReqCancel(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQID uIoReqId)
     433{
     434    RT_NOREF2(pInterface, uIoReqId);
     435    return VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND;
     436}
     437
     438/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqRead} */
     439static DECLCALLBACK(int) drvHostBaseIoReqRead(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbRead)
     440{
     441    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     442    PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
     443    LogFlow(("%s-%d: drvHostBaseIoReqRead: off=%#llx cbRead=%#x (%s)\n",
     444             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbRead, pThis->pszDevice));
     445    RTCritSectEnter(&pThis->CritSect);
     446
     447    /*
     448     * Check the state.
     449     */
     450    int rc;
     451    if (pThis->fMediaPresent)
     452    {
     453        void *pvBuf;
     454        rc = drvHostBaseBufferRetain(pThis, pReq, cbRead, false, &pvBuf);
     455        if (RT_SUCCESS(rc))
     456        {
     457            /*
     458             * Seek and read.
     459             */
     460            rc = drvHostBaseReadOs(pThis, off, pvBuf, cbRead);
     461            if (RT_SUCCESS(rc))
     462            {
     463                Log2(("%s-%d: drvHostBaseReadOs: off=%#llx cbRead=%#x\n"
     464                      "%16.*Rhxd\n",
     465                      pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbRead, cbRead, pvBuf));
     466            }
     467            else
     468                Log(("%s-%d: drvHostBaseIoReqRead: drvHostBaseReadOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
     469                     pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
     470                     off, pvBuf, cbRead, rc, pThis->pszDevice));
     471
     472            rc = drvHostBaseBufferRelease(pThis, pReq, cbRead, false, pvBuf);
     473        }
     474        else
     475            Log(("%s-%d: drvHostBaseIoReqRead: drvHostBaseBufferRetain(%#llx, %p, %#x) -> %Rrc ('%s')\n",
     476                 pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
     477                 off, pvBuf, cbRead, rc, pThis->pszDevice));
     478    }
     479    else
     480        rc = VERR_MEDIA_NOT_PRESENT;
     481
     482    RTCritSectLeave(&pThis->CritSect);
     483    LogFlow(("%s-%d: drvHostBaseIoReqRead: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
     484    return rc;
     485}
     486
     487/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqWrite} */
     488static DECLCALLBACK(int) drvHostBaseIoReqWrite(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbWrite)
     489{
     490    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     491    PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
     492    LogFlow(("%s-%d: drvHostBaseIoReqWrite: off=%#llx cbWrite=%#x (%s)\n",
     493             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbWrite, pThis->pszDevice));
     494    RTCritSectEnter(&pThis->CritSect);
     495
     496    /*
     497     * Check the state.
     498     */
     499    int rc;
     500    if (!pThis->fReadOnly)
     501    {
     502        if (pThis->fMediaPresent)
     503        {
     504            void *pvBuf;
     505            rc = drvHostBaseBufferRetain(pThis, pReq, cbWrite, true, &pvBuf);
     506            if (RT_SUCCESS(rc))
     507            {
     508                Log2(("%s-%d: drvHostBaseIoReqWrite: off=%#llx cbWrite=%#x\n"
     509                      "%16.*Rhxd\n",
     510                      pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbWrite, cbWrite, pvBuf));
     511                /*
     512                 * Seek and write.
     513                 */
     514                rc = drvHostBaseWriteOs(pThis, off, pvBuf, cbWrite);
     515                if (RT_FAILURE(rc))
     516                    Log(("%s-%d: drvHostBaseIoReqWrite: drvHostBaseWriteOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
     517                         pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
     518                         off, pvBuf, cbWrite, rc, pThis->pszDevice));
     519
     520                rc = drvHostBaseBufferRelease(pThis, pReq, cbWrite, true, pvBuf);
     521            }
     522        }
     523        else
     524            rc = VERR_MEDIA_NOT_PRESENT;
     525    }
     526    else
     527        rc = VERR_WRITE_PROTECT;
     528
     529    RTCritSectLeave(&pThis->CritSect);
     530    LogFlow(("%s-%d: drvHostBaseIoReqWrite: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
     531    return rc;
     532}
     533
     534/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFlush} */
     535static DECLCALLBACK(int) drvHostBaseIoReqFlush(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
     536{
     537    RT_NOREF1(hIoReq);
     538
     539    int rc;
     540    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     541    LogFlow(("%s-%d: drvHostBaseIoReqFlush: (%s)\n",
     542             pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->pszDevice));
     543    RTCritSectEnter(&pThis->CritSect);
     544
     545    if (pThis->fMediaPresent)
     546        rc = drvHostBaseFlushOs(pThis);
     547    else
     548        rc = VERR_MEDIA_NOT_PRESENT;
     549
     550    RTCritSectLeave(&pThis->CritSect);
     551    LogFlow(("%s-%d: drvHostBaseFlush: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
     552    return rc;
     553}
     554
     555/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqDiscard} */
     556static DECLCALLBACK(int) drvHostBaseIoReqDiscard(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, unsigned cRangesMax)
     557{
     558    RT_NOREF3(pInterface, hIoReq, cRangesMax);
     559    return VERR_NOT_SUPPORTED;
     560}
     561
     562/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetActiveCount} */
     563static DECLCALLBACK(uint32_t) drvHostBaseIoReqGetActiveCount(PPDMIMEDIAEX pInterface)
     564{
     565    RT_NOREF1(pInterface);
     566    return 0;
     567}
     568
     569/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetSuspendedCount} */
     570static DECLCALLBACK(uint32_t) drvHostBaseIoReqGetSuspendedCount(PPDMIMEDIAEX pInterface)
     571{
     572    RT_NOREF1(pInterface);
     573    return 0;
     574}
     575
     576/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedStart} */
     577static DECLCALLBACK(int) drvHostBaseIoReqQuerySuspendedStart(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc)
     578{
     579    RT_NOREF3(pInterface, phIoReq, ppvIoReqAlloc);
     580    return VERR_NOT_IMPLEMENTED;
     581}
     582
     583/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedNext} */
     584static DECLCALLBACK(int) drvHostBaseIoReqQuerySuspendedNext(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
     585                                                            PPDMMEDIAEXIOREQ phIoReqNext, void **ppvIoReqAllocNext)
     586{
     587    RT_NOREF4(pInterface, hIoReq, phIoReqNext, ppvIoReqAllocNext);
     588    return VERR_NOT_IMPLEMENTED;
     589}
     590
     591/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedSave} */
     592static DECLCALLBACK(int) drvHostBaseIoReqSuspendedSave(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
     593{
     594    RT_NOREF3(pInterface, pSSM, hIoReq);
     595    return VERR_NOT_IMPLEMENTED;
     596}
     597
     598/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedLoad} */
     599static DECLCALLBACK(int) drvHostBaseIoReqSuspendedLoad(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
     600{
     601    RT_NOREF3(pInterface, pSSM, hIoReq);
     602    return VERR_NOT_IMPLEMENTED;
    305603}
    306604
     
    442740    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
    443741    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNT, &pThis->IMount);
     742    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEX, pThis->pDrvMediaExPort ? &pThis->IMediaEx : NULL);
    444743    return NULL;
    445744}
     
    683982        RTStrFree(pThis->pszDeviceOpen);
    684983        pThis->pszDeviceOpen = NULL;
     984    }
     985
     986    if (pThis->pvBuf)
     987    {
     988        RTMemFree(pThis->pvBuf);
     989        pThis->pvBuf = NULL;
     990        pThis->cbBuf = 0;
    685991    }
    686992
     
    7401046    pThis->IMedia.pfnBiosIsVisible          = drvHostBaseIsVisible;
    7411047
     1048    /* IMediaEx */
     1049    pThis->IMediaEx.pfnQueryFeatures            = drvHostBaseQueryFeatures;
     1050    pThis->IMediaEx.pfnIoReqAllocSizeSet        = drvHostBaseIoReqAllocSizeSet;
     1051    pThis->IMediaEx.pfnIoReqAlloc               = drvHostBaseIoReqAlloc;
     1052    pThis->IMediaEx.pfnIoReqFree                = drvHostBaseIoReqFree;
     1053    pThis->IMediaEx.pfnIoReqQueryResidual       = drvHostBaseIoReqQueryResidual;
     1054    pThis->IMediaEx.pfnIoReqCancelAll           = drvHostBaseIoReqCancelAll;
     1055    pThis->IMediaEx.pfnIoReqCancel              = drvHostBaseIoReqCancel;
     1056    pThis->IMediaEx.pfnIoReqRead                = drvHostBaseIoReqRead;
     1057    pThis->IMediaEx.pfnIoReqWrite               = drvHostBaseIoReqWrite;
     1058    pThis->IMediaEx.pfnIoReqFlush               = drvHostBaseIoReqFlush;
     1059    pThis->IMediaEx.pfnIoReqDiscard             = drvHostBaseIoReqDiscard;
     1060    pThis->IMediaEx.pfnIoReqGetActiveCount      = drvHostBaseIoReqGetActiveCount;
     1061    pThis->IMediaEx.pfnIoReqGetSuspendedCount   = drvHostBaseIoReqGetSuspendedCount;
     1062    pThis->IMediaEx.pfnIoReqQuerySuspendedStart = drvHostBaseIoReqQuerySuspendedStart;
     1063    pThis->IMediaEx.pfnIoReqQuerySuspendedNext  = drvHostBaseIoReqQuerySuspendedNext;
     1064    pThis->IMediaEx.pfnIoReqSuspendedSave       = drvHostBaseIoReqSuspendedSave;
     1065    pThis->IMediaEx.pfnIoReqSuspendedLoad       = drvHostBaseIoReqSuspendedLoad;
     1066
    7421067    /* IMount. */
    7431068    pThis->IMount.pfnUnmount                = drvHostBaseUnmount;
     
    7561081
    7571082    /*
    758      * Get the IBlockPort & IMountNotify interfaces of the above driver/device.
     1083     * Get the IMediaPort & IMountNotify interfaces of the above driver/device.
    7591084     */
    7601085    pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
     
    7641089        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    7651090    }
     1091    pThis->pDrvMediaExPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT);
    7661092    pThis->pDrvMountNotify = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUNTNOTIFY);
    7671093
  • trunk/src/VBox/Devices/Storage/DrvHostBase.h

    r64316 r64320  
    6565    RTUUID                  Uuid;
    6666
    67     /** Pointer to the block port interface above us. */
     67    /** Pointer to the media port interface above us. */
    6868    PPDMIMEDIAPORT          pDrvMediaPort;
     69    /** Pointer to the extended media port interface above us. */
     70    PPDMIMEDIAEXPORT        pDrvMediaExPort;
    6971    /** Pointer to the mount notify interface above us. */
    7072    PPDMIMOUNTNOTIFY        pDrvMountNotify;
    7173    /** Our media interface. */
    7274    PDMIMEDIA               IMedia;
     75    /** Our extended media interface. */
     76    PDMIMEDIAEX             IMediaEx;
    7377    /** Our mountable interface. */
    7478    PDMIMOUNT               IMount;
     
    96100    PDMMEDIAGEOMETRY        LCHSGeometry;
    97101
     102    /** Pointer to the current buffer holding data. */
     103    void                    *pvBuf;
     104    /** Size of the buffer. */
     105    size_t                  cbBuf;
     106    /** Size of the I/O request to allocate. */
     107    size_t                  cbIoReqAlloc;
     108
    98109    /**
    99110     * Performs the locking / unlocking of the device.
     
    116127} DRVHOSTBASE;
    117128
     129
     130/**
     131 * Request structure fo a request.
     132 */
     133typedef struct DRVHOSTBASEREQ
     134{
     135    /** Start of the request data for the device above us. */
     136    uint8_t                  abAlloc[1];
     137} DRVHOSTBASEREQ;
     138/** Pointer to a request structure. */
     139typedef DRVHOSTBASEREQ *PDRVHOSTBASEREQ;
    118140
    119141DECLHIDDEN(int) DRVHostBaseInit(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, const char *pszCfgValid, PDMMEDIATYPE enmType);
     
    138160DECLHIDDEN(void) drvHostBaseDestructOs(PDRVHOSTBASE pThis);
    139161
     162DECLHIDDEN(int) drvHostBaseBufferRetain(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void **ppvBuf);
     163DECLHIDDEN(int) drvHostBaseBufferRelease(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void *pvBuf);
     164
    140165RT_C_DECLS_END
    141166
  • trunk/src/VBox/Devices/Storage/DrvHostDVD.cpp

    r64316 r64320  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_DRV_HOST_DVD
    23 #if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
    24 # define USE_MEDIA_POLLING
    25 #endif
    26 
    27 #if defined(RT_OS_SOLARIS) && defined(VBOX_WITH_SUID_WRAPPER)
    28 # include <auth_attr.h>
    29 #endif
    30 
    3123#include <iprt/asm.h>
    3224#include <VBox/vmm/pdmdrv.h>
     
    4234#include "VBoxDD.h"
    4335#include "DrvHostBase.h"
    44 
     36#include "ATAPIPassthrough.h"
     37
     38/**
     39 * Host DVD driver instance data.
     40 */
     41typedef struct DRVHOSTDVD
     42{
     43    /** Base drivr data. */
     44    DRVHOSTBASE             Core;
     45    /** The current tracklist of the loaded medium if passthrough is used. */
     46    PTRACKLIST              pTrackList;
     47} DRVHOSTDVD;
     48/** Pointer to the host DVD driver instance data. */
     49typedef DRVHOSTDVD *PDRVHOSTDVD;
    4550
    4651/*********************************************************************************************************************************
     
    4853*********************************************************************************************************************************/
    4954
     55
     56static PDMMEDIATXDIR drvHostDvdGetTxDirFromCmd(uint8_t bCdb)
     57{
     58    PDMMEDIATXDIR enmTxDir = PDMMEDIATXDIR_NONE;
     59
     60    switch (bCdb)
     61    {
     62        case SCSI_BLANK:
     63        case SCSI_CLOSE_TRACK_SESSION:
     64        case SCSI_LOAD_UNLOAD_MEDIUM:
     65        case SCSI_PAUSE_RESUME:
     66        case SCSI_PLAY_AUDIO_10:
     67        case SCSI_PLAY_AUDIO_12:
     68        case SCSI_PLAY_AUDIO_MSF:
     69        case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
     70        case SCSI_RESERVE_TRACK:
     71        case SCSI_SCAN:
     72        case SCSI_SEEK_10:
     73        case SCSI_REPAIR_TRACK:
     74        case SCSI_SET_CD_SPEED:
     75        case SCSI_SET_READ_AHEAD:
     76        case SCSI_START_STOP_UNIT:
     77        case SCSI_STOP_PLAY_SCAN:
     78        case SCSI_SYNCHRONIZE_CACHE:
     79        case SCSI_TEST_UNIT_READY:
     80        case SCSI_VERIFY_10:
     81            enmTxDir = PDMMEDIATXDIR_NONE;
     82            break;
     83        case SCSI_SET_STREAMING:
     84        case SCSI_ERASE_10:
     85        case SCSI_FORMAT_UNIT:
     86        case SCSI_MODE_SELECT_10:
     87        case SCSI_SEND_CUE_SHEET:
     88        case SCSI_SEND_DVD_STRUCTURE:
     89        case SCSI_SEND_EVENT:
     90        case SCSI_SEND_KEY:
     91        case SCSI_SEND_OPC_INFORMATION:
     92        case SCSI_WRITE_10:
     93        case SCSI_WRITE_AND_VERIFY_10:
     94        case SCSI_WRITE_12:
     95            enmTxDir = PDMMEDIATXDIR_TO_DEVICE;
     96            break;
     97        case SCSI_GET_CONFIGURATION:
     98        case SCSI_GET_EVENT_STATUS_NOTIFICATION:
     99        case SCSI_GET_PERFORMANCE:
     100        case SCSI_INQUIRY:
     101        case SCSI_MECHANISM_STATUS:
     102        case SCSI_MODE_SENSE_10:
     103        case SCSI_READ_10:
     104        case SCSI_READ_12:
     105        case SCSI_READ_BUFFER:
     106        case SCSI_READ_BUFFER_CAPACITY:
     107        case SCSI_READ_CAPACITY:
     108        case SCSI_READ_CD:
     109        case SCSI_READ_CD_MSF:
     110        case SCSI_READ_DISC_INFORMATION:
     111        case SCSI_READ_DVD_STRUCTURE:
     112        case SCSI_READ_FORMAT_CAPACITIES:
     113        case SCSI_READ_SUBCHANNEL:
     114        case SCSI_READ_TOC_PMA_ATIP:
     115        case SCSI_READ_TRACK_INFORMATION:
     116        case SCSI_REPORT_KEY:
     117        case SCSI_REQUEST_SENSE:
     118        case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */
     119            enmTxDir = PDMMEDIATXDIR_FROM_DEVICE;
     120            break;
     121
     122        case SCSI_WRITE_BUFFER:
     123#if 0
     124            switch (pbPacket[1] & 0x1f)
     125            {
     126                case 0x04: /* download microcode */
     127                case 0x05: /* download microcode and save */
     128                case 0x06: /* download microcode with offsets */
     129                case 0x07: /* download microcode with offsets and save */
     130                case 0x0e: /* download microcode with offsets and defer activation */
     131                case 0x0f: /* activate deferred microcode */
     132                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", s->iLUN));
     133                    atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     134                    break;
     135                default:
     136                    enmTxDir = PDMMEDIATXDIR_TO_DEVICE;
     137                    break;
     138            }
     139#endif
     140            break;
     141        case SCSI_REZERO_UNIT:
     142            /* Obsolete command used by cdrecord. What else would one expect?
     143             * This command is not sent to the drive, it is handled internally,
     144             * as the Linux kernel doesn't like it (message "scsi: unknown
     145             * opcode 0x01" in syslog) and replies with a sense code of 0,
     146             * which sends cdrecord to an endless loop. */
     147            //atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     148            break;
     149        default:
     150            LogRel(("HostDVD: passthrough unimplemented for command %#x\n", bCdb));
     151            //atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     152            break;
     153    }
     154
     155    return enmTxDir;
     156}
    50157
    51158/**
     
    74181    LogFlow(("%s: cmd[0]=%#04x txdir=%d pcbBuf=%d timeout=%d\n", __FUNCTION__, pbCmd[0], enmTxDir, *pcbBuf, cTimeoutMillies));
    75182
     183    RTCritSectEnter(&pThis->CritSect);
    76184    /*
    77185     * Pass the request on to the internal scsi command interface.
     
    92200            Log2(("  event %#02x %#02x %#02x %#02x\n", pbBuf[4], pbBuf[5], pbBuf[6], pbBuf[7]));
    93201    }
     202    RTCritSectLeave(&pThis->CritSect);
    94203
    95204    LogFlow(("%s: rc=%Rrc\n", __FUNCTION__, rc));
     
    98207
    99208
     209/** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSendScsiCmd} */
     210static DECLCALLBACK(int) drvHostDvdIoReqSendScsiCmd(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint32_t uLun,
     211                                                    const uint8_t *pbCdb, size_t cbCdb, PDMMEDIAEXIOREQSCSITXDIR enmTxDir,
     212                                                    size_t cbBuf, uint8_t *pabSense, size_t cbSense, uint8_t *pu8ScsiSts,
     213                                                    uint32_t cTimeoutMillies)
     214{
     215    RT_NOREF2(uLun, cTimeoutMillies);
     216
     217    PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
     218    PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
     219    int rc = VINF_SUCCESS;
     220    void *pvBuf = NULL;
     221
     222    LogFlow(("%s: pbCdb[0]=%#04x enmTxDir=%d cbBuf=%zu timeout=%u\n", __FUNCTION__, pbCdb[0], enmTxDir, cbBuf, cTimeoutMillies));
     223
     224    RTCritSectEnter(&pThis->CritSect);
     225    if (cbBuf)
     226    {
     227        bool fWrite = (enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN || enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE);
     228        rc = drvHostBaseBufferRetain(pThis, pReq, cbBuf, fWrite, &pvBuf);
     229    }
     230
     231    if (RT_SUCCESS(rc))
     232    {
     233        uint32_t cbBufTmp = (uint32_t)cbBuf;
     234        PDMMEDIATXDIR enmMediaTxDir = PDMMEDIATXDIR_NONE;
     235        /*
     236         * Pass the request on to the internal scsi command interface.
     237         * The command seems to be 12 bytes long, the docs a bit copy&pasty on the command length point...
     238         */
     239        if (enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN || enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE)
     240            memset(pvBuf, '\0', cbBuf); /* we got read size, but zero it anyway. */
     241
     242        if (cbBuf)
     243        {
     244            switch (enmTxDir)
     245            {
     246                case PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE:
     247                    enmMediaTxDir = PDMMEDIATXDIR_FROM_DEVICE;
     248                    break;
     249                case PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE:
     250                    enmMediaTxDir = PDMMEDIATXDIR_TO_DEVICE;
     251                    break;
     252                case PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN:
     253                    enmMediaTxDir = drvHostDvdGetTxDirFromCmd(pbCdb[0]);
     254                    break;
     255                case PDMMEDIAEXIOREQSCSITXDIR_NONE:
     256                default:
     257                    enmMediaTxDir = PDMMEDIATXDIR_NONE;
     258                    break;
     259            }
     260        }
     261
     262        rc = drvHostBaseScsiCmdOs(pThis, pbCdb, cbCdb, enmMediaTxDir, pvBuf, &cbBufTmp, pabSense, cbSense, cTimeoutMillies);
     263        if (rc == VERR_UNRESOLVED_ERROR)
     264        {
     265            /* sense information set */
     266            rc = VERR_DEV_IO_ERROR;
     267            *pu8ScsiSts = SCSI_STATUS_CHECK_CONDITION;
     268        }
     269
     270        if (pbCdb[0] == SCSI_GET_EVENT_STATUS_NOTIFICATION)
     271        {
     272            uint8_t *pbBuf = (uint8_t*)pvBuf;
     273            Log2(("Event Status Notification class=%#02x supported classes=%#02x\n", pbBuf[2], pbBuf[3]));
     274            if (RT_BE2H_U16(*(uint16_t*)pbBuf) >= 6)
     275                Log2(("  event %#02x %#02x %#02x %#02x\n", pbBuf[4], pbBuf[5], pbBuf[6], pbBuf[7]));
     276        }
     277
     278        if (cbBuf)
     279        {
     280            bool fWrite = (enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN || enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE);
     281            rc = drvHostBaseBufferRelease(pThis, pReq, cbBuf, fWrite, pvBuf);
     282        }
     283    }
     284    RTCritSectLeave(&pThis->CritSect);
     285
     286    LogFlow(("%s: rc=%Rrc\n", __FUNCTION__, rc));
     287    return rc;
     288}
     289
     290
    100291/* -=-=-=-=- driver interface -=-=-=-=- */
    101292
     293
     294/** @interface_method_impl{PDMDRVREG,pfnDestruct} */
     295static DECLCALLBACK(void) drvHostDvdDestruct(PPDMDRVINS pDrvIns)
     296{
     297    PDRVHOSTDVD pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTDVD);
     298
     299    if (pThis->pTrackList)
     300    {
     301        ATAPIPassthroughTrackListDestroy(pThis->pTrackList);
     302        pThis->pTrackList = NULL;
     303    }
     304
     305    DRVHostBaseDestruct(pDrvIns);
     306}
    102307
    103308/**
     
    109314{
    110315    RT_NOREF(fFlags);
    111     PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
     316    PDRVHOSTDVD pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTDVD);
    112317    LogFlow(("drvHostDvdConstruct: iInstance=%d\n", pDrvIns->iInstance));
    113318
     
    116321    if (RT_SUCCESS(rc) && fPassthrough)
    117322    {
    118         pThis->IMedia.pfnSendCmd = drvHostDvdSendCmd;
     323        pThis->Core.IMedia.pfnSendCmd            = drvHostDvdSendCmd;
     324        pThis->Core.IMediaEx.pfnIoReqSendScsiCmd = drvHostDvdIoReqSendScsiCmd;
    119325        /* Passthrough requires opening the device in R/W mode. */
    120         pThis->fReadOnlyConfig = false;
    121     }
    122 
    123     pThis->pfnDoLock = drvHostDvdDoLock;
     326        pThis->Core.fReadOnlyConfig = false;
     327    }
     328
     329    pThis->Core.pfnDoLock = drvHostDvdDoLock;
    124330
    125331    /*
     
    155361    ~0U,
    156362    /* cbInstance */
    157     sizeof(DRVHOSTBASE),
     363    sizeof(DRVHOSTDVD),
    158364    /* pfnConstruct */
    159365    drvHostDvdConstruct,
    160366    /* pfnDestruct */
    161     DRVHostBaseDestruct,
     367    drvHostDvdDestruct,
    162368    /* pfnRelocate */
    163369    NULL,
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