VirtualBox

Changeset 49093 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Oct 14, 2013 10:02:15 PM (11 years ago)
Author:
vboxsync
Message:

Storage/UsbMsd: Implement save state handlers

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/UsbMsd.cpp

    r48981 r49093  
    4949#define USBMSD_PID_CD               0x0031
    5050/** @} */
     51
     52/** Saved state version. */
     53#define USB_MSD_SAVED_STATE_VERSION 1
    5154
    5255/*******************************************************************************
     
    126129    USBMSDREQSTATE_DESTROY_ON_COMPLETION,
    127130    /** The end of the valid states. */
    128     USBMSDREQSTATE_END
     131    USBMSDREQSTATE_END,
     132    /** 32bit blow up hack. */
     133    USBMSDREQSTATE_32BIT_HACK = 0x7fffffff
    129134} USBMSDREQSTATE;
    130135
     
    955960
    956961/**
     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 */
     969static 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 */
     984static 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 */
     997static 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 */
     1014static 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 */
     1027static 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 */
     1040static 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 */
     1052static 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 */
     1096static 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/**
    9571191 * @copydoc PDMUSBREG::pfnUrbReap
    9581192 */
     
    16521886
    16531887/**
    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     else
    1697         ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    1698 }
    1699 
    1700 
    1701 /**
    17021888 * @copydoc PDMUSBREG::pfnVMSuspend
    17031889 */
     
    19002086                                   N_("MSD failed to query the PDMISCSICONNECTOR from the driver below it"));
    19012087
     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
    19022099    return VINF_SUCCESS;
    19032100}
     
    19162113    "USB Mass Storage Device, one LUN.",
    19172114    /* fFlags */
    1918     PDM_USBREG_HIGHSPEED_CAPABLE,
     2115    PDM_USBREG_HIGHSPEED_CAPABLE | PDM_USBREG_EMULATED_DEVICE,
    19192116    /* cMaxInstances */
    19202117    ~0U,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette