~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: DevLsiLogicSCSI.cpp $ */
 
1
/* $Id: DevLsiLogicSCSI.cpp 35353 2010-12-27 17:25:52Z vboxsync $ */
2
2
/** @file
3
3
 * VBox storage devices: LsiLogic LSI53c1030 SCSI controller.
4
4
 */
17
17
 
18
18
//#define DEBUG
19
19
#define LOG_GROUP LOG_GROUP_DEV_LSILOGICSCSI
20
 
#include <VBox/pdmdev.h>
21
 
#include <VBox/pdmqueue.h>
22
 
#include <VBox/pdmcritsect.h>
 
20
#include <VBox/vmm/pdmdev.h>
 
21
#include <VBox/vmm/pdmqueue.h>
 
22
#include <VBox/vmm/pdmcritsect.h>
23
23
#include <VBox/scsi.h>
24
24
#include <iprt/assert.h>
25
25
#include <iprt/asm.h>
35
35
#include "DevLsiLogicSCSI.h"
36
36
#include "VBoxSCSI.h"
37
37
 
38
 
#include "../Builtins.h"
 
38
#include "VBoxDD.h"
39
39
 
40
40
/** The current saved state version. */
41
41
#define LSILOGIC_SAVED_STATE_VERSION          3
84
84
    uint32_t                      Alignment0;
85
85
#endif
86
86
 
87
 
    /** Our base interace. */
 
87
    /** Our base interface. */
88
88
    PDMIBASE                      IBase;
89
89
    /** SCSI port interface. */
90
90
    PDMISCSIPORT                  ISCSIPort;
99
99
 
100
100
} LSILOGICDEVICE, *PLSILOGICDEVICE;
101
101
 
 
102
/** Pointer to a task state. */
 
103
typedef struct LSILOGICTASKSTATE *PLSILOGICTASKSTATE;
 
104
 
102
105
/**
103
106
 * Device instance data for the emulated
104
107
 * SCSI controller.
286
289
    /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
287
290
     * a port is entering the idle state. */
288
291
    bool volatile                  fSignalIdle;
 
292
    /** Flag whether we have tasks which need to be processed again- */
 
293
    bool volatile                  fRedo;
 
294
    /** List of tasks which can be redone. */
 
295
    R3PTRTYPE(volatile PLSILOGICTASKSTATE) pTasksRedoHead;
289
296
 
290
297
} LSILOGISCSI, *PLSILOGICSCSI;
291
298
 
316
323
} LSILOGICTASKSTATESGENTRY, *PLSILOGICTASKSTATESGENTRY;
317
324
 
318
325
/**
319
 
 * Task state object which holds all neccessary data while
 
326
 * Task state object which holds all necessary data while
320
327
 * processing the request from the guest.
321
328
 */
322
329
typedef struct LSILOGICTASKSTATE
323
330
{
 
331
    /** Next in the redo list. */
 
332
    PLSILOGICTASKSTATE         pRedoNext;
324
333
    /** Target device. */
325
334
    PLSILOGICDEVICE            pTargetDevice;
326
335
    /** The message request from the guest. */
356
365
    uint8_t                    abSenseBuffer[18];
357
366
    /** Flag whether the request was issued from the BIOS. */
358
367
    bool                       fBIOS;
359
 
} LSILOGICTASKSTATE, *PLSILOGICTASKSTATE;
 
368
} LSILOGICTASKSTATE;
360
369
 
361
370
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
362
371
 
423
432
 
424
433
/**
425
434
 * Sets a given interrupt status bit in the status register and
426
 
 * updates the interupt status.
 
435
 * updates the interrupt status.
427
436
 *
428
437
 * @returns nothing.
429
438
 * @param   pLsiLogic    Pointer to the device instance.
437
446
 
438
447
/**
439
448
 * Clears a given interrupt status bit in the status register and
440
 
 * updates the interupt status.
 
449
 * updates the interrupt status.
441
450
 *
442
451
 * @returns nothing.
443
452
 * @param   pLsiLogic    Pointer to the device instance.
624
633
#endif /* IN_RING3 */
625
634
 
