VirtualBox

Changeset 80499 in vbox


Ignore:
Timestamp:
Aug 29, 2019 2:47:17 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132993
Message:

Storage/DrvVirtioSCSI.cpp: Added code to handle event subscriptions and eventq handling. Various improvements to round-trip I/O with Linux at startup after feature negotiation and setup. Ready to try some preliminary device access from guest. See bugref:9440 Comment #58 for more info

Location:
trunk/src/VBox/Devices
Files:
4 edited

Legend:

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

    r80437 r80499  
    271271
    272272#define VIRTIOSCSI_T_AN_QUERY                     1           /** Asynchronous notification query                    */
    273 #define VIRTIOSCSI_T_AN_SUBSCRIBE                 2           /** Asynchronous notification Subscribe             */
     273#define VIRTIOSCSI_T_AN_SUBSCRIBE                 2           /** Asynchronous notification subscription             */
    274274
    275275#pragma pack(1)
     
    279279    uint32_t  uType;                                          /** type                                               */
    280280    uint8_t   uLUN[8];                                        /** lun                                                */
    281     uint32_t  uEventRequested;                                /** event_requested                                    */
     281    uint32_t  uEventsRequested;                                /** event_requested                                    */
    282282    // Device-writable part
    283283    uint32_t  uEventActual;                                   /** event_actual                                       */
     
    297297/** @} */
    298298
     299#define SUBSCRIBABLE_EVENTS \
     300              VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE \
     301            & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT \
     302            & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST \
     303            & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE \
     304            & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST \
     305            & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY
    299306
    300307/**
     
    346353    /** Status LED interface */
    347354    PDMILEDPORTS                    ILed;
     355
    348356    /** The status LED state for this device. */
    349357    PDMLED                          led;
     
    422430    bool volatile                   fSignalIdle;
    423431
     432    /** Events the guest has subscribed to get notifications of */
     433    uint32_t                        uSubscribedEvents;
     434
     435    /** Set if events missed due to lack of bufs avail on eventq */
     436    bool                            fEventsMissed;
     437
     438    /** VirtIO Host SCSI device runtime configuration parameters */
    424439    VIRTIOSCSI_CONFIG_T             virtioScsiConfig;
     440
     441    /** True if the guest/driver and VirtIO framework are in the ready state */
    425442    bool                            fVirtioReady;
     443
     444    /** True if VIRTIO_SCSI_F_T10_PI was negotiated */
    426445    bool                            fHasT10pi;
     446
     447    /** True if VIRTIO_SCSI_F_T10_PI was negotiated */
    427448    bool                            fHasHotplug;
     449
     450    /** True if VIRTIO_SCSI_F_T10_PI was negotiated */
    428451    bool                            fHasInOutBufs;
     452
     453    /** True if VIRTIO_SCSI_F_T10_PI was negotiated */
    429454    bool                            fHasLunChange;
    430455
    431 
    432 
    433456} VIRTIOSCSI, *PVIRTIOSCSI;
    434 
    435457
    436458/**
     
    444466    size_t                         cbPiOut;                  /**< Size of T10 pi in buffer                          */
    445467    uint8_t                       *pbPiOut;                  /**< Address of pi out buffer                          */
    446     uint8_t                       *pbDataOut;                /**< datain                                            */
     468    uint8_t                       *pbDataOut;                /**< dataout */
    447469    size_t                         cbPiIn;                   /**< Size of T10 pi buffer                             */
    448470    uint8_t                       *pbPiIn;                   /**< Address of pi in buffer                           */
     
    455477} VIRTIOSCSIREQ;
    456478
     479#define PTARGET_FROM_LUN_BUF(lunBuf) &pThis->aTargetInstances[lunBuf[1]];
     480
     481#define SET_LUN_BUF(target, lun, out) \
     482     out[0] = 0x01;  out[1] = target; out[2] = (lun >> 8) & 0x40;  out[3] = lun & 0xff;  *((uint16_t *)out + 4) = 0;
     483
    457484DECLINLINE(const char *) virtioGetTMFTypeText(uint32_t uSubType)
    458485{
     
    471498}
    472499
    473 DECLINLINE(const char *) virtioGetControlAsyncTypeText(uint32_t uType)
    474 {
    475     switch (uType)
    476     {
    477         case VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE:   return "OPERATIONAL CHANGE";
    478         case VIRTIOSCSI_EVT_ASYNC_POWER_MGMT:           return "POWER MGMT";
    479         case VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST:     return "EXTERNAL REQUEST";
    480         case VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE:         return "MEDIA CHANGE";
    481         case VIRTIOSCSI_EVT_ASYNC_MULTI_HOST:           return "MULTI HOST";
    482         case VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY:          return "DEVICE BUSY";
    483         default:                                        return "<unknown>";
    484     }
     500DECLINLINE(void) virtioGetControlAsyncMaskText(char *pszOutput, size_t cbOutput, uint32_t uAsyncTypesMask)
     501{
     502    RTStrPrintf(pszOutput, cbOutput, "%s%s%s%s%s%s",
     503        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) ? "CHANGE_OPERATION  "   : "",
     504        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)         ? "POWER_MGMT  "         : "",
     505        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)   ? "EXTERNAL_REQ  "       : "",
     506        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)       ? "MEDIA_CHANGE  "       : "",
     507        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)         ? "MULTI_HOST  "         : "",
     508        (uAsyncTypesMask & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)        ? "DEVICE_BUSY  "        : "");
    485509}
    486510
     
    535559            return VIRTIOSCSI_S_BAD_TARGET;
    536560
    537         case VERR_RESOURCE_BUSY:    /** TBD */
     561        case VERR_RESOURCE_BUSY:
    538562            return VIRTIOSCSI_S_BUSY;
    539563
    540         case VERR_STATE_CHANGED:    /** TBD */
     564        case VERR_STATE_CHANGED:
    541565            return VIRTIOSCSI_S_RESET;
    542566
    543         case VERR_CANCELLED:        /** TBD */
     567        case VERR_CANCELLED:
    544568            return VIRTIOSCSI_S_ABORTED;
    545569
    546         case VERR_IO_NOT_READY:     /** TBD */
     570        case VERR_IO_NOT_READY:
     571            return VIRTIOSCSI_S_TARGET_FAILURE;
     572
     573        case VERR_DEV_IO_ERROR:
     574            return VIRTIOSCSI_S_TRANSPORT_FAILURE;
     575
     576        case VERR_NOT_SUPPORTED:
    547577            return VIRTIOSCSI_S_NEXUS_FAILURE;
    548578
    549         case VERR_DEV_IO_ERROR:     /** TBD */
    550             return VIRTIOSCSI_S_TRANSPORT_FAILURE;
    551 
    552         case VERR_IO_GEN_FAILURE:   /** TBD */
     579        case VERR_IO_GEN_FAILURE:
    553580            return VIRTIOSCSI_S_FAILURE;
    554581    }
    555582    return VIRTIOSCSI_S_FAILURE;
    556583}
    557 
    558584
    559585/**
     
    599625        } \
    600626    }
     627
     628
    601629
    602630typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
     
    660688                                                    size_t cbCopy)
    661689{
    662 //    LogFunc(("\n"));
    663 
    664690    RT_NOREF(hIoReq);
    665691    RT_NOREF(pInterface);
     
    681707                                                  size_t cbCopy)
    682708{
    683 //    LogFunc(("\n"));
    684 
    685709    RT_NOREF(hIoReq);
    686710    RT_NOREF(pInterface);
     
    694718}
    695719
    696 
     720static int virtioScsiSendEvent(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason)
     721{
     722    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget];
     723
     724    VIRTIOSCSI_EVENT_T event = { uEventType, { 0 }, uReason };
     725    SET_LUN_BUF(pTarget->iLUN, 0, event.uLUN);
     726
     727    switch(uEventType)
     728    {
     729        case VIRTIOSCSI_T_NO_EVENT:
     730            if (uEventType & VIRTIOSCSI_T_EVENTS_MISSED)
     731                LogFunc(("LUN: %s Warning driver that events were missed\n", event.uLUN));
     732            else
     733                LogFunc(("LUN: %s Warning driver event info it queued is shorter than configured\n", event.uLUN));
     734            break;
     735        case VIRTIOSCSI_T_TRANSPORT_RESET:
     736            switch(uReason)
     737            {
     738                case VIRTIOSCSI_EVT_RESET_REMOVED:
     739                    LogFunc(("LUN: %s Target or LUN removed\n", event.uLUN));
     740                    break;
     741                case VIRTIOSCSI_EVT_RESET_RESCAN:
     742                    LogFunc(("LUN: %s Target or LUN added\n", event.uLUN));
     743                    break;
     744                case VIRTIOSCSI_EVT_RESET_HARD:
     745                    LogFunc(("LUN: %s Target was reset\n", event.uLUN));
     746                    break;
     747            }
     748            break;
     749        case VIRTIOSCSI_T_ASYNC_NOTIFY:
     750            char szTypeText[128];
     751            virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), uReason);
     752            LogFunc(("LUN: %s Delivering subscribed async notification %s\n", event.uLUN, szTypeText));
     753            break;
     754        case VIRTIOSCSI_T_PARAM_CHANGE:
     755            LogFunc(("LUN: %s PARAM_CHANGE sense code: 0x%x sense qualifier: 0x%x\n",
     756                        event.uLUN, uReason & 0xff, (uReason >> 8) & 0xff));
     757            break;
     758        default:
     759            LogFunc(("LUN: %s Unknown event type: %d, ignoring\n", event.uLUN, uEventType));
     760            return VINF_SUCCESS;
     761    }
     762
     763    if (virtioQueueIsEmpty(pThis->hVirtio, EVENTQ_IDX))
     764    {
     765        LogFunc(("eventq is empty, events missed!\n"));
     766        ASMAtomicWriteBool(&pThis->fEventsMissed, true);
     767        return VINF_SUCCESS;
     768    }
     769
     770    int rc = virtioQueueGet(pThis->hVirtio, EVENTQ_IDX, true, NULL, NULL);
     771    AssertRC(rc);
     772
     773    RTSGBUF reqSegBuf;
     774    RTSGSEG aReqSegs[] = { { &event, sizeof(event) } };
     775    RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
     776
     777    rc = virtioQueuePut (pThis->hVirtio, EVENTQ_IDX, &reqSegBuf, true);
     778    AssertRC(rc);
     779
     780    rc = virtioQueueSync(pThis->hVirtio, EVENTQ_IDX);
     781    AssertRC(rc);
     782
     783    return VINF_SUCCESS;
     784
     785}
     786
     787static int virtioScsiR3ScrapReq(PVIRTIOSCSI pThis, uint16_t qIdx, uint32_t rcReq)
     788{
     789    struct REQ_RESP_HDR respHdr;
     790    respHdr.uSenseLen = 0;
     791    respHdr.uResidual = 0;
     792    respHdr.uStatusQualifier = 0;  /** TBD. Seems to be for iSCSI. Can't find any real info */
     793    respHdr.uStatus = 0;
     794    respHdr.uResponse = virtioScsiMapVerrToVirtio(rcReq);
     795    RTSGBUF reqSegBuf;
     796    RTSGSEG aReqSegs[] = { { &respHdr, sizeof(respHdr) } };
     797    RTSgBufInit(&reqSegBuf, aReqSegs, 1);
     798    virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, false /* fFence */);
     799    virtioQueueSync(pThis->hVirtio, qIdx);
     800    LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr.uResponse)));
     801    return VINF_SUCCESS;
     802}
    697803
    698804static int virtioScsiR3ReqComplete(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq)
    699805{
    700 
    701806    PVIRTIOSCSITARGET pTarget = pReq->pTarget;
    702     PPDMIMEDIAEX      pIMediaEx = pTarget->pDrvMediaEx;
    703     uint8_t uResponse = virtioScsiMapVerrToVirtio((uint32_t)rcReq);
    704 
     807    PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx;
    705808    RTSGBUF reqSegBuf;
    706     unsigned cReqSegs = 0;
    707     if (!pReq)
    708     {
    709         Log(("No active request associated\n"));
    710         struct REQ_RESP_HDR respHdr;
    711         respHdr.uSenseLen = 0;
    712         respHdr.uResidual = 0;
    713         respHdr.uStatusQualifier = 0;       /** TBD. Seems to be for iSCSI. Can't find any real info */
    714         respHdr.uStatus = 0;
    715         respHdr.uResponse = uResponse;
    716         RTSGSEG aReqSegs[] = { { &respHdr, sizeof(respHdr) } };
    717         cReqSegs = 1;
    718         RTSgBufInit(&reqSegBuf, aReqSegs, cReqSegs);
    719 
    720     }
    721     else
    722     {
    723         Assert(pReq->pbDataIn && pReq->pbSense);
    724         ASMAtomicDecU32(&pTarget->cReqsInProgress);
    725 
    726         size_t cbResidual = 0;
    727         int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
    728         AssertRC(rc); Assert(cbResidual == (uint32_t)cbResidual);
    729 
    730         struct REQ_RESP_HDR respHdr;
    731         respHdr.uSenseLen = pReq->cbSense;
    732         respHdr.uResidual = cbResidual;
    733         respHdr.uStatusQualifier = 0;  /** TBD. Seems to be iSCSI specific. Can't find any real info */
    734         respHdr.uStatus = pReq->uStatus;
    735         respHdr.uResponse = uResponse;
    736 
    737         LogFunc(("SCSI Status = %x (%s)\n", pReq->uStatus, pReq->uStatus != SCSI_STATUS_OK ? "FAILED" : "SCSI_STATUS_OK"));
    738         LogFunc(("Response code: %s\n", virtioGetReqRespText(uResponse)));
    739 
    740         if (pReq->cbSense)
    741             LogFunc(("Sense: %.*Rhxs\n", pReq->cbSense, pReq->pbSense));
    742 
    743         if (pReq->cbDataIn)
    744             LogFunc(("Data In: %.*Rhxs\n", pReq->cbDataIn, pReq->pbDataIn));
    745 
    746         if (pReq->cbPiIn)
    747             LogFunc(("Pi In: %.*Rhxs\n", pReq->cbPiIn, pReq->pbPiIn));
    748 
    749         LogFunc(("Residual: %d\n", cbResidual));
    750 
    751         PRTSGSEG pReqSegs;
    752         if (pReq->pbPiIn)
    753         {
    754             RTSGSEG aReqSegs[] = {
    755                     { &respHdr,       sizeof(respHdr) },
    756                     { pReq->pbSense,  pReq->cbSense   },
    757                     { pReq->pbPiIn,   pReq->cbPiIn    },
    758                     { pReq->pbDataIn, pReq->cbDataIn  }
    759             };
    760             pReqSegs = aReqSegs;
    761             cReqSegs  = sizeof(aReqSegs) / sizeof(RTSGSEG);
    762         }
    763         else /** Much easier not to include piIn sgbuf than to account for it during copy! */
    764         {
    765             RTSGSEG aReqSegs[] = {
    766                     { &respHdr,       sizeof(respHdr) },
    767                     { pReq->pbSense,  pReq->cbSense   },
    768                     { pReq->pbDataIn, pReq->cbDataIn  }
    769             };
    770             pReqSegs = aReqSegs;
    771             cReqSegs  = sizeof(aReqSegs) / sizeof(RTSGSEG);
    772         }
    773         RTSgBufInit(&reqSegBuf, pReqSegs, cReqSegs);
     809
     810    Assert(pReq->pbDataIn && pReq->pbSense);
     811    ASMAtomicDecU32(&pTarget->cReqsInProgress);
     812
     813    size_t cbResidual = 0;
     814    int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);
     815    AssertRC(rc); Assert(cbResidual == (uint32_t)cbResidual);
     816
     817    struct REQ_RESP_HDR respHdr;
     818    respHdr.uSenseLen = pReq->cbSense;
     819    respHdr.uResidual = cbResidual;
     820    respHdr.uStatusQualifier = 0;  /** TBD. Seems to be iSCSI specific. Can't find any real info */
     821    respHdr.uStatus = pReq->uStatus;
     822    respHdr.uResponse = virtioScsiMapVerrToVirtio(rcReq);
     823
     824    LogFunc(("SCSI Status = %x (%s)\n", pReq->uStatus, pReq->uStatus != SCSI_STATUS_OK ? "FAILED" : "SCSI_STATUS_OK"));
     825    LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr.uResponse)));
     826
     827    if (pReq->cbSense)
     828        LogFunc(("Sense: %.*Rhxs\n", pReq->cbSense, pReq->pbSense));
     829
     830    if (pReq->cbDataIn)
     831        LogFunc(("Data In: %.*Rhxs\n", pReq->cbDataIn, pReq->pbDataIn));
     832
     833    if (pReq->cbPiIn)
     834        LogFunc(("Pi In: %.*Rhxs\n", pReq->cbPiIn, pReq->pbPiIn));
     835
     836    LogFunc(("Residual: %d\n", cbResidual));
     837
     838    if (pReq->pbPiIn)
     839    {
     840        RTSGSEG aReqSegs[] = {
     841                { &respHdr,       sizeof(respHdr) },
     842                { pReq->pbSense,  pReq->cbSense   },
     843                { pReq->pbPiIn,   pReq->cbPiIn    },
     844                { pReq->pbDataIn, pReq->cbDataIn  }
     845        };
     846        RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
     847    }
     848    else /** Much easier not to include piIn sgbuf than to account for it during copy! */
     849    {
     850        RTSGSEG aReqSegs[] = {
     851                { &respHdr,       sizeof(respHdr) },
     852                { pReq->pbSense,  pReq->cbSense   },
     853                { pReq->pbDataIn, pReq->cbDataIn  }
     854        };
     855        RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    774856    }
    775857
     
    784866                   VERR_BUFFER_OVERFLOW);
    785867
    786     virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, false /** TBD spec doesn't say */);
     868    /**
     869     * Following doesn't put up memory barrier (fence).
     870     * VirtIO 1.0 Spec requires mem. barrier for ctrl cmds
     871     * but doesn't mention fences in regard to requests. */
     872    virtioQueuePut(pThis->hVirtio, pReq->qIdx, &reqSegBuf, false /* fFence */);
    787873    virtioQueueSync(pThis->hVirtio, pReq->qIdx);
    788874
     
    790876    RTMemFree(pReq->pbDataIn);
    791877
    792     if (pReq)
    793         pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
     878    pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq);
    794879
    795880    if (pTarget->cReqsInProgress == 0 && pThis->fSignalIdle)
     
    799884}
    800885
    801 
    802886/**
    803887 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     
    806890                                                       void *pvIoReqAlloc, int rcReq)
    807891{
    808 //    LogFunc(("\n"));
    809892    RT_NOREF(hIoReq);
    810893    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     
    817900    RT_NOREF(pInSgBuf);
    818901    RT_NOREF(qIdx);
     902
    819903    AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_NOT_IMPLEMENTED);
    820904
     
    849933    uint8_t *pbCdb = pVirtqReq->uCdb;
    850934
    851     LogFunc(("LUN: %.8Rhxs, id: %RX64, attr: %x, prio: %d, crn: %x\n"
     935    uint8_t  uTarget = pVirtqReq->cmdHdr.uLUN[1];
     936    uint32_t uLUN = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff;
     937
     938    LogFunc(("LUN: %.8Rhxs, (target:%d, lun:%d) id: %RX64, attr: %x, prio: %d, crn: %x\n"
    852939             "                     CDB: %.*Rhxs\n",
    853             pVirtqReq->cmdHdr.uLUN, pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr,
    854             pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn, cbCdb, pbCdb));
     940            pVirtqReq->cmdHdr.uLUN, uTarget, uLUN, pVirtqReq->cmdHdr.uId,
     941            pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn, cbCdb,  pbCdb));
     942    if (uTarget >= pThis->cTargets)
     943        virtioScsiR3ScrapReq(pThis, qIdx, VERR_IO_BAD_UNIT);
    855944
    856945    off_t    uPiOutOff = 0;
     
    882971        LogFunc(("pi_out[]: %.*Rhxs\n", cbPiOut, pVirtqReq->uPiOut));
    883972
    884     uint8_t  uTarget = pVirtqReq->cmdHdr.uLUN[1];
    885     if (uTarget > pThis->cTargets)
    886         virtioScsiR3ReqComplete(pThis, NULL, VERR_IO_BAD_UNIT);
    887 
    888     Assert(uTarget <= pThis->cTargets);
    889 
    890     uint32_t uLUN = pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3];
    891 
    892973    PDMMEDIAEXIOREQ   hIoReq = NULL;
    893974    PVIRTIOSCSIREQ    pReq;
     
    895976    PPDMIMEDIAEX      pIMediaEx = pTarget->pDrvMediaEx;
    896977
    897     size_t cbDataIn  = cbIn - (cbRespHdr + cbSense); /** tbd: cbPiIn */
     978    size_t cbDataIn  = cbIn - (cbRespHdr + cbSense + cbPiIn);
    898979
    899980    if (RT_LIKELY(pTarget->fPresent))
    900981    {
    901         int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uTag */,
     982        int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */,
    902983                                      PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
    903984
     
    913994        pReq->pbDataOut = pbDataOut;
    914995        pReq->cbPiIn    = cbPiIn;
    915         pReq->pbPiIn    = cbPiIn ? (uint8_t *)RTMemAllocZ(cbPiIn) : NULL;
    916         AssertMsgReturn(!cbPiIn || pReq->pbPiIn,   ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
    917 
     996        if (cbPiIn)
     997        {
     998            pReq->pbPiIn = (uint8_t *)RTMemAllocZ(cbPiIn);
     999            AssertMsgReturn(pReq->pbPiIn, ("Out of memory allocating pi_in buffer"),  VERR_NO_MEMORY);
     1000        }
    9181001        pReq->cbDataIn  = cbDataIn;
    9191002        pReq->pbDataIn  = (uint8_t *)RTMemAllocZ(cbDataIn);
     
    9321015
    9331016        if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
    934             virtioScsiR3ReqComplete(pThis, pReq, rc);
     1017            virtioScsiR3ScrapReq(pThis, qIdx, rc);
     1018    } else {
     1019         virtioScsiR3ScrapReq(pThis, qIdx, VERR_IO_NOT_READY);
    9351020    }
    9361021
     
    9541039    AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY);
    9551040
     1041     /**
     1042      * Get control command into virtual memory
     1043      */
    9561044    off_t cbOff = 0;
    9571045    size_t cbSeg = 0;
     
    9701058     * See VirtIO 1.0 specification section 5.6.6.2
    9711059     */
    972     uint32_t uEvtActual  =  VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
     1060    uint32_t uSubscribedEvents  =
     1061                            VIRTIOSCSI_EVT_ASYNC_POWER_MGMT
    9731062                          | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST
    9741063                          | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE
     
    9791068    switch(pScsiCtrl->uType)
    9801069    {
    981         case VIRTIOSCSI_T_TMF: /** Guest SCSI driver has invoked a SCSI Task Management Function */
     1070        case VIRTIOSCSI_T_TMF: /* Task Management Functions */
    9821071        {
    9831072            PVIRTIOSCSI_CTRL_TMF_T pScsiCtrlTmf = (PVIRTIOSCSI_CTRL_TMF_T)pScsiCtrl;
    984             LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sTask Mgt Function: %s\n",
     1073            LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sTask Mgt Function: %s (not yet implemented)\n",
    9851074                QUEUENAME(qIdx), pScsiCtrlTmf->uLUN,
    9861075                CBQUEUENAME(qIdx) + 18, "", virtioGetTMFTypeText(pScsiCtrlTmf->uSubtype)));
     
    9921081                    break;
    9931082                case VIRTIOSCSI_T_TMF_ABORT_TASK_SET:
     1083                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    9941084                    break;
    9951085                case VIRTIOSCSI_T_TMF_CLEAR_ACA:
     1086                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    9961087                    break;
    9971088                case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET:
     1089                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    9981090                    break;
    9991091                case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET:
     1092                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    10001093                    break;
    10011094                case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET:
     1095                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    10021096                    break;
    10031097                case VIRTIOSCSI_T_TMF_QUERY_TASK:
     1098                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    10041099                    break;
    10051100                case VIRTIOSCSI_T_TMF_QUERY_TASK_SET:
     1101                    uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    10061102                    break;
    10071103                default:
     
    10151111            break;
    10161112        }
    1017         case VIRTIOSCSI_T_AN_QUERY: /** Guest SCSI driver querying supported async event notifications */
     1113        case VIRTIOSCSI_T_AN_QUERY: /** Guest SCSI driver is querying supported async event notifications */
    10181114        {
    10191115            PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnQuery = (PVIRTIOSCSI_CTRL_AN_T)pScsiCtrl;
    1020             LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, type: %s\n",
    1021                 QUEUENAME(qIdx), pScsiCtrlAnQuery->uLUN,
    1022                 CBQUEUENAME(qIdx) + 30, "", virtioGetControlAsyncTypeText(pScsiCtrlAnQuery->uEventRequested)));
    1023 
    1024             uEvtActual &= pScsiCtrlAnQuery->uEventRequested;
     1116
     1117            char szTypeText[128];
     1118            virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnQuery->uEventsRequested);
     1119
     1120            LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, types: %s\n",
     1121                QUEUENAME(qIdx), pScsiCtrlAnQuery->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));
     1122
     1123            uSubscribedEvents &= pScsiCtrlAnQuery->uEventsRequested;
    10251124            uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
    10261125
    1027             RTSGSEG aReqSegs[] = { { &uEvtActual, sizeof(uEvtActual) },  { &uResponse, sizeof(uResponse)  } };
     1126            RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
    10281127            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    10291128
    10301129            break;
    10311130        }
    1032         case VIRTIOSCSI_T_AN_SUBSCRIBE: /** Guest SCSI driver subscribing to async event notification(s) */
     1131        case VIRTIOSCSI_T_AN_SUBSCRIBE: /** Guest SCSI driver is subscribing to async event notification(s) */
    10331132        {
    10341133            PVIRTIOSCSI_CTRL_AN_T pScsiCtrlAnSubscribe = (PVIRTIOSCSI_CTRL_AN_T)pScsiCtrl;
    1035             LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, type: %s\n",
    1036                 QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uLUN,
    1037                 CBQUEUENAME(qIdx) + 30, "", virtioGetControlAsyncTypeText(pScsiCtrlAnSubscribe->uEventRequested)));
    1038 
    1039             uEvtActual &= pScsiCtrlAnSubscribe->uEventRequested;
    1040             pThis->uAsyncEvtsEnabled = uEvtActual;
     1134
     1135            if (pScsiCtrlAnSubscribe->uEventsRequested & ~SUBSCRIBABLE_EVENTS)
     1136                Log(("Unsupported bits in event subscription event mask: 0x%x\n", pScsiCtrlAnSubscribe->uEventsRequested));
     1137
     1138            char szTypeText[128];
     1139            virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->uEventsRequested);
     1140
     1141            LogFunc(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, types: %s\n",
     1142                QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText));
     1143
     1144            uSubscribedEvents &= pScsiCtrlAnSubscribe->uEventsRequested;
     1145            pThis->uAsyncEvtsEnabled = uSubscribedEvents;
    10411146
    10421147            /**
    10431148             * TBD: Verify correct status code if request mask is only partially fulfillable
    10441149             *      and confirm when to use 'complete' vs. 'succeeded' See VirtIO 1.0 spec section 5.6.6.2 and read SAM docs*/
    1045             if (uEvtActual == pScsiCtrlAnSubscribe->uEventRequested)
     1150            if (uSubscribedEvents == pScsiCtrlAnSubscribe->uEventsRequested)
    10461151                uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED;
    10471152            else
    10481153                uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE;
    10491154
    1050             RTSGSEG aReqSegs[] = { { &uEvtActual, sizeof(uEvtActual) },  { &uResponse, sizeof(uResponse)  } };
     1155            RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) },  { &uResponse, sizeof(uResponse)  } };
    10511156            RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG));
    10521157
     
    11011206        if (virtioQueueIsEmpty(pThis->hVirtio, qIdx))
    11021207        {
    1103 
    11041208            /** Interlocks avoid missing alarm while going to sleep & notifier doesn't wake the awoken */
    11051209            ASMAtomicWriteBool(&pWorker->fSleeping, true);
     
    11311235        else
    11321236            virtioScsiSubmitReq(pThis, qIdx, pInSgBuf, pOutSgBuf);
    1133 
    1134 
    11351237    }
    11361238    return VINF_SUCCESS;
     1239}
     1240
     1241
     1242/*static void virtioScsiEventToClient(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1243{ } */
     1244
     1245
     1246/**
     1247 * Implementation invokes this to reset the VirtIO device
     1248 */
     1249static void virtioScsiDeviceReset(PVIRTIOSCSI pThis)
     1250{
     1251    pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
     1252    pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT;
     1253    virtioResetAll(pThis->hVirtio);
     1254}
     1255
     1256static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
     1257                                    const void *pv, size_t cb, uint8_t fWrite)
     1258{
     1259    int rc = VINF_SUCCESS;
     1260    if (MATCH_SCSI_CONFIG(uNumQueues))
     1261    {
     1262        SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
     1263    }
     1264    else
     1265    if (MATCH_SCSI_CONFIG(uSegMax))
     1266    {
     1267        SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
     1268    }
     1269    else
     1270    if (MATCH_SCSI_CONFIG(uMaxSectors))
     1271    {
     1272        SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
     1273    }
     1274    else
     1275    if (MATCH_SCSI_CONFIG(uCmdPerLun))
     1276    {
     1277        SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
     1278    }
     1279    else
     1280    if (MATCH_SCSI_CONFIG(uEventInfoSize))
     1281    {
     1282        SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
     1283    }
     1284    else
     1285    if (MATCH_SCSI_CONFIG(uSenseSize))
     1286    {
     1287        SCSI_CONFIG_ACCESSOR(uSenseSize);
     1288    }
     1289    else
     1290    if (MATCH_SCSI_CONFIG(uCdbSize))
     1291    {
     1292        SCSI_CONFIG_ACCESSOR(uCdbSize);
     1293    }
     1294    else
     1295    if (MATCH_SCSI_CONFIG(uMaxChannel))
     1296    {
     1297        SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
     1298    }
     1299    else
     1300    if (MATCH_SCSI_CONFIG(uMaxTarget))
     1301    {
     1302        SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
     1303    }
     1304    else
     1305    if (MATCH_SCSI_CONFIG(uMaxLun))
     1306    {
     1307        SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
     1308    }
     1309    else
     1310    {
     1311        LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
     1312        rc = VERR_ACCESS_DENIED;
     1313    }
     1314    return rc;
     1315}
     1316
     1317
     1318
     1319/**
     1320 * virtio-scsi VirtIO Device-specific capabilities read callback
     1321 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     1322 *
     1323 * @param   pDevIns     The device instance.
     1324 * @param   uOffset     Offset within device specific capabilities struct
     1325 * @param   pv          Buffer in which to save read data
     1326 * @param   cb          Number of bytes to read
     1327 */
     1328static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     1329{
     1330    int rc = VINF_SUCCESS;
     1331    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1332
     1333    rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, false);
     1334
     1335    return rc;
     1336}
     1337
     1338/**
     1339 * virtio-scsi VirtIO Device-specific capabilities read callback
     1340 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     1341 *
     1342 * @param   pDevIns     The device instance.
     1343 * @param   uOffset     Offset within device specific capabilities struct
     1344 * @param   pv          Buffer in which to save read data
     1345 * @param   cb          Number of bytes to write
     1346 */
     1347static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
     1348{
     1349    int rc = VINF_SUCCESS;
     1350    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     1351
     1352    rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, true);
     1353
     1354    return rc;
     1355}
     1356
     1357DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)
     1358{
     1359    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);
     1360}
     1361
     1362DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)
     1363{
     1364    if (pThis->fHasHotplug)
     1365        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1366                VIRTIOSCSI_EVT_RESET_REMOVED);
     1367}
     1368
     1369DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)
     1370{
     1371    if (pThis->fHasHotplug)
     1372        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1373                VIRTIOSCSI_EVT_RESET_RESCAN);
     1374}
     1375
     1376DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)
     1377{
     1378    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,
     1379            VIRTIOSCSI_EVT_RESET_HARD);
     1380}
     1381
     1382DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1383{
     1384    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)
     1385        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1386                VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);
     1387}
     1388
     1389DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)
     1390{
     1391    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)
     1392        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1393                VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);
     1394}
     1395
     1396DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)
     1397{
     1398    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)
     1399        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1400                VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);
     1401}
     1402
     1403DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)
     1404{
     1405    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)
     1406        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1407                VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);
     1408}
     1409
     1410DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)
     1411{
     1412    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)
     1413        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1414                VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);
     1415}
     1416
     1417DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)
     1418{
     1419    if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)
     1420        virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,
     1421                VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);
     1422}
     1423
     1424
     1425DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)
     1426{
     1427    uint32_t uReason = uSenseQualifier << 8 | uSenseCode;
     1428    virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);
     1429
    11371430}
    11381431
     
    11451438    PWORKER pWorker = &pThis->aWorker[qIdx];
    11461439
    1147     LogFunc(("%s has available data\n", QUEUENAME(qIdx)));
     1440
    11481441    RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));
    11491442
    11501443    if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))
    11511444    {
     1445        LogFunc(("%s has available data\n", QUEUENAME(qIdx)));
    11521446        /** Wake queue's worker thread up if sleeping */
    11531447        if (!ASMAtomicXchgBool(&pWorker->fNotified, true))
     
    11611455        }
    11621456    }
     1457    else if (qIdx == EVENTQ_IDX)
     1458    {
     1459        LogFunc(("Driver queued buffer(s) to %s\n"));
     1460        if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))
     1461            virtioScsiReportEventsMissed(pThis, 0);
     1462    }
    11631463    else
    11641464        LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));
     
    11881488}
    11891489
    1190 /*static void virtioScsiEventToClient(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    1191 { } */
    1192 
    1193 
    1194 /**
    1195  * Implementation invokes this to reset the VirtIO device
    1196  */
    1197 static void virtioScsiDeviceReset(PVIRTIOSCSI pThis)
    1198 {
    1199     pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT;
    1200     pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT;
    1201     virtioResetAll(pThis->hVirtio);
    1202 }
    1203 
    1204 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset,
    1205                                     const void *pv, size_t cb, uint8_t fWrite)
    1206 {
    1207     int rc = VINF_SUCCESS;
    1208     if (MATCH_SCSI_CONFIG(uNumQueues))
    1209     {
    1210         SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);
    1211     }
    1212     else
    1213     if (MATCH_SCSI_CONFIG(uSegMax))
    1214     {
    1215         SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
    1216     }
    1217     else
    1218     if (MATCH_SCSI_CONFIG(uMaxSectors))
    1219     {
    1220         SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
    1221     }
    1222     else
    1223     if (MATCH_SCSI_CONFIG(uCmdPerLun))
    1224     {
    1225         SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
    1226     }
    1227     else
    1228     if (MATCH_SCSI_CONFIG(uEventInfoSize))
    1229     {
    1230         SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
    1231     }
    1232     else
    1233     if (MATCH_SCSI_CONFIG(uSenseSize))
    1234     {
    1235         SCSI_CONFIG_ACCESSOR(uSenseSize);
    1236     }
    1237     else
    1238     if (MATCH_SCSI_CONFIG(uCdbSize))
    1239     {
    1240         SCSI_CONFIG_ACCESSOR(uCdbSize);
    1241     }
    1242     else
    1243     if (MATCH_SCSI_CONFIG(uMaxChannel))
    1244     {
    1245         SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
    1246     }
    1247     else
    1248     if (MATCH_SCSI_CONFIG(uMaxTarget))
    1249     {
    1250         SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
    1251     }
    1252     else
    1253     if (MATCH_SCSI_CONFIG(uMaxLun))
    1254     {
    1255         SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
    1256     }
    1257     else
    1258     {
    1259         LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));
    1260         rc = VERR_ACCESS_DENIED;
    1261     }
    1262     return rc;
    1263 }
    1264 
    1265 
    1266 
    1267 /**
    1268  * virtio-scsi VirtIO Device-specific capabilities read callback
    1269  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    1270  *
    1271  * @param   pDevIns     The device instance.
    1272  * @param   uOffset     Offset within device specific capabilities struct
    1273  * @param   pv          Buffer in which to save read data
    1274  * @param   cb          Number of bytes to read
    1275  */
    1276 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    1277 {
    1278     int rc = VINF_SUCCESS;
    1279     PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1280 
    1281 //    LogFunc(("Read from Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
    1282 //              uOffset, cb));
    1283 
    1284     rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, false);
    1285 
    1286     return rc;
    1287 }
    1288 
    1289 /**
    1290  * virtio-scsi VirtIO Device-specific capabilities read callback
    1291  * (other VirtIO capabilities and features are handled in VirtIO implementation)
    1292  *
    1293  * @param   pDevIns     The device instance.
    1294  * @param   uOffset     Offset within device specific capabilities struct
    1295  * @param   pv          Buffer in which to save read data
    1296  * @param   cb          Number of bytes to write
    1297  */
    1298 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)
    1299 {
    1300     int rc = VINF_SUCCESS;
    1301     PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    1302 
    1303 //    LogFunc(("Write to Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",
    1304 //              uOffset, cb));
    1305 
    1306     rc = virtioScsiR3CfgAccessed(pThis, uOffset, pv, cb, true);
    1307 
    1308     return rc;
    1309 }
    1310 
    1311 
    13121490/**
    13131491 * Turns on/off the write status LED.
     
    13701548    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    13711549    PVIRTIOSCSI pThis = pTarget->CTX_SUFF(pVirtioScsi);
    1372 
     1550    LogFunc(("LUN %d Ejected!\n", pTarget->iLUN));
    13731551    if (pThis->pMediaNotify)
    13741552        virtioScsiSetWriteLed(pTarget, false);
     
    14291607{
    14301608    RT_NOREF(pDevIns);
    1431     /** TBD cancel outstanding I/O */
     1609    Log(("\n"));
     1610
    14321611    return true;
    14331612}
     
    14471626          if (pTarget->cReqsInProgress != 0)
    14481627          {
    1449               fIoInProgress = true;;
     1628              fIoInProgress = true;
    14501629              break;
    14511630          }
     
    19132092        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
    19142093        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
    1915         pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL;
     2094        pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL; /* When used avoids copyFromBuf CopyToBuf*/
    19162095        pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
     2096
     2097
    19172098        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
    19182099        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3TargetQueryStatusLed;
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r80437 r80499  
    11/* $Id$ */
    22/** @file
    3  * Virtio_1_0 - Virtio Common Functions (VirtQ, virtqueue, Virtio PCI)
     3 * Virtio_1_0 - Virtio Common (PCI, feature & config mgt, queue mgt & proxy, notification mgt)
    44 */
    55
     
    259259    RTSgBufInit(&pVirtqProxy->outSgBuf,(PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut);
    260260
    261     *ppInSegs  = &pVirtqProxy->inSgBuf;
    262     *ppOutSegs = &pVirtqProxy->outSgBuf;
     261    if (ppInSegs)
     262        *ppInSegs  = &pVirtqProxy->inSgBuf;
     263    if (ppOutSegs)
     264        *ppOutSegs = &pVirtqProxy->outSgBuf;
    263265
    264266    Log2Func(("%s -- segs out: %u,  segs in: %u --\n",
     
    362364    Log2Func(("%s\n", pVirtqProxy->szVirtqName));
    363365
     366
    364367    /** Inform client */
    365368    pVirtio->virtioCallbacks.pfnVirtioQueueNotified((VIRTIOHANDLE)pVirtio, pVirtio->pClientContext, qIdx);
     
    472475    pVirtQ->uAvailIdx = 0;
    473476    pVirtQ->uUsedIdx  = 0;
     477    pVirtio->uQueueEnable[qIdx] = false;
    474478    pVirtio->uQueueSize[qIdx] = VIRTQ_MAX_SIZE;
    475479    pVirtio->uQueueNotifyOff[qIdx] = qIdx;
    476480}
     481
    477482
    478483static void virtioResetDevice(PVIRTIOSTATE pVirtio)
     
    519524static void virtioGuestResetted(PVIRTIOSTATE pVirtio)
    520525{
    521     LogFunc(("Guest reset the device"));
     526    LogFunc(("Guest reset the device\n"));
    522527
    523528    /** Let the client know */
     
    770775    {
    771776        *(uint8_t *)pv = pVirtio->uISR;
    772         Log2Func(("Read and clear 0x%02x from uISR (interrupt type: virtq: %d, dev config: %d)\n",
    773               pVirtio->uISR, pVirtio->uISR & VIRTIO_ISR_VIRTQ_INTERRUPT,
    774               !!(pVirtio->uISR & VIRTIO_ISR_DEVICE_CONFIG)));
     777        Log2Func(("Read and clear ISR\n"));
    775778        pVirtio->uISR = 0; /** VirtIO specification requires reads of ISR to clear it */
    776779        virtioLowerInterrupt(pVirtio);
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r80437 r80499  
    215215 * @param pSgBuf    - Caller's sgbuf of one or more virtual memory segments
    216216 *                    to write to the queue. This is useful because some kinds
    217  *                    of transactions involve variable length sub-components
     217 *                    of transactions involve variable length subcomponents
    218218 *                    whose size can only be known near the time of writing.
    219219 * @parame fFence   - If set put up copy fence (memory barrier) after
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h

    r80437 r80499  
    4040#define VIRTIO_F_RING_EVENT_IDX             RT_BIT_64(29)        /**< Doc bug: Goes under two names in spec     */
    4141
    42 #define VIRTIO_DEV_INDEPENDENT_FEATURES_OFFERED ( VIRTIO_F_EVENT_IDX ) /**< TBD: Add VIRTIO_F_INDIRECT_DESC     */
     42#define VIRTIO_DEV_INDEPENDENT_FEATURES_OFFERED ( 0 )            /**< TBD: Add VIRTIO_F_INDIRECT_DESC     */
    4343
    4444#define VIRTIO_ISR_VIRTQ_INTERRUPT           RT_BIT_32(0)        /**< Virtq interrupt bit of ISR register       */
     
    364364static void        virtioWriteUsedAvailEvent  (PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uAvailEventIdx);
    365365
     366
    366367DECLINLINE(int) virtqIsEventNeeded(uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld)
    367368{
     
    504505                          &uAvailEventIdx, sizeof(uAvailEventIdx));
    505506}
     507
    506508
    507509/**
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