Changeset 80499 in vbox
- Timestamp:
- Aug 29, 2019 2:47:17 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132993
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80437 r80499 271 271 272 272 #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 */ 274 274 275 275 #pragma pack(1) … … 279 279 uint32_t uType; /** type */ 280 280 uint8_t uLUN[8]; /** lun */ 281 uint32_t uEvent Requested; /** event_requested */281 uint32_t uEventsRequested; /** event_requested */ 282 282 // Device-writable part 283 283 uint32_t uEventActual; /** event_actual */ … … 297 297 /** @} */ 298 298 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 299 306 300 307 /** … … 346 353 /** Status LED interface */ 347 354 PDMILEDPORTS ILed; 355 348 356 /** The status LED state for this device. */ 349 357 PDMLED led; … … 422 430 bool volatile fSignalIdle; 423 431 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 */ 424 439 VIRTIOSCSI_CONFIG_T virtioScsiConfig; 440 441 /** True if the guest/driver and VirtIO framework are in the ready state */ 425 442 bool fVirtioReady; 443 444 /** True if VIRTIO_SCSI_F_T10_PI was negotiated */ 426 445 bool fHasT10pi; 446 447 /** True if VIRTIO_SCSI_F_T10_PI was negotiated */ 427 448 bool fHasHotplug; 449 450 /** True if VIRTIO_SCSI_F_T10_PI was negotiated */ 428 451 bool fHasInOutBufs; 452 453 /** True if VIRTIO_SCSI_F_T10_PI was negotiated */ 429 454 bool fHasLunChange; 430 455 431 432 433 456 } VIRTIOSCSI, *PVIRTIOSCSI; 434 435 457 436 458 /** … … 444 466 size_t cbPiOut; /**< Size of T10 pi in buffer */ 445 467 uint8_t *pbPiOut; /**< Address of pi out buffer */ 446 uint8_t *pbDataOut; /**< data in*/468 uint8_t *pbDataOut; /**< dataout */ 447 469 size_t cbPiIn; /**< Size of T10 pi buffer */ 448 470 uint8_t *pbPiIn; /**< Address of pi in buffer */ … … 455 477 } VIRTIOSCSIREQ; 456 478 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 457 484 DECLINLINE(const char *) virtioGetTMFTypeText(uint32_t uSubType) 458 485 { … … 471 498 } 472 499 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 } 500 DECLINLINE(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 " : ""); 485 509 } 486 510 … … 535 559 return VIRTIOSCSI_S_BAD_TARGET; 536 560 537 case VERR_RESOURCE_BUSY: /** TBD */561 case VERR_RESOURCE_BUSY: 538 562 return VIRTIOSCSI_S_BUSY; 539 563 540 case VERR_STATE_CHANGED: /** TBD */564 case VERR_STATE_CHANGED: 541 565 return VIRTIOSCSI_S_RESET; 542 566 543 case VERR_CANCELLED: /** TBD */567 case VERR_CANCELLED: 544 568 return VIRTIOSCSI_S_ABORTED; 545 569 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: 547 577 return VIRTIOSCSI_S_NEXUS_FAILURE; 548 578 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: 553 580 return VIRTIOSCSI_S_FAILURE; 554 581 } 555 582 return VIRTIOSCSI_S_FAILURE; 556 583 } 557 558 584 559 585 /** … … 599 625 } \ 600 626 } 627 628 601 629 602 630 typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ; … … 660 688 size_t cbCopy) 661 689 { 662 // LogFunc(("\n"));663 664 690 RT_NOREF(hIoReq); 665 691 RT_NOREF(pInterface); … … 681 707 size_t cbCopy) 682 708 { 683 // LogFunc(("\n"));684 685 709 RT_NOREF(hIoReq); 686 710 RT_NOREF(pInterface); … … 694 718 } 695 719 696 720 static 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 787 static 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 } 697 803 698 804 static int virtioScsiR3ReqComplete(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq) 699 805 { 700 701 806 PVIRTIOSCSITARGET pTarget = pReq->pTarget; 702 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 703 uint8_t uResponse = virtioScsiMapVerrToVirtio((uint32_t)rcReq); 704 807 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 705 808 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)); 774 856 } 775 857 … … 784 866 VERR_BUFFER_OVERFLOW); 785 867 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 */); 787 873 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 788 874 … … 790 876 RTMemFree(pReq->pbDataIn); 791 877 792 if (pReq) 793 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); 878 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); 794 879 795 880 if (pTarget->cReqsInProgress == 0 && pThis->fSignalIdle) … … 799 884 } 800 885 801 802 886 /** 803 887 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} … … 806 890 void *pvIoReqAlloc, int rcReq) 807 891 { 808 // LogFunc(("\n"));809 892 RT_NOREF(hIoReq); 810 893 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); … … 817 900 RT_NOREF(pInSgBuf); 818 901 RT_NOREF(qIdx); 902 819 903 AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_NOT_IMPLEMENTED); 820 904 … … 849 933 uint8_t *pbCdb = pVirtqReq->uCdb; 850 934 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" 852 939 " 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); 855 944 856 945 off_t uPiOutOff = 0; … … 882 971 LogFunc(("pi_out[]: %.*Rhxs\n", cbPiOut, pVirtqReq->uPiOut)); 883 972 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 892 973 PDMMEDIAEXIOREQ hIoReq = NULL; 893 974 PVIRTIOSCSIREQ pReq; … … 895 976 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 896 977 897 size_t cbDataIn = cbIn - (cbRespHdr + cbSense ); /** tbd: cbPiIn */978 size_t cbDataIn = cbIn - (cbRespHdr + cbSense + cbPiIn); 898 979 899 980 if (RT_LIKELY(pTarget->fPresent)) 900 981 { 901 int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* u Tag*/,982 int rc = pIMediaEx->pfnIoReqAlloc(pIMediaEx, &hIoReq, (void **)&pReq, 0 /* uIoReqId */, 902 983 PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 903 984 … … 913 994 pReq->pbDataOut = pbDataOut; 914 995 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 } 918 1001 pReq->cbDataIn = cbDataIn; 919 1002 pReq->pbDataIn = (uint8_t *)RTMemAllocZ(cbDataIn); … … 932 1015 933 1016 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); 935 1020 } 936 1021 … … 954 1039 AssertMsgReturn(pScsiCtrl, ("Out of memory"), VERR_NO_MEMORY); 955 1040 1041 /** 1042 * Get control command into virtual memory 1043 */ 956 1044 off_t cbOff = 0; 957 1045 size_t cbSeg = 0; … … 970 1058 * See VirtIO 1.0 specification section 5.6.6.2 971 1059 */ 972 uint32_t uEvtActual = VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 1060 uint32_t uSubscribedEvents = 1061 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT 973 1062 | VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST 974 1063 | VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE … … 979 1068 switch(pScsiCtrl->uType) 980 1069 { 981 case VIRTIOSCSI_T_TMF: /* * Guest SCSI driver has invoked a SCSI Task Management Function*/1070 case VIRTIOSCSI_T_TMF: /* Task Management Functions */ 982 1071 { 983 1072 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", 985 1074 QUEUENAME(qIdx), pScsiCtrlTmf->uLUN, 986 1075 CBQUEUENAME(qIdx) + 18, "", virtioGetTMFTypeText(pScsiCtrlTmf->uSubtype))); … … 992 1081 break; 993 1082 case VIRTIOSCSI_T_TMF_ABORT_TASK_SET: 1083 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 994 1084 break; 995 1085 case VIRTIOSCSI_T_TMF_CLEAR_ACA: 1086 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 996 1087 break; 997 1088 case VIRTIOSCSI_T_TMF_CLEAR_TASK_SET: 1089 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 998 1090 break; 999 1091 case VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET: 1092 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1000 1093 break; 1001 1094 case VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET: 1095 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1002 1096 break; 1003 1097 case VIRTIOSCSI_T_TMF_QUERY_TASK: 1098 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1004 1099 break; 1005 1100 case VIRTIOSCSI_T_TMF_QUERY_TASK_SET: 1101 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1006 1102 break; 1007 1103 default: … … 1015 1111 break; 1016 1112 } 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 */ 1018 1114 { 1019 1115 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; 1025 1124 uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE; 1026 1125 1027 RTSGSEG aReqSegs[] = { { &u EvtActual, sizeof(uEvtActual) }, { &uResponse, sizeof(uResponse) } };1126 RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) }, { &uResponse, sizeof(uResponse) } }; 1028 1127 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG)); 1029 1128 1030 1129 break; 1031 1130 } 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) */ 1033 1132 { 1034 1133 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; 1041 1146 1042 1147 /** 1043 1148 * TBD: Verify correct status code if request mask is only partially fulfillable 1044 1149 * and confirm when to use 'complete' vs. 'succeeded' See VirtIO 1.0 spec section 5.6.6.2 and read SAM docs*/ 1045 if (u EvtActual == pScsiCtrlAnSubscribe->uEventRequested)1150 if (uSubscribedEvents == pScsiCtrlAnSubscribe->uEventsRequested) 1046 1151 uResponse = VIRTIOSCSI_S_FUNCTION_SUCCEEDED; 1047 1152 else 1048 1153 uResponse = VIRTIOSCSI_S_FUNCTION_COMPLETE; 1049 1154 1050 RTSGSEG aReqSegs[] = { { &u EvtActual, sizeof(uEvtActual) }, { &uResponse, sizeof(uResponse) } };1155 RTSGSEG aReqSegs[] = { { &uSubscribedEvents, sizeof(uSubscribedEvents) }, { &uResponse, sizeof(uResponse) } }; 1051 1156 RTSgBufInit(&reqSegBuf, aReqSegs, sizeof(aReqSegs) / sizeof(RTSGSEG)); 1052 1157 … … 1101 1206 if (virtioQueueIsEmpty(pThis->hVirtio, qIdx)) 1102 1207 { 1103 1104 1208 /** Interlocks avoid missing alarm while going to sleep & notifier doesn't wake the awoken */ 1105 1209 ASMAtomicWriteBool(&pWorker->fSleeping, true); … … 1131 1235 else 1132 1236 virtioScsiSubmitReq(pThis, qIdx, pInSgBuf, pOutSgBuf); 1133 1134 1135 1237 } 1136 1238 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 */ 1249 static 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 1256 static 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 */ 1328 static 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 */ 1347 static 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 1357 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget) 1358 { 1359 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0); 1360 } 1361 1362 DECLINLINE(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 1369 DECLINLINE(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 1376 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget) 1377 { 1378 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1379 VIRTIOSCSI_EVT_RESET_HARD); 1380 } 1381 1382 DECLINLINE(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 1389 DECLINLINE(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 1396 DECLINLINE(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 1403 DECLINLINE(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 1410 DECLINLINE(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 1417 DECLINLINE(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 1425 DECLINLINE(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 1137 1430 } 1138 1431 … … 1145 1438 PWORKER pWorker = &pThis->aWorker[qIdx]; 1146 1439 1147 LogFunc(("%s has available data\n", QUEUENAME(qIdx))); 1440 1148 1441 RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX))); 1149 1442 1150 1443 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx)) 1151 1444 { 1445 LogFunc(("%s has available data\n", QUEUENAME(qIdx))); 1152 1446 /** Wake queue's worker thread up if sleeping */ 1153 1447 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) … … 1161 1455 } 1162 1456 } 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 } 1163 1463 else 1164 1464 LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx)); … … 1188 1488 } 1189 1489 1190 /*static void virtioScsiEventToClient(PPDMDEVINS pDevIns, PPDMTHREAD pThread)1191 { } */1192 1193 1194 /**1195 * Implementation invokes this to reset the VirtIO device1196 */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 else1213 if (MATCH_SCSI_CONFIG(uSegMax))1214 {1215 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);1216 }1217 else1218 if (MATCH_SCSI_CONFIG(uMaxSectors))1219 {1220 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);1221 }1222 else1223 if (MATCH_SCSI_CONFIG(uCmdPerLun))1224 {1225 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);1226 }1227 else1228 if (MATCH_SCSI_CONFIG(uEventInfoSize))1229 {1230 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);1231 }1232 else1233 if (MATCH_SCSI_CONFIG(uSenseSize))1234 {1235 SCSI_CONFIG_ACCESSOR(uSenseSize);1236 }1237 else1238 if (MATCH_SCSI_CONFIG(uCdbSize))1239 {1240 SCSI_CONFIG_ACCESSOR(uCdbSize);1241 }1242 else1243 if (MATCH_SCSI_CONFIG(uMaxChannel))1244 {1245 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);1246 }1247 else1248 if (MATCH_SCSI_CONFIG(uMaxTarget))1249 {1250 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);1251 }1252 else1253 if (MATCH_SCSI_CONFIG(uMaxLun))1254 {1255 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);1256 }1257 else1258 {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 callback1269 * (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 struct1273 * @param pv Buffer in which to save read data1274 * @param cb Number of bytes to read1275 */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 callback1291 * (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 struct1295 * @param pv Buffer in which to save read data1296 * @param cb Number of bytes to write1297 */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 1312 1490 /** 1313 1491 * Turns on/off the write status LED. … … 1370 1548 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 1371 1549 PVIRTIOSCSI pThis = pTarget->CTX_SUFF(pVirtioScsi); 1372 1550 LogFunc(("LUN %d Ejected!\n", pTarget->iLUN)); 1373 1551 if (pThis->pMediaNotify) 1374 1552 virtioScsiSetWriteLed(pTarget, false); … … 1429 1607 { 1430 1608 RT_NOREF(pDevIns); 1431 /** TBD cancel outstanding I/O */ 1609 Log(("\n")); 1610 1432 1611 return true; 1433 1612 } … … 1447 1626 if (pTarget->cReqsInProgress != 0) 1448 1627 { 1449 fIoInProgress = true; ;1628 fIoInProgress = true; 1450 1629 break; 1451 1630 } … … 1913 2092 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsiR3IoReqStateChanged; 1914 2093 pTarget->IMediaExPort.pfnMediumEjected = virtioScsiR3MediumEjected; 1915 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL; 2094 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL; /* When used avoids copyFromBuf CopyToBuf*/ 1916 2095 pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 2096 2097 1917 2098 pTarget->IBase.pfnQueryInterface = virtioScsiR3TargetQueryInterface; 1918 2099 pTarget->ILed.pfnQueryStatusLed = virtioScsiR3TargetQueryStatusLed; -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80437 r80499 1 1 /* $Id$ */ 2 2 /** @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) 4 4 */ 5 5 … … 259 259 RTSgBufInit(&pVirtqProxy->outSgBuf,(PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut); 260 260 261 *ppInSegs = &pVirtqProxy->inSgBuf; 262 *ppOutSegs = &pVirtqProxy->outSgBuf; 261 if (ppInSegs) 262 *ppInSegs = &pVirtqProxy->inSgBuf; 263 if (ppOutSegs) 264 *ppOutSegs = &pVirtqProxy->outSgBuf; 263 265 264 266 Log2Func(("%s -- segs out: %u, segs in: %u --\n", … … 362 364 Log2Func(("%s\n", pVirtqProxy->szVirtqName)); 363 365 366 364 367 /** Inform client */ 365 368 pVirtio->virtioCallbacks.pfnVirtioQueueNotified((VIRTIOHANDLE)pVirtio, pVirtio->pClientContext, qIdx); … … 472 475 pVirtQ->uAvailIdx = 0; 473 476 pVirtQ->uUsedIdx = 0; 477 pVirtio->uQueueEnable[qIdx] = false; 474 478 pVirtio->uQueueSize[qIdx] = VIRTQ_MAX_SIZE; 475 479 pVirtio->uQueueNotifyOff[qIdx] = qIdx; 476 480 } 481 477 482 478 483 static void virtioResetDevice(PVIRTIOSTATE pVirtio) … … 519 524 static void virtioGuestResetted(PVIRTIOSTATE pVirtio) 520 525 { 521 LogFunc(("Guest reset the device "));526 LogFunc(("Guest reset the device\n")); 522 527 523 528 /** Let the client know */ … … 770 775 { 771 776 *(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")); 775 778 pVirtio->uISR = 0; /** VirtIO specification requires reads of ISR to clear it */ 776 779 virtioLowerInterrupt(pVirtio); -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r80437 r80499 215 215 * @param pSgBuf - Caller's sgbuf of one or more virtual memory segments 216 216 * to write to the queue. This is useful because some kinds 217 * of transactions involve variable length sub -components217 * of transactions involve variable length subcomponents 218 218 * whose size can only be known near the time of writing. 219 219 * @parame fFence - If set put up copy fence (memory barrier) after -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r80437 r80499 40 40 #define VIRTIO_F_RING_EVENT_IDX RT_BIT_64(29) /**< Doc bug: Goes under two names in spec */ 41 41 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 */ 43 43 44 44 #define VIRTIO_ISR_VIRTQ_INTERRUPT RT_BIT_32(0) /**< Virtq interrupt bit of ISR register */ … … 364 364 static void virtioWriteUsedAvailEvent (PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uAvailEventIdx); 365 365 366 366 367 DECLINLINE(int) virtqIsEventNeeded(uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld) 367 368 { … … 504 505 &uAvailEventIdx, sizeof(uAvailEventIdx)); 505 506 } 507 506 508 507 509 /**
Note:
See TracChangeset
for help on using the changeset viewer.