626
635
/**
627
 
 * Takes neccessary steps to finish a reply frame.
 
636
 * Takes necessary steps to finish a reply frame.
628
637
 *
629
638
 * @returns nothing
630
639
 * @param   pLsiLogic       Pointer to the device instance
915
924
            AssertRC(rc);
916
925
            break;
917
926
        }
 
927
        case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD:
 
928
        {
 
929
            PMptFWUploadRequest pFWUploadReq = (PMptFWUploadRequest)pMessageHdr;
 
930
 
 
931
            pReply->FWUpload.u8ImageType        = pFWUploadReq->u8ImageType;
 
932
            pReply->FWUpload.u8MessageLength    = 6;
 
933
            pReply->FWUpload.u32ActualImageSize = 0;
 
934
            break;
 
935
        }
 
936
        case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD:
 
937
        {
 
938
            //PMptFWDownloadRequest pFWDownloadReq = (PMptFWDownloadRequest)pMessageHdr;
 
939
 
 
940
            pReply->FWDownload.u8MessageLength    = 5;
 
941
            break;
 
942
        }
918
943
        case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: /* Should be handled already. */
919
944
        default:
920
945
            AssertMsgFailed(("Invalid request function %#x\n", pMessageHdr->u8Function));
1352
1377
#ifdef IN_RING3
1353
1378
 
1354
1379
/**
1355
 
 * Copies a contigous buffer into the scatter gather list provided by the guest.
 
1380
 * Copies a contiguous buffer into the scatter gather list provided by the guest.
1356
1381
 *
1357
1382
 * @returns nothing
1358
1383
 * @param   pTaskState    Pointer to the task state which contains the SGL.
1889
1914
}
1890
1915
#endif
1891
1916
 
 
1917
static void lsilogicWarningDiskFull(PPDMDEVINS pDevIns)
 
1918
{
 
1919
    int rc;
 
1920
    LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance));
 
1921
    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
 
1922
                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
 
1923
    AssertRC(rc);
 
1924
}
 
1925
 
 
1926
static void lsilogicWarningFileTooBig(PPDMDEVINS pDevIns)
 
1927
{
 
1928
    int rc;
 
1929
    LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance));
 
1930
    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
 
1931
                                    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"));
 
1932
    AssertRC(rc);
 
1933
}
 
1934
 
 
1935
static void lsilogicWarningISCSI(PPDMDEVINS pDevIns)
 
1936
{
 
1937
    int rc;
 
1938
    LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
 
1939
    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
 
1940
                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
 
1941
    AssertRC(rc);
 
1942
}
 
1943
 
 
1944
static void lsilogicWarningUnknown(PPDMDEVINS pDevIns, int rc)
 
1945
{
 
1946
    int rc2;
 
1947
    LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
 
1948
    rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
 
1949
                                     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);
 
1950
    AssertRC(rc2);
 
1951
}
 
1952
 
 
1953
static void lsilogicRedoSetWarning(PLSILOGICSCSI pThis, int rc)
 
1954
{
 
1955
    if (rc == VERR_DISK_FULL)
 
1956
        lsilogicWarningDiskFull(pThis->CTX_SUFF(pDevIns));
 
1957
    else if (rc == VERR_FILE_TOO_BIG)
 
1958
        lsilogicWarningFileTooBig(pThis->CTX_SUFF(pDevIns));
 
1959
    else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
 
1960
    {
 
1961
        /* iSCSI connection abort (first error) or failure to reestablish
 
1962
         * connection (second error). Pause VM. On resume we'll retry. */
 
1963
        lsilogicWarningISCSI(pThis->CTX_SUFF(pDevIns));
 
1964
    }
 
1965
    else
 
1966
        lsilogicWarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
 
1967
}
 
1968
 
1892
1969
/**
1893
1970
 * Processes a SCSI I/O request by setting up the request
1894
1971
 * and sending it to the underlying SCSI driver.
2015
2092
    return rc;
2016
2093
}
2017
2094
 
2018
 
/**
2019
 
 * Called upon completion of the request from the SCSI driver below.
2020
 
 * This function frees all allocated ressources and notifies the guest
2021
 
 * that the process finished by asserting an interrupt.
2022
 
 *
2023
 
 * @returns VBox status code.
2024
 
 * @param   pInterface    Pointer to the interface the called funtion belongs to.
2025
 
 * @param   pSCSIRequest  Pointer to the SCSI request which finished.
2026
 
 */
2027
 
static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
 
2095
 
 
2096
static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
 
2097
                                                            int rcCompletion, bool fRedo, int rcReq)
