Changeset 64222 in vbox
- Timestamp:
- Oct 12, 2016 12:40:16 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/UsbMsd.cpp
r63482 r64222 53 53 54 54 /** Saved state version. */ 55 #define USB_MSD_SAVED_STATE_VERSION 1 55 #define USB_MSD_SAVED_STATE_VERSION 2 56 /** Saved state vesion before the cleanup. */ 57 #define USB_MSD_SAVED_STATE_VERSION_PRE_CLEANUP 1 56 58 57 59 … … 145 147 /** The state of the request. */ 146 148 USBMSDREQSTATE enmState; 149 /** The I/O requesthandle .*/ 150 PDMMEDIAEXIOREQ hIoReq; 147 151 /** The size of the data buffer. */ 148 152 uint32_t cbBuf; … … 153 157 /** The current Cbw when we're in the pending state. */ 154 158 USBCBW Cbw; 155 /** The current SCSI request. */156 PDMSCSIREQUEST ScsiReq;157 /** The scatter-gather segment used by ScsiReq for describing pbBuf. */158 RTSGSEG ScsiReqSeg;159 /** The sense buffer for the current SCSI request. */160 uint8_t ScsiReqSense[64];161 159 /** The status of a completed SCSI request. */ 162 int iScsiReqStatus; 163 /** Pointer to the USB device instance owning it. */ 164 PPDMUSBINS pUsbIns; 160 uint8_t iScsiReqStatus; 165 161 } USBMSDREQ; 166 162 /** Pointer to a USB MSD request. */ … … 208 204 * (0 - default, 1 - the only, i.e configured.) */ 209 205 uint8_t bConfigurationValue; 210 #if 0211 /** The state of the MSD (state machine).*/212 USBMSDSTATE enmState;213 #endif214 206 /** Endpoint 0 is the default control pipe, 1 is the host->dev bulk pipe and 2 215 207 * is the dev->host one. */ … … 255 247 /** The base interface for LUN\#0. */ 256 248 PDMIBASE IBase; 257 /** The SCSI port interface for LUN\#0 */ 258 PDMISCSIPORT IScsiPort; 249 /** The media port interface fo LUN\#0. */ 250 PDMIMEDIAPORT IMediaPort; 251 /** The extended media port interface for LUN\#0 */ 252 PDMIMEDIAEXPORT IMediaExPort; 259 253 260 254 /** The base interface for the SCSI driver connected to LUN\#0. */ 261 255 PPDMIBASE pIBase; 262 /** The SCSI connector interface for the SCSI driver connected to LUN\#0. */ 263 PPDMISCSICONNECTOR pIScsiConnector; 256 /** The media interface for th SCSI drver conected to LUN\#0. */ 257 PPDMIMEDIA pIMedia; 258 /** The extended media inerface for the SCSI driver connected to LUN\#0. */ 259 PPDMIMEDIAEX pIMediaEx; 264 260 } Lun0; 265 261 … … 818 814 * 819 815 * @returns Pointer to the new request. NULL if we're out of memory. 820 * @param pUsbIns The instance allocating it. 821 */ 822 static PUSBMSDREQ usbMsdReqAlloc(PPDMUSBINS pUsbIns) 823 { 824 PUSBMSDREQ pReq = (PUSBMSDREQ)PDMUsbHlpMMHeapAllocZ(pUsbIns, sizeof(*pReq)); 825 if (pReq) 826 { 827 pReq->enmState = USBMSDREQSTATE_READY; 828 pReq->iScsiReqStatus = -1; 829 pReq->pUsbIns = pUsbIns; 816 * @param pThis The MSD instance. 817 */ 818 static PUSBMSDREQ usbMsdReqAlloc(PUSBMSD pThis) 819 { 820 PUSBMSDREQ pReq = NULL; 821 PDMMEDIAEXIOREQ hIoReq = NULL; 822 823 int rc = pThis->Lun0.pIMediaEx->pfnIoReqAlloc(pThis->Lun0.pIMediaEx, &hIoReq, (void **)&pReq, 824 0 /* uTag */, PDMIMEDIAEX_F_DEFAULT); 825 if (RT_SUCCESS(rc)) 826 { 827 pReq->hIoReq = hIoReq; 828 pReq->enmState = USBMSDREQSTATE_READY; 829 pReq->iScsiReqStatus = 0xff; 830 830 } 831 831 else 832 LogRel(("usbMsdReqAlloc: Out of memory\n")); 832 LogRel(("usbMsdReqAlloc: Out of memory (%Rrc)\n", rc)); 833 833 834 return pReq; 834 835 } … … 838 839 * Frees a request. 839 840 * 841 * @param pThis The MSD instance. 840 842 * @param pReq The request. 841 843 */ 842 static void usbMsdReqFree(PUSBMSD REQ pReq)844 static void usbMsdReqFree(PUSBMSD pThis, PUSBMSDREQ pReq) 843 845 { 844 846 /* … … 848 850 && pReq->enmState != USBMSDREQSTATE_EXECUTING 849 851 && pReq->enmState < USBMSDREQSTATE_END); 850 PPDMUSBINS pUsbIns = p Req->pUsbIns;852 PPDMUSBINS pUsbIns = pThis->pUsbIns; 851 853 AssertPtrReturnVoid(pUsbIns); 852 854 AssertReturnVoid(PDM_VERSION_ARE_COMPATIBLE(pUsbIns->u32Version, PDM_USBINS_VERSION)); … … 855 857 * Invalidate it and free the associated resources. 856 858 */ 857 pReq->enmState = USBMSDREQSTATE_INVALID; 858 pReq->cbBuf = 0; 859 pReq->offBuf = 0; 860 pReq->ScsiReq.pbCDB = NULL; 861 pReq->ScsiReq.paScatterGatherHead = NULL; 862 pReq->ScsiReq.pbSenseBuffer = NULL; 863 pReq->ScsiReq.pvUser = NULL; 864 pReq->ScsiReqSeg.cbSeg = 0; 865 pReq->ScsiReqSeg.pvSeg = NULL; 859 pReq->enmState = USBMSDREQSTATE_INVALID; 860 pReq->cbBuf = 0; 861 pReq->offBuf = 0; 866 862 867 863 if (pReq->pbBuf) … … 871 867 } 872 868 873 PDMUsbHlpMMHeapFree(pUsbIns, pReq); 869 int rc = pThis->Lun0.pIMediaEx->pfnIoReqFree(pThis->Lun0.pIMediaEx, pReq->hIoReq); 870 AssertRC(rc); 874 871 } 875 872 … … 889 886 890 887 /* Setup the SCSI request. */ 891 pReq->ScsiReq.uLogicalUnit = pReq->Cbw.bCBWLun; 892 pReq->ScsiReq.uDataDirection = (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT 893 ? PDMSCSIREQUESTTXDIR_TO_DEVICE 894 : PDMSCSIREQUESTTXDIR_FROM_DEVICE; 895 pReq->ScsiReq.cbCDB = pReq->Cbw.bCBWCBLength; 896 897 pReq->ScsiReq.pbCDB = &pReq->Cbw.CBWCB[0]; 898 pReq->offBuf = 0; 899 pReq->ScsiReqSeg.pvSeg = pReq->pbBuf; 900 pReq->ScsiReqSeg.cbSeg = pReq->Cbw.dCBWDataTransferLength; 901 pReq->ScsiReq.cbScatterGather = pReq->Cbw.dCBWDataTransferLength; 902 pReq->ScsiReq.cScatterGatherEntries = 1; 903 pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg; 904 pReq->ScsiReq.cbSenseBuffer = sizeof(pReq->ScsiReqSense); 905 pReq->ScsiReq.pbSenseBuffer = &pReq->ScsiReqSense[0]; 906 pReq->ScsiReq.pvUser = NULL; 907 RT_ZERO(pReq->ScsiReqSense); 908 pReq->iScsiReqStatus = -1; 888 pReq->offBuf = 0; 889 pReq->iScsiReqStatus = 0xff; 909 890 } 910 891 … … 914 895 * 915 896 * @returns Success indicator (true/false) 916 * @param pReq 917 * @param cbBuf The required buffer space. 918 */ 919 static int usbMsdReqEnsureBuffer(PUSBMSDREQ pReq, uint32_t cbBuf) 897 * @param pThis The MSD instance. 898 * @param pReq The request. 899 * @param cbBuf The required buffer space. 900 */ 901 static int usbMsdReqEnsureBuffer(PUSBMSD pThis, PUSBMSDREQ pReq, uint32_t cbBuf) 920 902 { 921 903 if (RT_LIKELY(pReq->cbBuf >= cbBuf)) … … 923 905 else 924 906 { 925 PDMUsbHlpMMHeapFree(p Req->pUsbIns, pReq->pbBuf);907 PDMUsbHlpMMHeapFree(pThis->pUsbIns, pReq->pbBuf); 926 908 pReq->cbBuf = 0; 927 909 928 910 cbBuf = RT_ALIGN_Z(cbBuf, 0x1000); 929 pReq->pbBuf = (uint8_t *)PDMUsbHlpMMHeapAllocZ(p Req->pUsbIns, cbBuf);911 pReq->pbBuf = (uint8_t *)PDMUsbHlpMMHeapAllocZ(pThis->pUsbIns, cbBuf); 930 912 if (!pReq->pbBuf) 931 913 return false; … … 1015 997 1016 998 /* Device reset: Wait for up to 10 ms. If it doesn't work, ditch 1017 who e the request structure. We'll allocate a new one when needed. */999 whole the request structure. We'll allocate a new one when needed. */ 1018 1000 Log(("usbMsdResetWorker: Waiting for completion...\n")); 1019 1001 Assert(!pThis->fSignalResetSem); … … 1043 1025 { 1044 1026 pReq->enmState = USBMSDREQSTATE_READY; 1045 pReq->iScsiReqStatus = -1;1027 pReq->iScsiReqStatus = 0xff; 1046 1028 } 1047 1029 … … 1077 1059 1078 1060 /** 1079 * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted} 1080 */ 1081 static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, 1082 int rcCompletion, bool fRedo, int rcReq) 1083 { 1084 RT_NOREF(fRedo, rcReq); 1085 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort); 1086 PUSBMSDREQ pReq = RT_FROM_MEMBER(pSCSIRequest, USBMSDREQ, ScsiReq); 1087 1088 Log(("usbMsdLun0ScsiRequestCompleted: pReq=%p dCBWTag=%#x iScsiReqStatus=%u \n", pReq, pReq->Cbw.dCBWTag, rcCompletion)); 1061 * Process a completed request. 1062 * 1063 * @returns nothing. 1064 * @param pThis The MSD instance. 1065 * @param pReq The request. 1066 * @param rcReq The completion status. 1067 */ 1068 static void usbMsdReqComplete(PUSBMSD pThis, PUSBMSDREQ pReq, int rcReq) 1069 { 1070 RT_NOREF1(rcReq); 1071 1072 Log(("usbMsdLun0IoReqCompleteNotify: pReq=%p dCBWTag=%#x iScsiReqStatus=%u \n", pReq, pReq->Cbw.dCBWTag, pReq->iScsiReqStatus)); 1089 1073 RTCritSectEnter(&pThis->CritSect); 1090 1074 … … 1093 1077 Assert(pReq->enmState == USBMSDREQSTATE_EXECUTING); 1094 1078 Assert(pThis->pReq == pReq); 1095 pReq->iScsiReqStatus = rcCompletion;1096 1079 1097 1080 /* … … 1102 1085 { 1103 1086 pReq->enmState = USBMSDREQSTATE_STATUS; 1104 Log(("usbMsdLun0 ScsiRequestCompleted: Entering STATUS\n"));1087 Log(("usbMsdLun0IoReqCompleteNotify: Entering STATUS\n")); 1105 1088 } 1106 1089 else 1107 1090 { 1108 1091 pReq->enmState = USBMSDREQSTATE_DATA_TO_HOST; 1109 Log(("usbMsdLun0 ScsiRequestCompleted: Entering DATA_TO_HOST\n"));1092 Log(("usbMsdLun0IoReqCompleteNotify: Entering DATA_TO_HOST\n")); 1110 1093 } 1111 1094 … … 1125 1108 else 1126 1109 { 1127 Log(("usbMsdLun0 ScsiRequestCompleted: freeing %p\n", pReq));1128 usbMsdReqFree(p Req);1110 Log(("usbMsdLun0IoReqCompleteNotify: freeing %p\n", pReq)); 1111 usbMsdReqFree(pThis, pReq); 1129 1112 } 1130 1113 … … 1139 1122 1140 1123 RTCritSectLeave(&pThis->CritSect); 1124 } 1125 1126 1127 /** 1128 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 1129 */ 1130 static DECLCALLBACK(int) usbMsdLun0IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1131 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 1132 size_t cbCopy) 1133 { 1134 RT_NOREF2(pInterface, hIoReq); 1135 int rc = VINF_SUCCESS; 1136 PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc; 1137 1138 if (RT_UNLIKELY(offDst + cbCopy > pReq->cbBuf)) 1139 rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 1140 else 1141 { 1142 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, pReq->pbBuf + offDst, cbCopy); 1143 Assert(cbCopied == cbCopy); 1144 } 1145 1146 return rc; 1147 } 1148 1149 1150 /** 1151 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 1152 */ 1153 static DECLCALLBACK(int) usbMsdLun0IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1154 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 1155 size_t cbCopy) 1156 { 1157 RT_NOREF2(pInterface, hIoReq); 1158 int rc = VINF_SUCCESS; 1159 PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc; 1160 1161 if (RT_UNLIKELY(offSrc + cbCopy > pReq->cbBuf)) 1162 rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 1163 else 1164 { 1165 size_t cbCopied = RTSgBufCopyFromBuf(pSgBuf, pReq->pbBuf + offSrc, cbCopy); 1166 Assert(cbCopied == cbCopy); 1167 } 1168 1169 return rc; 1170 } 1171 1172 1173 /** 1174 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 1175 */ 1176 static DECLCALLBACK(int) usbMsdLun0IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1177 void *pvIoReqAlloc, int rcReq) 1178 { 1179 RT_NOREF1(hIoReq); 1180 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IMediaExPort); 1181 PUSBMSDREQ pReq = (PUSBMSDREQ)pvIoReqAlloc; 1182 1183 usbMsdReqComplete(pThis, pReq, rcReq); 1141 1184 return VINF_SUCCESS; 1142 1185 } … … 1144 1187 1145 1188 /** 1189 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 1190 */ 1191 static DECLCALLBACK(void) usbMsdLun0IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 1192 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 1193 { 1194 RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState); 1195 AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n")); 1196 } 1197 1198 1199 /** 1200 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 1201 */ 1202 static DECLCALLBACK(void) usbMsdLun0MediumEjected(PPDMIMEDIAEXPORT pInterface) 1203 { 1204 RT_NOREF1(pInterface); /** @todo */ 1205 } 1206 1207 1208 /** 1146 1209 * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation} 1147 1210 */ 1148 static DECLCALLBACK(int) usbMsdLun0QueryDeviceLocation(PPDMI SCSIPORT pInterface, const char **ppcszController,1211 static DECLCALLBACK(int) usbMsdLun0QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 1149 1212 uint32_t *piInstance, uint32_t *piLUN) 1150 1213 { 1151 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.I ScsiPort);1214 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IMediaPort); 1152 1215 PPDMUSBINS pUsbIns = pThis->pUsbIns; 1153 1216 … … 1171 1234 PUSBMSD pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IBase); 1172 1235 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase); 1173 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pThis->Lun0.IScsiPort); 1236 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->Lun0.IMediaPort); 1237 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pThis->Lun0.IMediaExPort); 1174 1238 return NULL; 1175 1239 } … … 1220 1284 PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncSuspendOrPowerOffDone); 1221 1285 else 1286 { 1222 1287 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 1288 1289 if (pThis->pReq) 1290 { 1291 usbMsdReqFree(pThis, pThis->pReq); 1292 pThis->pReq = NULL; 1293 } 1294 } 1223 1295 } 1224 1296 … … 1305 1377 SSMR3PutU32(pSSM, pReq->offBuf); 1306 1378 SSMR3PutMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw)); 1307 SSMR3PutU32(pSSM, pReq->ScsiReq.uLogicalUnit); 1308 SSMR3PutU32(pSSM, pReq->ScsiReq.uDataDirection); 1309 SSMR3PutU32(pSSM, pReq->ScsiReq.cbCDB); 1310 SSMR3PutU32(pSSM, pReq->ScsiReq.cbScatterGather); 1311 SSMR3PutMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense)); 1312 SSMR3PutS32(pSSM, pReq->iScsiReqStatus); 1379 SSMR3PutU8(pSSM, pReq->iScsiReqStatus); 1313 1380 } 1314 1381 … … 1351 1418 if (fReqAlloc) 1352 1419 { 1353 PUSBMSDREQ pReq = usbMsdReqAlloc(p UsbIns);1420 PUSBMSDREQ pReq = usbMsdReqAlloc(pThis); 1354 1421 AssertReturn(pReq, VERR_NO_MEMORY); 1355 1422 pThis->pReq = pReq; … … 1361 1428 if (cbBuf) 1362 1429 { 1363 if (usbMsdReqEnsureBuffer(p Req, cbBuf))1430 if (usbMsdReqEnsureBuffer(pThis, pReq, cbBuf)) 1364 1431 { 1365 1432 AssertPtr(pReq->pbBuf); … … 1373 1440 SSMR3GetU32(pSSM, &pReq->offBuf); 1374 1441 SSMR3GetMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw)); 1375 SSMR3GetU32(pSSM, &pReq->ScsiReq.uLogicalUnit); 1376 SSMR3GetU32(pSSM, (uint32_t *)&pReq->ScsiReq.uDataDirection); 1377 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbCDB); 1378 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbScatterGather); 1379 SSMR3GetMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense)); 1380 rc = SSMR3GetS32(pSSM, &pReq->iScsiReqStatus); 1442 1443 if (uVersion >= USB_MSD_SAVED_STATE_VERSION_PRE_CLEANUP) 1444 rc = SSMR3GetU8(pSSM, &pReq->iScsiReqStatus); 1445 else 1446 { 1447 int32_t iScsiReqStatus; 1448 1449 /* Skip old fields which are unused now or can be determined from the CBW. */ 1450 SSMR3Skip(pSSM, 4 * 4 + 64); 1451 rc = SSMR3GetS32(pSSM, &iScsiReqStatus); 1452 pReq->iScsiReqStatus = (uint8_t)iScsiReqStatus; 1453 } 1381 1454 AssertRCReturn(rc, rc); 1382 1383 /* Setup the rest of the SCSI request. */1384 pReq->ScsiReq.cbCDB = pReq->Cbw.bCBWCBLength;1385 pReq->ScsiReq.pbCDB = &pReq->Cbw.CBWCB[0];1386 pReq->ScsiReqSeg.pvSeg = pReq->pbBuf;1387 pReq->ScsiReqSeg.cbSeg = pReq->ScsiReq.cbScatterGather;1388 pReq->ScsiReq.cScatterGatherEntries = 1;1389 pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg;1390 pReq->ScsiReq.cbSenseBuffer = sizeof(pReq->ScsiReqSense);1391 pReq->ScsiReq.pbSenseBuffer = &pReq->ScsiReqSense[0];1392 pReq->ScsiReq.pvUser = NULL;1393 1455 } 1394 1456 … … 1463 1525 1464 1526 RTCritSectLeave(&pThis->CritSect); 1465 return VINF_SUCCESS;1466 }1467 1468 1469 /**1470 * Fails an illegal SCSI request.1471 *1472 * @returns VBox status code.1473 * @param pThis The MSD instance data.1474 * @param pReq The MSD request.1475 * @param bAsc The ASC for the SCSI_SENSE_ILLEGAL_REQUEST.1476 * @param bAscq The ASC qualifier.1477 * @param pszWhy For logging why.1478 */1479 static int usbMsdScsiIllegalRequest(PUSBMSD pThis, PUSBMSDREQ pReq, uint8_t bAsc, uint8_t bAscq, const char *pszWhy)1480 {1481 RT_NOREF(bAsc, bAscq, pszWhy);1482 Log(("usbMsdScsiIllegalRequest: bAsc=%#x bAscq=%#x %s\n", bAsc, bAscq, pszWhy));1483 1484 RT_ZERO(pReq->ScsiReqSense);1485 pReq->ScsiReqSense[0] = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;1486 pReq->ScsiReqSense[2] = SCSI_SENSE_ILLEGAL_REQUEST;1487 pReq->ScsiReqSense[7] = 10;1488 pReq->ScsiReqSense[12] = SCSI_ASC_INVALID_MESSAGE;1489 pReq->ScsiReqSense[13] = 0; /* Should be ASCQ but it has the same value for success. */1490 1491 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);1492 return VINF_SUCCESS;1493 }1494 1495 1496 /**1497 * The SCSI driver doesn't handle SCSI_REQUEST_SENSE but instead1498 * returns the sense info with the request.1499 *1500 */1501 static int usbMsdHandleScsiReqestSense(PUSBMSD pThis, PUSBMSDREQ pReq, PCUSBCBW pCbw)1502 {1503 Log(("usbMsdHandleScsiReqestSense: Entering EXECUTING (dCBWTag=%#x).\n", pReq->Cbw.dCBWTag));1504 Assert(pReq == pThis->pReq);1505 pReq->enmState = USBMSDREQSTATE_EXECUTING;1506 1507 /* validation */1508 if ((pCbw->bmCBWFlags & USBCBW_DIR_MASK) != USBCBW_DIR_IN)1509 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "direction");1510 if (pCbw->bCBWCBLength < 6)1511 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "length");1512 if ((pCbw->CBWCB[1] >> 5) != pCbw->bCBWLun)1513 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "lun");1514 if (pCbw->bCBWLun != 0)1515 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INVALID_MESSAGE, 0, "lun0");1516 if (pCbw->CBWCB[4] < 6)1517 return usbMsdScsiIllegalRequest(pThis, pReq, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0, "out length");1518 1519 /* If the previous command succeeded successfully, whip up some sense data. */1520 if ( pReq->iScsiReqStatus == SCSI_STATUS_OK1521 && pReq->ScsiReqSense[0] == 0)1522 {1523 RT_ZERO(pReq->ScsiReqSense);1524 #if 0 /** @todo something upsets linux about this stuff. Needs investigation. */1525 pReq->ScsiReqSense[0] = 0x80 | SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;1526 pReq->ScsiReqSense[0] = SCSI_SENSE_RESPONSE_CODE_CURR_FIXED;1527 pReq->ScsiReqSense[2] = SCSI_SENSE_NONE;1528 pReq->ScsiReqSense[7] = 10;1529 pReq->ScsiReqSense[12] = SCSI_ASC_NONE;1530 pReq->ScsiReqSense[13] = SCSI_ASC_NONE; /* Should be ASCQ but it has the same value for success. */1531 #endif1532 }1533 1534 /* Copy the data into the result buffer. */1535 size_t cbCopy = RT_MIN(pCbw->dCBWDataTransferLength, sizeof(pReq->ScsiReqSense));1536 Log(("usbMsd: SCSI_REQUEST_SENSE - CBWCB[4]=%#x iOldState=%d, %u bytes, raw: %.*Rhxs\n",1537 pCbw->CBWCB[4], pReq->iScsiReqStatus, pCbw->dCBWDataTransferLength, RT_MAX(1, cbCopy), pReq->ScsiReqSense));1538 memcpy(pReq->pbBuf, &pReq->ScsiReqSense[0], cbCopy);1539 1540 usbMsdReqPrepare(pReq, pCbw);1541 1542 /* Do normal completion. */1543 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);1544 1527 return VINF_SUCCESS; 1545 1528 } … … 1562 1545 pReq->enmState = USBMSDREQSTATE_EXECUTING; 1563 1546 1564 switch (pReq->ScsiReq.pbCDB[0]) 1565 { 1566 case SCSI_REQUEST_SENSE: 1567 { 1568 } 1569 1570 default: 1571 return pThis->Lun0.pIScsiConnector->pfnSCSIRequestSend(pThis->Lun0.pIScsiConnector, &pReq->ScsiReq); 1572 } 1573 } 1574 1575 /** 1576 * Validates a SCSI request before passing it down to the SCSI driver. 1577 * 1578 * @returns true / false. The request will be completed on failure. 1579 * @param pThis The MSD instance data. 1580 * @param pCbw The USB command block wrapper. 1581 * @param pUrb The URB. 1582 */ 1583 static bool usbMsdIsValidCommand(PUSBMSD pThis, PCUSBCBW pCbw, PVUSBURB pUrb) 1584 { 1585 RT_NOREF(pThis, pUrb); 1586 switch (pCbw->CBWCB[0]) 1587 { 1588 case SCSI_REQUEST_SENSE: 1589 /** @todo validate this. */ 1590 return true; 1591 1592 default: 1593 return true; 1594 } 1547 PDMMEDIAEXIOREQSCSITXDIR enmTxDir = pReq->Cbw.dCBWDataTransferLength == 0 1548 ? PDMMEDIAEXIOREQSCSITXDIR_NONE 1549 : (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT 1550 ? PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE 1551 : PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE; 1552 1553 return pThis->Lun0.pIMediaEx->pfnIoReqSendScsiCmd(pThis->Lun0.pIMediaEx, pReq->hIoReq, pReq->Cbw.bCBWLun, 1554 &pReq->Cbw.CBWCB[0], pReq->Cbw.bCBWCBLength, enmTxDir, 1555 pReq->Cbw.dCBWDataTransferLength, NULL, 0, 1556 &pReq->iScsiReqStatus, 20 * RT_MS_1SEC); 1595 1557 } 1596 1558 … … 1667 1629 } 1668 1630 1669 if (!usbMsdIsValidCommand(pThis, pCbw, pUrb))1670 return VINF_SUCCESS;1671 1672 1631 /* 1673 1632 * Make sure we've got a request and a sufficient buffer space. … … 1679 1638 if (!pReq) 1680 1639 { 1681 pReq = usbMsdReqAlloc(pThis ->pUsbIns);1640 pReq = usbMsdReqAlloc(pThis); 1682 1641 if (!pReq) 1683 1642 return usbMsdCompleteStall(pThis, NULL, pUrb, "Request allocation failure"); 1684 1643 pThis->pReq = pReq; 1685 1644 } 1686 if (!usbMsdReqEnsureBuffer(p Req, pCbw->dCBWDataTransferLength))1645 if (!usbMsdReqEnsureBuffer(pThis, pReq, pCbw->dCBWDataTransferLength)) 1687 1646 return usbMsdCompleteStall(pThis, NULL, pUrb, "Buffer allocation failure"); 1688 1647 1689 1648 /* 1690 * Special case REQUEST SENSE requests, usbMsdReqPrepare will 1691 * trash the sense data otherwise. 1649 * Prepare the request. Kick it off right away if possible. 1692 1650 */ 1693 if (pCbw->CBWCB[0] == SCSI_REQUEST_SENSE) 1694 usbMsdHandleScsiReqestSense(pThis, pReq, pCbw); 1651 usbMsdReqPrepare(pReq, pCbw); 1652 1653 if ( pReq->Cbw.dCBWDataTransferLength == 0 1654 || (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_IN) 1655 { 1656 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev"); 1657 if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 1658 usbMsdReqComplete(pThis, pReq, rc); 1659 else if (RT_FAILURE(rc)) 1660 { 1661 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc)); 1662 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #1"); 1663 } 1664 } 1695 1665 else 1696 1666 { 1697 /* 1698 * Prepare the request. Kick it off right away if possible. 1699 */ 1700 usbMsdReqPrepare(pReq, pCbw); 1701 1702 if ( pReq->Cbw.dCBWDataTransferLength == 0 1703 || (pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_IN) 1704 { 1705 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev"); 1706 if (RT_FAILURE(rc)) 1707 { 1708 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc)); 1709 return usbMsdCompleteStall(pThis, NULL, pUrb, "SCSI Submit #1"); 1710 } 1711 } 1712 else 1713 { 1714 Log(("usbMsdHandleBulkHostToDev: Entering DATA_FROM_HOST.\n")); 1715 pReq->enmState = USBMSDREQSTATE_DATA_FROM_HOST; 1716 } 1667 Log(("usbMsdHandleBulkHostToDev: Entering DATA_FROM_HOST.\n")); 1668 pReq->enmState = USBMSDREQSTATE_DATA_FROM_HOST; 1717 1669 } 1718 1670 … … 1739 1691 { 1740 1692 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkHostToDev"); 1741 if (RT_FAILURE(rc)) 1693 if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 1694 usbMsdReqComplete(pThis, pReq, rc); 1695 else if (RT_FAILURE(rc)) 1742 1696 { 1743 1697 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc)); … … 1825 1779 pCsw->bCSWStatus = pReq->iScsiReqStatus == SCSI_STATUS_OK 1826 1780 ? USBCSW_STATUS_OK 1827 : pReq->iScsiReqStatus >= 01781 : pReq->iScsiReqStatus < 0xff 1828 1782 ? USBCSW_STATUS_FAILED 1829 1783 : USBCSW_STATUS_PHASE_ERROR; … … 1832 1786 if ((pReq->Cbw.bmCBWFlags & USBCBW_DIR_MASK) == USBCBW_DIR_OUT) 1833 1787 pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK 1834 ? pReq->Cbw.dCBWDataTransferLength - pReq->ScsiReq.cbScatterGather1788 ? 0 1835 1789 : pReq->Cbw.dCBWDataTransferLength; 1836 1790 else 1837 1791 pCsw->dCSWDataResidue = pCsw->bCSWStatus == USBCSW_STATUS_OK 1838 1792 ? 0 1839 : pReq-> ScsiReq.cbScatterGather;1793 : pReq->Cbw.dCBWDataTransferLength; 1840 1794 Log(("usbMsd: CSW: dCSWTag=%#x bCSWStatus=%d dCSWDataResidue=%#x\n", 1841 1795 pCsw->dCSWTag, pCsw->bCSWStatus, pCsw->dCSWDataResidue)); … … 1860 1814 } 1861 1815 1862 /* Adjust the request and kick it off. Special case the no-data1863 case since the SCSI driver doesn't like that. */1864 pReq->ScsiReq.cbScatterGather = pReq->offBuf;1865 pReq->ScsiReqSeg.cbSeg = pReq->offBuf;1866 if (!pReq->offBuf)1867 {1868 Log(("usbMsdHandleBulkDevToHost: Entering EXECUTING (offBuf=0x0).\n"));1869 pReq->enmState = USBMSDREQSTATE_EXECUTING;1870 1871 usbMsdQueueAddTail(&pThis->ToHostQueue, pUrb);1872 LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));1873 1874 usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);1875 return VINF_SUCCESS;1876 }1877 1878 1816 int rc = usbMsdSubmitScsiCommand(pThis, pReq, "usbMsdHandleBulkDevToHost"); 1879 if (RT_FAILURE(rc)) 1817 if (RT_SUCCESS(rc) && rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 1818 usbMsdReqComplete(pThis, pReq, rc); 1819 else if (RT_FAILURE(rc)) 1880 1820 { 1881 1821 Log(("usbMsd: Failed sending SCSI request to driver: %Rrc\n", rc)); … … 2154 2094 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 2155 2095 2156 LogFlow(("usbMsdD etach/#%u:\n", pUsbIns->iInstance));2096 LogFlow(("usbMsdDriverAttach/#%u:\n", pUsbIns->iInstance)); 2157 2097 2158 2098 AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n")); … … 2162 2102 /* the usual paranoia */ 2163 2103 AssertRelease(!pThis->Lun0.pIBase); 2164 AssertRelease(!pThis->Lun0.pIScsiConnector); 2104 AssertRelease(!pThis->Lun0.pIMedia); 2105 AssertRelease(!pThis->Lun0.pIMediaEx); 2165 2106 2166 2107 /* … … 2171 2112 if (RT_SUCCESS(rc)) 2172 2113 { 2173 /* Get SCSI connector interface. */ 2174 pThis->Lun0.pIScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR); 2175 AssertMsgReturn(pThis->Lun0.pIScsiConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE); 2114 /* Get media and extended media interface. */ 2115 pThis->Lun0.pIMedia = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIA); 2116 AssertMsgReturn(pThis->Lun0.pIMedia, ("Missing media interface below\n"), VERR_PDM_MISSING_INTERFACE); 2117 pThis->Lun0.pIMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIAEX); 2118 AssertMsgReturn(pThis->Lun0.pIMediaEx, ("Missing extended media interface below\n"), VERR_PDM_MISSING_INTERFACE); 2119 2120 rc = pThis->Lun0.pIMediaEx->pfnIoReqAllocSizeSet(pThis->Lun0.pIMediaEx, sizeof(USBMSDREQ)); 2121 AssertMsgRCReturn(rc, ("MSD failed to set I/O request size!\n"), VERR_PDM_MISSING_INTERFACE); 2176 2122 } 2177 2123 else … … 2181 2127 { 2182 2128 pThis->Lun0.pIBase = NULL; 2183 pThis->Lun0.pIScsiConnector = NULL; 2184 } 2185 2186 /* 2187 * Find out what kind of device we are. 2188 */ 2189 PDMSCSILUNTYPE enmLunType; 2129 pThis->Lun0.pIMedia = NULL; 2130 pThis->Lun0.pIMediaEx = NULL; 2131 } 2132 2190 2133 pThis->fIsCdrom = false; 2191 rc = pThis->Lun0.pIScsiConnector->pfnQueryLUNType(pThis->Lun0.pIScsiConnector, 0 /*iLun*/, &enmLunType); 2192 if (RT_SUCCESS(rc)) 2193 { 2194 /* Anything else will be reported as a hard disk. */ 2195 if (enmLunType == PDMSCSILUNTYPE_MMC) 2196 pThis->fIsCdrom = true; 2197 } 2134 PDMMEDIATYPE enmType = pThis->Lun0.pIMedia->pfnGetType(pThis->Lun0.pIMedia); 2135 /* Anything else will be reported as a hard disk. */ 2136 if (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD) 2137 pThis->fIsCdrom = true; 2198 2138 2199 2139 return rc; … … 2209 2149 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 2210 2150 2211 LogFlow(("usbMsdD etach/#%u:\n", pUsbIns->iInstance));2151 LogFlow(("usbMsdDriverDetach/#%u:\n", pUsbIns->iInstance)); 2212 2152 2213 2153 AssertMsg(iLUN == 0, ("UsbMsd: No other LUN than 0 is supported\n")); 2214 2154 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, 2215 2155 ("UsbMsd: Device does not support hotplugging\n")); 2156 2157 if (pThis->pReq) 2158 { 2159 usbMsdReqFree(pThis, pThis->pReq); 2160 pThis->pReq = NULL; 2161 } 2216 2162 2217 2163 /* … … 2219 2165 */ 2220 2166 pThis->Lun0.pIBase = NULL; 2221 pThis->Lun0.pIScsiConnector = NULL; 2167 pThis->Lun0.pIMedia = NULL; 2168 pThis->Lun0.pIMediaEx = NULL; 2222 2169 } 2223 2170 … … 2275 2222 } 2276 2223 2277 if (pThis->pReq)2278 {2279 usbMsdReqFree(pThis->pReq);2280 pThis->pReq = NULL;2281 }2282 2283 2224 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT) 2284 2225 { … … 2309 2250 * will not misbehave. 2310 2251 */ 2311 pThis->pUsbIns = pUsbIns; 2312 pThis->hEvtDoneQueue = NIL_RTSEMEVENT; 2313 pThis->hEvtReset = NIL_RTSEMEVENTMULTI; 2314 pThis->Lun0.IBase.pfnQueryInterface = usbMsdLun0QueryInterface; 2315 pThis->Lun0.IScsiPort.pfnSCSIRequestCompleted = usbMsdLun0ScsiRequestCompleted; 2316 pThis->Lun0.IScsiPort.pfnQueryDeviceLocation = usbMsdLun0QueryDeviceLocation; 2252 pThis->pUsbIns = pUsbIns; 2253 pThis->hEvtDoneQueue = NIL_RTSEMEVENT; 2254 pThis->hEvtReset = NIL_RTSEMEVENTMULTI; 2255 pThis->Lun0.IBase.pfnQueryInterface = usbMsdLun0QueryInterface; 2256 pThis->Lun0.IMediaPort.pfnQueryDeviceLocation = usbMsdLun0QueryDeviceLocation; 2257 pThis->Lun0.IMediaExPort.pfnIoReqCompleteNotify = usbMsdLun0IoReqCompleteNotify; 2258 pThis->Lun0.IMediaExPort.pfnIoReqCopyFromBuf = usbMsdLun0IoReqCopyFromBuf; 2259 pThis->Lun0.IMediaExPort.pfnIoReqCopyToBuf = usbMsdLun0IoReqCopyToBuf; 2260 pThis->Lun0.IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 2261 pThis->Lun0.IMediaExPort.pfnIoReqStateChanged = usbMsdLun0IoReqStateChanged; 2262 pThis->Lun0.IMediaExPort.pfnMediumEjected = usbMsdLun0MediumEjected; 2317 2263 usbMsdQueueInit(&pThis->ToHostQueue); 2318 2264 usbMsdQueueInit(&pThis->DoneQueue); … … 2340 2286 if (RT_FAILURE(rc)) 2341 2287 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("MSD failed to attach SCSI driver")); 2342 pThis->Lun0.pI ScsiConnector = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMISCSICONNECTOR);2343 if (!pThis->Lun0.pI ScsiConnector)2288 pThis->Lun0.pIMedia = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIA); 2289 if (!pThis->Lun0.pIMedia) 2344 2290 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, 2345 N_("MSD failed to query the PDMISCSICONNECTOR from the driver below it")); 2291 N_("MSD failed to query the PDMIMEDIA from the driver below it")); 2292 pThis->Lun0.pIMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMIMEDIAEX); 2293 if (!pThis->Lun0.pIMediaEx) 2294 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, 2295 N_("MSD failed to query the PDMIMEDIAEX from the driver below it")); 2346 2296 2347 2297 /* 2348 2298 * Find out what kind of device we are. 2349 2299 */ 2350 PDMSCSILUNTYPE enmLunType;2351 2300 pThis->fIsCdrom = false; 2352 rc = pThis->Lun0.pIScsiConnector->pfnQueryLUNType(pThis->Lun0.pIScsiConnector, 0 /*iLun*/, &enmLunType); 2353 if (RT_SUCCESS(rc)) 2354 { 2355 /* Anything else will be reported as a hard disk. */ 2356 if (enmLunType == PDMSCSILUNTYPE_MMC) 2357 pThis->fIsCdrom = true; 2358 } 2301 PDMMEDIATYPE enmType = pThis->Lun0.pIMedia->pfnGetType(pThis->Lun0.pIMedia); 2302 /* Anything else will be reported as a hard disk. */ 2303 if (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD) 2304 pThis->fIsCdrom = true; 2305 2306 rc = pThis->Lun0.pIMediaEx->pfnIoReqAllocSizeSet(pThis->Lun0.pIMediaEx, sizeof(USBMSDREQ)); 2307 if (RT_FAILURE(rc)) 2308 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("MSD failed to set I/O request size!")); 2359 2309 2360 2310 /*
Note:
See TracChangeset
for help on using the changeset viewer.