Changeset 80657 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Sep 9, 2019 7:14:32 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 133188
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80647 r80657 88 88 #define VIRTIOSCSI_SENSE_SIZE_DEFAULT 96 /**< VirtIO 1.0: 96 on reset, guest can change */ 89 89 #define VIRTIOSCSI_CDB_SIZE_DEFAULT 32 /**< VirtIO 1.0: 32 on reset, guest can change */ 90 #define VIRTIOSCSI_PI_BYTES_IN 1 /**< Value TBD (see section 5.6.6.1) */91 #define VIRTIOSCSI_PI_BYTES_OUT 1 /**< Value TBD (see section 5.6.6.1) */92 #define VIRTIOSCSI_DATA_OUT 512 /**< Value TBD (see section 5.6.6.1) */90 #define virtioScsi_PI_BYTES_IN 1 /**< Value TBD (see section 5.6.6.1) */ 91 #define virtioScsi_PI_BYTES_OUT 1 /**< Value TBD (see section 5.6.6.1) */ 92 #define virtioScsi_DATA_OUT 512 /**< Value TBD (see section 5.6.6.1) */ 93 93 94 94 /** … … 379 379 { 380 380 /** Pointer to PCI device that owns this target instance. - R3 pointer */ 381 R3PTRTYPE(struct VIRTIOSCSI *) pVirtioScsi R3;381 R3PTRTYPE(struct VIRTIOSCSI *) pVirtioScsi; 382 382 383 383 /** Pointer to attached driver's base interface. */ … … 415 415 /** The status LED state for this device. */ 416 416 PDMLED led; 417 418 /** Number of requests active */419 volatile uint32_t cReqsInProgress;420 417 421 418 } VIRTIOSCSITARGET, *PVIRTIOSCSITARGET; … … 486 483 uint64_t cTargets; 487 484 485 /** Total number of requests active across all targets */ 486 volatile uint32_t cActiveReqs; 487 488 488 /** True if PDMDevHlpAsyncNotificationCompleted should be called when port goes idle */ 489 489 bool volatile fSignalIdle; … … 512 512 /** True if VIRTIO_SCSI_F_T10_PI was negotiated */ 513 513 bool fHasLunChange; 514 515 /** True if in the process of resetting */ 516 bool fResetting; 517 518 /** True if in the process of suspending */ 519 bool fSuspending; 520 521 /** True if in the process of powering off */ 522 bool fPoweringOff; 523 524 /** True if in the process of quiescing I/O */ 525 bool fQuiescing; 526 527 514 528 515 529 } VIRTIOSCSI, *PVIRTIOSCSI; … … 655 669 #ifdef BOOTABLE_SUPPORT_TBD 656 670 /** @callback_method_impl{FNIOMIOPORTIN} */ 657 static DECLCALLBACK(int) virtioScsi R3BiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,671 static DECLCALLBACK(int) virtioScsiBiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst, 658 672 uint32_t *pcTransfers, unsigned cb); 659 673 { 660 674 } 661 675 /** @callback_method_impl{FNIOMIOPORTOUT} */ 662 static DECLCALLBACK(int) virtioScsi R3BiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb);676 static DECLCALLBACK(int) virtioScsiBiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb); 663 677 { 664 678 } 665 679 /** @callback_method_impl{FNIOMIOPORTOUTSTRING} */ 666 static DECLCALLBACK(int) virtioScsi R3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,680 static DECLCALLBACK(int) virtioScsiBiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc, 667 681 uint32_t *pcTransfers, unsigned cb); 668 682 { 669 683 } 670 684 /** @callback_method_impl{FNIOMIOPORTINSTRING} */ 671 static DECLCALLBACK(int) virtioScsi R3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,685 static DECLCALLBACK(int) virtioScsiBiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst, 672 686 uint32_t *pcTransfers, unsigned cb); 673 687 { … … 700 714 701 715 /** 702 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}703 */704 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,705 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)706 {707 708 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);709 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);710 711 switch (enmState)712 {713 case PDMMEDIAEXIOREQSTATE_SUSPENDED:714 {715 /* Make sure the request is not accounted for so the VM can suspend successfully. */716 uint32_t cTasksActive = ASMAtomicDecU32(&pTarget->cReqsInProgress);717 if (!cTasksActive && pTarget->CTX_SUFF(pVirtioScsi)->fSignalIdle)718 PDMDevHlpAsyncNotificationCompleted(pTarget->CTX_SUFF(pVirtioScsi)->pDevInsR3);719 break;720 }721 case PDMMEDIAEXIOREQSTATE_ACTIVE:722 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */723 ASMAtomicIncU32(&pTarget->cReqsInProgress);724 break;725 default:726 AssertMsgFailed(("Invalid request state given %u\n", enmState));727 }728 }729 730 /**731 716 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 732 717 */ 733 static DECLCALLBACK(int) virtioScsi R3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,718 static DECLCALLBACK(int) virtioScsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 734 719 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, size_t cbCopy) 735 720 { … … 744 729 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 745 730 */ 746 static DECLCALLBACK(int) virtioScsi R3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,731 static DECLCALLBACK(int) virtioScsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 747 732 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, size_t cbCopy) 748 733 { … … 842 827 static int virtioScsiReqErr(PVIRTIOSCSI pThis, uint16_t qIdx, struct REQ_RESP_HDR *pRespHdr, uint8_t *pbSense) 843 828 { 829 844 830 uint8_t *abSenseBuf = (uint8_t *)RTMemAllocZ(pThis->virtioScsiConfig.uSenseSize); 845 831 AssertReturn(abSenseBuf, VERR_NO_MEMORY); … … 862 848 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 863 849 850 if (pThis->fResetting) 851 pRespHdr->uResponse = VIRTIOSCSI_S_RESET; 852 864 853 virtioQueuePut(pThis->hVirtio, qIdx, &reqSegBuf, true /* fFence */); 865 854 virtioQueueSync(pThis->hVirtio, qIdx); … … 867 856 RTMemFree(abSenseBuf); 868 857 858 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) 859 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns)); 860 869 861 Log(("---------------------------------------------------------------------------------\n")); 870 862 … … 872 864 } 873 865 874 /** TBD: VirtIO 1.0 spec 5.6.6.1.1 requires some request actions on reset that are 875 * not implemented. Specifically either canceling outstanding I/O or 876 * returning VIRTIOSCSI_S_FAILURE for those requests. Since there's no 877 * way to cancel I/O on VSCSI at this time the only the only other 878 * possibility is to wait for the outstanding request count to drop 879 * and return the failure code for any-and-all until that's done before 880 * allowing a reset to continue. 881 */ 882 static int virtioScsiReqFinish(PVIRTIOSCSI pThis, PVIRTIOSCSIREQ pReq, int rcReq) 883 { 866 /** 867 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 868 */ 869 static DECLCALLBACK(int) virtioScsiIoReqFinish(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 870 void *pvIoReqAlloc, int rcReq) 871 { 872 RT_NOREF(pInterface); 873 874 PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc; 884 875 PVIRTIOSCSITARGET pTarget = pReq->pTarget; 876 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 885 877 PPDMIMEDIAEX pIMediaEx = pTarget->pDrvMediaEx; 886 878 887 ASMAtomicDecU32(&pTarget->cReqsInProgress);888 889 879 size_t cbResidual = 0, cbXfer = 0; 890 int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual);880 int rc = pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, hIoReq, &cbResidual); 891 881 AssertRC(rc); 892 882 893 rc = pIMediaEx->pfnIoReqQueryXferSize(pIMediaEx, pReq->hIoReq, &cbXfer);883 rc = pIMediaEx->pfnIoReqQueryXferSize(pIMediaEx, hIoReq, &cbXfer); 894 884 AssertRC(rc); 895 885 … … 902 892 /** VirtIO 1.0 spec 5.6.6.1.1 says device MUST return a VirtIO response byte value. 903 893 * Some are returned during the submit phase, and a few are not mapped at all, 904 * wherein anything that can't map specifically gets mapped to VIRTIOSCSI_S_FAILURE */ 905 switch(rcReq) 906 { 907 case SCSI_STATUS_OK: 908 if (pReq->uStatus != SCSI_STATUS_CHECK_CONDITION) 909 { 910 respHdr.uResponse = VIRTIOSCSI_S_OK; 894 * wherein anything that can't map specifically gets mapped to VIRTIOSCSI_S_FAILURE 895 */ 896 if (pThis->fResetting) 897 respHdr.uResponse = VIRTIOSCSI_S_RESET; 898 else 899 { 900 switch(rcReq) 901 { 902 case SCSI_STATUS_OK: 903 if (pReq->uStatus != SCSI_STATUS_CHECK_CONDITION) 904 { 905 respHdr.uResponse = VIRTIOSCSI_S_OK; 906 break; 907 } 908 case SCSI_STATUS_CHECK_CONDITION: 909 { 910 uint8_t uSenseKey = pReq->pbSense[2]; 911 switch (uSenseKey) 912 { 913 case SCSI_SENSE_ABORTED_COMMAND: 914 respHdr.uResponse = VIRTIOSCSI_S_ABORTED; 915 break; 916 case SCSI_SENSE_COPY_ABORTED: 917 respHdr.uResponse = VIRTIOSCSI_S_ABORTED; 918 break; 919 case SCSI_SENSE_UNIT_ATTENTION: 920 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 921 break; 922 case SCSI_SENSE_HARDWARE_ERROR: 923 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 924 break; 925 case SCSI_SENSE_NOT_READY: 926 respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. re-tryable */ 927 break; 928 default: 929 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 930 break; 931 } 932 } 911 933 break; 912 } 913 case SCSI_STATUS_CHECK_CONDITION: 914 { 915 uint8_t uSenseKey = pReq->pbSense[2]; 916 switch (uSenseKey) 917 { 918 case SCSI_SENSE_ABORTED_COMMAND: 919 respHdr.uResponse = VIRTIOSCSI_S_ABORTED; 920 break; 921 case SCSI_SENSE_COPY_ABORTED: 922 respHdr.uResponse = VIRTIOSCSI_S_ABORTED; 923 break; 924 case SCSI_SENSE_UNIT_ATTENTION: 925 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 926 break; 927 case SCSI_SENSE_HARDWARE_ERROR: 928 respHdr.uResponse = VIRTIOSCSI_S_TARGET_FAILURE; 929 break; 930 case SCSI_SENSE_NOT_READY: 931 respHdr.uResponse = VIRTIOSCSI_S_BUSY; /* e.g. re-tryable */ 932 break; 933 default: 934 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 935 break; 936 } 937 } 938 break; 939 940 default: 941 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 942 break; 934 935 default: 936 respHdr.uResponse = VIRTIOSCSI_S_FAILURE; 937 break; 938 } 943 939 } 944 940 945 941 Log2Func(("status: (%d) %s, response: (%d) %s\n", 946 pReq->uStatus, SCSIStatusText(pReq->uStatus), respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse))); 942 pReq->uStatus, SCSIStatusText(pReq->uStatus), 943 respHdr.uResponse, virtioGetReqRespText(respHdr.uResponse))); 947 944 948 945 if (RT_FAILURE(rcReq)) … … 1000 997 respHdr.uResidual = pReq->cbDataIn; 1001 998 virtioScsiReqErr(pThis, pReq->qIdx, &respHdr, abSense); 999 return VINF_SUCCESS; 1002 1000 } 1003 1001 else … … 1038 1036 virtioQueueSync(pThis->hVirtio, pReq->qIdx); 1039 1037 1038 1040 1039 Log(("-----------------------------------------------------------------------------------------\n")); 1041 1040 } … … 1043 1042 virtioScsiFreeReq(pTarget, pReq); 1044 1043 1045 if ( pTarget->cReqsInProgress == 0 && pThis->fSignalIdle)1046 PDMDevHlpAsyncNotificationCompleted(pThis-> pDevInsR3);1044 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) 1045 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns)); 1047 1046 1048 1047 return VINF_SUCCESS; … … 1053 1052 { 1054 1053 AssertMsgReturn(pOutSgBuf->cSegs, ("Req. has no OUT data, unexpected/TBD\n"), VERR_INVALID_PARAMETER); 1054 1055 ASMAtomicIncU32(&pThis->cActiveReqs); 1055 1056 1056 1057 size_t cbOut = RTSgBufCalcTotalLength(pOutSgBuf); … … 1073 1074 Log3Func(("id: %RX64, attr: %x, prio: %d, crn: %x\n", 1074 1075 pVirtqReq->cmdHdr.uId, pVirtqReq->cmdHdr.uTaskAttr, pVirtqReq->cmdHdr.uPrio, pVirtqReq->cmdHdr.uCrn)); 1076 1077 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget]; 1075 1078 1076 1079 /** … … 1094 1097 size_t cbDataIn = cbIn - uDataInOff; 1095 1098 1099 /** 1100 * Handle submission errors 1101 */ 1102 if (pThis->fResetting) 1103 { 1104 Log2Func(("Aborting req submission because reset is in progress\n")); 1105 struct REQ_RESP_HDR respHdr = { 0 }; 1106 respHdr.uSenseLen = 0; 1107 respHdr.uStatus = SCSI_STATUS_OK; 1108 respHdr.uResponse = VIRTIOSCSI_S_RESET; 1109 respHdr.uResidual = cbDataIn + cbDataOut; 1110 virtioScsiReqErr(pThis, qIdx, &respHdr, NULL); 1111 RTMemFree(pVirtqReq); 1112 return VINF_SUCCESS; 1113 } 1114 else 1096 1115 if (uTarget >= pThis->cTargets || uLUN != 0) 1097 1116 { 1117 Log2Func(("Error submitting request to bad target (%d) or bad LUN (%d)\n", uTarget, uLUN)); 1098 1118 uint8_t abSense[] = { RT_BIT(7) | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED, 1099 1119 0, SCSI_SENSE_ILLEGAL_REQUEST, … … 1108 1128 return VINF_SUCCESS; 1109 1129 } 1110 1111 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[uTarget]; 1112 1130 else 1113 1131 if (RT_UNLIKELY(!pTarget->fPresent)) 1114 1132 { … … 1126 1144 } 1127 1145 1146 /** 1147 * Have underlying driver allocate a req of size set during initialization of this device. 1148 */ 1128 1149 PDMMEDIAEXIOREQ hIoReq = NULL; 1129 1150 PVIRTIOSCSIREQ pReq; … … 1135 1156 AssertMsgRCReturn(rc, ("Failed to allocate I/O request, rc=%Rrc\n", rc), rc); 1136 1157 1158 /** 1159 * Prepare req's parameters for submission 1160 */ 1137 1161 if (pThis->fHasT10pi) 1138 1162 { … … 1164 1188 } 1165 1189 1166 ASMAtomicIncU32(&pTarget->cReqsInProgress);1167 1168 1190 rc = pIMediaEx->pfnIoReqSendScsiCmd(pIMediaEx, pReq->hIoReq, uLUN, 1169 1191 pVirtqReq->uCdb, pThis->virtioScsiConfig.uCdbSize, … … 1176 1198 { 1177 1199 /** 1178 * This rc value from DrvSCSI/send SCSI cmd means the request failed early 1179 * (no mem, buf copy callback, request buffer creation, or req enqueue), 1180 * and not submitted to lower layers, error it out. 1200 * Getting here means the request failed in early in the submission to the lower level driver, 1201 * and there will be no callback to the finished/completion function for this request 1181 1202 */ 1182 Log2Func((" Error submitting request!\n"));1203 Log2Func(("Request submission error from lower-level driver\n")); 1183 1204 size_t cbResidual; 1184 1205 pIMediaEx->pfnIoReqQueryResidual(pIMediaEx, pReq->hIoReq, &cbResidual); … … 1206 1227 } 1207 1228 1208 return VINF_SUCCESS;1209 }1210 1211 /**1212 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}1213 */1214 static DECLCALLBACK(int) virtioScsiR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,1215 void *pvIoReqAlloc, int rcReq)1216 {1217 RT_NOREF(hIoReq);1218 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);1219 virtioScsiReqFinish(pTarget->CTX_SUFF(pVirtioScsi), (PVIRTIOSCSIREQ)pvIoReqAlloc, rcReq);1220 1229 return VINF_SUCCESS; 1221 1230 } … … 1366 1375 * @param pThread The send thread. 1367 1376 */ 1368 static DECLCALLBACK(int) virtioScsi R3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)1377 static DECLCALLBACK(int) virtioScsiWorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1369 1378 { 1370 1379 RT_NOREF(pThread); … … 1376 1385 static int virtioScsiWorker(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1377 1386 { 1378 1379 1387 int rc; 1380 1388 uint16_t qIdx = ((uint64_t)pThread->pvUser) & 0xffff; … … 1389 1397 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 1390 1398 { 1399 if (pThis->fQuiescing || !pThis->fQueueAttached[qIdx]) 1400 { 1401 Log6Func(("Skipping wakeup (quiescing or reset)\n")); 1402 continue; 1403 } 1404 1391 1405 if (virtioQueueIsEmpty(pThis->hVirtio, qIdx)) 1392 1406 { … … 1423 1437 if (RT_FAILURE(rc)) 1424 1438 { 1425 LogRel(("Fatal error submitting req packet, resetting %Rrc", rc)); 1426 /** TBD: MUST AT LEAD RETURN VIRTIO_SCSI_S_FAILURE for all pending I/O, Aborting is an option! */ 1427 virtioResetAll(pThis->hVirtio); 1439 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1428 1440 } 1429 1441 } … … 1437 1449 1438 1450 1439 /** 1440 * Implementation invokes this to reset the VirtIO device 1441 */ 1442 static void virtioScsiDeviceReset(PVIRTIOSCSI pThis) 1443 { 1444 pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT; 1445 pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; 1446 virtioResetAll(pThis->hVirtio); 1447 } 1448 1449 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset, 1451 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget) 1452 { 1453 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0); 1454 } 1455 1456 DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget) 1457 { 1458 if (pThis->fHasHotplug) 1459 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1460 VIRTIOSCSI_EVT_RESET_REMOVED); 1461 } 1462 1463 DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget) 1464 { 1465 if (pThis->fHasHotplug) 1466 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1467 VIRTIOSCSI_EVT_RESET_RESCAN); 1468 } 1469 1470 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget) 1471 { 1472 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET, 1473 VIRTIOSCSI_EVT_RESET_HARD); 1474 } 1475 1476 DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1477 { 1478 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE) 1479 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1480 VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE); 1481 } 1482 1483 DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget) 1484 { 1485 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT) 1486 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1487 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT); 1488 } 1489 1490 DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget) 1491 { 1492 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST) 1493 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1494 VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST); 1495 } 1496 1497 DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget) 1498 { 1499 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE) 1500 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1501 VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE); 1502 } 1503 1504 DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget) 1505 { 1506 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST) 1507 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1508 VIRTIOSCSI_EVT_ASYNC_MULTI_HOST); 1509 } 1510 1511 DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget) 1512 { 1513 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY) 1514 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY, 1515 VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY); 1516 } 1517 1518 1519 DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier) 1520 { 1521 uint32_t uReason = uSenseQualifier << 8 | uSenseCode; 1522 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason); 1523 1524 } 1525 1526 static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx) 1527 { 1528 RT_NOREF(hVirtio); 1529 1530 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT); 1531 PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient; 1532 PWORKER pWorker = &pThis->aWorker[qIdx]; 1533 1534 1535 RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX))); 1536 1537 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx)) 1538 { 1539 Log6Func(("%s has available data\n", QUEUENAME(qIdx))); 1540 /** Wake queue's worker thread up if sleeping */ 1541 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) 1542 { 1543 if (ASMAtomicReadBool(&pWorker->fSleeping)) 1544 { 1545 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx))); 1546 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess); 1547 AssertRC(rc); 1548 } 1549 } 1550 } 1551 else if (qIdx == EVENTQ_IDX) 1552 { 1553 Log3Func(("Driver queued buffer(s) to %s\n")); 1554 if (ASMAtomicXchgBool(&pThis->fEventsMissed, false)) 1555 virtioScsiReportEventsMissed(pThis, 0); 1556 } 1557 else 1558 LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx)); 1559 } 1560 1561 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient, bool fVirtioReady) 1562 { 1563 RT_NOREF(hVirtio); 1564 PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient; 1565 1566 pThis->fVirtioReady = fVirtioReady; 1567 1568 if (fVirtioReady) 1569 { 1570 LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n")); 1571 uint64_t features = virtioGetNegotiatedFeatures(hVirtio); 1572 pThis->fHasT10pi = features & VIRTIO_SCSI_F_T10_PI; 1573 pThis->fHasHotplug = features & VIRTIO_SCSI_F_HOTPLUG; 1574 pThis->fHasInOutBufs = features & VIRTIO_SCSI_F_INOUT; 1575 pThis->fHasLunChange = features & VIRTIO_SCSI_F_CHANGE; 1576 pThis->fQuiescing = false; 1577 pThis->fResetting = false; 1578 1579 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++) 1580 pThis->fQueueAttached[i] = true; 1581 } 1582 else 1583 { 1584 LogFunc(("VirtIO is resetting\n")); 1585 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++) 1586 pThis->fQueueAttached[i] = false; 1587 } 1588 } 1589 1590 /** 1591 * virtio-scsi debugger info callback. 1592 * 1593 * @param pDevIns The device instance. 1594 * @param pHlp The output helpers. 1595 * @param pszArgs The arguments. 1596 */ 1597 static DECLCALLBACK(void) virtioScsiInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 1598 { 1599 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1600 bool fVerbose = false; 1601 1602 /* Parse arguments. */ 1603 if (pszArgs) 1604 fVerbose = strstr(pszArgs, "verbose") != NULL; 1605 1606 /* Show basic information. */ 1607 pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ", 1608 pDevIns->pReg->szName, 1609 pDevIns->iInstance); 1610 pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets); 1611 } 1612 1613 /** 1614 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 1615 */ 1616 static DECLCALLBACK(void) virtioScsiMediumEjected(PPDMIMEDIAEXPORT pInterface) 1617 { 1618 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 1619 PVIRTIOSCSI pThis = pTarget->pVirtioScsi; 1620 LogFunc(("LUN %d Ejected!\n", pTarget->iLUN)); 1621 if (pThis->pMediaNotify) 1622 { 1623 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY, 1624 (PFNRT)pThis->pMediaNotify->pfnEjected, 2, 1625 pThis->pMediaNotify, pTarget->iLUN); 1626 AssertRC(rc); 1627 } 1628 1629 } 1630 1631 /** @callback_method_impl{FNSSMDEVLIVEEXEC} */ 1632 static DECLCALLBACK(int) virtioScsiLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1633 { 1634 LogFunc(("callback")); 1635 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1636 RT_NOREF(pThis); 1637 RT_NOREF(uPass); 1638 RT_NOREF(pSSM); 1639 return VINF_SSM_DONT_CALL_AGAIN; 1640 } 1641 1642 /** @callback_method_impl{FNSSMDEVLOADEXEC} */ 1643 static DECLCALLBACK(int) virtioScsiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1644 { 1645 LogFunc(("callback")); 1646 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1647 RT_NOREF(pThis); 1648 RT_NOREF(uPass); 1649 RT_NOREF(pSSM); 1650 RT_NOREF(uVersion); 1651 return VINF_SSM_DONT_CALL_AGAIN; 1652 } 1653 1654 /** @callback_method_impl{FNSSMDEVSAVEEXEC} */ 1655 static DECLCALLBACK(int) virtioScsiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1656 { 1657 LogFunc(("callback")); 1658 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1659 1660 RT_NOREF(pThis); 1661 RT_NOREF(pSSM); 1662 return VINF_SUCCESS; 1663 } 1664 1665 /** @callback_method_impl{FNSSMDEVLOADDONE} */ 1666 static DECLCALLBACK(int) virtioScsiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1667 { 1668 LogFunc(("callback")); 1669 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1670 RT_NOREF(pThis); 1671 RT_NOREF(pSSM); 1672 return VINF_SUCCESS; 1673 } 1674 1675 /** Let guest to use the queues */ 1676 static void enableQueues(PVIRTIOSCSI pThis) 1677 { 1678 for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 1679 virtioQueueEnable(pThis->hVirtio, qIdx, true); 1680 } 1681 1682 /** Tell guest to stop using the queues */ 1683 static void disableQueues(PVIRTIOSCSI pThis) 1684 { 1685 /** Tell guest to stop sending stuff */ 1686 for (int qIdx = 0; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 1687 virtioQueueEnable(pThis->hVirtio, qIdx, false); 1688 } 1689 1690 /** 1691 * Handle callback from PDM's async notification mechanism. 1692 * In this case, the callback is triggered when I/O activity is quiesced. 1693 * 1694 * @returns true if we've quiesced, false if we're still working. 1695 * @param pDevIns The device instance. 1696 */ 1697 static DECLCALLBACK(bool) virtioScsiDeviceQuiesced(PPDMDEVINS pDevIns) 1698 { 1699 LogFunc(("\n")); 1700 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1701 1702 if (pThis->fResetting) 1703 { 1704 Log2Func(("Resetting VirtIO\n")); 1705 1706 /** Reset virtio infrastructure */ 1707 virtioResetAll(pThis->hVirtio); 1708 1709 /** Reset negotiable device-specific config parameters to VirtIO-specified default values */ 1710 pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT; 1711 pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; 1712 1713 pThis->fQuiescing = false; 1714 1715 /** fQuiescing and fReset flags get cleared during [re-]initialization */ 1716 } 1717 else if (pThis->fSuspending || pThis->fPoweringOff) 1718 { 1719 /* Lower-level driver (DrvVD) has already suspended any I/O on wait queue */ 1720 } 1721 return false; 1722 } 1723 1724 static void virtioScsiQuiesceDevice(PPDMDEVINS pDevIns) 1725 { 1726 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1727 1728 pThis->fQuiescing = true; /* inhibit worker thread's de-queing */ 1729 disableQueues(pThis); /* inhibit guest use of virtq's */ 1730 1731 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiDeviceQuiesced); 1732 1733 /** If already quiesced invoke async callback. */ 1734 if (!ASMAtomicReadU32(&pThis->cActiveReqs)) 1735 PDMDevHlpAsyncNotificationCompleted(pDevIns); 1736 } 1737 1738 /** 1739 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 1740 */ 1741 static DECLCALLBACK(void) virtioScsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1742 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 1743 { 1744 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState); 1745 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); 1746 1747 switch (enmState) 1748 { 1749 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 1750 { 1751 /* Stop considering this request active */ 1752 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThis->fQuiescing) 1753 PDMDevHlpAsyncNotificationCompleted(pThis->CTX_SUFF(pDevIns)); 1754 break; 1755 } 1756 case PDMMEDIAEXIOREQSTATE_ACTIVE: 1757 ASMAtomicIncU32(&pThis->cActiveReqs); 1758 break; 1759 default: 1760 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 1761 } 1762 } 1763 1764 /** 1765 * @interface_method_impl{PDMDEVREG,pfnResume} 1766 */ 1767 static DECLCALLBACK(void) virtioScsiResume(PPDMDEVINS pDevIns) 1768 { 1769 LogFunc(("\n")); 1770 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1771 pThis->fSuspending = pThis->fQuiescing = false; 1772 enableQueues(pThis); 1773 } 1774 1775 /** 1776 * @interface_method_impl{PDMDEVREG,pfnSuspend} 1777 */ 1778 static DECLCALLBACK(void) virtioScsiSuspend(PPDMDEVINS pDevIns) 1779 { 1780 LogFunc(("\n")); 1781 1782 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1783 1784 pThis->fSuspending = true; 1785 1786 virtioScsiQuiesceDevice(pDevIns); 1787 1788 for (uint32_t i = 0; i < pThis->cTargets; i++) 1789 { 1790 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i]; 1791 if (pTarget->pDrvBase) 1792 if (pTarget->pDrvMediaEx) 1793 pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx); 1794 } 1795 } 1796 1797 /** 1798 * Common worker for virtioScsiSuspend and virtioScsiPowerOff. 1799 */ 1800 static void virtioScsiPowerOn(PPDMDEVINS pDevIns) 1801 { 1802 LogFunc(("\n")); 1803 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1804 pThis->fPoweringOff = pThis->fQuiescing = false; 1805 enableQueues(pThis); 1806 } 1807 1808 /** 1809 * Common worker for virtioScsiSuspend and virtioScsiPowerOff. 1810 */ 1811 static void virtioScsiPowerOff(PPDMDEVINS pDevIns) 1812 { 1813 LogFunc(("\n")); 1814 1815 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1816 1817 pThis->fPoweringOff = true; 1818 virtioScsiQuiesceDevice(pDevIns); 1819 1820 for (uint32_t i = 0; i < pThis->cTargets; i++) 1821 { 1822 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i]; 1823 if (pTarget->pDrvBase) 1824 if (pTarget->pDrvMediaEx) 1825 pTarget->pDrvMediaEx->pfnNotifySuspend(pTarget->pDrvMediaEx); 1826 } 1827 } 1828 1829 /** 1830 * @copydoc FNPDMDEVRESET 1831 */ 1832 static DECLCALLBACK(void) virtioScsiReset(PPDMDEVINS pDevIns) 1833 { 1834 LogFunc(("\n")); 1835 1836 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1837 pThis->fResetting = true; 1838 1839 virtioScsiQuiesceDevice(pDevIns); 1840 } 1841 1842 /** 1843 * Turns on/off the write status LED. 1844 * 1845 * @param pTarget Pointer to the target device 1846 * @param fOn New LED state. 1847 */ 1848 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1849 { 1850 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off")); 1851 if (fOn) 1852 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1; 1853 else 1854 pTarget->led.Actual.s.fWriting = fOn; 1855 } 1856 1857 /** 1858 * Turns on/off the read status LED. 1859 * 1860 * @param pTarget Pointer to the device state structure. 1861 * @param fOn New LED state. 1862 */ 1863 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn) 1864 { 1865 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off")); 1866 if (fOn) 1867 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1; 1868 else 1869 pTarget->led.Actual.s.fReading = fOn; 1870 } 1871 1872 /** 1873 * Gets the pointer to the status LED of a unit. 1874 * 1875 * @returns VBox status code. 1876 * @param pInterface Pointer to the interface structure containing the called function pointer. 1877 * @param iLUN The unit which status LED we desire. 1878 * @param ppLed Where to store the LED pointer. 1879 */ 1880 static DECLCALLBACK(int) virtioScsiTargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 1881 { 1882 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed); 1883 if (iLUN == 0) 1884 { 1885 *ppLed = &pTarget->led; 1886 Assert((*ppLed)->u32Magic == PDMLED_MAGIC); 1887 return VINF_SUCCESS; 1888 } 1889 return VERR_PDM_LUN_NOT_FOUND; 1890 } 1891 1892 /** 1893 * Gets the pointer to the status LED of a unit. 1894 * 1895 * @returns VBox status code. 1896 * @param pInterface Pointer to the interface structure containing the called function pointer. 1897 * @param iLUN The unit which status LED we desire. 1898 * @param ppLed Where to store the LED pointer. 1899 */ 1900 static DECLCALLBACK(int) virtioScsiDeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 1901 { 1902 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds); 1903 if (iLUN < pThis->cTargets) 1904 { 1905 *ppLed = &pThis->aTargetInstances[iLUN].led; 1906 Assert((*ppLed)->u32Magic == PDMLED_MAGIC); 1907 return VINF_SUCCESS; 1908 } 1909 return VERR_PDM_LUN_NOT_FOUND; 1910 } 1911 1912 static int virtioScsiCfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffset, 1450 1913 const void *pv, size_t cb, uint8_t fWrite) 1451 1914 { … … 1488 1951 } 1489 1952 1490 1491 1492 1953 /** 1493 1954 * virtio-scsi VirtIO Device-specific capabilities read callback … … 1499 1960 * @param cb Number of bytes to read 1500 1961 */ 1501 static DECLCALLBACK(int) virtioScsi R3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)1962 static DECLCALLBACK(int) virtioScsiDevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb) 1502 1963 { 1503 1964 int rc = VINF_SUCCESS; 1504 1965 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1505 1966 1506 rc = virtioScsi R3CfgAccessed(pThis, uOffset, pv, cb, false);1967 rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, false); 1507 1968 1508 1969 return rc; … … 1518 1979 * @param cb Number of bytes to write 1519 1980 */ 1520 static DECLCALLBACK(int) virtioScsi R3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)1981 static DECLCALLBACK(int) virtioScsiDevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb) 1521 1982 { 1522 1983 int rc = VINF_SUCCESS; 1523 1984 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 1524 1985 1525 rc = virtioScsi R3CfgAccessed(pThis, uOffset, pv, cb, true);1986 rc = virtioScsiCfgAccessed(pThis, uOffset, pv, cb, true); 1526 1987 1527 1988 return rc; 1528 }1529 1530 DECLINLINE(void) virtioScsiReportEventsMissed(PVIRTIOSCSI pThis, uint16_t uTarget)1531 {1532 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_NO_EVENT | VIRTIOSCSI_T_EVENTS_MISSED, 0);1533 }1534 1535 DECLINLINE(void) virtioScsiReportTargetRemoved(PVIRTIOSCSI pThis, uint16_t uTarget)1536 {1537 if (pThis->fHasHotplug)1538 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,1539 VIRTIOSCSI_EVT_RESET_REMOVED);1540 }1541 1542 DECLINLINE(void) virtioScsiReportTargetAdded(PVIRTIOSCSI pThis, uint16_t uTarget)1543 {1544 if (pThis->fHasHotplug)1545 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,1546 VIRTIOSCSI_EVT_RESET_RESCAN);1547 }1548 1549 DECLINLINE(void) virtioScsiReportTargetReset(PVIRTIOSCSI pThis, uint16_t uTarget)1550 {1551 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_TRANSPORT_RESET,1552 VIRTIOSCSI_EVT_RESET_HARD);1553 }1554 1555 DECLINLINE(void) virtioScsiReportOperChange(PVIRTIOSCSI pThis, uint16_t uTarget)1556 {1557 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE)1558 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1559 VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE);1560 }1561 1562 DECLINLINE(void) virtioScsiReportPowerMsg(PVIRTIOSCSI pThis, uint16_t uTarget)1563 {1564 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_POWER_MGMT)1565 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1566 VIRTIOSCSI_EVT_ASYNC_POWER_MGMT);1567 }1568 1569 DECLINLINE(void) virtioScsiReportExtReq(PVIRTIOSCSI pThis, uint16_t uTarget)1570 {1571 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST)1572 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1573 VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST);1574 }1575 1576 DECLINLINE(void) virtioScsiReportMediaChange(PVIRTIOSCSI pThis, uint16_t uTarget)1577 {1578 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE)1579 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1580 VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE);1581 }1582 1583 DECLINLINE(void) virtioScsiReportMultiHost(PVIRTIOSCSI pThis, uint16_t uTarget)1584 {1585 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_MULTI_HOST)1586 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1587 VIRTIOSCSI_EVT_ASYNC_MULTI_HOST);1588 }1589 1590 DECLINLINE(void) virtioScsiReportDeviceBusy(PVIRTIOSCSI pThis, uint16_t uTarget)1591 {1592 if (pThis->uSubscribedEvents & VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY)1593 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_ASYNC_NOTIFY,1594 VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY);1595 }1596 1597 1598 DECLINLINE(void) virtioScsiReportParamChange(PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uSenseCode, uint32_t uSenseQualifier)1599 {1600 uint32_t uReason = uSenseQualifier << 8 | uSenseCode;1601 virtioScsiSendEvent(pThis, uTarget, VIRTIOSCSI_T_PARAM_CHANGE, uReason);1602 1603 }1604 1605 static DECLCALLBACK(void) virtioScsiNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx)1606 {1607 RT_NOREF(hVirtio);1608 1609 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);1610 PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;1611 PWORKER pWorker = &pThis->aWorker[qIdx];1612 1613 1614 RTLogFlush(RTLogDefaultInstanceEx(RT_MAKE_U32(0, UINT16_MAX)));1615 1616 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))1617 {1618 Log6Func(("%s has available data\n", QUEUENAME(qIdx)));1619 /** Wake queue's worker thread up if sleeping */1620 if (!ASMAtomicXchgBool(&pWorker->fNotified, true))1621 {1622 if (ASMAtomicReadBool(&pWorker->fSleeping))1623 {1624 Log6Func(("waking %s worker.\n", QUEUENAME(qIdx)));1625 int rc = SUPSemEventSignal(pThis->pSupDrvSession, pWorker->hEvtProcess);1626 AssertRC(rc);1627 }1628 }1629 }1630 else if (qIdx == EVENTQ_IDX)1631 {1632 Log3Func(("Driver queued buffer(s) to %s\n"));1633 if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))1634 virtioScsiReportEventsMissed(pThis, 0);1635 }1636 else1637 LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));1638 }1639 1640 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient, bool fVirtioReady)1641 {1642 RT_NOREF(hVirtio);1643 PVIRTIOSCSI pThis = (PVIRTIOSCSI)pClient;1644 pThis->fVirtioReady = fVirtioReady;1645 if (fVirtioReady)1646 {1647 LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n"));1648 uint64_t features = virtioGetNegotiatedFeatures(hVirtio);1649 pThis->fHasT10pi = features & VIRTIO_SCSI_F_T10_PI;1650 pThis->fHasHotplug = features & VIRTIO_SCSI_F_HOTPLUG;1651 pThis->fHasInOutBufs = features & VIRTIO_SCSI_F_INOUT;1652 pThis->fHasLunChange = features & VIRTIO_SCSI_F_CHANGE;1653 }1654 else1655 {1656 LogFunc(("VirtIO is resetting\n"));1657 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++)1658 pThis->fQueueAttached[i] = false;1659 }1660 }1661 1662 /**1663 * Turns on/off the write status LED.1664 *1665 * @param pTarget Pointer to the target device1666 * @param fOn New LED state.1667 */1668 void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)1669 {1670 LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));1671 if (fOn)1672 pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;1673 else1674 pTarget->led.Actual.s.fWriting = fOn;1675 }1676 1677 /**1678 * Turns on/off the read status LED.1679 *1680 * @param pTarget Pointer to the device state structure.1681 * @param fOn New LED state.1682 */1683 void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)1684 {1685 LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));1686 if (fOn)1687 pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;1688 else1689 pTarget->led.Actual.s.fReading = fOn;1690 }1691 1692 /**1693 * virtio-scsi debugger info callback.1694 *1695 * @param pDevIns The device instance.1696 * @param pHlp The output helpers.1697 * @param pszArgs The arguments.1698 */1699 static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)1700 {1701 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1702 bool fVerbose = false;1703 1704 /* Parse arguments. */1705 if (pszArgs)1706 fVerbose = strstr(pszArgs, "verbose") != NULL;1707 1708 /* Show basic information. */1709 pHlp->pfnPrintf(pHlp, "%s#%d: virtio-scsci ",1710 pDevIns->pReg->szName,1711 pDevIns->iInstance);1712 pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets);1713 }1714 1715 /**1716 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}1717 */1718 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)1719 {1720 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);1721 PVIRTIOSCSI pThis = pTarget->CTX_SUFF(pVirtioScsi);1722 LogFunc(("LUN %d Ejected!\n", pTarget->iLUN));1723 if (pThis->pMediaNotify)1724 {1725 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,1726 (PFNRT)pThis->pMediaNotify->pfnEjected, 2,1727 pThis->pMediaNotify, pTarget->iLUN);1728 AssertRC(rc);1729 }1730 1731 }1732 1733 /** @callback_method_impl{FNSSMDEVLIVEEXEC} */1734 static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)1735 {1736 LogFunc(("callback"));1737 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1738 RT_NOREF(pThis);1739 RT_NOREF(uPass);1740 RT_NOREF(pSSM);1741 return VINF_SSM_DONT_CALL_AGAIN;1742 }1743 1744 /** @callback_method_impl{FNSSMDEVLOADEXEC} */1745 static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)1746 {1747 LogFunc(("callback"));1748 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1749 RT_NOREF(pThis);1750 RT_NOREF(uPass);1751 RT_NOREF(pSSM);1752 RT_NOREF(uVersion);1753 return VINF_SSM_DONT_CALL_AGAIN;1754 }1755 1756 /** @callback_method_impl{FNSSMDEVSAVEEXEC} */1757 static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)1758 {1759 LogFunc(("callback"));1760 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1761 1762 RT_NOREF(pThis);1763 RT_NOREF(pSSM);1764 return VINF_SUCCESS;1765 }1766 1767 /** @callback_method_impl{FNSSMDEVLOADDONE} */1768 static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)1769 {1770 LogFunc(("callback"));1771 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1772 RT_NOREF(pThis);1773 RT_NOREF(pSSM);1774 return VINF_SUCCESS;1775 }1776 1777 1778 /**1779 * Callback employed by virtioScsiR3PDMReset.1780 *1781 * @returns true if we've quiesced, false if we're still working.1782 * @param pDevIns The device instance.1783 */1784 static DECLCALLBACK(bool) virtioScsiR3IsAsyncResetDone(PPDMDEVINS pDevIns)1785 {1786 RT_NOREF(pDevIns);1787 Log(("\n"));1788 1789 return true;1790 }1791 1792 /**1793 * @copydoc FNPDMDEVRESET1794 */1795 static DECLCALLBACK(void) virtioScsiR3PDMReset(PPDMDEVINS pDevIns)1796 {1797 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1798 ASMAtomicWriteBool(&pThis->fSignalIdle, true);1799 1800 bool fIoInProgress = false;1801 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aTargetInstances); i++)1802 {1803 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];1804 if (pTarget->cReqsInProgress != 0)1805 {1806 fIoInProgress = true;1807 break;1808 }1809 }1810 if (!fIoInProgress)1811 PDMDevHlpSetAsyncNotification(pDevIns, virtioScsiR3IsAsyncResetDone);1812 else1813 ASMAtomicWriteBool(&pThis->fSignalIdle, false);1814 1815 virtioScsiDeviceReset(pThis);1816 1989 } 1817 1990 … … 1832 2005 * @remark A relocation CANNOT fail. 1833 2006 */ 1834 static DECLCALLBACK(void) virtioScsiR 3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)2007 static DECLCALLBACK(void) virtioScsiRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 1835 2008 { 1836 2009 LogFunc(("Relocating virtio-scsi")); … … 1843 2016 { 1844 2017 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i]; 1845 pTarget->pVirtioScsi R3 = pThis;;2018 pTarget->pVirtioScsi = pThis; 1846 2019 } 1847 2020 … … 1853 2026 } 1854 2027 1855 static DECLCALLBACK(int) virtioScsi R3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,2028 static DECLCALLBACK(int) virtioScsiQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 1856 2029 uint32_t *piInstance, uint32_t *piLUN) 1857 2030 { 1858 PVIRTIOSCSITARGET pT hisTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort);1859 PPDMDEVINS pDevIns = pT hisTarget->CTX_SUFF(pVirtioScsi)->CTX_SUFF(pDevIns);2031 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaPort); 2032 PPDMDEVINS pDevIns = pTarget->pVirtioScsi->CTX_SUFF(pDevIns); 1860 2033 1861 2034 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER); … … 1865 2038 *ppcszController = pDevIns->pReg->szName; 1866 2039 *piInstance = pDevIns->iInstance; 1867 *piLUN = pT hisTarget->iLUN;2040 *piLUN = pTarget->iLUN; 1868 2041 1869 2042 return VINF_SUCCESS; … … 1871 2044 1872 2045 /** 1873 * Gets the pointer to the status LED of a unit.1874 *1875 * @returns VBox status code.1876 * @param pInterface Pointer to the interface structure containing the called function pointer.1877 * @param iLUN The unit which status LED we desire.1878 * @param ppLed Where to store the LED pointer.1879 */1880 static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)1881 {1882 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);1883 if (iLUN == 0)1884 {1885 *ppLed = &pTarget->led;1886 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);1887 return VINF_SUCCESS;1888 }1889 return VERR_PDM_LUN_NOT_FOUND;1890 }1891 1892 1893 /**1894 * Gets the pointer to the status LED of a unit.1895 *1896 * @returns VBox status code.1897 * @param pInterface Pointer to the interface structure containing the called function pointer.1898 * @param iLUN The unit which status LED we desire.1899 * @param ppLed Where to store the LED pointer.1900 */1901 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)1902 {1903 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);1904 if (iLUN < pThis->cTargets)1905 {1906 *ppLed = &pThis->aTargetInstances[iLUN].led;1907 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);1908 return VINF_SUCCESS;1909 }1910 return VERR_PDM_LUN_NOT_FOUND;1911 }1912 1913 1914 /**1915 * Memory mapped I/O Handler for read operations.1916 *1917 * @returns VBox status code.1918 *1919 * @param pDevIns The device instance.1920 * @param pvUser User argument.1921 * @param GCPhysAddr Physical address (in GC) where the read starts.1922 * @param pv Where to store the result.1923 * @param cb Number of bytes read.1924 */1925 PDMBOTHCBDECL(int) virtioScsiMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)1926 {1927 RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);1928 LogFunc(("Read from MMIO area\n"));1929 return VINF_SUCCESS;1930 }1931 1932 /**1933 * Memory mapped I/O Handler for write operations.1934 *1935 * @returns VBox status code.1936 *1937 * @param pDevIns The device instance.1938 * @param pvUser User argument.1939 * @param GCPhysAddr Physical address (in GC) where the read starts.1940 * @param pv Where to fetch the result.1941 * @param cb Number of bytes to write.1942 */1943 PDMBOTHCBDECL(int) virtioScsiMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)1944 {1945 RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);1946 LogFunc(("Write to MMIO area\n"));1947 return VINF_SUCCESS;1948 }1949 1950 /**1951 * @callback_method_impl{FNPCIIOREGIONMAP}1952 */1953 static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,1954 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)1955 {1956 RT_NOREF(pPciDev, iRegion);1957 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);1958 int rc = VINF_SUCCESS;1959 1960 Assert(cb >= 32);1961 1962 switch (iRegion)1963 {1964 case 0:1965 LogFunc(("virtio-scsi MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));1966 1967 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */1968 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,1969 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,1970 virtioScsiMMIOWrite, virtioScsiMMIORead,1971 "virtio-scsi MMIO");1972 pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;1973 return rc;1974 case 1:1975 /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */1976 AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));1977 default:1978 AssertMsgFailed(("Invalid enmType=%d\n", enmType));1979 }1980 return VERR_GENERAL_FAILURE; /* Should never get here */1981 }1982 1983 /**1984 2046 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1985 2047 */ 1986 static DECLCALLBACK(void *) virtioScsi R3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)2048 static DECLCALLBACK(void *) virtioScsiTargetQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1987 2049 { 1988 2050 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase); … … 1997 2059 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1998 2060 */ 1999 static DECLCALLBACK(void *) virtioScsi R3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)2061 static DECLCALLBACK(void *) virtioScsiDeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID) 2000 2062 { 2001 2063 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase); … … 2017 2079 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2018 2080 */ 2019 static DECLCALLBACK(void) virtioScsi R3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)2081 static DECLCALLBACK(void) virtioScsiDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 2020 2082 { 2021 2083 RT_NOREF(fFlags); … … 2045 2107 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 2046 2108 */ 2047 static DECLCALLBACK(int) virtioScsi R3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)2109 static DECLCALLBACK(int) virtioScsiAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 2048 2110 { 2049 2111 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); … … 2161 2223 pVirtioPciParams->uInterruptPin = 0x01; 2162 2224 2163 pThis->IBase.pfnQueryInterface = virtioScsi R3DeviceQueryInterface;2225 pThis->IBase.pfnQueryInterface = virtioScsiDeviceQueryInterface; 2164 2226 2165 2227 /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */ … … 2177 2239 rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance, 2178 2240 VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED, 2179 virtioScsi R3DevCapRead,2180 virtioScsi R3DevCapWrite,2241 virtioScsiDevCapRead, 2242 virtioScsiDevCapWrite, 2181 2243 virtioScsiStatusChanged, 2182 2244 virtioScsiNotified, 2183 virtioScsi R3LiveExec,2184 virtioScsi R3SaveExec,2185 virtioScsi R3LoadExec,2186 virtioScsi R3LoadDone,2245 virtioScsiLiveExec, 2246 virtioScsiSaveExec, 2247 virtioScsiLoadExec, 2248 virtioScsiLoadDone, 2187 2249 sizeof(VIRTIOSCSI_CONFIG_T) /* cbDevSpecificCap */, 2188 2250 (void *)&pThis->virtioScsiConfig /* pDevSpecificCap */); … … 2207 2269 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->aWorker[qIdx].pThread, 2208 2270 (void *)(uint64_t)qIdx, virtioScsiWorker, 2209 virtioScsi R3WorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx));2271 virtioScsiWorkerWakeUp, 0, RTTHREADTYPE_IO, QUEUENAME(qIdx)); 2210 2272 if (rc != VINF_SUCCESS) 2211 2273 { … … 2221 2283 } 2222 2284 2223 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_MEM_IO, 32,2224 PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map);2225 if (RT_FAILURE(rc))2226 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: cannot register PCI mmio address space"));2227 2228 2285 #ifdef BOOTABLE_SUPPORT_TBD 2229 2286 if (fBootable) … … 2231 2288 /* Register I/O port space for BIOS access. */ 2232 2289 rc = PDMDevHlpIOPortRegister(pDevIns, VIRTIOSCSI_BIOS_IO_PORT, 4, NULL, 2233 virtioScsi R3BiosIoPortWrite, virtioScsiR3BiosIoPortRead,2234 virtioScsi R3BiosIoPortWriteStr, virtioScsiR3BiosIoPortReadStr,2290 virtioScsiBiosIoPortWrite, virtioScsiBiosIoPortRead, 2291 virtioScsiBiosIoPortWriteStr, virtioScsiBiosIoPortReadStr, 2235 2292 "virtio-scsi BIOS"); 2236 2293 if (RT_FAILURE(rc)) … … 2249 2306 /* Initialize static parts of the device. */ 2250 2307 pTarget->iLUN = iLUN; 2251 pTarget->pVirtioScsi R3= pThis;2252 2253 pTarget->IBase.pfnQueryInterface = virtioScsi R3TargetQueryInterface;2308 pTarget->pVirtioScsi = pThis; 2309 2310 pTarget->IBase.pfnQueryInterface = virtioScsiTargetQueryInterface; 2254 2311 2255 2312 /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */ 2256 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsi R3QueryDeviceLocation;2257 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsi R3IoReqCompleteNotify;2258 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsi R3IoReqCopyFromBuf;2259 pTarget->IMediaExPort.pfnIoReqCopyToBuf = virtioScsi R3IoReqCopyToBuf;2260 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsi R3IoReqStateChanged;2261 pTarget->IMediaExPort.pfnMediumEjected = virtioScsi R3MediumEjected;2313 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsiQueryDeviceLocation; 2314 pTarget->IMediaExPort.pfnIoReqCompleteNotify = virtioScsiIoReqFinish; 2315 pTarget->IMediaExPort.pfnIoReqCopyFromBuf = virtioScsiIoReqCopyFromBuf; 2316 pTarget->IMediaExPort.pfnIoReqCopyToBuf = virtioScsiIoReqCopyToBuf; 2317 pTarget->IMediaExPort.pfnIoReqStateChanged = virtioScsiIoReqStateChanged; 2318 pTarget->IMediaExPort.pfnMediumEjected = virtioScsiMediumEjected; 2262 2319 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL; /* When used avoids copyFromBuf CopyToBuf*/ 2263 2320 pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 2264 2321 2265 2322 2266 pTarget->IBase.pfnQueryInterface = virtioScsi R3TargetQueryInterface;2267 pTarget->ILed.pfnQueryStatusLed = virtioScsi R3TargetQueryStatusLed;2268 pThis->ILeds.pfnQueryStatusLed = virtioScsi R3DeviceQueryStatusLed;2323 pTarget->IBase.pfnQueryInterface = virtioScsiTargetQueryInterface; 2324 pTarget->ILed.pfnQueryStatusLed = virtioScsiTargetQueryStatusLed; 2325 pThis->ILeds.pfnQueryStatusLed = virtioScsiDeviceQueryStatusLed; 2269 2326 pTarget->led.u32Magic = PDMLED_MAGIC; 2270 2327 … … 2327 2384 char szTmp[128]; 2328 2385 RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance); 2329 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsi R3Info);2386 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiInfo); 2330 2387 2331 2388 return rc; … … 2341 2398 /* .szName = */ "virtio-scsi", 2342 2399 #ifdef VIRTIOSCSI_GC_SUPPORT 2343 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0, 2400 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0 2401 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION 2402 | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION, 2344 2403 #else 2345 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS, 2404 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS 2405 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION 2406 | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION, 2346 2407 #endif 2347 2408 /* .fClass = */ PDM_DEVREG_CLASS_MISC, … … 2358 2419 /* .pfnConstruct = */ virtioScsiConstruct, 2359 2420 /* .pfnDestruct = */ virtioScsiDestruct, 2360 /* .pfnRelocate = */ virtioScsiR 3Relocate,2421 /* .pfnRelocate = */ virtioScsiRelocate, 2361 2422 /* .pfnMemSetup = */ NULL, 2362 /* .pfnPowerOn = */ NULL,2363 /* .pfnReset = */ virtioScsiR 3PDMReset,2364 /* .pfnSuspend = */ NULL,2365 /* .pfnResume = */ NULL,2366 /* .pfnAttach = */ virtioScsi R3Attach,2367 /* .pfnDetach = */ virtioScsi R3Detach,2423 /* .pfnPowerOn = */ virtioScsiPowerOn, 2424 /* .pfnReset = */ virtioScsiReset, 2425 /* .pfnSuspend = */ virtioScsiSuspend, 2426 /* .pfnResume = */ virtioScsiResume, 2427 /* .pfnAttach = */ virtioScsiAttach, 2428 /* .pfnDetach = */ virtioScsiDetach, 2368 2429 /* .pfnQueryInterface = */ NULL, 2369 2430 /* .pfnInitComplete = */ NULL, 2370 /* .pfnPowerOff = */ NULL,2431 /* .pfnPowerOff = */ virtioScsiPowerOff, 2371 2432 /* .pfnSoftReset = */ NULL, 2372 2433 /* .pfnReserved0 = */ NULL,
Note:
See TracChangeset
for help on using the changeset viewer.