2028
2098
{
2029
2099
    PLSILOGICTASKSTATE pTaskState      = (PLSILOGICTASKSTATE)pSCSIRequest->pvUser;
2030
2100
    PLSILOGICDEVICE    pLsiLogicDevice = pTaskState->pTargetDevice;
2031
2101
    PLSILOGICSCSI      pLsiLogic       = pLsiLogicDevice->CTX_SUFF(pLsiLogic);
2032
2102
 
 
2103
    /* If the task failed but it is possible to redo it again after a suspend
 
2104
     * add it to the list. */
 
2105
    if (fRedo)
 
2106
    {
 
2107
        if (!pTaskState->fBIOS)
 
2108
            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
 
2109
 
 
2110
        /* Add to the list. */
 
2111
        do
 
2112
        {
 
2113
            pTaskState->pRedoNext = ASMAtomicReadPtrT(&pLsiLogic->pTasksRedoHead, PLSILOGICTASKSTATE);
 
2114
        } while (!ASMAtomicCmpXchgPtr(&pLsiLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
 
2115
 
 
2116
        /* Suspend the VM if not done already. */
 
2117
        if (!ASMAtomicXchgBool(&pLsiLogic->fRedo, true))
 
2118
            lsilogicRedoSetWarning(pLsiLogic, rcReq);
 
2119
    }
 
2120
    else
 
2121
    {
 
2122
        if (RT_UNLIKELY(pTaskState->fBIOS))
 
2123
        {
 
2124
            int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
 
2125
            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
 
2126
        }
 
2127
        else
 
2128
        {
 
2129
#if 0
 
2130
            lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
 
2131
#else
 
2132
            RTGCPHYS GCPhysAddrSenseBuffer;
 
2133
 
 
2134
            GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
 
2135
            GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
 
2136
 
 
2137
            /* Copy the sense buffer over. */
 
2138
            PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
 
2139
                                 RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
 
2140
                               ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
 
2141
                               : pTaskState->PDMScsiRequest.cbSenseBuffer);
 
2142
#endif
 
2143
            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
 
2144
 
 
2145
 
 
2146
            if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
 
2147
                lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
 
2148
            else
 
2149
            {
 
2150
                /* The SCSI target encountered an error during processing post a reply. */
 
2151
                memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
 
2152
                pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
 
2153
                pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
 
2154
                pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
 
2155
                pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
 
2156
                pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
 
2157
                pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
 
2158
                pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
 
2159
                pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
 
2160
                pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
 
2161
                pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
 
2162
                pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
 
2163
                pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
 
2164
                pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
 
2165
                pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
 
2166
                pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
 
2167
 
 
2168
                lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
 
2169
            }
 
2170
        }
 
2171
 
 
2172
        RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
 
2173
    }
 
2174
 
2033
2175
    ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
2034
2176
 
2035
 
    if (RT_UNLIKELY(pTaskState->fBIOS))
2036
 
    {
2037
 
        int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
2038
 
        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
2039
 
    }
2040
 
    else
2041
 
    {
2042
 
#if 0
2043
 
        lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
2044
 
#else
2045
 
        RTGCPHYS GCPhysAddrSenseBuffer;
2046
 
 
2047
 
        GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
2048
 
        GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
2049
 
 
2050
 
        /* Copy the sense buffer over. */
2051
 
        PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
2052
 
                             RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
2053
 
                           ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
2054
 
                           : pTaskState->PDMScsiRequest.cbSenseBuffer);
2055
 
#endif
2056
 
        lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
2057
 
 
2058
 
 
2059
 
        if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
2060
 
            lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
2061
 
        else
2062
 
        {
2063
 
            /* The SCSI target encountered an error during processing post a reply. */
2064
 
            memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
2065
 
            pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
2066
 
            pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
2067
 
            pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
2068
 
            pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
2069
 
            pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
2070
 
            pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
2071
 
            pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
2072
 
            pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
2073
 
            pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
2074
 
            pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
2075
 
            pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
2076
 
            pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
2077
 
            pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
2078
 
            pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
2079
 
            pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
2080
 
 
2081
 
            lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
2082
 
        }
2083
 
    }
2084
 
 
2085
 
    RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
2086
 
 
2087
2177
    if (pLsiLogicDevice->cOutstandingRequests == 0 && pLsiLogic->fSignalIdle)
2088
2178
        PDMDevHlpAsyncNotificationCompleted(pLsiLogic->pDevInsR3);
2089
2179
 
2090
2180
    return VINF_SUCCESS;
2091
2181
}
2092
2182
 
 
2183
static DECLCALLBACK(int) lsilogicQueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
 
