VirtualBox

Changeset 33274 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Oct 20, 2010 5:54:35 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66842
Message:

BusLogic: Implement suspend on error

File:
1 edited

Legend:

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

    r33101 r33274  
    5959
    6060/** State saved version. */
    61 #define BUSLOGIC_SAVED_STATE_MINOR_VERSION 1
     61#define BUSLOGIC_SAVED_STATE_MINOR_VERSION 2
     62
     63/** Saved state version before the suspend on error feature was implemented. */
     64#define BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING 1
    6265
    6366/**
     
    259262#pragma pack()
    260263
     264/** Pointer to a task state structure. */
     265typedef struct BUSLOGICTASKSTATE *PBUSLOGICTASKSTATE;
     266
    261267/**
    262268 * Main BusLogic device state.
     
    391397     * a port is entering the idle state. */
    392398    bool volatile                   fSignalIdle;
     399    /** Flag whether we have tasks which need to be processed again- */
     400    bool volatile                   fRedo;
     401    /** List of tasks which can be redone. */
     402    R3PTRTYPE(volatile PBUSLOGICTASKSTATE) pTasksRedoHead;
    393403
    394404} BUSLOGIC, *PBUSLOGIC;
     
    737747typedef struct BUSLOGICTASKSTATE
    738748{
     749    /** Next in the redo list. */
     750    PBUSLOGICTASKSTATE             pRedoNext;
    739751    /** Device this task is assigned to. */
    740752    R3PTRTYPE(PBUSLOGICDEVICE)     pTargetDeviceR3;
     
    751763    /** Flag whether this is a request from the BIOS. */
    752764    bool                fBIOS;
    753 } BUSLOGICTASKSTATE, *PBUSLOGICTASKSTATE;
     765} BUSLOGICTASKSTATE;
    754766
    755767#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     
    18161828}
    18171829
     1830static void buslogicWarningDiskFull(PPDMDEVINS pDevIns)
     1831{
     1832    int rc;
     1833    LogRel(("BusLogic#%d: Host disk full\n", pDevIns->iInstance));
     1834    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_DISKFULL",
     1835                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
     1836    AssertRC(rc);
     1837}
     1838
     1839static void buslogicWarningFileTooBig(PPDMDEVINS pDevIns)
     1840{
     1841    int rc;
     1842    LogRel(("BusLogic#%d: File too big\n", pDevIns->iInstance));
     1843    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_FILETOOBIG",
     1844                                    N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));
     1845    AssertRC(rc);
     1846}
     1847
     1848static void buslogicWarningISCSI(PPDMDEVINS pDevIns)
     1849{
     1850    int rc;
     1851    LogRel(("BusLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
     1852    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_ISCSIDOWN",
     1853                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
     1854    AssertRC(rc);
     1855}
     1856
     1857static void buslogicWarningUnknown(PPDMDEVINS pDevIns, int rc)
     1858{
     1859    int rc2;
     1860    LogRel(("BusLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
     1861    rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_UNKNOWN",
     1862                                     N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc);
     1863    AssertRC(rc2);
     1864}
     1865
     1866static void buslogicRedoSetWarning(PBUSLOGIC pThis, int rc)
     1867{
     1868    if (rc == VERR_DISK_FULL)
     1869        buslogicWarningDiskFull(pThis->CTX_SUFF(pDevIns));
     1870    else if (rc == VERR_FILE_TOO_BIG)
     1871        buslogicWarningFileTooBig(pThis->CTX_SUFF(pDevIns));
     1872    else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
     1873    {
     1874        /* iSCSI connection abort (first error) or failure to reestablish
     1875         * connection (second error). Pause VM. On resume we'll retry. */
     1876        buslogicWarningISCSI(pThis->CTX_SUFF(pDevIns));
     1877    }
     1878    else
     1879        buslogicWarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
     1880}
     1881
     1882
    18181883static int buslogicPrepareBIOSSCSIRequest(PBUSLOGIC pBusLogic)
    18191884{
     
    20252090    LogFlowFunc(("after decrement %u\n", pBusLogicDevice->cOutstandingRequests));
    20262091
    2027     if (pTaskState->fBIOS)
    2028     {
    2029         rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, pSCSIRequest);
    2030         AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
     2092    if (fRedo)
     2093    {
     2094        if (!pTaskState->fBIOS)
     2095        {
     2096            buslogicDataBufferFree(pTaskState);
     2097
     2098            if (pTaskState->pbSenseBuffer)
     2099                buslogicSenseBufferFree(pTaskState, false /* fCopy */);
     2100        }
     2101
     2102        /* Add to the list. */
     2103        do
     2104        {
     2105            pTaskState->pRedoNext = ASMAtomicReadPtrT(&pBusLogic->pTasksRedoHead, PBUSLOGICTASKSTATE);
     2106        } while (!ASMAtomicCmpXchgPtr(&pBusLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
     2107
     2108        /* Suspend the VM if not done already. */
     2109        if (!ASMAtomicXchgBool(&pBusLogic->fRedo, true))
     2110            buslogicRedoSetWarning(pBusLogic, rcReq);
    20312111    }
    20322112    else
    20332113    {
    2034         buslogicDataBufferFree(pTaskState);
    2035 
    2036         if (pTaskState->pbSenseBuffer)
    2037             buslogicSenseBufferFree(pTaskState, (rcCompletion != SCSI_STATUS_OK));
    2038 
    2039         buslogicSendIncomingMailbox(pBusLogic, pTaskState,
    2040                                     BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
    2041                                     BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    2042                                     BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
    2043     }
    2044 
    2045     /* Add task to the cache. */
    2046     RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
     2114        if (pTaskState->fBIOS)
     2115        {
     2116            rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, pSCSIRequest);
     2117            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
     2118        }
     2119        else
     2120        {
     2121            buslogicDataBufferFree(pTaskState);
     2122
     2123            if (pTaskState->pbSenseBuffer)
     2124                buslogicSenseBufferFree(pTaskState, (rcCompletion != SCSI_STATUS_OK));
     2125
     2126            buslogicSendIncomingMailbox(pBusLogic, pTaskState,
     2127                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
     2128                                        BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
     2129                                        BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
     2130        }
     2131
     2132        /* Add task to the cache. */
     2133        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
     2134    }
    20472135
    20482136    if (pBusLogicDevice->cOutstandingRequests == 0 && pBusLogic->fSignalIdle)
     
    20502138
    20512139    return VINF_SUCCESS;
     2140}
     2141
     2142static int buslogicDeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
     2143{
     2144    int rc = VINF_SUCCESS;
     2145
     2146    /* Fetch CCB. */
     2147    RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
     2148    PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
     2149                        &pTaskState->CommandControlBlockGuest, sizeof(CommandControlBlock));
     2150
     2151    PBUSLOGICDEVICE pTargetDevice = &pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId];
     2152    pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
     2153
     2154#ifdef DEBUG
     2155    buslogicDumpCCBInfo(&pTaskState->CommandControlBlockGuest);
     2156#endif
     2157
     2158    /* Alloc required buffers. */
     2159    rc = buslogicDataBufferAlloc(pTaskState);
     2160    AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));
     2161
     2162    if (pTaskState->CommandControlBlockGuest.cbSenseData)
     2163    {
     2164        rc = buslogicSenseBufferAlloc(pTaskState);
     2165        AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
     2166    }
     2167
     2168    /* Check if device is present on bus. If not return error immediately and don't process this further. */
     2169    if (!pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId].fPresent)
     2170    {
     2171        buslogicDataBufferFree(pTaskState);
     2172
     2173        if (pTaskState->pbSenseBuffer)
     2174            buslogicSenseBufferFree(pTaskState, true);
     2175
     2176        buslogicSendIncomingMailbox(pBusLogic, pTaskState,
     2177                                    BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
     2178                                    BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
     2179                                    BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
     2180
     2181        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
     2182    }
     2183    else
     2184    {
     2185        /* Setup SCSI request. */
     2186        pTaskState->PDMScsiRequest.uLogicalUnit = pTaskState->CommandControlBlockGuest.uLogicalUnit;
     2187
     2188        if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)
     2189            pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_UNKNOWN;
     2190        else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
     2191            pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
     2192        else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
     2193            pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE;
     2194        else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
     2195            pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE;
     2196        else
     2197            AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.uDataDirection));
     2198
     2199        pTaskState->PDMScsiRequest.cbCDB                 = pTaskState->CommandControlBlockGuest.cbCDB;
     2200        pTaskState->PDMScsiRequest.pbCDB                 = pTaskState->CommandControlBlockGuest.aCDB;
     2201        if (pTaskState->DataSeg.cbSeg)
     2202        {
     2203            pTaskState->PDMScsiRequest.cbScatterGather       = pTaskState->DataSeg.cbSeg;
     2204            pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;
     2205            pTaskState->PDMScsiRequest.paScatterGatherHead   = &pTaskState->DataSeg;
     2206        }
     2207        else
     2208        {
     2209            pTaskState->PDMScsiRequest.cbScatterGather       = 0;
     2210            pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;
     2211            pTaskState->PDMScsiRequest.paScatterGatherHead   = NULL;
     2212        }
     2213        pTaskState->PDMScsiRequest.cbSenseBuffer         = pTaskState->CommandControlBlockGuest.cbSenseData;
     2214        pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pbSenseBuffer;
     2215        pTaskState->PDMScsiRequest.pvUser                = pTaskState;
     2216
     2217        ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
     2218        rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
     2219        AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
     2220    }
     2221
     2222    return rc;
    20522223}
    20532224
     
    21012272
    21022273    if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
    2103     {
    2104         /* Fetch CCB now. */
    2105         RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
    2106         PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
    2107                             &pTaskState->CommandControlBlockGuest, sizeof(CommandControlBlock));
    2108 
    2109         PBUSLOGICDEVICE pTargetDevice = &pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId];
    2110         pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
    2111 
    2112 #ifdef DEBUG
    2113         buslogicDumpCCBInfo(&pTaskState->CommandControlBlockGuest);
    2114 #endif
    2115 
    2116         /* Alloc required buffers. */
    2117         rc = buslogicDataBufferAlloc(pTaskState);
    2118         AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));
    2119 
    2120         if (pTaskState->CommandControlBlockGuest.cbSenseData)
    2121         {
    2122             rc = buslogicSenseBufferAlloc(pTaskState);
    2123             AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
    2124         }
    2125 
    2126         /* Check if device is present on bus. If not return error immediately and don't process this further. */
    2127         if (!pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId].fPresent)
    2128         {
    2129             buslogicDataBufferFree(pTaskState);
    2130 
    2131             if (pTaskState->pbSenseBuffer)
    2132                 buslogicSenseBufferFree(pTaskState, true);
    2133 
    2134             buslogicSendIncomingMailbox(pBusLogic, pTaskState,
    2135                                         BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
    2136                                         BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    2137                                         BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    2138 
    2139             RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    2140         }
    2141         else
    2142         {
    2143             /* Setup SCSI request. */
    2144             pTaskState->PDMScsiRequest.uLogicalUnit          = pTaskState->CommandControlBlockGuest.uLogicalUnit;
    2145 
    2146             if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)
    2147                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_UNKNOWN;
    2148             else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
    2149                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
    2150             else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
    2151                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE;
    2152             else if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
    2153                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE;
    2154             else
    2155                 AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.uDataDirection));
    2156 
    2157             pTaskState->PDMScsiRequest.cbCDB                 = pTaskState->CommandControlBlockGuest.cbCDB;
    2158             pTaskState->PDMScsiRequest.pbCDB                 = pTaskState->CommandControlBlockGuest.aCDB;
    2159             if (pTaskState->DataSeg.cbSeg)
    2160             {
    2161                 pTaskState->PDMScsiRequest.cbScatterGather       = pTaskState->DataSeg.cbSeg;
    2162                 pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;
    2163                 pTaskState->PDMScsiRequest.paScatterGatherHead   = &pTaskState->DataSeg;
    2164             }
    2165             else
    2166             {
    2167                 pTaskState->PDMScsiRequest.cbScatterGather       = 0;
    2168                 pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;
    2169                 pTaskState->PDMScsiRequest.paScatterGatherHead   = NULL;
    2170             }
    2171             pTaskState->PDMScsiRequest.cbSenseBuffer         = pTaskState->CommandControlBlockGuest.cbSenseData;
    2172             pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pbSenseBuffer;
    2173             pTaskState->PDMScsiRequest.pvUser                = pTaskState;
    2174 
    2175             LogFlowFunc(("before increment %u\n", pTargetDevice->cOutstandingRequests));
    2176             ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
    2177             LogFlowFunc(("after increment %u\n", pTargetDevice->cOutstandingRequests));
    2178             rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
    2179             AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
    2180         }
    2181     }
     2274        rc = buslogicDeviceSCSIRequestSetup(pBusLogic, pTaskState);
    21822275    else if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
    21832276    {
     
    21862279    else
    21872280        AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", pTaskState->MailboxGuest.u.out.uActionCode));
     2281
     2282    AssertRC(rc);
    21882283
    21892284    /* We got the mailbox, mark it as free in the guest. */
     
    22312326
    22322327    return true;
     2328}
     2329
     2330/**
     2331 * Kicks the controller to process pending tasks after the VM was resumed
     2332 * or loaded from a saved state.
     2333 *
     2334 * @returns nothing.
     2335 * @param   pThis    The LsiLogic device instance.
     2336 */
     2337static void buslogicKick(PBUSLOGIC pThis)
     2338{
     2339    if (pThis->fRedo)
     2340    {
     2341        pThis->fRedo = false;
     2342        if (pThis->VBoxSCSI.fBusy)
     2343        {
     2344           
     2345            /* The BIOS had a request active when we got suspended. Resume it. */
     2346            int rc = buslogicPrepareBIOSSCSIRequest(pThis);
     2347            AssertRC(rc);
     2348        }
     2349        else
     2350        {
     2351            /* Queue all pending tasks again. */
     2352            PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
     2353
     2354            pThis->pTasksRedoHead = NULL;
     2355
     2356            while (pTaskState)
     2357            {
     2358                PBUSLOGICTASKSTATE pCur = pTaskState;
     2359
     2360                int rc = buslogicDeviceSCSIRequestSetup(pThis, pCur);
     2361                AssertRC(rc);
     2362
     2363                pTaskState = pTaskState->pRedoNext;
     2364            }
     2365        }
     2366    }
    22332367}
    22342368
     
    22932427    SSMR3PutBool  (pSSM, pBusLogic->VBoxSCSI.fBusy);
    22942428    SSMR3PutU8    (pSSM, pBusLogic->VBoxSCSI.enmState);
    2295     if (pBusLogic->VBoxSCSI.cbCDB)
     2429    if (pBusLogic->VBoxSCSI.cbBuf)
    22962430        SSMR3PutMem(pSSM, pBusLogic->VBoxSCSI.pBuf, pBusLogic->VBoxSCSI.cbBuf);
    22972431
     2432    /*
     2433     * Save the physical addresses of the command control blocks of still pending tasks.
     2434     * They are processed again on resume.
     2435     *
     2436     * The number of pending tasks needs to be determined first.
     2437     */
     2438    uint32_t cTasks = 0;
     2439
     2440    PBUSLOGICTASKSTATE pTaskState = pBusLogic->pTasksRedoHead;
     2441    if (pBusLogic->fRedo)
     2442    {
     2443        while (pTaskState)
     2444        {
     2445            cTasks++;
     2446            pTaskState = pTaskState->pRedoNext;
     2447        }
     2448    }
     2449    SSMR3PutU32(pSSM, cTasks);
     2450
     2451    /* Write the address of every task now. */
     2452    pTaskState = pBusLogic->pTasksRedoHead;
     2453    while (pTaskState)
     2454    {
     2455        SSMR3PutU32(pSSM, pTaskState->MailboxGuest.u32PhysAddrCCB);
     2456        pTaskState = pTaskState->pRedoNext;
     2457    }
     2458
    22982459    return SSMR3PutU32(pSSM, ~0);
    22992460}
    23002461
     2462static DECLCALLBACK(int) buslogicLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     2463{
     2464    PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
     2465
     2466    buslogicKick(pThis);
     2467    return VINF_SUCCESS;
     2468}
     2469
    23012470static DECLCALLBACK(int) buslogicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    23022471{
    23032472    PBUSLOGIC   pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
    2304     int         rc;
     2473    int         rc = VINF_SUCCESS;
    23052474
    23062475    /* We support saved states only from this and older versions. */
     
    23632532    SSMR3GetBool(pSSM, (bool *)&pBusLogic->VBoxSCSI.fBusy);
    23642533    SSMR3GetU8  (pSSM, (uint8_t *)&pBusLogic->VBoxSCSI.enmState);
    2365     if (pBusLogic->VBoxSCSI.cbCDB)
    2366     {
    2367         pBusLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pBusLogic->VBoxSCSI.cbCDB);
     2534    if (pBusLogic->VBoxSCSI.cbBuf)
     2535    {
     2536        pBusLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pBusLogic->VBoxSCSI.cbBuf);
    23682537        if (!pBusLogic->VBoxSCSI.pBuf)
    23692538        {
     
    23752544    }
    23762545
    2377     uint32_t u32;
    2378     rc = SSMR3GetU32(pSSM, &u32);
    2379     if (RT_FAILURE(rc))
    2380         return rc;
    2381     AssertMsgReturn(u32 == ~0U, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    2382 
    2383     return VINF_SUCCESS;
     2546    if (pBusLogic->VBoxSCSI.fBusy)
     2547        pBusLogic->fRedo = true;
     2548
     2549    if (uVersion > BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING)
     2550    {
     2551        /* Check if there are pending tasks saved. */
     2552        uint32_t cTasks = 0;
     2553
     2554        SSMR3GetU32(pSSM, &cTasks);
     2555
     2556        if (cTasks)
     2557            pBusLogic->fRedo = true;
     2558
     2559        for (uint32_t i = 0; i < cTasks; i++)
     2560        {
     2561            PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)RTMemCacheAlloc(pBusLogic->hTaskCache);
     2562            if (!pTaskState)
     2563            {
     2564                rc = VERR_NO_MEMORY;
     2565                break;
     2566            }
     2567
     2568            rc = SSMR3GetU32(pSSM, &pTaskState->MailboxGuest.u32PhysAddrCCB);
     2569            if (RT_FAILURE(rc))
     2570            {
     2571                RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
     2572                break;
     2573            }
     2574
     2575            /* Link into the list. */
     2576            pTaskState->pRedoNext = pBusLogic->pTasksRedoHead;
     2577            pBusLogic->pTasksRedoHead = pTaskState;
     2578        }
     2579    }
     2580
     2581    if (RT_SUCCESS(rc))
     2582    {
     2583        uint32_t u32;
     2584        rc = SSMR3GetU32(pSSM, &u32);
     2585        if (RT_SUCCESS(rc))
     2586            AssertMsgReturn(u32 == ~0U, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
     2587    }
     2588
     2589    return rc;
    23842590}
    23852591
     
    24942700 * Common worker for ahciR3Suspend and ahciR3PowerOff.
    24952701 */
    2496 static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
     2702static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns, bool fPowerOff)
    24972703{
    24982704    PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
     
    25022708        PDMDevHlpSetAsyncNotification(pDevIns, buslogicR3IsAsyncSuspendOrPowerOffDone);
    25032709    else
     2710    {
    25042711        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
     2712
     2713        AssertMsg(!pThis->fNotificationSend, ("The PDM Queue should be empty at this point\n"));
     2714
     2715        if (pThis->fRedo)
     2716        {
     2717            if (fPowerOff)
     2718            {
     2719                /* Free tasks which would have been queued again on resume. */
     2720                PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
     2721
     2722                pThis->pTasksRedoHead = NULL;
     2723
     2724                while (pTaskState)
     2725                {
     2726                    PBUSLOGICTASKSTATE pFree;
     2727
     2728                    pFree = pTaskState;
     2729                    pTaskState = pTaskState->pRedoNext;
     2730
     2731                    RTMemCacheFree(pThis->hTaskCache, pFree);
     2732                }
     2733                pThis->fRedo = false;
     2734            }
     2735            else if (pThis->VBoxSCSI.fBusy)
     2736            {
     2737                /* Destroy the task because the BIOS interface has all necessary information. */
     2738                Assert(pThis->pTasksRedoHead->fBIOS);
     2739                Assert(!pThis->pTasksRedoHead->pRedoNext);
     2740
     2741                RTMemCacheFree(pThis->hTaskCache, pThis->pTasksRedoHead);
     2742                pThis->pTasksRedoHead = NULL;
     2743            }
     2744        }
     2745    }
    25052746}
    25062747
     
    25132754{
    25142755    Log(("buslogicSuspend\n"));
    2515     buslogicR3SuspendOrPowerOff(pDevIns);
    2516 }
     2756    buslogicR3SuspendOrPowerOff(pDevIns, false /* fPoweroff */);
     2757}
     2758
     2759/**
     2760 * Resume notification.
     2761 *
     2762 * @param   pDevIns     The device instance data.
     2763 */
     2764static DECLCALLBACK(void) buslogicResume(PPDMDEVINS pDevIns)
     2765{
     2766    Log(("buslogicResume\n"));
     2767    PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
     2768    buslogicKick(pThis);
     2769}
     2770
    25172771
    25182772/**
     
    26522906{
    26532907    Log(("buslogicPowerOff\n"));
    2654     buslogicR3SuspendOrPowerOff(pDevIns);
     2908    buslogicR3SuspendOrPowerOff(pDevIns, true /* fPoweroff */);
    26552909}
    26562910
     
    26692923
    26702924    PDMR3CritSectDelete(&pThis->CritSectIntr);
     2925
     2926    /*
     2927     * Free all tasks which are still hanging around
     2928     * (Power off after the VM was suspended).
     2929     */
     2930    if (pThis->fRedo)
     2931    {
     2932        /* Free tasks which would have been queued again on resume. */
     2933        PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
     2934
     2935        pThis->pTasksRedoHead = NULL;
     2936
     2937        while (pTaskState)
     2938        {
     2939            PBUSLOGICTASKSTATE pFree;
     2940
     2941            pFree = pTaskState;
     2942            pTaskState = pTaskState->pRedoNext;
     2943
     2944            RTMemCacheFree(pThis->hTaskCache, pFree);
     2945        }
     2946        pThis->fRedo = false;
     2947    }
    26712948
    26722949    int rc = RTMemCacheDestroy(pThis->hTaskCache);
     
    28253102    }
    28263103
    2827     rc = PDMDevHlpSSMRegister3(pDevIns, BUSLOGIC_SAVED_STATE_MINOR_VERSION, sizeof(*pThis),
    2828                                buslogicLiveExec, buslogicSaveExec, buslogicLoadExec);
     3104    rc = PDMDevHlpSSMRegisterEx(pDevIns, BUSLOGIC_SAVED_STATE_MINOR_VERSION, sizeof(*pThis), NULL,
     3105                                NULL, buslogicLiveExec, NULL,
     3106                                NULL, buslogicSaveExec, NULL,
     3107                                NULL, buslogicLoadExec, buslogicLoadDone);
    28293108    if (RT_FAILURE(rc))
    28303109        return PDMDEV_SET_ERROR(pDevIns, rc, N_("BusLogic cannot register save state handlers"));
     
    28753154    buslogicSuspend,
    28763155    /* pfnResume */
    2877     NULL,
     3156    buslogicResume,
    28783157    /* pfnAttach */
    28793158    buslogicAttach,
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