Changeset 49093 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Oct 14, 2013 10:02:15 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/UsbMsd.cpp
r48981 r49093 49 49 #define USBMSD_PID_CD 0x0031 50 50 /** @} */ 51 52 /** Saved state version. */ 53 #define USB_MSD_SAVED_STATE_VERSION 1 51 54 52 55 /******************************************************************************* … … 126 129 USBMSDREQSTATE_DESTROY_ON_COMPLETION, 127 130 /** The end of the valid states. */ 128 USBMSDREQSTATE_END 131 USBMSDREQSTATE_END, 132 /** 32bit blow up hack. */ 133 USBMSDREQSTATE_32BIT_HACK = 0x7fffffff 129 134 } USBMSDREQSTATE; 130 135 … … 955 960 956 961 /** 962 * Checks if all asynchronous I/O is finished. 963 * 964 * Used by usbMsdVMReset, usbMsdVMSuspend and usbMsdVMPowerOff. 965 * 966 * @returns true if quiesced, false if busy. 967 * @param pUsbIns The USB device instance. 968 */ 969 static bool usbMsdAllAsyncIOIsFinished(PPDMUSBINS pUsbIns) 970 { 971 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 972 973 if ( VALID_PTR(pThis->pReq) 974 && pThis->pReq->enmState == USBMSDREQSTATE_EXECUTING) 975 return false; 976 977 return true; 978 } 979 980 /** 981 * @callback_method_impl{FNPDMDEVASYNCNOTIFY, 982 * Callback employed by usbMsdVMSuspend and usbMsdVMPowerOff.} 983 */ 984 static DECLCALLBACK(bool) usbMsdIsAsyncSuspendOrPowerOffDone(PPDMUSBINS pUsbIns) 985 { 986 if (!usbMsdAllAsyncIOIsFinished(pUsbIns)) 987 return false; 988 989 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 990 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 991 return true; 992 } 993 994 /** 995 * Common worker for usbMsdVMSuspend and usbMsdVMPowerOff. 996 */ 997 static void usbMsdSuspendOrPowerOff(PPDMUSBINS pUsbIns) 998 { 999 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1000 1001 ASMAtomicWriteBool(&pThis->fSignalIdle, true); 1002 if (!usbMsdAllAsyncIOIsFinished(pUsbIns)) 1003 PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncSuspendOrPowerOffDone); 1004 else 1005 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 1006 } 1007 1008 1009 /* -=-=-=-=- Saved State -=-=-=-=- */ 1010 1011 /** 1012 * @copydoc FNUSBSSMSAVEPREP 1013 */ 1014 static DECLCALLBACK(int) usbMsdSavePrep(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM) 1015 { 1016 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1017 1018 Assert(usbMsdAllAsyncIOIsFinished(pUsbIns)); 1019 Assert(usbMsdQueueIsEmpty(&pThis->ToHostQueue)); 1020 Assert(usbMsdQueueIsEmpty(&pThis->DoneQueue)); 1021 return VINF_SUCCESS; 1022 } 1023 1024 /** 1025 * @copydoc FNUSBSSMLOADPREP 1026 */ 1027 static DECLCALLBACK(int) usbMsdLoadPrep(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM) 1028 { 1029 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1030 1031 Assert(usbMsdAllAsyncIOIsFinished(pUsbIns)); 1032 Assert(usbMsdQueueIsEmpty(&pThis->ToHostQueue)); 1033 Assert(usbMsdQueueIsEmpty(&pThis->DoneQueue)); 1034 return VINF_SUCCESS; 1035 } 1036 1037 /** 1038 * @copydoc FNUSBSSMLIVEEXEC 1039 */ 1040 static DECLCALLBACK(int) usbMsdLiveExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass) 1041 { 1042 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1043 1044 /* config. */ 1045 SSMR3PutBool(pSSM, pThis->Lun0.pIBase != NULL); 1046 return VINF_SSM_DONT_CALL_AGAIN; 1047 } 1048 1049 /** 1050 * @copydoc FNUSBSSMSAVEEXEC 1051 */ 1052 static DECLCALLBACK(int) usbMsdSaveExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM) 1053 { 1054 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1055 uint32_t i; 1056 int rc; 1057 1058 /* The config */ 1059 rc = usbMsdLiveExec(pUsbIns, pSSM, SSM_PASS_FINAL); 1060 AssertRCReturn(rc, rc); 1061 1062 SSMR3PutU8(pSSM, pThis->bConfigurationValue); 1063 SSMR3PutBool(pSSM, pThis->aEps[0].fHalted); 1064 SSMR3PutBool(pSSM, pThis->aEps[1].fHalted); 1065 SSMR3PutBool(pSSM, pThis->aEps[2].fHalted); 1066 SSMR3PutBool(pSSM, pThis->pReq != NULL); 1067 1068 if (pThis->pReq) 1069 { 1070 PUSBMSDREQ pReq = pThis->pReq; 1071 1072 SSMR3PutU32(pSSM, pReq->enmState); 1073 SSMR3PutU32(pSSM, pReq->cbBuf); 1074 if (pReq->cbBuf) 1075 { 1076 AssertPtr(pReq->pbBuf); 1077 SSMR3PutMem(pSSM, pReq->pbBuf, pReq->cbBuf); 1078 } 1079 1080 SSMR3PutU32(pSSM, pReq->offBuf); 1081 SSMR3PutMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw)); 1082 SSMR3PutU32(pSSM, pReq->ScsiReq.uLogicalUnit); 1083 SSMR3PutU32(pSSM, pReq->ScsiReq.uDataDirection); 1084 SSMR3PutU32(pSSM, pReq->ScsiReq.cbCDB); 1085 SSMR3PutU32(pSSM, pReq->ScsiReq.cbScatterGather); 1086 SSMR3PutMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense)); 1087 SSMR3PutS32(pSSM, pReq->iScsiReqStatus); 1088 } 1089 1090 return SSMR3PutU32(pSSM, UINT32_MAX); /* sanity/terminator */ 1091 } 1092 1093 /** 1094 * @copydoc FNUSBSSMLOADEXEC 1095 */ 1096 static DECLCALLBACK(int) usbMsdLoadExec(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1097 { 1098 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD); 1099 uint32_t u32; 1100 int rc; 1101 1102 if (uVersion > USB_MSD_SAVED_STATE_VERSION) 1103 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 1104 1105 /* Verify config. */ 1106 bool fInUse; 1107 rc = SSMR3GetBool(pSSM, &fInUse); 1108 AssertRCReturn(rc, rc); 1109 if (fInUse != (pThis->Lun0.pIBase != NULL)) 1110 return SSMR3SetCfgError(pSSM, RT_SRC_POS, 1111 N_("The %s VM is missing a USB mass storage device. Please make sure the source and target VMs have compatible storage configurations"), 1112 fInUse ? "target" : "source"); 1113 1114 if (uPass == SSM_PASS_FINAL) 1115 { 1116 /* Restore data. */ 1117 bool fReqAlloc = false; 1118 1119 Assert(!pThis->pReq); 1120 1121 SSMR3GetU8(pSSM, &pThis->bConfigurationValue); 1122 SSMR3GetBool(pSSM, &pThis->aEps[0].fHalted); 1123 SSMR3GetBool(pSSM, &pThis->aEps[1].fHalted); 1124 SSMR3GetBool(pSSM, &pThis->aEps[2].fHalted); 1125 SSMR3GetBool(pSSM, &fReqAlloc); 1126 1127 if (fReqAlloc) 1128 { 1129 PUSBMSDREQ pReq = usbMsdReqAlloc(pUsbIns); 1130 1131 if (pReq) 1132 { 1133 uint32_t cbBuf = 0; 1134 1135 pThis->pReq = pReq; 1136 1137 SSMR3GetU32(pSSM, (uint32_t *)&pReq->enmState); 1138 SSMR3GetU32(pSSM, &cbBuf); 1139 if (cbBuf) 1140 { 1141 if (usbMsdReqEnsureBuffer(pReq, cbBuf)) 1142 { 1143 AssertPtr(pReq->pbBuf); 1144 Assert(cbBuf = pReq->cbBuf); 1145 SSMR3GetMem(pSSM, pReq->pbBuf, pReq->cbBuf); 1146 } 1147 else 1148 rc = VERR_NO_MEMORY; 1149 } 1150 1151 if (RT_SUCCESS(rc)) 1152 { 1153 SSMR3GetU32(pSSM, &pReq->offBuf); 1154 SSMR3GetMem(pSSM, &pReq->Cbw, sizeof(pReq->Cbw)); 1155 SSMR3GetU32(pSSM, &pReq->ScsiReq.uLogicalUnit); 1156 SSMR3GetU32(pSSM, (uint32_t *)&pReq->ScsiReq.uDataDirection); 1157 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbCDB); 1158 SSMR3GetU32(pSSM, &pReq->ScsiReq.cbScatterGather); 1159 SSMR3GetMem(pSSM, &pReq->ScsiReqSense[0], sizeof(pReq->ScsiReqSense)); 1160 SSMR3GetS32(pSSM, &pReq->iScsiReqStatus); 1161 1162 /* Setup the rest of the SCSI request. */ 1163 pReq->ScsiReq.cbCDB = pReq->Cbw.bCBWCBLength; 1164 pReq->ScsiReq.pbCDB = &pReq->Cbw.CBWCB[0]; 1165 pReq->ScsiReqSeg.pvSeg = pReq->pbBuf; 1166 pReq->ScsiReqSeg.cbSeg = pReq->ScsiReq.cbScatterGather; 1167 pReq->ScsiReq.cScatterGatherEntries = 1; 1168 pReq->ScsiReq.paScatterGatherHead = &pReq->ScsiReqSeg; 1169 pReq->ScsiReq.cbSenseBuffer = sizeof(pReq->ScsiReqSense); 1170 pReq->ScsiReq.pbSenseBuffer = &pReq->ScsiReqSense[0]; 1171 pReq->ScsiReq.pvUser = NULL; 1172 } 1173 } 1174 else 1175 rc = VERR_NO_MEMORY; 1176 } 1177 1178 if (RT_SUCCESS(rc)) 1179 rc = SSMR3GetU32(pSSM, &u32); 1180 1181 if (RT_FAILURE(rc)) 1182 return rc; 1183 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 1184 } 1185 1186 return VINF_SUCCESS; 1187 } 1188 1189 1190 /** 957 1191 * @copydoc PDMUSBREG::pfnUrbReap 958 1192 */ … … 1652 1886 1653 1887 /** 1654 * Checks if all asynchronous I/O is finished.1655 *1656 * Used by usbMsdVMReset, usbMsdVMSuspend and usbMsdVMPowerOff.1657 *1658 * @returns true if quiesced, false if busy.1659 * @param pUsbIns The USB device instance.1660 */1661 static bool usbMsdAllAsyncIOIsFinished(PPDMUSBINS pUsbIns)1662 {1663 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);1664 1665 if ( VALID_PTR(pThis->pReq)1666 && pThis->pReq->enmState == USBMSDREQSTATE_EXECUTING)1667 return false;1668 1669 return true;1670 }1671 1672 /**1673 * @callback_method_impl{FNPDMDEVASYNCNOTIFY,1674 * Callback employed by usbMsdVMSuspend and usbMsdVMPowerOff.}1675 */1676 static DECLCALLBACK(bool) usbMsdIsAsyncSuspendOrPowerOffDone(PPDMUSBINS pUsbIns)1677 {1678 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))1679 return false;1680 1681 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);1682 ASMAtomicWriteBool(&pThis->fSignalIdle, false);1683 return true;1684 }1685 1686 /**1687 * Common worker for usbMsdVMSuspend and usbMsdVMPowerOff.1688 */1689 static void usbMsdSuspendOrPowerOff(PPDMUSBINS pUsbIns)1690 {1691 PUSBMSD pThis = PDMINS_2_DATA(pUsbIns, PUSBMSD);1692 1693 ASMAtomicWriteBool(&pThis->fSignalIdle, true);1694 if (!usbMsdAllAsyncIOIsFinished(pUsbIns))1695 PDMUsbHlpSetAsyncNotification(pUsbIns, usbMsdIsAsyncSuspendOrPowerOffDone);1696 else1697 ASMAtomicWriteBool(&pThis->fSignalIdle, false);1698 }1699 1700 1701 /**1702 1888 * @copydoc PDMUSBREG::pfnVMSuspend 1703 1889 */ … … 1900 2086 N_("MSD failed to query the PDMISCSICONNECTOR from the driver below it")); 1901 2087 2088 /* 2089 * Register the saved state data unit. 2090 */ 2091 rc = PDMUsbHlpSSMRegister(pUsbIns, USB_MSD_SAVED_STATE_VERSION, sizeof(*pThis), 2092 NULL, usbMsdLiveExec, NULL, 2093 usbMsdSavePrep, usbMsdSaveExec, NULL, 2094 usbMsdLoadPrep, usbMsdLoadExec, NULL); 2095 if (RT_FAILURE(rc)) 2096 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, 2097 N_("MSD failed to register SSM save state handlers")); 2098 1902 2099 return VINF_SUCCESS; 1903 2100 } … … 1916 2113 "USB Mass Storage Device, one LUN.", 1917 2114 /* fFlags */ 1918 PDM_USBREG_HIGHSPEED_CAPABLE ,2115 PDM_USBREG_HIGHSPEED_CAPABLE | PDM_USBREG_EMULATED_DEVICE, 1919 2116 /* cMaxInstances */ 1920 2117 ~0U,
Note:
See TracChangeset
for help on using the changeset viewer.