2184
                                                     uint32_t *piInstance, uint32_t *piLUN)
 
2185
{
 
2186
    PLSILOGICDEVICE pLsiLogicDevice = PDMISCSIPORT_2_PLSILOGICDEVICE(pInterface);
 
2187
    PPDMDEVINS pDevIns = pLsiLogicDevice->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
 
2188
 
 
2189
    AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
 
2190
    AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
 
2191
    AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
 
2192
 
 
2193
    *ppcszController = pDevIns->pReg->szName;
 
2194
    *piInstance = pDevIns->iInstance;
 
2195
    *piLUN = pLsiLogicDevice->iLUN;
 
2196
 
 
2197
    return VINF_SUCCESS;
 
2198
}
 
2199
 
2093
2200
/**
2094
2201
 * Return the configuration page header and data
2095
2202
 * which matches the given page type and number.
3032
3139
    pManufacturingPage7->u.fields.u8NumPhys = pThis->cPorts;
3033
3140
    pPages->pManufacturingPage7 = pManufacturingPage7;
3034
3141
 
3035
 
    /* SAS I/O unit page 0 - Port specific informations. */
 
3142
    /* SAS I/O unit page 0 - Port specific information. */
3036
3143
    pPages->cbSASIOUnitPage0 = LSILOGICSCSI_SASIOUNIT0_GET_SIZE(pThis->cPorts);
3037
3144
    PMptConfigurationPageSASIOUnit0 pSASPage0 = (PMptConfigurationPageSASIOUnit0)RTMemAllocZ(pPages->cbSASIOUnitPage0);
3038
3145
    AssertPtr(pSASPage0);
3056
3163
    pSASPage1->u.fields.u16AdditionalControlFlags = 0;
3057
3164
    pPages->pSASIOUnitPage1 = pSASPage1;
3058
3165
 
3059
 
    /* SAS I/O unit page 2 - Port specific informations. */
 
3166
    /* SAS I/O unit page 2 - Port specific information. */
3060
3167
    pPages->SASIOUnitPage2.u.fields.ExtHeader.u8PageType       =   MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
3061
3168
                                                                 | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED;
3062
3169
    pPages->SASIOUnitPage2.u.fields.ExtHeader.u8PageNumber     = 2;
3063
3170
    pPages->SASIOUnitPage2.u.fields.ExtHeader.u8ExtPageType    = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT;
3064
3171
    pPages->SASIOUnitPage2.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASIOUnit2) / 4;
3065
3172
 
3066
 
    /* SAS I/O unit page 3 - Port specific informations. */
 
3173
    /* SAS I/O unit page 3 - Port specific information. */
3067
3174
    pPages->SASIOUnitPage3.u.fields.ExtHeader.u8PageType       =   MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
3068
3175
                                                                 | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED;
3069
3176
    pPages->SASIOUnitPage3.u.fields.ExtHeader.u8PageNumber     = 3;
3274
3381
                                              MptConfigurationPageManufacturing5, 5,
3275
3382
                                              MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY);
3276
3383
 
3277
 
    /* Manufacturing Page 6 - Product sepcific settings. */
 
3384
    /* Manufacturing Page 6 - Product specific settings. */
3278
3385
    MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage6,
3279
3386
                                              MptConfigurationPageManufacturing6, 6,
3280
3387
                                              MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3281
3388
 
3282
 
    /* Manufacturing Page 8 -  Product sepcific settings. */
 
3389
    /* Manufacturing Page 8 -  Product specific settings. */
3283
3390
    MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage8,
3284
3391
                                              MptConfigurationPageManufacturing8, 8,
3285
3392
                                              MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3286
3393
 
3287
 
    /* Manufacturing Page 9 -  Product sepcific settings. */
 
3394
    /* Manufacturing Page 9 -  Product specific settings. */
3288
3395
    MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage9,
3289
3396
                                              MptConfigurationPageManufacturing9, 9,
3290
3397
                                              MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3291
3398
 
3292
 
    /* Manufacturing Page 10 -  Product sepcific settings. */
 
3399
    /* Manufacturing Page 10 -  Product specific settings. */
3293
3400
    MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage10,
3294
3401
                                              MptConfigurationPageManufacturing10, 10,
3295
3402
                                              MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3490
3597
                //cbRequest = sizeof(MptEventAckRequest);
3491
3598
                break;
3492
3599
            case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD:
3493
 
                AssertMsgFailed(("todo\n"));
 
3600
                cbRequest = sizeof(MptFWDownloadRequest);
 
