- Timestamp:
- Sep 1, 2019 4:28:56 PM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80522 r80527 179 179 struct REQ_RESP_HDR 180 180 { 181 uint32_t uSenseLen;/**< sense_len */181 uint32_t cbSense; /**< sense_len */ 182 182 uint32_t uResidual; /**< residual */ 183 183 uint16_t uStatusQualifier; /**< status_qualifier */ … … 620 620 return cbMax; 621 621 } 622 DECLINLINE(uint8_t) virtioScsiMapVerrToVirtio(uint32_t vboxRc)623 {624 switch(vboxRc)625 {626 case VINF_SUCCESS:627 return VIRTIOSCSI_S_OK;628 629 case VERR_PDM_MEDIAEX_IOBUF_OVERFLOW:630 return VIRTIOSCSI_S_OVERRUN;631 632 case VERR_PDM_MEDIAEX_IOBUF_UNDERRUN:633 return VIRTIOSCSI_S_TRANSPORT_FAILURE;634 635 case VERR_IO_BAD_UNIT:636 return VIRTIOSCSI_S_BAD_TARGET;637 638 case VERR_RESOURCE_BUSY:639 return VIRTIOSCSI_S_BUSY;640 641 case VERR_STATE_CHANGED:642 return VIRTIOSCSI_S_RESET;643 644 case VERR_CANCELLED:645 return VIRTIOSCSI_S_ABORTED;646 647 case VERR_IO_NOT_READY:648 return VIRTIOSCSI_S_TARGET_FAILURE;649 650 case VERR_DEV_IO_ERROR:651 return VIRTIOSCSI_S_TRANSPORT_FAILURE;652 653 case VERR_NOT_SUPPORTED:654 return VIRTIOSCSI_S_NEXUS_FAILURE;655 656 case VERR_IO_GEN_FAILURE:657 return VIRTIOSCSI_S_FAILURE;658 }659 return VIRTIOSCSI_S_FAILURE;660 }661 622 662 623 /** … … 772 733 /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */ 773 734 memcpy(pReq->pbDataIn + offDst, pSgBuf->paSegs[0].pvSeg, cbCopy); 774 775 735 return VINF_SUCCESS; 776 736 } … … 788 748 789 749 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc; 790 791 750 /** DrvSCSI.cpp, that issues this callback, just sticks one segment in the buffer */ 792 751 memcpy(pSgBuf->paSegs[0].pvSeg, pReq->pbDataOut + offSrc, cbCopy); … … 862 821 } 863 822 864 /**865 * This is called to complete a request buffer immediately866 *867 * @param pThis - PDM driver instance state868 * @param qIdx - Queue index869 * @param rcReq - VirtualBox code to map to VirtIO response code.870 *871 * @returns virtual box status code872 */873 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, uint32_t rcReq)874 {875 struct REQ_RESP_HDR respHdr;876 respHdr.uSenseLen = 0;877 respHdr.uResidual = 0;878 respHdr.uStatusQualifier = 0; /** TBD. Seems to be for iSCSI. Can't find any real info */879 respHdr.uStatus = 0;880 respHdr.uResponse = virtioScsiMapVerrToVirtio(rcReq);881 RTSGBUF reqSegBuf;882 RTSGSEG aReqSegs[] = { { &respHdr, sizeof(respHdr) } };883 RTSgBufInit(&reqSegBuf, aReqSegs, 1);884 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */);885 virtioQueueSync(pThis->hVirtio, qIdx);886 LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr.uResponse)));887 Log(("---------------------------------------------------------------------------------\n"));888 return VINF_SUCCESS;889 }890 891 823 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq) 892 824 { … … 907 839 908 840 struct REQ_RESP_HDR respHdr; 909 respHdr. uSenseLen= pReq->cbSense;841 respHdr.cbSense = pReq->cbSense; 910 842 respHdr.uResidual = cbResidual; 911 respHdr.uStatusQualifier = 0; /** TBD. Seems to be iSCSI specific. Can't find any real info */ 912 respHdr.uStatus = pReq->uStatus; 913 respHdr.uResponse = virtioScsiMapVerrToVirtio(rcReq); 914 843 respHdr.uStatus = pReq->uStatus; 844 respHdr.uResponse = rcReq; 845 respHdr.uStatusQualifier = 0; 915 846 916 847 LogFunc(("Status: %s (0x%x%x) Response: %s (0x%x%x)\n", … … 920 851 if (pReq->cbSense) 921 852 { 853 pReq->pbSense[12] = 0x25; 854 pReq->pbSense[13] = 0x00; 922 855 Log2Func(("Sense: %s\n", SCSISenseText(pReq->pbSense[2]))); 923 Log2Func(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[1 2])));924 virtioScsiHexDump( 856 Log2Func(("Sense Ext3: %s\n", SCSISenseExtText(pReq->pbSense[12], pReq->pbSense[13]))); 857 virtioScsiHexDump(pReq->pbSense, pReq->cbSense, 0, "\nSense"); 925 858 } 926 859 927 860 if (pReq->cbDataIn) 928 virtioScsiHexDump( 861 virtioScsiHexDump(pReq->pbDataIn, pReq->cbDataIn, 0, "\ndatain"); 929 862 930 863 if (pReq->cbPiIn) 931 virtioScsiHexDump( 864 virtioScsiHexDump(pReq->pbPiIn, pReq->cbPiIn, 0, "\nPi in"); 932 865 933 866 if (cbResidual) … … 976 909 RTMemFree(pReq->pbSense); 977 910 RTMemFree(pReq->pbDataIn); 911 RTMemFree(pReq->pbPiIn); 978 912 979 913 pIMediaEx->pfnIoReqFree(pIMediaEx, pReq->hIoReq); … … 986 920 987 921 /** 988 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 989 */ 990 static DECLCALLBACK(int) virtioScsiR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 991 void *pvIoReqAlloc, int rcReq) 992 { 993 RT_NOREF(hIoReq); 994 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 995 virtioScsiReqFinish(pTarget->CTX_SUFF(pVirtioScsi), (PVIRTIOSCSIREQ)pvIoReqAlloc, rcReq); 922 * This is called to complete a request immediately 923 * 924 * @param pThis - PDM driver instance state 925 * @param qIdx - Queue index 926 * @param respHdr - Response header 927 * @param pbSense - Pointer to sense buffer or NULL if none. 928 * 929 * @returns virtual box status code 930 */ 931 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *respHdr, uint8_t *pbSense) 932 { 933 int cSegs = 0; 934 RTSGSEG aReqSegs[2]; 935 aReqSegs[cSegs].pvSeg = &respHdr; 936 aReqSegs[cSegs++].cbSeg = sizeof(respHdr); 937 if (respHdr->cbSense) 938 { 939 aReqSegs[cSegs].pvSeg = pbSense; 940 aReqSegs[cSegs++].cbSeg = respHdr->cbSense; 941 } 942 RTSGBUF reqSegBuf; 943 RTSgBufInit(&reqSegBuf, aReqSegs, cSegs); 944 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */); 945 virtioQueueSync(pThis->hVirtio, qIdx); 946 LogFunc(("Response code: %s\n", virtioGetReqRespText(respHdr->uResponse))); 947 Log(("---------------------------------------------------------------------------------\n")); 996 948 return VINF_SUCCESS; 997 949 } … … 1011 963 size_t cbRespHdr = sizeof(REQ_RESP_HDR); 1012 964 965 1013 966 AssertMsgReturn(cbOut >= RT_SIZEOFMEMB(VIRTIOSCSI_REQ_CMD_T, cmdHdr), ("Req to short"), VERR_BUFFER_UNDERFLOW); 1014 967 … … 1017 970 cbCdb -= (cbCmdHdr - cbOut); 1018 971 1019 /**1020 * For the time being, assume one descriptor chain has the complete req data to write to device,1021 * and that it's not too much to shove into virtual memory at once1022 */1023 972 PVIRTIOSCSI_REQ_CMD_T pVirtqReq = (PVIRTIOSCSI_REQ_CMD_T)RTMemAllocZ(cbOut); 1024 973 off_t cbOff = 0; … … 1037 986 uint32_t uLUN = (pVirtqReq->cmdHdr.uLUN[2] << 8 | pVirtqReq->cmdHdr.uLUN[3]) & 0x3fff; 1038 987 1039 LogFunc(("[%s] 988 LogFunc(("[%s]%*s (Target: %d LUN: %d) CDB: %.*Rhxs\n", 1040 989 SCSICmdText(pbCdb[0]), uTarget, uLUN, 1041 990 virtioScsiEstimateCdbLen(pbCdb[0], pThis->virtioScsiConfig.uCdbSize), pbCdb)); … … 1044 993 pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn)); 1045 994 1046 if (uTarget >= pThis->cTargets)1047 {1048 virtioScsiReqFinish(pThis, qIdx, VERR_IO_BAD_UNIT);1049 return VINF_SUCCESS;1050 }1051 if (uLUN != 0)1052 {1053 virtioScsiReqFinish(pThis, qIdx, VERR_IO_BAD_UNIT);1054 return VINF_SUCCESS;1055 }1056 995 1057 996 off_t uPiOutOff = 0; … … 1078 1017 1079 1018 if (cbDataOut) 1080 virtioScsiHexDump( 1019 virtioScsiHexDump(pVirtqReq->uDataOut, cbDataOut, 0, "\ndataout"); 1081 1020 1082 1021 … … 1090 1029 1091 1030 size_t cbDataIn = cbIn - (cbRespHdr + cbSense + cbPiIn); 1031 1032 if (uTarget >= pThis->cTargets) 1033 { 1034 struct REQ_RESP_HDR respHdr; 1035 respHdr.cbSense = 0; 1036 respHdr.uResidual = cbDataOut + cbDataIn; 1037 respHdr.uStatus = SCSI_STATUS_OK; 1038 respHdr.uResponse = VIRTIOSCSI_S_BAD_TARGET; 1039 respHdr.uStatusQualifier = 0; 1040 virtioScsiReqFinish(pThis, qIdx, &respHdr, NULL /* pbSense */); 1041 return VINF_SUCCESS; 1042 } 1043 1044 struct REQ_RESP_HDR respHdr = { 0 }; 1045 if (uLUN != 0) 1046 { 1047 /** 1048 * This is needed for the time being to respond with the right error condition and sense data 1049 * at the right time. It doesn't work to send requests to bad luns down to DrvSCSI. It returs 1050 * success for the INQUIRY commands and then starts failing future requests with BAD PARAM errors. 1051 * Unfortunately that's too late for Linux. If it doesn't get the bad lun error at inquiry it 1052 * seems to mishandle the error on future requests and will create 8 devices for the target and 1053 * it gets ugly. */ 1054 1055 uint8_t pbSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 0, SCSI_SENSE_ILLEGAL_REQUEST, 1056 0, 0, 0, 0, 10, SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED, 0, 0 }; 1057 respHdr.cbSense = sizeof(pbSense); 1058 respHdr.uResidual = cbDataIn + cbDataOut; 1059 respHdr.uStatus = SCSI_STATUS_CHECK_CONDITION; 1060 respHdr.uResponse = VIRTIOSCSI_S_OK; 1061 respHdr.uStatusQualifier = 0; 1062 virtioScsiReqFinish(pThis, qIdx, &respHdr, pbSense); 1063 return VINF_SUCCESS; 1064 } 1092 1065 1093 1066 if (RT_LIKELY(pTarget->fPresent)) … … 1136 1109 if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 1137 1110 { 1138 pIMediaEx->pfnIoReqFree(pIMediaEx, hIoReq); 1139 virtioScsiReqFinish(pThis, qIdx, rc); 1111 size_t cbResidual; 1112 pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual); 1113 respHdr.cbSense = 0; 1114 respHdr.uResidual = (uint32_t)cbResidual; 1115 respHdr.uStatus = SCSI_STATUS_OK; 1116 respHdr.uResponse = VIRTIOSCSI_S_OK; 1117 respHdr.uStatusQualifier = 0; 1118 virtioScsiReqFinish(pThis, qIdx, &respHdr, NULL /* pbSense */); 1140 1119 return VINF_SUCCESS; 1141 1120 } 1142 1121 } else { 1143 virtioScsiReqFinish(pThis, qIdx, VERR_IO_NOT_READY); 1122 respHdr.cbSense = 0; 1123 respHdr.uResidual = cbDataOut + cbDataIn; 1124 respHdr.uStatus = SCSI_STATUS_OK; 1125 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 1126 respHdr.uStatusQualifier = 0; 1127 virtioScsiReqFinish(pThis, qIdx, &respHdr, NULL /* pbSense */); 1144 1128 return VINF_SUCCESS; 1145 1129 1146 1130 } 1147 1131 1132 return VINF_SUCCESS; 1133 } 1134 1135 /** 1136 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 1137 */ 1138 static DECLCALLBACK(int) virtioScsiR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1139 void *pvIoReqAlloc, int rcReq) 1140 { 1141 RT_NOREF(hIoReq); 1142 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 1143 virtioScsiReqFinish(pTarget->CTX_SUFF(pVirtioScsi), (PVIRTIOSCSIREQ)pvIoReqAlloc, rcReq); 1148 1144 return VINF_SUCCESS; 1149 1145 } … … 1244 1240 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnQuery->uEventsRequested); 1245 1241 1246 Log 2Func(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, types: %s\n",1242 Log3Func(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Query, types: %s\n", 1247 1243 QUEUENAME(qIdx), pScsiCtrlAnQuery->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText)); 1248 1244 … … 1265 1261 virtioGetControlAsyncMaskText(szTypeText, sizeof(szTypeText), pScsiCtrlAnSubscribe->uEventsRequested); 1266 1262 1267 Log 2Func(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, types: %s\n",1263 Log3Func(("%s, VirtIO LUN: %.8Rhxs\n%*sAsync Subscribe, types: %s\n", 1268 1264 QUEUENAME(qIdx), pScsiCtrlAnSubscribe->uLUN, CBQUEUENAME(qIdx) + 30, "", szTypeText)); 1269 1265 … … 1352 1348 if (rc == VERR_NOT_AVAILABLE) 1353 1349 { 1354 Log 2Func(("Nothing found in %s\n", QUEUENAME(qIdx)));1350 Log3Func(("Nothing found in %s\n", QUEUENAME(qIdx))); 1355 1351 continue; 1356 1352 } … … 1360 1356 virtioScsiCtrl(pThis, qIdx, pInSgBuf, pOutSgBuf); 1361 1357 else 1362 virtioScsiReqSubmit(pThis, qIdx, pInSgBuf, pOutSgBuf); 1358 { 1359 rc = virtioScsiReqSubmit(pThis, qIdx, pInSgBuf, pOutSgBuf); 1360 if (RT_FAILURE(rc)) 1361 { 1362 LogRel(("Fatal error submitting req packet, resetting %Rrc", rc)); 1363 /** TBD: MUST AT LEAD RETURN VIRTIO_SCSI_S_FAILURE for all pending I/O, Aborting is an option! */ 1364 virtioResetAll(pThis->hVirtio); 1365 } 1366 } 1363 1367 } 1364 1368 return VINF_SUCCESS; … … 1598 1602 if (fVirtioReady) 1599 1603 { 1600 LogFunc(("VirtIO ready\n--------------------------------------------------------------------------------- "));1604 LogFunc(("VirtIO ready\n---------------------------------------------------------------------------------\n")); 1601 1605 uint64_t features = virtioGetNegotiatedFeatures(hVirtio); 1602 1606 pThis->fHasT10pi = features & VIRTIO_SCSI_F_T10_PI; -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r80522 r80527 638 638 Log3Func(("Guest wrote uDeviceStatus ................ (")); 639 639 virtioLogDeviceStatus(pVirtio->uDeviceStatus); 640 Log ((")\n"));640 Log3((")\n")); 641 641 if (pVirtio->uDeviceStatus == 0) 642 642 virtioGuestResetted(pVirtio); … … 656 656 *(uint32_t *)pv = pVirtio->uDeviceStatus; 657 657 virtioLogDeviceStatus(pVirtio->uDeviceStatus); 658 Log ((")\n"));658 Log3((")\n")); 659 659 } 660 660 } -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r80522 r80527 512 512 { 513 513 if (status == 0) 514 Log (("RESET"));514 Log3(("RESET")); 515 515 else 516 516 {
Note:
See TracChangeset
for help on using the changeset viewer.