- Timestamp:
- Oct 3, 2016 4:23:11 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
r64093 r64132 24 24 #include <VBox/vmm/pdmdrv.h> 25 25 #include <VBox/vmm/pdmifs.h> 26 #include <VBox/vmm/pdmqueue.h> 26 27 #include <VBox/vmm/pdmstorageifs.h> 27 28 #include <VBox/vmm/pdmthread.h> … … 40 41 /** The maximum number of release log entries per device. */ 41 42 #define MAX_LOG_REL_ERRORS 1024 43 44 /** 45 * Eject state. 46 */ 47 typedef struct DRVSCSIEJECTSTATE 48 { 49 /** The item core for the PDM queue. */ 50 PDMQUEUEITEMCORE Core; 51 /** Event semaphore to signal when complete. */ 52 RTSEMEVENT hSemEvt; 53 } DRVSCSIEJECTSTATE; 54 typedef DRVSCSIEJECTSTATE *PDRVSCSIEJECTSTATE; 42 55 43 56 /** … … 89 102 /** Pointer to the extended media port interface of the device above. */ 90 103 PPDMIMEDIAEXPORT pDevMediaExPort; 104 /** Pointer to the media port interface of the device above. */ 105 PPDMIMEDIAPORT pDevMediaPort; 91 106 /** pointer to the Led port interface of the dveice above. */ 92 107 PPDMILEDPORTS pLedPort; 93 108 /** The scsi connector interface .*/ 94 109 PDMISCSICONNECTOR ISCSIConnector; 110 /** The media interface for the device above. */ 111 PDMIMEDIA IMedia; 95 112 /** The extended media interface for the device above. */ 96 113 PDMIMEDIAEX IMediaEx; … … 125 142 /** Errors printed in the release log. */ 126 143 unsigned cErrors; 127 /** Medium is readonly */128 bool fReadonly;129 144 130 145 /** Size of the I/O request to allocate. */ 131 146 size_t cbIoReqAlloc; 147 /** Size of a VSCSI I/O request. */ 148 size_t cbVScsiIoReqAlloc; 149 /** Queue to defer unmounting to EMT. */ 150 PPDMQUEUE pQueue; 132 151 } DRVSCSI, *PDRVSCSI; 133 152 … … 167 186 168 187 /* We need to store the I/O request handle so we can get it when VSCSI queues an I/O request. */ 169 return pThis->pDrvMediaEx->pfnIoReqAllocSizeSet(pThis->pDrvMediaEx, cbVScsiIoReqAlloc + sizeof(PDMMEDIAEXIOREQ)); 188 int rc = pThis->pDrvMediaEx->pfnIoReqAllocSizeSet(pThis->pDrvMediaEx, cbVScsiIoReqAlloc + sizeof(PDMMEDIAEXIOREQ)); 189 if (RT_SUCCESS(rc)) 190 pThis->cbVScsiIoReqAlloc = cbVScsiIoReqAlloc + sizeof(PDMMEDIAEXIOREQ); 191 192 return rc; 170 193 } 171 194 … … 245 268 246 269 return VINF_SUCCESS; 270 } 271 272 /** @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumEject} */ 273 static DECLCALLBACK(int) drvscsiEject(VSCSILUN hVScsiLun, void *pvScsiLunUser) 274 { 275 RT_NOREF(hVScsiLun); 276 PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser; 277 int rc = VINF_SUCCESS; 278 RTSEMEVENT hSemEvt = NIL_RTSEMEVENT; 279 280 /* This must be done from EMT. */ 281 rc = RTSemEventCreate(&hSemEvt); 282 if (RT_SUCCESS(rc)) 283 { 284 PDRVSCSIEJECTSTATE pEjectState = (PDRVSCSIEJECTSTATE)PDMQueueAlloc(pThis->pQueue); 285 if (pEjectState) 286 { 287 pEjectState->hSemEvt = hSemEvt; 288 PDMQueueInsert(pThis->pQueue, &pEjectState->Core); 289 290 /* Wait for completion. */ 291 rc = RTSemEventWait(pEjectState->hSemEvt, RT_INDEFINITE_WAIT); 292 } 293 else 294 rc = VERR_NO_MEMORY; 295 296 RTSemEventDestroy(pEjectState->hSemEvt); 297 } 298 299 return rc; 247 300 } 248 301 … … 379 432 *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL; 380 433 381 if (pThis-> fReadonly)434 if (pThis->pDrvMedia->pfnIsReadOnly(pThis->pDrvMedia)) 382 435 *pfFeatures |= VSCSI_LUN_FEATURE_READONLY; 383 436 … … 640 693 } 641 694 695 /* -=-=-=-=- IMedia -=-=-=-=- */ 696 697 /** @interface_method_impl{PDMIMEDIA,pfnGetType} */ 698 static DECLCALLBACK(PDMMEDIATYPE) drvscsiGetType(PPDMIMEDIA pInterface) 699 { 700 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMedia); 701 VSCSILUNTYPE enmLunType; 702 703 int rc = VSCSIDeviceLunQueryType(pThis->hVScsiDevice, 0, &enmLunType); 704 if (RT_FAILURE(rc)) 705 return PDMMEDIATYPE_ERROR; 706 707 switch (enmLunType) 708 { 709 case VSCSILUNTYPE_SBC: 710 return PDMMEDIATYPE_HARD_DISK; 711 case VSCSILUNTYPE_MMC: 712 return PDMMEDIATYPE_CDROM; 713 default: 714 return PDMMEDIATYPE_ERROR; 715 } 716 717 return PDMMEDIATYPE_ERROR; 718 } 719 720 /** @interface_method_impl{PDMIMEDIA,pfnGetUuid} */ 721 static DECLCALLBACK(int) drvscsiGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid) 722 { 723 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMedia); 724 725 int rc = VINF_SUCCESS; 726 if (pThis->pDrvMedia) 727 rc = pThis->pDrvMedia->pfnGetUuid(pThis->pDrvMedia, pUuid); 728 else 729 RTUuidClear(pUuid); 730 731 return rc; 732 } 733 642 734 /* -=-=-=-=- IMediaEx -=-=-=-=- */ 643 735 … … 706 798 { 707 799 RT_NOREF1(pInterface); 708 return V ERR_NOT_IMPLEMENTED;800 return VINF_SUCCESS; 709 801 } 710 802 … … 713 805 { 714 806 RT_NOREF2(pInterface, uIoReqId); 715 return VERR_ NOT_IMPLEMENTED;807 return VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND; 716 808 } 717 809 … … 756 848 int rc = VINF_SUCCESS; 757 849 850 Log(("Dump for pReq=%#p Command: %s\n", pReq, SCSICmdText(pbCdb[0]))); 851 Log(("cbCdb=%u\n", cbCdb)); 852 for (uint32_t i = 0; i < cbCdb; i++) 853 Log(("pbCdb[%u]=%#x\n", i, pbCdb[i])); 854 Log(("cbBuf=%zu\n", cbBuf)); 855 758 856 pReq->enmXferDir = enmTxDir; 759 857 pReq->cbBuf = cbBuf; … … 773 871 pReq->Seg.cbSeg = cbBuf; 774 872 775 if ( enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN 776 || enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE) 873 if ( cbBuf 874 && ( enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN 875 || enmTxDir == PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE)) 777 876 { 778 877 RTSGBUF SgBuf; … … 875 974 } 876 975 976 /** 977 * Consumer for the queue 978 * 979 * @returns Success indicator. 980 * If false the item will not be removed and the flushing will stop. 981 * @param pDrvIns The driver instance. 982 * @param pItem The item to consume. Upon return this item will be freed. 983 */ 984 static DECLCALLBACK(bool) drvscsiR3NotifyQueueConsumer(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItem) 985 { 986 PDRVSCSIEJECTSTATE pEjectState = (PDRVSCSIEJECTSTATE)pItem; 987 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 988 989 int rc = pThis->pDrvMount->pfnUnmount(pThis->pDrvMount, false/*=fForce*/, true/*=fEject*/); 990 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED); 991 if (RT_SUCCESS(rc)) 992 { 993 if (pThis->pDevMediaExPort) 994 pThis->pDevMediaExPort->pfnMediumEjected(pThis->pDevMediaExPort); 995 } 996 997 RTSemEventSignal(pEjectState->hSemEvt); 998 return true; 999 } 1000 877 1001 /* -=-=-=-=- IBase -=-=-=-=- */ 878 1002 … … 889 1013 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSICONNECTOR, &pThis->ISCSIConnector); 890 1014 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEX, pThis->pDevMediaExPort ? &pThis->IMediaEx : NULL); 1015 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, pThis->pDevMediaPort ? &pThis->IMedia : NULL); 891 1016 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IPort); 892 1017 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pThis->IMountNotify); … … 901 1026 PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IPort); 902 1027 903 return pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, ppcszController, 904 piInstance, piLUN); 1028 if (pThis->pDevScsiPort) 1029 return pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, ppcszController, 1030 piInstance, piLUN); 1031 if (pThis->pDevMediaPort) 1032 return pThis->pDevMediaPort->pfnQueryDeviceLocation(pThis->pDevMediaPort, ppcszController, 1033 piInstance, piLUN); 1034 1035 return VERR_NOT_SUPPORTED; 905 1036 } 906 1037 … … 999 1130 else 1000 1131 return true; 1132 } 1133 1134 /** @copydoc FNPDMDRVATTACH */ 1135 static DECLCALLBACK(int) drvscsiAttach(PPDMDRVINS pDrvIns, uint32_t fFlags) 1136 { 1137 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 1138 1139 LogFlowFunc(("pDrvIns=%#p fFlags=%#x\n", pDrvIns, fFlags)); 1140 1141 AssertMsgReturn((fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG), 1142 ("SCSI: Hotplugging is not supported\n"), 1143 VERR_INVALID_PARAMETER); 1144 1145 /* 1146 * Try attach driver below and query it's media interface. 1147 */ 1148 int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pThis->pDrvBase); 1149 AssertMsgReturn(RT_SUCCESS(rc), ("Attaching driver below failed rc=%Rrc\n", rc), rc); 1150 1151 /* 1152 * Query the media interface. 1153 */ 1154 pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIA); 1155 AssertMsgReturn(VALID_PTR(pThis->pDrvMedia), ("VSCSI configuration error: No media interface!\n"), 1156 VERR_PDM_MISSING_INTERFACE); 1157 1158 /* Query the extended media interface. */ 1159 pThis->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIAEX); 1160 AssertMsgReturn(VALID_PTR(pThis->pDrvMediaEx), ("VSCSI configuration error: No extended media interface!\n"), 1161 VERR_PDM_MISSING_INTERFACE); 1162 1163 pThis->pDrvMount = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMOUNT); 1164 1165 if (pThis->cbVScsiIoReqAlloc) 1166 { 1167 rc = pThis->pDrvMediaEx->pfnIoReqAllocSizeSet(pThis->pDrvMediaEx, pThis->cbVScsiIoReqAlloc); 1168 AssertMsgReturn(RT_SUCCESS(rc), ("Setting the I/O request allocation size failed with rc=%Rrc\n", rc), rc); 1169 } 1170 1171 if (pThis->pDrvMount) 1172 { 1173 if (pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia)) 1174 { 1175 rc = VINF_SUCCESS; VSCSILunMountNotify(pThis->hVScsiLun); 1176 AssertMsgReturn(RT_SUCCESS(rc), ("Failed to notify the LUN of media being mounted\n"), rc); 1177 } 1178 else 1179 { 1180 rc = VINF_SUCCESS; VSCSILunUnmountNotify(pThis->hVScsiLun); 1181 AssertMsgReturn(RT_SUCCESS(rc), ("Failed to notify the LUN of media being unmounted\n"), rc); 1182 } 1183 } 1184 1185 return rc; 1186 } 1187 1188 /** @copydoc FNPDMDRVDETACH */ 1189 static DECLCALLBACK(void) drvscsiDetach(PPDMDRVINS pDrvIns, uint32_t fFlags) 1190 { 1191 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 1192 1193 LogFlowFunc(("pDrvIns=%#p fFlags=%#x\n", pDrvIns, fFlags)); 1194 1195 AssertMsgReturnVoid((fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG), 1196 ("SCSI: Hotplugging is not supported\n")); 1197 1198 /* 1199 * Zero some important members. 1200 */ 1201 pThis->pDrvBase = NULL; 1202 pThis->pDrvMedia = NULL; 1203 pThis->pDrvMediaEx = NULL; 1204 pThis->pDrvMount = NULL; 1001 1205 } 1002 1206 … … 1064 1268 1065 1269 pDrvIns->IBase.pfnQueryInterface = drvscsiQueryInterface; 1270 1271 /* IMedia */ 1272 pThis->IMedia.pfnRead = NULL; 1273 pThis->IMedia.pfnReadPcBios = NULL; 1274 pThis->IMedia.pfnWrite = NULL; 1275 pThis->IMedia.pfnFlush = NULL; 1276 pThis->IMedia.pfnSendCmd = NULL; 1277 pThis->IMedia.pfnMerge = NULL; 1278 pThis->IMedia.pfnSetSecKeyIf = NULL; 1279 pThis->IMedia.pfnGetSize = NULL; 1280 pThis->IMedia.pfnGetSectorSize = NULL; 1281 pThis->IMedia.pfnIsReadOnly = NULL; 1282 pThis->IMedia.pfnBiosGetPCHSGeometry = NULL; 1283 pThis->IMedia.pfnBiosSetPCHSGeometry = NULL; 1284 pThis->IMedia.pfnBiosGetLCHSGeometry = NULL; 1285 pThis->IMedia.pfnBiosSetLCHSGeometry = NULL; 1286 pThis->IMedia.pfnBiosIsVisible = NULL; 1287 pThis->IMedia.pfnGetType = drvscsiGetType; 1288 pThis->IMedia.pfnGetUuid = drvscsiGetUuid; 1289 pThis->IMedia.pfnDiscard = NULL; 1066 1290 1067 1291 /* IMediaEx */ … … 1094 1318 pThis->IPortEx.pfnIoReqStateChanged = drvscsiIoReqStateChanged; 1095 1319 1096 /* Query the SCSI port interface above. */1320 /* Query the optional SCSI port interface above. */ 1097 1321 pThis->pDevScsiPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISCSIPORT); 1098 AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE); 1322 1323 /* Query the optional media port interface above. */ 1324 pThis->pDevMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT); 1099 1325 1100 1326 /* Query the optional extended media port interface above. */ 1101 1327 pThis->pDevMediaExPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT); 1328 1329 AssertMsgReturn(pThis->pDevScsiPort || pThis->pDevMediaExPort, 1330 ("Missing SCSI or extended media port interface above\n"), VERR_PDM_MISSING_INTERFACE); 1102 1331 1103 1332 /* Query the optional LED interface above. */ … … 1116 1345 * Validate and read configuration. 1117 1346 */ 1118 if (!CFGMR3AreValuesValid(pCfg, " Readonly\0"))1347 if (!CFGMR3AreValuesValid(pCfg, "")) 1119 1348 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, 1120 1349 N_("SCSI configuration error: unknown option specified")); 1121 1350 1122 rc = CFGMR3QueryBoolDef(pCfg, "Readonly", &pThis->fReadonly, false);1123 if (RT_FAILURE(rc))1124 return PDMDRV_SET_ERROR(pDrvIns, rc,1125 N_("SCSI configuration error: failed to read \"Readonly\" as boolean"));1126 1127 1351 /* 1128 * Try attach driver below and query it's blockinterface.1352 * Try attach driver below and query it's media interface. 1129 1353 */ 1130 1354 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pThis->pDrvBase); … … 1132 1356 1133 1357 /* 1134 * Query the block and blockbios interfaces.1358 * Query the media interface. 1135 1359 */ 1136 1360 pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIA); … … 1175 1399 pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize = drvscsiGetSize; 1176 1400 pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSectorSize = drvscsiGetSectorSize; 1401 pThis->VScsiIoCallbacks.pfnVScsiLunMediumEject = drvscsiEject; 1177 1402 pThis->VScsiIoCallbacks.pfnVScsiLunReqTransferEnqueue = drvscsiReqTransferEnqueue; 1178 1403 pThis->VScsiIoCallbacks.pfnVScsiLunGetFeatureFlags = drvscsiGetFeatureFlags; … … 1211 1436 uint32_t iCtrlLun = 0; 1212 1437 1213 rc = pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, &pszCtrl, &iCtrlInstance, &iCtrlLun); 1438 if (pThis->pDevScsiPort) 1439 rc = pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, &pszCtrl, &iCtrlInstance, &iCtrlLun); 1440 if (pThis->pDevMediaPort) 1441 rc = pThis->pDevMediaPort->pfnQueryDeviceLocation(pThis->pDevMediaPort, &pszCtrl, &iCtrlInstance, &iCtrlLun); 1214 1442 if (RT_SUCCESS(rc)) 1215 1443 { … … 1235 1463 if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD) 1236 1464 LogRel(("SCSI#%d: Enabled UNMAP support\n", pDrvIns->iInstance)); 1465 1466 rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVSCSIEJECTSTATE), 1, 0, drvscsiR3NotifyQueueConsumer, 1467 "SCSI-Eject", &pThis->pQueue); 1468 if (RT_FAILURE(rc)) 1469 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 1470 N_("VSCSI configuration error: Failed to create notification queue")); 1237 1471 1238 1472 return VINF_SUCCESS; … … 1279 1513 NULL, 1280 1514 /* pfnAttach */ 1281 NULL,1515 drvscsiAttach, 1282 1516 /* pfnDetach */ 1283 NULL,1517 drvscsiDetach, 1284 1518 /* pfnPowerOff */ 1285 1519 drvscsiPowerOff, -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
r64064 r64132 473 473 474 474 /** 475 * Wrapper for the eject medium I/O callback. 476 * 477 * @returns VBox status code. 478 * @param pVScsiLun The LUN. 479 */ 480 DECLINLINE(int) vscsiLunMediumEject(PVSCSILUNINT pVScsiLun) 481 { 482 return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunMediumEject(pVScsiLun, 483 pVScsiLun->pvVScsiLunUser); 484 } 485 486 /** 475 487 * Wrapper for the I/O request enqueue I/O callback. 476 488 * -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
r64065 r64132 1028 1028 case SCSI_START_STOP_UNIT: 1029 1029 { 1030 /** @todo: Improve START STOP UNIT */ 1031 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1030 int rc2 = VINF_SUCCESS; 1031 switch (pVScsiReq->pbCDB[4] & 3) 1032 { 1033 case 0: /* 00 - Stop motor */ 1034 case 1: /* 01 - Start motor */ 1035 break; 1036 case 2: /* 10 - Eject media */ 1037 rc2 = vscsiLunMediumEject(pVScsiLun); 1038 break; 1039 case 3: /* 11 - Load media */ 1040 /** @todo */ 1041 break; 1042 } 1043 if (RT_SUCCESS(rc2)) 1044 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1045 else 1046 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED, 0x02); 1032 1047 break; 1033 1048 } … … 1084 1099 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 1085 1100 { 1086 pVScsiLunMmc->fLocked = pVScsiReq->pbCDB[4] & 1;1101 pVScsiLunMmc->fLocked = RT_BOOL(pVScsiReq->pbCDB[4] & 0x01); 1087 1102 vscsiLunMediumSetLock(pVScsiLun, pVScsiLunMmc->fLocked); 1088 1103 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
Note:
See TracChangeset
for help on using the changeset viewer.