3601
                break;
 
3602
            case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD:
 
3603
                cbRequest = sizeof(MptFWUploadRequest);
3494
3604
                break;
3495
3605
            default:
3496
3606
                AssertMsgFailed(("Unknown function issued %u\n", pTaskState->GuestRequest.Header.u8Function));
3611
3721
            ASMAtomicIncU32(&pTaskState->pTargetDevice->cOutstandingRequests);
3612
3722
 
3613
3723
            rc = pTaskState->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->pTargetDevice->pDrvSCSIConnector,
3614
 
                                                                                    &pTaskState->PDMScsiRequest);
 
3724
                                                                                  &pTaskState->PDMScsiRequest);
3615
3725
            AssertMsgRCReturn(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc), rc);
3616
3726
            return VINF_SUCCESS;
3617
3727
        }
3836
3946
     * Parse args.
3837
3947
     */
3838
3948
    if (pszArgs)
3839
 
        fVerbose = strstr(pszArgs, "verbose");
 
3949
        fVerbose = strstr(pszArgs, "verbose") != NULL;
3840
3950
 
3841
3951
    /*
3842
3952
     * Show info.
3970
4080
    pThis->pRequestQueueBaseR3   = NULL;
3971
4081
}
3972
4082
 
 
4083
/**
 
4084
 * Kicks the controller to process pending tasks after the VM was resumed
 
4085
 * or loaded from a saved state.
 
4086
 *
 
4087
 * @returns nothing.
 
4088
 * @param   pThis    The LsiLogic device instance.
 
4089
 */
 
4090
static void lsilogicKick(PLSILOGICSCSI pThis)
 
4091
{
 
4092
    if (pThis->fNotificationSend)
 
4093
    {
 
4094
        /* Send a notifier to the PDM queue that there are pending requests. */
 
4095
        PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pNotificationQueue));
 
4096
        AssertMsg(pItem, ("Allocating item for queue failed\n"));
 
4097
        PDMQueueInsert(pThis->CTX_SUFF(pNotificationQueue), (PPDMQUEUEITEMCORE)pItem);
 
4098
    }
 
4099
    else if (pThis->VBoxSCSI.fBusy)
 
4100
    {
 
4101
        /* The BIOS had a request active when we got suspended. Resume it. */
 
4102
        int rc = lsilogicPrepareBIOSSCSIRequest(pThis);
 
4103
        AssertRC(rc);
 
4104
    }
 
4105
 
 
4106
}
 
4107
 
3973
4108
static DECLCALLBACK(int) lsilogicLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
3974
4109
{
3975
4110
    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
4134
4269
    SSMR3PutU32   (pSSM, pLsiLogic->VBoxSCSI.iBuf);
4135
4270
    SSMR3PutBool  (pSSM, pLsiLogic->VBoxSCSI.fBusy);
4136
4271
    SSMR3PutU8    (pSSM, pLsiLogic->VBoxSCSI.enmState);
4137
 
    if (pLsiLogic->VBoxSCSI.cbCDB)
 
4272
    if (pLsiLogic->VBoxSCSI.cbBuf)
4138
4273
        SSMR3PutMem(pSSM, pLsiLogic->VBoxSCSI.pBuf, pLsiLogic->VBoxSCSI.cbBuf);
4139
4274
 
4140
4275
    return SSMR3PutU32(pSSM, ~0);
4141
4276
}
4142
4277
 
 
4278
static DECLCALLBACK(int) lsilogicLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
 
4279
{
 
4280
    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
 
4281
 
 
4282
    lsilogicKick(pThis);
 
4283
    return VINF_SUCCESS;
 
4284
}
 
4285
 
4143
4286
static DECLCALLBACK(int) lsilogicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
4144
4287
{
4145
4288
    PLSILOGICSCSI   pLsiLogic = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
4408
4551
    SSMR3GetU32 (pSSM, &pLsiLogic->VBoxSCSI.iBuf);
4409
4552
    SSMR3GetBool(pSSM, (bool *)&pLsiLogic->VBoxSCSI.fBusy);
4410
4553
    SSMR3GetU8  (pSSM, (uint8_t *)&pLsiLogic->VBoxSCSI.enmState);
4411
 
    if (pLsiLogic->VBoxSCSI.cbCDB)
 
4554
    if (pLsiLogic->VBoxSCSI.cbBuf)
4412
4555
    {
4413
 
        pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbCDB);
 
4556
        pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbBuf);
