VirtualBox

Changeset 80657 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Sep 9, 2019 7:14:32 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133188
Message:

Storage/DevVirtioScsi.cpp: Start to implement suspend/resume/reset/power on and power off handling. Compiles and code still does SCSI stuff, but the code is untested and unfinished. Posted questions to bugref:9440, Comment #83

File:
1 edited

Legend:

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

    r80647 r80657  
    8888#define VIRTIOSCSI_SENSE_SIZE_DEFAULT               96          /**< VirtIO 1.0: 96 on reset, guest can change       */
    8989#define VIRTIOSCSI_CDB_SIZE_DEFAULT                 32          /**< VirtIO 1.0: 32 on reset, guest can change       */
    90 #define VIRTIOSCSI_PI_BYTES_IN                      1           /**< Value TBD (see section 5.6.6.1)                 */
    91 #define VIRTIOSCSI_PI_BYTES_OUT                     1           /**< Value TBD (see section 5.6.6.1)                 */
    92 #define VIRTIOSCSI_DATA_OUT                         512         /**< Value TBD (see section 5.6.6.1)                 */
     90#define virtioScsi_PI_BYTES_IN                      1           /**< Value TBD (see section 5.6.6.1)                 */
     91#define virtioScsi_PI_BYTES_OUT                     1           /**< Value TBD (see section 5.6.6.1)                 */
     92#define virtioScsi_DATA_OUT                         512         /**< Value TBD (see section 5.6.6.1)                 */
    9393
    9494/**
     
    379379{
    380380    /** Pointer to PCI device that owns this target instance. - R3 pointer */
    381     R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiR3;
     381    R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsi;
    382382
    383383    /** Pointer to attached driver's base interface. */
     
    415415    /** The status LED state for this device. */
    416416    PDMLED                          led;
    417 
    418     /** Number of requests active */
    419     volatile uint32_t               cReqsInProgress;
    420417
    421418} VIRTIOSCSITARGET, *PVIRTIOSCSITARGET;
     
    486483    uint64_t                        cTargets;
    487484
     485    /** Total number of requests active across all targets */
     486    volatile uint32_t               cActiveReqs;
     487
    488488    /** True if PDMDevHlpAsyncNotificationCompleted should be called when port goes idle */
    489489    bool volatile                   fSignalIdle;
     
    512512    /** True if VIRTIO_SCSI_F_T10_PI was negotiated */
    513513    bool                            fHasLunChange;
     514
     515    /** True if in the process of resetting */
     516    bool                            fResetting;
     517
     518    /** True if in the process of suspending  */
     519    bool                            fSuspending;
     520
     521    /** True if in the process of powering off */
     522    bool                            fPoweringOff;
     523
     524    /** True if in the process of quiescing I/O */
     525    bool                            fQuiescing;
     526
     527
    514528
    515529} VIRTIOSCSI, *PVIRTIOSCSI;
     
    655669#ifdef BOOTABLE_SUPPORT_TBD
    656670/** @callback_method_impl{FNIOMIOPORTIN} */
    657 static DECLCALLBACK(int) virtioScsiR3BiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
     671static DECLCALLBACK(int) virtioScsiBiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
    658672                                                    uint32_t *pcTransfers, unsigned cb);
    659673{
    660674}
    661675/** @callback_method_impl{FNIOMIOPORTOUT} */
    662 static DECLCALLBACK(int) virtioScsiR3BiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb);
     676static DECLCALLBACK(int) virtioScsiBiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb);
    663677{
    664678}
    665679/** @callback_method_impl{FNIOMIOPORTOUTSTRING} */
    666 static DECLCALLBACK(int) virtioScsiR3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,
     680static DECLCALLBACK(int) virtioScsiBiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,
    667681                                                        uint32_t *pcTransfers, unsigned cb);
    668682{
    669683}
    670684/** @callback_method_impl{FNIOMIOPORTINSTRING} */
    671 static DECLCALLBACK(int) virtioScsiR3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
     685static DECLCALLBACK(int) virtioScsiBiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
    672686                                                       uint32_t *pcTransfers, unsigned cb);
    673687{
     
    700714
    701715/**
    702  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
    703  */
    704 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    705                                                       void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
    706 {
    707 
    708     RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
    709     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    710 
    711     switch (enmState)
    712     {
    713         case PDMMEDIAEXIOREQSTATE_SUSPENDED:
    714         {
    715             /* Make sure the request is not accounted for so the VM can suspend successfully. */
    716             uint32_t cTasksActive = ASMAtomicDecU32(&pTarget->cReqsInProgress);
    717             if (!cTasksActive && pTarget->CTX_SUFF(pVirtioScsi)->fSignalIdle)
    718                 PDMDevHlpAsyncNotificationCompleted(pTarget->CTX_SUFF(pVirtioScsi)->pDevInsR3);
    719             break;
    720         }
    721         case PDMMEDIAEXIOREQSTATE_ACTIVE:
    722             /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
    723             ASMAtomicIncU32(&pTarget->cReqsInProgress);
    724             break;
    725         default:
    726             AssertMsgFailed(("Invalid request state given %u\n", enmState));
    727     }
    728 }
    729 
    730 /**
    731716 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
    732717 */
    733 static DECLCALLBACK(int) virtioScsiR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     718static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    734719                                                      void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy)
    735720{
     
    744729 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
    745730 */
    746 static DECLCALLBACK(int) virtioScsiR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     731static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    747732                                                    void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy)
    748733{
     
    842827static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense)
    843828{
     829
    844830    uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize);
    845831    AssertReturn(abSenseBuf, VERR_NO_MEMORY);
     
    862848    RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs));
    863849
     850    if (pThis->fResetting)
     851        pRespHdr->uResponse = VIRTIOSCSI_S_RESET;
     852
    864853    virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);
    865854    virtioQueueSync(pThis->hVirtio, qIdx);
     
    867856    RTMemFree(abSenseBuf);
    868857
     858    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     859        PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
     860
    869861    Log(("---------------------------------------------------------------------------------\n"));
    870862
     
    872864}
    873865
    874 /** TBD: VirtIO 1.0 spec 5.6.6.1.1 requires some request actions on reset that are
    875  *       not implemented.  Specifically either canceling outstanding I/O or
    876  *       returning VIRTIOSCSI_S_FAILURE for those requests.  Since there's no
    877  *       way to cancel I/O on VSCSI at this time the only the only other
    878  *       possibility is to wait for the outstanding request count to drop
    879  *       and return the failure code for any-and-all until that's done before
    880  *       allowing a reset to continue.
    881  */
    882 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq)
    883 {
     866/**
     867 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     868 */
     869static DECLCALLBACK(int) virtioScsiIoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     870                                               void *pvIoReqAlloc, int rcReq)
     871{
     872    RT_NOREF(pInterface);
     873
     874    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    884875    PVIRTIOSCSITARGET pTarget = pReq->pTarget;
     876    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
    885877    PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx;
    886878
    887     ASMAtomicDecU32(&pTarget->cReqsInProgress);
    888 
    889879    size_t cbResidual = 0, cbXfer = 0;
    890     int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
     880    int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, hIoReq, &cbResidual);
    891881    AssertRC(rc);
    892882
    893     rc = pIMediaEx->pfnIoReqQueryXferSize(pIMediaEx, pReq->hIoReq, &cbXfer);
     883    rc = pIMediaEx->pfnIoReqQueryXferSize(pIMediaEx, hIoReq, &cbXfer);
    894884    AssertRC(rc);
    895885
     
    902892    /** VirtIO 1.0 spec 5.6.6.1.1 says device MUST return a VirtIO response byte value.
    903893     *  Some are returned during the submit phase, and a few are not mapped at all,
    904      *  wherein anything that can't map specifically gets mapped to VIRTIOSCSI_S_FAILURE */
    905     switch(rcReq)
    906     {
    907         case SCSI_STATUS_OK:
    908             if (pReq->uStatus != SCSI_STATUS_CHECK_CONDITION)
    909             {
    910                 respHdr.uResponse = VIRTIOSCSI_S_OK;
     894     *  wherein anything that can't map specifically gets mapped to VIRTIOSCSI_S_FAILURE
     895     */
     896    if (pThis->fResetting)
     897        respHdr.uResponse = VIRTIOSCSI_S_RESET;
     898    else
     899    {
     900        switch(rcReq)
     901        {
     902            case SCSI_STATUS_OK:
     903                if (pReq->uStatus != SCSI_STATUS_CHECK_CONDITION)
     904                {
     905                    respHdr.uResponse = VIRTIOSCSI_S_OK;
     906                    break;
     907                }
     908            case SCSI_STATUS_CHECK_CONDITION:
     909                {
     910                    uint8_t uSenseKey = pReq->pbSense[2];
     911                    switch (uSenseKey)
     912                    {
     913                        case SCSI_SENSE_ABORTED_COMMAND:
     914                            respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
     915                            break;
     916                        case SCSI_SENSE_COPY_ABORTED:
     917                            respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
     918                            break;
     919                        case SCSI_SENSE_UNIT_ATTENTION:
     920                            respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
     921                            break;
     922                        case SCSI_SENSE_HARDWARE_ERROR:
     923                            respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
     924                            break;
     925                        case SCSI_SENSE_NOT_READY:
     926                            respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. re-tryable */
     927                            break;
     928                        default:
     929                            respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
     930                            break;
     931                    }
     932                }
    911933                break;
    912             }
    913         case SCSI_STATUS_CHECK_CONDITION:
    914             {
    915                 uint8_t uSenseKey = pReq->pbSense[2];
    916                 switch (uSenseKey)
    917                 {
    918                     case SCSI_SENSE_ABORTED_COMMAND:
    919                         respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
    920                         break;
    921                     case SCSI_SENSE_COPY_ABORTED:
    922                         respHdr.uResponse = VIRTIOSCSI_S_ABORTED;
    923                         break;
    924                     case SCSI_SENSE_UNIT_ATTENTION:
    925                         respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
    926                         break;
    927                     case SCSI_SENSE_HARDWARE_ERROR:
    928                         respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE;
    929                         break;
    930                     case SCSI_SENSE_NOT_READY:
    931                         respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. re-tryable */
    932                         break;
    933                     default:
    934                         respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    935                         break;
    936                 }
    937             }
    938             break;
    939 
    940         default:
    941             respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
    942             break;
     934
     935            default:
     936                respHdr.uResponse = VIRTIOSCSI_S_FAILURE;
     937                break;
     938        }
    943939    }
    944940
    945941    Log2Func(("status: (%d) %s,   response: (%d) %s\n",
    946               pReq->uStatus, SCSIStatusText(pReq->uStatus), respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse)));
     942              pReq->uStatus, SCSIStatusText(pReq->uStatus),
     943              respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse)));
    947944
    948945    if (RT_FAILURE(rcReq))
     
    1000997        respHdr.uResidual = pReq->cbDataIn;
    1001998        virtioScsiReqErr(pThis, pReq->qIdx, &respHdr, abSense);
     999        return VINF_SUCCESS;
    10021000    }
    10031001    else
     
    10381036        virtioQueueSync(pThis->hVirtio, pReq->qIdx);
    10391037
     1038
    10401039        Log(("-----------------------------------------------------------------------------------------\n"));
    10411040    }
     
    10431042    virtioScsiFreeReq(pTarget, pReq);
    10441043
    1045     if (pTarget->cReqsInProgress == 0 && pThis->fSignalIdle)
    1046         PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
     1044    if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     1045        PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
    10471046
    10481047    return VINF_SUCCESS;
     
    10531052{
    10541053    AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_INVALID_PARAMETER);
     1054
     1055    ASMAtomicIncU32(&pThis->cActiveReqs);
    10551056
    10561057    size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf);
     
    10731074    Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n",
    10741075        pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn));
     1076
     1077    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
    10751078
    10761079    /**
     
    10941097    size_t  cbDataIn  = cbIn  - uDataInOff;
    10951098
     1099    /**
     1100     * Handle submission errors
     1101     */
     1102    if (pThis->fResetting)
     1103    {
     1104        Log2Func(("Aborting req submission because reset is in progress\n"));
     1105        struct REQ_RESP_HDR respHdr = { 0 };
     1106        respHdr.uSenseLen = 0;
     1107        respHdr.uStatus   = SCSI_STATUS_OK;
     1108        respHdr.uResponse = VIRTIOSCSI_S_RESET;
     1109        respHdr.uResidual = cbDataIn + cbDataOut;
     1110        virtioScsiReqErr(pThis, qIdx, &respHdr, NULL);
     1111        RTMemFree(pVirtqReq);
     1112        return VINF_SUCCESS;
     1113    }
     1114    else
    10961115    if (uTarget >= pThis->cTargets || uLUN != 0)
    10971116    {
     1117        Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, uLUN));
    10981118        uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED,
    10991119                              0, SCSI_SENSE_ILLEGAL_REQUEST,
     
    11081128        return VINF_SUCCESS;
    11091129    }
    1110 
    1111     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
    1112 
     1130    else
    11131131    if (RT_UNLIKELY(!pTarget->fPresent))
    11141132    {
     
    11261144    }
    11271145
     1146    /**
     1147     * Have underlying driver allocate a req of size set during initialization of this device.
     1148     */
    11281149    PDMMEDIAEXIOREQ   hIoReq = NULL;
    11291150    PVIRTIOSCSIREQ    pReq;
     
    11351156    AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc);
    11361157
     1158    /**
     1159     * Prepare req's parameters for submission
     1160     */
    11371161    if (pThis->fHasT10pi)
    11381162    {
     
    11641188    }
    11651189
    1166     ASMAtomicIncU32(&pTarget->cReqsInProgress);
    1167 
    11681190    rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN,
    11691191                                        pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize,
     
    11761198    {
    11771199        /**
    1178          * This rc value from DrvSCSI/send SCSI cmd means the request failed early
    1179          * (no mem, buf copy callback, request buffer creation, or req enqueue),
    1180          * and not submitted to lower layers, error it out.
     1200         * Getting here means the request failed in early in the submission to the lower level driver,
     1201         * and there will be no callback to the finished/completion function for this request
    11811202         */
    1182         Log2Func(("Error submitting request!\n"));
     1203        Log2Func(("Request submission error from lower-level driver\n"));
    11831204        size_t cbResidual;
    11841205        pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
     
    12061227    }
    12071228
    1208     return VINF_SUCCESS;
    1209 }
    1210 
    1211 /**
    1212  * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
    1213  */
    1214 static DECLCALLBACK(int) virtioScsiR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
    1215                                                        void *pvIoReqAlloc, int rcReq)
    1216 {
    1217     RT_NOREF(hIoReq);
    1218     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    1219     virtioScsiReqFinish(pTarget->CTX_SUFF(pVirtioScsi), (PVIRTIOSCSIREQ)pvIoReqAlloc, rcReq);
    12201229    return VINF_SUCCESS;
    12211230}
     
    13661375 * @param   pThread     The send thread.
    13671376 */
    1368 static DECLCALLBACK(int) virtioScsiR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1377static DECLCALLBACK(int) virtioScsiWorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    13691378{
    13701379    RT_NOREF(pThread);
     
    13761385static int virtioScsiWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    13771386{
    1378 
    13791387    int rc;
    13801388    uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff;
     
    13891397    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    13901398    {
     1399        if (pThis->fQuiescing || !pThis->fQueueAttached[qIdx])
     1400        {
     1401            Log6Func(("Skipping wakeup (quiescing or reset)\n"));
     1402            continue;
     1403        }
     1404
    13911405        if (virtioQueueIsEmpty(pThis->hVirtio, qIdx))
    13921406        {
     
    14231437            if (RT_FAILURE(rc))
    14241438            {
    1425                 LogRel(("Fatal error submitting req packet, resetting %Rrc", rc));
    1426                 /** TBD: MUST AT LEAD RETURN VIRTIO_SCSI_S_FAILURE for all pending I/O, Aborting is an option! */
    1427                 virtioResetAll(pThis->hVirtio);
     1439                LogRel(("Error submitting req packet, resetting %Rrc", rc));
    14281440            }
    14291441        }
     
    14371449
    14381450
    1439 /**
    1440  * Implementation invokes this to reset the VirtIO device
    1441  */
    1442 static void virtioScsiDeviceReset(PVIRTIOSCSI pThis)
    1443 {
    1444     pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
    1445     pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT;
    1446     virtioResetAll(pThis->hVirtio);
    1447 }
    1448 
    1449 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
     1451DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
     1452{
     1453    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
     1454}
     1455
     1456DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
     1457{
     1458    if (pThis->fHasHotplug)
     1459        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1460                VIRTIOSCSI_EVT_RESET_REMOVED);
     1461}
     1462
     1463DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
     1464{
     1465    if (pThis->fHasHotplug)
     1466        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1467                VIRTIOSCSI_EVT_RESET_RESCAN);
     1468}
     1469
     1470DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
     1471{
     1472    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1473            VIRTIOSCSI_EVT_RESET_HARD);
     1474}
     1475
     1476DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1477{
     1478    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
     1479        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1480                VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
     1481}
     1482
     1483DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
     1484{
     1485    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
     1486        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1487                VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
     1488}
     1489
     1490DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
     1491{
     1492    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
     1493        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1494                VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
     1495}
     1496
     1497DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1498{
     1499    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
     1500        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1501                VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
     1502}
     1503
     1504DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
     1505{
     1506    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
     1507        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1508                VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
     1509}
     1510
     1511DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
     1512{
     1513    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
     1514        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1515                VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
     1516}
     1517
     1518
     1519DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
     1520{
     1521    uint32_t uReason = uSenseQualifier << 8 | uSenseCode;
     1522    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
     1523
     1524}
     1525
     1526static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
     1527{
     1528    RT_NOREF(hVirtio);
     1529
     1530    AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
     1531    PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
     1532    PWORKER pWorker = &pThis->aWorker[qIdx];
     1533
     1534
     1535    RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));
     1536
     1537    if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
     1538    {
     1539        Log6Func(("%s has available data\n", QUEUENAME(qIdx)));
     1540        /** Wake queue's worker thread up if sleeping */
     1541        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     1542        {
     1543            if (ASMAtomicReadBool(&pWorker->fSleeping))
     1544            {
     1545                Log6Func(("waking %s worker.\n", QUEUENAME(qIdx)));
     1546                int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess);
     1547                AssertRC(rc);
     1548            }
     1549        }
     1550    }
     1551    else if (qIdx == EVENTQ_IDX)
     1552    {
     1553        Log3Func(("Driver queued buffer(s) to %s\n"));
     1554        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
     1555            virtioScsiReportEventsMissed(pThis, 0);
     1556    }
     1557    else
     1558        LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
     1559}
     1560
     1561static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  bool fVirtioReady)
     1562{
     1563    RT_NOREF(hVirtio);
     1564    PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
     1565
     1566    pThis->fVirtioReady = fVirtioReady;
     1567
     1568    if (fVirtioReady)
     1569    {
     1570        LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n"));
     1571        uint64_t features    = virtioGetNegotiatedFeatures(hVirtio);
     1572        pThis->fHasT10pi     = features & VIRTIO_SCSI_F_T10_PI;
     1573        pThis->fHasHotplug   = features & VIRTIO_SCSI_F_HOTPLUG;
     1574        pThis->fHasInOutBufs = features & VIRTIO_SCSI_F_INOUT;
     1575        pThis->fHasLunChange = features & VIRTIO_SCSI_F_CHANGE;
     1576        pThis->fQuiescing    = false;
     1577        pThis->fResetting    = false;
     1578
     1579        for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
     1580            pThis->fQueueAttached[i] = true;
     1581    }
     1582    else
     1583    {
     1584        LogFunc(("VirtIO is resetting\n"));
     1585        for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
     1586            pThis->fQueueAttached[i] = false;
     1587    }
     1588}
     1589
     1590/**
     1591 * virtio-scsi debugger info callback.
     1592 *
     1593 * @param   pDevIns     The device instance.
     1594 * @param   pHlp        The output helpers.
     1595 * @param   pszArgs     The arguments.
     1596 */
     1597static DECLCALLBACK(void) virtioScsiInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     1598{
     1599    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1600    bool fVerbose = false;
     1601
     1602    /* Parse arguments. */
     1603    if (pszArgs)
     1604        fVerbose = strstr(pszArgs, "verbose") != NULL;
     1605
     1606    /* Show basic information. */
     1607    pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",
     1608                    pDevIns->pReg->szName,
     1609                    pDevIns->iInstance);
     1610    pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets);
     1611}
     1612
     1613/**
     1614 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     1615 */
     1616static DECLCALLBACK(void) virtioScsiMediumEjected(PPDMIMEDIAEXPORT pInterface)
     1617{
     1618    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     1619    PVIRTIOSCSI pThis = pTarget->pVirtioScsi;
     1620    LogFunc(("LUN %d Ejected!\n", pTarget->iLUN));
     1621    if (pThis->pMediaNotify)
     1622    {
     1623         int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
     1624                                   (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
     1625                                    pThis->pMediaNotify, pTarget->iLUN);
     1626         AssertRC(rc);
     1627    }
     1628
     1629}
     1630
     1631/** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
     1632static DECLCALLBACK(int) virtioScsiLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
     1633{
     1634    LogFunc(("callback"));
     1635    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1636    RT_NOREF(pThis);
     1637    RT_NOREF(uPass);
     1638    RT_NOREF(pSSM);
     1639    return VINF_SSM_DONT_CALL_AGAIN;
     1640}
     1641
     1642/** @callback_method_impl{FNSSMDEVLOADEXEC}  */
     1643static DECLCALLBACK(int) virtioScsiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     1644{
     1645    LogFunc(("callback"));
     1646    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1647    RT_NOREF(pThis);
     1648    RT_NOREF(uPass);
     1649    RT_NOREF(pSSM);
     1650    RT_NOREF(uVersion);
     1651    return VINF_SSM_DONT_CALL_AGAIN;
     1652}
     1653
     1654/** @callback_method_impl{FNSSMDEVSAVEEXEC}  */
     1655static DECLCALLBACK(int) virtioScsiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     1656{
     1657    LogFunc(("callback"));
     1658    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1659
     1660    RT_NOREF(pThis);
     1661    RT_NOREF(pSSM);
     1662    return VINF_SUCCESS;
     1663}
     1664
     1665/** @callback_method_impl{FNSSMDEVLOADDONE}  */
     1666static DECLCALLBACK(int) virtioScsiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     1667{
     1668    LogFunc(("callback"));
     1669    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1670    RT_NOREF(pThis);
     1671    RT_NOREF(pSSM);
     1672    return VINF_SUCCESS;
     1673}
     1674
     1675/** Let guest to use the queues */
     1676static void enableQueues(PVIRTIOSCSI pThis)
     1677{
     1678    for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     1679        virtioQueueEnable(pThis->hVirtio, qIdx, true);
     1680}
     1681
     1682/** Tell guest to stop using the queues */
     1683static void disableQueues(PVIRTIOSCSI pThis)
     1684{
     1685    /** Tell guest to stop sending stuff */
     1686    for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++)
     1687        virtioQueueEnable(pThis->hVirtio, qIdx, false);
     1688}
     1689
     1690/**
     1691 * Handle callback from PDM's async notification mechanism.
     1692 * In this case, the callback is triggered when I/O activity is quiesced.
     1693 *
     1694 * @returns true if we've quiesced, false if we're still working.
     1695 * @param   pDevIns     The device instance.
     1696 */
     1697static DECLCALLBACK(bool) virtioScsiDeviceQuiesced(PPDMDEVINS pDevIns)
     1698{
     1699    LogFunc(("\n"));
     1700    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1701
     1702    if (pThis->fResetting)
     1703    {
     1704        Log2Func(("Resetting VirtIO\n"));
     1705
     1706        /** Reset virtio infrastructure */
     1707        virtioResetAll(pThis->hVirtio);
     1708
     1709        /** Reset negotiable device-specific config parameters to VirtIO-specified default values */
     1710        pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
     1711        pThis->virtioScsiConfig.uCdbSize   = VIRTIOSCSI_CDB_SIZE_DEFAULT;
     1712
     1713        pThis->fQuiescing = false;
     1714
     1715        /** fQuiescing and fReset flags get cleared during [re-]initialization */
     1716    }
     1717    else if (pThis->fSuspending || pThis->fPoweringOff)
     1718    {
     1719        /* Lower-level driver (DrvVD) has already suspended any I/O on wait queue */
     1720    }
     1721    return false;
     1722}
     1723
     1724static void virtioScsiQuiesceDevice(PPDMDEVINS pDevIns)
     1725{
     1726    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1727
     1728    pThis->fQuiescing = true;  /* inhibit worker thread's de-queing */
     1729    disableQueues(pThis);      /* inhibit guest use of virtq's */
     1730
     1731    PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiDeviceQuiesced);
     1732
     1733    /** If already quiesced invoke async callback.  */
     1734    if (!ASMAtomicReadU32(&pThis->cActiveReqs))
     1735        PDMDevHlpAsyncNotificationCompleted(pDevIns);
     1736}
     1737
     1738/**
     1739 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     1740 */
     1741static DECLCALLBACK(void) virtioScsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     1742                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     1743{
     1744    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
     1745    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
     1746
     1747    switch (enmState)
     1748    {
     1749        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
     1750        {
     1751            /* Stop considering this request active */
     1752            if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing)
     1753                PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns));
     1754            break;
     1755        }
     1756        case PDMMEDIAEXIOREQSTATE_ACTIVE:
     1757            ASMAtomicIncU32(&pThis->cActiveReqs);
     1758            break;
     1759        default:
     1760            AssertMsgFailed(("Invalid request state given %u\n", enmState));
     1761    }
     1762}
     1763
     1764/**
     1765 * @interface_method_impl{PDMDEVREG,pfnResume}
     1766 */
     1767static DECLCALLBACK(void) virtioScsiResume(PPDMDEVINS pDevIns)
     1768{
     1769    LogFunc(("\n"));
     1770    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1771    pThis->fSuspending = pThis->fQuiescing = false;
     1772    enableQueues(pThis);
     1773}
     1774
     1775/**
     1776 * @interface_method_impl{PDMDEVREG,pfnSuspend}
     1777 */
     1778static DECLCALLBACK(void) virtioScsiSuspend(PPDMDEVINS pDevIns)
     1779{
     1780    LogFunc(("\n"));
     1781
     1782    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1783
     1784    pThis->fSuspending = true;
     1785
     1786    virtioScsiQuiesceDevice(pDevIns);
     1787
     1788    for (uint32_t i = 0; i < pThis->cTargets; i++)
     1789    {
     1790        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
     1791        if (pTarget->pDrvBase)
     1792            if (pTarget->pDrvMediaEx)
     1793                pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx);
     1794    }
     1795}
     1796
     1797 /**
     1798  * Common worker for virtioScsiSuspend and virtioScsiPowerOff.
     1799  */
     1800static void virtioScsiPowerOn(PPDMDEVINS pDevIns)
     1801{
     1802    LogFunc(("\n"));
     1803    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1804    pThis->fPoweringOff = pThis->fQuiescing = false;
     1805    enableQueues(pThis);
     1806}
     1807
     1808 /**
     1809  * Common worker for virtioScsiSuspend and virtioScsiPowerOff.
     1810  */
     1811static void virtioScsiPowerOff(PPDMDEVINS pDevIns)
     1812{
     1813    LogFunc(("\n"));
     1814
     1815    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1816
     1817    pThis->fPoweringOff = true;
     1818    virtioScsiQuiesceDevice(pDevIns);
     1819
     1820    for (uint32_t i = 0; i < pThis->cTargets; i++)
     1821    {
     1822        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
     1823        if (pTarget->pDrvBase)
     1824            if (pTarget->pDrvMediaEx)
     1825                pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx);
     1826    }
     1827}
     1828
     1829/**
     1830 * @copydoc FNPDMDEVRESET
     1831 */
     1832static DECLCALLBACK(void) virtioScsiReset(PPDMDEVINS pDevIns)
     1833{
     1834    LogFunc(("\n"));
     1835
     1836    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1837    pThis->fResetting = true;
     1838
     1839    virtioScsiQuiesceDevice(pDevIns);
     1840}
     1841
     1842/**
     1843 * Turns on/off the write status LED.
     1844 *
     1845 * @param   pTarget         Pointer to the target device
     1846 * @param   fOn             New LED state.
     1847 */
     1848void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     1849{
     1850    LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     1851    if (fOn)
     1852        pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
     1853    else
     1854        pTarget->led.Actual.s.fWriting = fOn;
     1855}
     1856
     1857/**
     1858 * Turns on/off the read status LED.
     1859 *
     1860 * @param   pTarget         Pointer to the device state structure.
     1861 * @param   fOn             New LED state.
     1862 */
     1863void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     1864{
     1865    LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     1866    if (fOn)
     1867        pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
     1868    else
     1869        pTarget->led.Actual.s.fReading = fOn;
     1870}
     1871
     1872/**
     1873 * Gets the pointer to the status LED of a unit.
     1874 *
     1875 * @returns VBox status code.
     1876 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1877 * @param   iLUN            The unit which status LED we desire.
     1878 * @param   ppLed           Where to store the LED pointer.
     1879 */
     1880static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     1881{
     1882  PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
     1883    if (iLUN == 0)
     1884    {
     1885        *ppLed = &pTarget->led;
     1886        Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
     1887        return VINF_SUCCESS;
     1888    }
     1889    return VERR_PDM_LUN_NOT_FOUND;
     1890}
     1891
     1892/**
     1893 * Gets the pointer to the status LED of a unit.
     1894 *
     1895 * @returns VBox status code.
     1896 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1897 * @param   iLUN            The unit which status LED we desire.
     1898 * @param   ppLed           Where to store the LED pointer.
     1899 */
     1900static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     1901{
     1902    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
     1903    if (iLUN < pThis->cTargets)
     1904    {
     1905        *ppLed = &pThis->aTargetInstances[iLUN].led;
     1906        Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
     1907        return VINF_SUCCESS;
     1908    }
     1909    return VERR_PDM_LUN_NOT_FOUND;
     1910 }
     1911
     1912static int virtioScsiCfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
    14501913                                    const void *pv, size_t cb, uint8_t fWrite)
    14511914{
     
    14881951}
    14891952
    1490 
    1491 
    14921953/**
    14931954 * virtio-scsi VirtIO Device-specific capabilities read callback
     
    14991960 * @param   cb          Number of bytes to read
    15001961 */
    1501 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     1962static DECLCALLBACK(int) virtioScsiDevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    15021963{
    15031964    int rc = VINF_SUCCESS;
    15041965    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    15051966
    1506     rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, false);
     1967    rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, false);
    15071968
    15081969    return rc;
     
    15181979 * @param   cb          Number of bytes to write
    15191980 */
    1520 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     1981static DECLCALLBACK(int) virtioScsiDevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    15211982{
    15221983    int rc = VINF_SUCCESS;
    15231984    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    15241985
    1525     rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, true);
     1986    rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, true);
    15261987
    15271988    return rc;
    1528 }
    1529 
    1530 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
    1531 {
    1532     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
    1533 }
    1534 
    1535 DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
    1536 {
    1537     if (pThis->fHasHotplug)
    1538         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1539                 VIRTIOSCSI_EVT_RESET_REMOVED);
    1540 }
    1541 
    1542 DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
    1543 {
    1544     if (pThis->fHasHotplug)
    1545         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1546                 VIRTIOSCSI_EVT_RESET_RESCAN);
    1547 }
    1548 
    1549 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
    1550 {
    1551     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
    1552             VIRTIOSCSI_EVT_RESET_HARD);
    1553 }
    1554 
    1555 DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
    1556 {
    1557     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
    1558         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1559                 VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
    1560 }
    1561 
    1562 DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
    1563 {
    1564     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
    1565         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1566                 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
    1567 }
    1568 
    1569 DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
    1570 {
    1571     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
    1572         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1573                 VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
    1574 }
    1575 
    1576 DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
    1577 {
    1578     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
    1579         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1580                 VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
    1581 }
    1582 
    1583 DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
    1584 {
    1585     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
    1586         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1587                 VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
    1588 }
    1589 
    1590 DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
    1591 {
    1592     if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
    1593         virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
    1594                 VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
    1595 }
    1596 
    1597 
    1598 DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
    1599 {
    1600     uint32_t uReason = uSenseQualifier << 8 | uSenseCode;
    1601     virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
    1602 
    1603 }
    1604 
    1605 static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)
    1606 {
    1607     RT_NOREF(hVirtio);
    1608 
    1609     AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);
    1610     PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
    1611     PWORKER pWorker = &pThis->aWorker[qIdx];
    1612 
    1613 
    1614     RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));
    1615 
    1616     if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
    1617     {
    1618         Log6Func(("%s has available data\n", QUEUENAME(qIdx)));
    1619         /** Wake queue's worker thread up if sleeping */
    1620         if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
    1621         {
    1622             if (ASMAtomicReadBool(&pWorker->fSleeping))
    1623             {
    1624                 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx)));
    1625                 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess);
    1626                 AssertRC(rc);
    1627             }
    1628         }
    1629     }
    1630     else if (qIdx == EVENTQ_IDX)
    1631     {
    1632         Log3Func(("Driver queued buffer(s) to %s\n"));
    1633         if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
    1634             virtioScsiReportEventsMissed(pThis, 0);
    1635     }
    1636     else
    1637         LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
    1638 }
    1639 
    1640 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient,  bool fVirtioReady)
    1641 {
    1642     RT_NOREF(hVirtio);
    1643     PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;
    1644     pThis->fVirtioReady = fVirtioReady;
    1645     if (fVirtioReady)
    1646     {
    1647         LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n"));
    1648         uint64_t features = virtioGetNegotiatedFeatures(hVirtio);
    1649         pThis->fHasT10pi     = features & VIRTIO_SCSI_F_T10_PI;
    1650         pThis->fHasHotplug   = features & VIRTIO_SCSI_F_HOTPLUG;
    1651         pThis->fHasInOutBufs = features & VIRTIO_SCSI_F_INOUT;
    1652         pThis->fHasLunChange = features & VIRTIO_SCSI_F_CHANGE;
    1653     }
    1654     else
    1655     {
    1656         LogFunc(("VirtIO is resetting\n"));
    1657         for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)
    1658             pThis->fQueueAttached[i] = false;
    1659     }
    1660 }
    1661 
    1662 /**
    1663  * Turns on/off the write status LED.
    1664  *
    1665  * @param   pTarget         Pointer to the target device
    1666  * @param   fOn             New LED state.
    1667  */
    1668 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    1669 {
    1670     LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
    1671     if (fOn)
    1672         pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
    1673     else
    1674         pTarget->led.Actual.s.fWriting = fOn;
    1675 }
    1676 
    1677 /**
    1678  * Turns on/off the read status LED.
    1679  *
    1680  * @param   pTarget         Pointer to the device state structure.
    1681  * @param   fOn             New LED state.
    1682  */
    1683 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
    1684 {
    1685     LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
    1686     if (fOn)
    1687         pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
    1688     else
    1689         pTarget->led.Actual.s.fReading = fOn;
    1690 }
    1691 
    1692 /**
    1693  * virtio-scsi debugger info callback.
    1694  *
    1695  * @param   pDevIns     The device instance.
    1696  * @param   pHlp        The output helpers.
    1697  * @param   pszArgs     The arguments.
    1698  */
    1699 static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    1700 {
    1701     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1702     bool fVerbose = false;
    1703 
    1704     /* Parse arguments. */
    1705     if (pszArgs)
    1706         fVerbose = strstr(pszArgs, "verbose") != NULL;
    1707 
    1708     /* Show basic information. */
    1709     pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",
    1710                     pDevIns->pReg->szName,
    1711                     pDevIns->iInstance);
    1712     pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets);
    1713 }
    1714 
    1715 /**
    1716  * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
    1717  */
    1718 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
    1719 {
    1720     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    1721     PVIRTIOSCSI pThis = pTarget->CTX_SUFF(pVirtioScsi);
    1722     LogFunc(("LUN %d Ejected!\n", pTarget->iLUN));
    1723     if (pThis->pMediaNotify)
    1724     {
    1725          int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
    1726                                    (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
    1727                                     pThis->pMediaNotify, pTarget->iLUN);
    1728          AssertRC(rc);
    1729     }
    1730 
    1731 }
    1732 
    1733 /** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
    1734 static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    1735 {
    1736     LogFunc(("callback"));
    1737     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1738     RT_NOREF(pThis);
    1739     RT_NOREF(uPass);
    1740     RT_NOREF(pSSM);
    1741     return VINF_SSM_DONT_CALL_AGAIN;
    1742 }
    1743 
    1744 /** @callback_method_impl{FNSSMDEVLOADEXEC}  */
    1745 static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    1746 {
    1747     LogFunc(("callback"));
    1748     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1749     RT_NOREF(pThis);
    1750     RT_NOREF(uPass);
    1751     RT_NOREF(pSSM);
    1752     RT_NOREF(uVersion);
    1753     return VINF_SSM_DONT_CALL_AGAIN;
    1754 }
    1755 
    1756 /** @callback_method_impl{FNSSMDEVSAVEEXEC}  */
    1757 static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    1758 {
    1759     LogFunc(("callback"));
    1760     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1761 
    1762     RT_NOREF(pThis);
    1763     RT_NOREF(pSSM);
    1764     return VINF_SUCCESS;
    1765 }
    1766 
    1767 /** @callback_method_impl{FNSSMDEVLOADDONE}  */
    1768 static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    1769 {
    1770     LogFunc(("callback"));
    1771     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1772     RT_NOREF(pThis);
    1773     RT_NOREF(pSSM);
    1774     return VINF_SUCCESS;
    1775 }
    1776 
    1777 
    1778 /**
    1779  * Callback employed by virtioScsiR3PDMReset.
    1780  *
    1781  * @returns true if we've quiesced, false if we're still working.
    1782  * @param   pDevIns     The device instance.
    1783  */
    1784 static DECLCALLBACK(bool) virtioScsiR3IsAsyncResetDone(PPDMDEVINS pDevIns)
    1785 {
    1786     RT_NOREF(pDevIns);
    1787     Log(("\n"));
    1788 
    1789     return true;
    1790 }
    1791 
    1792 /**
    1793  * @copydoc FNPDMDEVRESET
    1794  */
    1795 static DECLCALLBACK(void) virtioScsiR3PDMReset(PPDMDEVINS pDevIns)
    1796 {
    1797     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1798     ASMAtomicWriteBool(&pThis->fSignalIdle, true);
    1799 
    1800     bool fIoInProgress = false;
    1801     for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aTargetInstances); i++)
    1802     {
    1803           PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
    1804           if (pTarget->cReqsInProgress != 0)
    1805           {
    1806               fIoInProgress = true;
    1807               break;
    1808           }
    1809     }
    1810     if (!fIoInProgress)
    1811         PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3IsAsyncResetDone);
    1812     else
    1813         ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    1814 
    1815     virtioScsiDeviceReset(pThis);
    18161989}
    18171990
     
    18322005 * @remark  A relocation CANNOT fail.
    18332006 */
    1834 static DECLCALLBACK(void) virtioScsiR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     2007static DECLCALLBACK(void) virtioScsiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    18352008{
    18362009    LogFunc(("Relocating virtio-scsi"));
     
    18432016    {
    18442017        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
    1845         pTarget->pVirtioScsiR3 = pThis;;
     2018        pTarget->pVirtioScsi = pThis;
    18462019    }
    18472020
     
    18532026}
    18542027
    1855 static DECLCALLBACK(int) virtioScsiR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
     2028static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    18562029                                                       uint32_t *piInstance, uint32_t *piLUN)
    18572030{
    1858     PVIRTIOSCSITARGET pThisTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
    1859     PPDMDEVINS pDevIns = pThisTarget->CTX_SUFF(pVirtioScsi)->CTX_SUFF(pDevIns);
     2031    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);
     2032    PPDMDEVINS pDevIns = pTarget->pVirtioScsi->CTX_SUFF(pDevIns);
    18602033
    18612034    AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
     
    18652038    *ppcszController = pDevIns->pReg->szName;
    18662039    *piInstance = pDevIns->iInstance;
    1867     *piLUN = pThisTarget->iLUN;
     2040    *piLUN = pTarget->iLUN;
    18682041
    18692042    return VINF_SUCCESS;
     
    18712044
    18722045/**
    1873  * Gets the pointer to the status LED of a unit.
    1874  *
    1875  * @returns VBox status code.
    1876  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1877  * @param   iLUN            The unit which status LED we desire.
    1878  * @param   ppLed           Where to store the LED pointer.
    1879  */
    1880 static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    1881 {
    1882     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
    1883     if (iLUN == 0)
    1884     {
    1885         *ppLed = &pTarget->led;
    1886         Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
    1887         return VINF_SUCCESS;
    1888     }
    1889     return VERR_PDM_LUN_NOT_FOUND;
    1890   }
    1891 
    1892 
    1893 /**
    1894  * Gets the pointer to the status LED of a unit.
    1895  *
    1896  * @returns VBox status code.
    1897  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    1898  * @param   iLUN            The unit which status LED we desire.
    1899  * @param   ppLed           Where to store the LED pointer.
    1900  */
    1901 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    1902 {
    1903     PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
    1904     if (iLUN < pThis->cTargets)
    1905     {
    1906         *ppLed = &pThis->aTargetInstances[iLUN].led;
    1907         Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
    1908         return VINF_SUCCESS;
    1909     }
    1910     return VERR_PDM_LUN_NOT_FOUND;
    1911 }
    1912 
    1913 
    1914 /**
    1915  * Memory mapped I/O Handler for read operations.
    1916  *
    1917  * @returns VBox status code.
    1918  *
    1919  * @param   pDevIns     The device instance.
    1920  * @param   pvUser      User argument.
    1921  * @param   GCPhysAddr  Physical address (in GC) where the read starts.
    1922  * @param   pv          Where to store the result.
    1923  * @param   cb          Number of bytes read.
    1924  */
    1925 PDMBOTHCBDECL(int) virtioScsiMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    1926 {
    1927     RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    1928     LogFunc(("Read from MMIO area\n"));
    1929     return VINF_SUCCESS;
    1930 }
    1931 
    1932 /**
    1933  * Memory mapped I/O Handler for write operations.
    1934  *
    1935  * @returns VBox status code.
    1936  *
    1937  * @param   pDevIns     The device instance.
    1938  * @param   pvUser      User argument.
    1939  * @param   GCPhysAddr  Physical address (in GC) where the read starts.
    1940  * @param   pv          Where to fetch the result.
    1941  * @param   cb          Number of bytes to write.
    1942  */
    1943 PDMBOTHCBDECL(int) virtioScsiMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    1944 {
    1945     RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    1946     LogFunc(("Write to MMIO area\n"));
    1947     return VINF_SUCCESS;
    1948 }
    1949 
    1950 /**
    1951  * @callback_method_impl{FNPCIIOREGIONMAP}
    1952  */
    1953 static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    1954                                            RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    1955 {
    1956     RT_NOREF(pPciDev, iRegion);
    1957     PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1958     int rc = VINF_SUCCESS;
    1959 
    1960     Assert(cb >= 32);
    1961 
    1962     switch (iRegion)
    1963     {
    1964         case 0:
    1965             LogFunc(("virtio-scsi MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
    1966 
    1967             /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    1968             rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    1969                                    IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    1970                                    virtioScsiMMIOWrite, virtioScsiMMIORead,
    1971                                    "virtio-scsi MMIO");
    1972             pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
    1973             return rc;
    1974         case 1:
    1975             /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */
    1976             AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));
    1977         default:
    1978             AssertMsgFailed(("Invalid enmType=%d\n", enmType));
    1979     }
    1980     return VERR_GENERAL_FAILURE; /* Should never get here */
    1981 }
    1982 
    1983 /**
    19842046 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    19852047 */
    1986 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     2048static DECLCALLBACK(void *) virtioScsiTargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    19872049{
    19882050     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
     
    19972059 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    19982060 */
    1999 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     2061static DECLCALLBACK(void *) virtioScsiDeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    20002062{
    20012063    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
     
    20172079 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    20182080 */
    2019 static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     2081static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    20202082{
    20212083    RT_NOREF(fFlags);
     
    20452107 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    20462108 */
    2047 static DECLCALLBACK(int)  virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     2109static DECLCALLBACK(int)  virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    20482110{
    20492111    PVIRTIOSCSI       pThis   = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     
    21612223    pVirtioPciParams->uInterruptPin  = 0x01;
    21622224
    2163     pThis->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
     2225    pThis->IBase.pfnQueryInterface = virtioScsiDeviceQueryInterface;
    21642226
    21652227    /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */
     
    21772239    rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,
    21782240                         VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED,
    2179                          virtioScsiR3DevCapRead,
    2180                          virtioScsiR3DevCapWrite,
     2241                         virtioScsiDevCapRead,
     2242                         virtioScsiDevCapWrite,
    21812243                         virtioScsiStatusChanged,
    21822244                         virtioScsiNotified,
    2183                          virtioScsiR3LiveExec,
    2184                          virtioScsiR3SaveExec,
    2185                          virtioScsiR3LoadExec,
    2186                          virtioScsiR3LoadDone,
     2245                         virtioScsiLiveExec,
     2246                         virtioScsiSaveExec,
     2247                         virtioScsiLoadExec,
     2248                         virtioScsiLoadDone,
    21872249                         sizeof(VIRTIOSCSI_CONFIG_T) /* cbDevSpecificCap */,
    21882250                         (void *)&pThis->virtioScsiConfig /* pDevSpecificCap */);
     
    22072269            rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorker[qIdx].pThread,
    22082270                                       (void *)(uint64_t)qIdx, virtioScsiWorker,
    2209                                        virtioScsiR3WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
     2271                                       virtioScsiWorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));
    22102272            if (rc != VINF_SUCCESS)
    22112273            {
     
    22212283    }
    22222284
    2223     rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_MEM_IO, 32,
    2224                                       PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map);
    2225     if (RT_FAILURE(rc))
    2226         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: cannot register PCI mmio address space"));
    2227 
    22282285#ifdef BOOTABLE_SUPPORT_TBD
    22292286    if (fBootable)
     
    22312288        /* Register I/O port space for BIOS access. */
    22322289        rc = PDMDevHlpIOPortRegister(pDevIns, VIRTIOSCSI_BIOS_IO_PORT, 4, NULL,
    2233                                      virtioScsiR3BiosIoPortWrite, virtioScsiR3BiosIoPortRead,
    2234                                      virtioScsiR3BiosIoPortWriteStr, virtioScsiR3BiosIoPortReadStr,
     2290                                     virtioScsiBiosIoPortWrite, virtioScsiBiosIoPortRead,
     2291                                     virtioScsiBiosIoPortWriteStr, virtioScsiBiosIoPortReadStr,
    22352292                                     "virtio-scsi BIOS");
    22362293        if (RT_FAILURE(rc))
     
    22492306        /* Initialize static parts of the device. */
    22502307        pTarget->iLUN = iLUN;
    2251         pTarget->pVirtioScsiR3 = pThis;
    2252 
    2253         pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
     2308        pTarget->pVirtioScsi = pThis;
     2309
     2310        pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
    22542311
    22552312        /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
    2256         pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
    2257         pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiR3IoReqCompleteNotify;
    2258         pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiR3IoReqCopyFromBuf;
    2259         pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiR3IoReqCopyToBuf;
    2260         pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
    2261         pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
     2313        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiQueryDeviceLocation;
     2314        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiIoReqFinish;
     2315        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiIoReqCopyFromBuf;
     2316        pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiIoReqCopyToBuf;
     2317        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiIoReqStateChanged;
     2318        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiMediumEjected;
    22622319        pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL; /* When used avoids copyFromBuf CopyToBuf*/
    22632320        pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
    22642321
    22652322
    2266         pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
    2267         pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3TargetQueryStatusLed;
    2268         pThis->ILeds.pfnQueryStatusLed                   = virtioScsiR3DeviceQueryStatusLed;
     2323        pTarget->IBase.pfnQueryInterface                 = virtioScsiTargetQueryInterface;
     2324        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiTargetQueryStatusLed;
     2325        pThis->ILeds.pfnQueryStatusLed                   = virtioScsiDeviceQueryStatusLed;
    22692326        pTarget->led.u32Magic                            = PDMLED_MAGIC;
    22702327
     
    23272384    char szTmp[128];
    23282385    RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
    2329     PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info);
     2386    PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiInfo);
    23302387
    23312388    return rc;
     
    23412398    /* .szName = */                 "virtio-scsi",
    23422399#ifdef VIRTIOSCSI_GC_SUPPORT
    2343     /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
     2400    /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0
     2401                                    | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION
     2402                                    | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION,
    23442403#else
    2345     /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS,
     2404    /* .fFlags = */                 PDM_DEVREG_FLAGS_DEFAULT_BITS
     2405                                    | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION
     2406                                    | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION,
    23462407#endif
    23472408    /* .fClass = */                 PDM_DEVREG_CLASS_MISC,
     
    23582419    /* .pfnConstruct = */           virtioScsiConstruct,
    23592420    /* .pfnDestruct = */            virtioScsiDestruct,
    2360     /* .pfnRelocate = */            virtioScsiR3Relocate,
     2421    /* .pfnRelocate = */            virtioScsiRelocate,
    23612422    /* .pfnMemSetup = */            NULL,
    2362     /* .pfnPowerOn = */             NULL,
    2363     /* .pfnReset = */               virtioScsiR3PDMReset,
    2364     /* .pfnSuspend = */             NULL,
    2365     /* .pfnResume = */              NULL,
    2366     /* .pfnAttach = */              virtioScsiR3Attach,
    2367     /* .pfnDetach = */              virtioScsiR3Detach,
     2423    /* .pfnPowerOn = */             virtioScsiPowerOn,
     2424    /* .pfnReset = */               virtioScsiReset,
     2425    /* .pfnSuspend = */             virtioScsiSuspend,
     2426    /* .pfnResume = */              virtioScsiResume,
     2427    /* .pfnAttach = */              virtioScsiAttach,
     2428    /* .pfnDetach = */              virtioScsiDetach,
    23682429    /* .pfnQueryInterface = */      NULL,
    23692430    /* .pfnInitComplete = */        NULL,
    2370     /* .pfnPowerOff = */            NULL,
     2431    /* .pfnPowerOff = */            virtioScsiPowerOff,
    23712432    /* .pfnSoftReset = */           NULL,
    23722433    /* .pfnReserved0 = */           NULL,
Note: See TracChangeset for help on using the changeset viewer.

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