4414
4557
        if (!pLsiLogic->VBoxSCSI.pBuf)
4415
4558
        {
4416
4559
            LogRel(("LsiLogic: Out of memory during restore.\n"));
4549
4692
    if (!lsilogicR3AllAsyncIOIsFinished(pDevIns))
4550
4693
        PDMDevHlpSetAsyncNotification(pDevIns, lsilogicR3IsAsyncSuspendOrPowerOffDone);
4551
4694
    else
 
4695
    {
4552
4696
        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
 
4697
 
 
4698
        AssertMsg(!pThis->fNotificationSend, ("The PDM Queue should be empty at this point\n"));
 
4699
 
 
4700
        if (pThis->fRedo)
 
4701
        {
 
4702
            /*
 
4703
             * We have tasks which we need to redo. Put the message frame addresses
 
4704
             * into the request queue (we save the requests).
 
4705
             * Guest execution is suspended at this point so there is no race between us and
 
4706
             * lsilogicRegisterWrite.
 
4707
             */
 
4708
            PLSILOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
 
4709
 
 
4710
            pThis->pTasksRedoHead = NULL;
 
4711
 
 
4712
            while (pTaskState)
 
4713
            {
 
4714
                PLSILOGICTASKSTATE pFree;
 
4715
 
 
4716
                if (!pTaskState->fBIOS)
 
4717
                {
 
4718
                    /* Write only the lower 32bit part of the address. */
 
4719
                    ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
 
4720
                                      pTaskState->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
 
4721
 
 
4722
                    pThis->uRequestQueueNextEntryFreeWrite++;
 
4723
                    pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
 
4724
 
 
4725
                    pThis->fNotificationSend = true;
 
4726
                }
 
4727
                else
 
4728
                {
 
4729
                    AssertMsg(!pTaskState->pRedoNext, ("Only one BIOS task can be active!\n"));
 
4730
                    vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pTaskState->PDMScsiRequest);
 
4731
                }
 
4732
 
 
4733
                pFree = pTaskState;
 
4734
                pTaskState = pTaskState->pRedoNext;
 
4735
 
 
4736
                RTMemCacheFree(pThis->hTaskCache, pFree);
 
4737
            }
 
4738
            pThis->fRedo = false;
 
4739
        }
 
4740
    }
4553
4741
}
4554
4742
 
4555
4743
/**
4564
4752
}
4565
4753
 
4566
4754
/**
 
4755
 * Resume notification.
 
4756
 *
 
4757
 * @param   pDevIns     The device instance data.
 
4758
 */
 
4759
static DECLCALLBACK(void) lsilogicResume(PPDMDEVINS pDevIns)
 
4760
{
 
4761
    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
 
4762
 
 
4763
    Log(("lsilogicResume\n"));
 
4764
 
 
4765
    lsilogicKick(pThis);
 
4766
}
 
4767
 
 
4768
/**
4567
4769
 * Detach notification.
4568
4770
 *
4569
4771
 * One harddisk at one port has been unplugged.
4753
4955
    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
4754
4956
    int rc = VINF_SUCCESS;
4755
4957
    char *pszCtrlType = NULL;
 
4958
    char  szDevTag[20], szTaggedText[64];
 
4959
    bool fBootable = true;
4756
4960
    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
4757
4961
 
4758
4962
    /*
4763
4967
                                    "ReplyQueueDepth\0"
4764
4968
                                    "RequestQueueDepth\0"
4765
4969
                                    "ControllerType\0"
4766
 
                                    "NumPorts\0");
 
4970
                                    "NumPorts\0"
 
4971
                                    "Bootable\0");
4767
4972
    if (RT_FAILURE(rc))
4768
4973
        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
4769
4974
                                N_("LsiLogic configuration error: unknown option specified"));
4805
5010
    rc = lsilogicGetCtrlTypeFromString(pThis, pszCtrlType);
4806
5011
    MMR3HeapFree(pszCtrlType);
4807
5012
 
 
5013
    RTStrPrintf(szDevTag, sizeof(szDevTag), "LSILOGIC%s-%d",
 
5014
                pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI ? "SPI" : "SAS",
 
5015
                iInstance);
 
5016
 
 
5017
 
4808
5018
    if (RT_FAILURE(rc))
4809
5019
        return PDMDEV_SET_ERROR(pDevIns, rc,
4810
5020
                                N_("LsiLogic configuration error: failed to determine controller type from string"));
4824
5034
        return PDMDEV_SET_ERROR(pDevIns, rc,
4825
5035
                                N_("LsiLogic configuration error: failed to read NumPorts as integer"));
4826
5036
 
 
5037
    rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &fBootable, true);
 
5038
    if (RT_FAILURE(rc))
 
5039
        return PDMDEV_SET_ERROR(pDevIns, rc,
 
5040
                                N_("LsiLogic configuration error: failed to read Bootable as boolean"));
 
5041
    Log(("%s: Bootable=%RTbool\n", __FUNCTION__, fBootable));
 
5042
 
4827
5043
    /* Init static parts. */
4828
5044
    PCIDevSetVendorId(&pThis->PciDev, LSILOGICSCSI_PCI_VENDOR_ID); /* LsiLogic */
4829
5045
 
4847
5063
    PCIDevSetClassBase   (&pThis->PciDev,   0x01); /* Mass storage */
4848
5064
    PCIDevSetInterruptPin(&pThis->PciDev,   0x01); /* Interrupt pin A */
4849
5065
 
 
5066
#ifdef VBOX_WITH_MSI_DEVICES
 
5067
    PCIDevSetStatus(&pThis->PciDev,   VBOX_PCI_STATUS_CAP_LIST);
 
5068
    PCIDevSetCapabilityList(&pThis->PciDev, 0x80);
 
5069
#endif
 
5070
 
4850
5071
    pThis->pDevInsR3 = pDevIns;
4851
5072
    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
4852
5073
    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
4860
5081
    if (RT_FAILURE(rc))
4861
5082
        return rc;
4862
5083
 
 
5084
#ifdef VBOX_WITH_MSI_DEVICES
 
5085
    PDMMSIREG aMsiReg;
 
5086
    RT_ZERO(aMsiReg);
 
5087
    /* use this code for MSI-X support */
 
5088
#if 0
 
5089
    aMsiReg.cMsixVectors = 1;
 
5090
    aMsiReg.iMsixCapOffset = 0x80;
 
5091
    aMsiReg.iMsixNextOffset = 0x0;
 
5092
    aMsiReg.iMsixBar = 3;
 
5093
#else
 
5094
    aMsiReg.cMsiVectors = 1;
 
5095
    aMsiReg.iMsiCapOffset = 0x80;
 
5096
    aMsiReg.iMsiNextOffset = 0x0;
 
5097
#endif
 
5098
    rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg);
 
5099
    if (RT_FAILURE (rc))
 
5100
    {
 
5101
        LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
 
5102
        /* That's OK, we can work without MSI */
 
5103
        PCIDevSetCapabilityList(&pThis->PciDev, 0x0);
 
5104
    }
 
5105
#endif
 
5106
 
4863
5107
    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, LSILOGIC_PCI_SPACE_IO_SIZE, PCI_ADDRESS_SPACE_IO, lsilogicMap);
4864
5108
    if (RT_FAILURE(rc))
4865
5109
        return rc;
4872
5116
    if (RT_FAILURE(rc))
4873
5117
        return rc;
4874
5118
 
4875
 
    /* Intialize task queue. (Need two items to handle SMP guest concurrency.) */
 
5119
    /* Initialize task queue. (Need two items to handle SMP guest concurrency.) */
 
5120
    RTStrPrintf(szTaggedText, sizeof(szTaggedText), "%s-Task", szDevTag);
4876
5121
    rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 2, 0,
4877
5122
                              lsilogicNotifyQueueConsumer, true,
4878
 
                              pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI
4879
 
                              ? "LsiLogic-Task"
4880
 
                              : "LsiLogicSAS-Task",
 
5123
                              szTaggedText,
4881
5124
                              &pThis->pNotificationQueueR3);
4882
5125
    if (RT_FAILURE(rc))
4883
5126
        return rc;
4900
5143
    /*
4901
5144
     * Create critical sections protecting the reply post and free queues.
4902
5145
     */
 
5146
    RTStrPrintf(szTaggedText, sizeof(szTaggedText), "%sRFQ", szDevTag);
4903
5147
    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->ReplyFreeQueueCritSect, RT_SRC_POS,
4904
 
                               pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI
4905
 
                               ? "LsiLogicRFQ"
4906
 
                               : "LsiLogicSasRFQ");
 
5148
                               szTaggedText);
4907
5149
    if (RT_FAILURE(rc))
4908
5150
        return PDMDEV_SET_ERROR(pDevIns, rc,
4909
5151
                                N_("LsiLogic: cannot create critical section for reply free queue"));
4910
5152
 
 
5153
    RTStrPrintf(szTaggedText, sizeof(szTaggedText), "%sRPQ", szDevTag);
4911
5154
    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->ReplyPostQueueCritSect, RT_SRC_POS,
4912
 
                               pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI
4913
 
                               ? "LsiLogicRPQ"
4914
 
                               : "LsiLogicSasRPQ");
 
5155
                               szTaggedText);
4915
5156
    if (RT_FAILURE(rc))
4916
5157
        return PDMDEV_SET_ERROR(pDevIns, rc,
4917
5158
                                N_("LsiLogic: cannot create critical section for reply post queue"));
4951
5192
        pDevice->Led.u32Magic                      = PDMLED_MAGIC;
4952
5193
        pDevice->IBase.pfnQueryInterface           = lsilogicDeviceQueryInterface;
4953
5194
        pDevice->ISCSIPort.pfnSCSIRequestCompleted = lsilogicDeviceSCSIRequestCompleted;
 
5195
        pDevice->ISCSIPort.pfnQueryDeviceLocation  = lsilogicQueryDeviceLocation;
4954
5196
        pDevice->ILed.pfnQueryStatusLed            = lsilogicDeviceQueryStatusLed;
4955
5197
 
4956
5198
        RTStrPrintf(szName, sizeof(szName), "Device%d", i);
4993
5235
    rc = vboxscsiInitialize(&pThis->VBoxSCSI);
4994
5236
    AssertRC(rc);
4995
5237
 
4996
 
    /* Register I/O port space in ISA region for BIOS access. */
4997
 
    if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
4998
 
        rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_ISA_IO_PORT, 3, NULL,
4999
 
                                     lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5000
 
                                     lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5001
 
                                     "LsiLogic BIOS");
5002
 
    else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
5003
 
        rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_SAS_ISA_IO_PORT, 3, NULL,
5004
 
                                     lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5005
 
                                     lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5006
 
                                     "LsiLogic SAS BIOS");
5007
 
    else
5008
 
        AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
 
5238
    /*
 
5239
     * Register I/O port space in ISA region for BIOS access
 
5240
     * if the controller is marked as bootable.
 
5241
     */
 
5242
    if (fBootable)
 
5243
    {
 
5244
        if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
 
5245
            rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_ISA_IO_PORT, 3, NULL,
 
5246
                                         lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
 
5247
                                         lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
 
5248
                                         "LsiLogic BIOS");
 
5249
        else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
 
5250
            rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_SAS_ISA_IO_PORT, 3, NULL,
 
5251
                                         lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
 
5252
                                         lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
 
5253
                                         "LsiLogic SAS BIOS");
 
5254
        else
 
5255
            AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
5009
5256
 
5010
 
    if (RT_FAILURE(rc))
5011
 
        return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register legacy I/O handlers"));
 
5257
        if (RT_FAILURE(rc))
 
5258
            return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register legacy I/O handlers"));
 
5259
    }
5012
5260
 
5013
5261
    /* Register save state handlers. */
5014
 
    rc = PDMDevHlpSSMRegister3(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis),
5015
 
                               lsilogicLiveExec, lsilogicSaveExec, lsilogicLoadExec);
 
5262
    rc = PDMDevHlpSSMRegisterEx(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
 
5263
                                NULL, lsilogicLiveExec, NULL,
 
5264
                                NULL, lsilogicSaveExec, NULL,
 
5265
                                NULL, lsilogicLoadExec, lsilogicLoadDone);
5016
5266
    if (RT_FAILURE(rc))
5017
5267
        return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register save state handlers"));
5018
5268
 
5074
5324
    /* pfnSuspend */
5075
5325
    lsilogicSuspend,
5076
5326
    /* pfnResume */
5077
 
    NULL,
 
5327
    lsilogicResume,
5078
5328
    /* pfnAttach */
5079
5329
    lsilogicAttach,
5080
5330
    /* pfnDetach */
5130
5380
    /* pfnSuspend */
5131
5381
    lsilogicSuspend,
5132
5382
    /* pfnResume */
5133
 
    NULL,
 
5383
    lsilogicResume,
5134
5384
    /* pfnAttach */
5135
5385
    lsilogicAttach,
5136
5386
    /* pfnDetach */
5149
5399
 
5150
5400
#endif /* IN_RING3 */
5151
5401
#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
5152