VirtualBox

Changeset 64224 in vbox for trunk/src


Ignore:
Timestamp:
Oct 12, 2016 12:54:51 PM (8 years ago)
Author:
vboxsync
Message:

LsiLogic,BusLogic,VBoxSCSI: Convert to PDMIMEDIAEX and friends

Location:
trunk/src/VBox/Devices
Files:
5 edited

Legend:

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

    r63690 r64224  
    112112    /** Our base interface. */
    113113    PDMIBASE                      IBase;
    114     /** SCSI port interface. */
    115     PDMISCSIPORT                  ISCSIPort;
     114    /** Media port interface. */
     115    PDMIMEDIAPORT                 IMediaPort;
     116    /** Extended media port interface. */
     117    PDMIMEDIAEXPORT               IMediaExPort;
    116118    /** Led interface. */
    117119    PDMILEDPORTS                  ILed;
    118120    /** Pointer to the attached driver's base interface. */
    119121    R3PTRTYPE(PPDMIBASE)          pDrvBase;
    120     /** Pointer to the underlying SCSI connector interface. */
    121     R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector;
     122    /** Pointer to the attached driver's media interface. */
     123    R3PTRTYPE(PPDMIMEDIA)         pDrvMedia;
     124    /** Pointer to the attached driver's extended media interface. */
     125    R3PTRTYPE(PPDMIMEDIAEX)       pDrvMediaEx;
    122126    /** The status LED state for this device. */
    123127    PDMLED                        Led;
     
    313317
    314318/** Pointer to a task state structure. */
    315 typedef struct BUSLOGICTASKSTATE *PBUSLOGICTASKSTATE;
     319typedef struct BUSLOGICREQ *PBUSLOGICREQ;
    316320
    317321/**
     
    436440    PDMCRITSECT                     CritSectIntr;
    437441
    438     /** Cache for task states. */
    439     R3PTRTYPE(RTMEMCACHE)           hTaskCache;
    440 
    441442    /** Device state for BIOS access. */
    442443    VBOXSCSI                        VBoxSCSI;
     
    460461     * a port is entering the idle state. */
    461462    bool volatile                   fSignalIdle;
    462     /** Flag whether we have tasks which need to be processed again. */
    463     bool volatile                   fRedo;
    464463    /** Flag whether the worker thread is sleeping. */
    465464    volatile bool                   fWrkThreadSleeping;
     
    467466     * worker thread needs to process. */
    468467    volatile bool                   fBiosReqPending;
    469     /** List of tasks which can be redone. */
    470     R3PTRTYPE(volatile PBUSLOGICTASKSTATE) pTasksRedoHead;
    471468
    472469    /** The support driver session handle. */
     
    477474    SUPSEMEVENT                     hEvtProcess;
    478475
     476    /** Pointer to the array of addresses to redo. */
     477    R3PTRTYPE(PRTGCPHYS)            paGCPhysAddrCCBRedo;
     478    /** Number of addresses the redo array holds. */
     479    uint32_t                        cReqsRedo;
     480
    479481#ifdef LOG_ENABLED
     482    volatile uint32_t               cInMailboxesReady;
     483#else
    480484# if HC_ARCH_BITS == 64
    481485    uint32_t                        Alignment4;
    482486# endif
    483 
    484     volatile uint32_t               cInMailboxesReady;
    485487#endif
    486488
     
    956958 * Task state for a CCB request.
    957959 */
    958 typedef struct BUSLOGICTASKSTATE
    959 {
    960     /** Next in the redo list. */
    961     PBUSLOGICTASKSTATE             pRedoNext;
     960typedef struct BUSLOGICREQ
     961{
     962    /** PDM extended media interface I/O request hande. */
     963    PDMMEDIAEXIOREQ                hIoReq;
    962964    /** Device this task is assigned to. */
    963     R3PTRTYPE(PBUSLOGICDEVICE)     pTargetDeviceR3;
     965    PBUSLOGICDEVICE                pTargetDevice;
    964966    /** The command control block from the guest. */
    965     CCBU                CommandControlBlockGuest;
    966     /** Mailbox read from guest memory. */
    967     Mailbox32           MailboxGuest;
    968     /** The SCSI request we pass to the underlying SCSI engine. */
    969     PDMSCSIREQUEST      PDMScsiRequest;
    970     /** Data buffer segment */
    971     RTSGSEG             DataSeg;
     967    CCBU                           CCBGuest;
     968    /** Guest physical address of th CCB. */
     969    RTGCPHYS                       GCPhysAddrCCB;
    972970    /** Pointer to the R3 sense buffer. */
    973     uint8_t            *pbSenseBuffer;
     971    uint8_t                        *pbSenseBuffer;
    974972    /** Flag whether this is a request from the BIOS. */
    975     bool                fBIOS;
     973    bool                           fBIOS;
    976974    /** 24-bit request flag (default is 32-bit). */
    977     bool                fIs24Bit;
    978     /** S/G entry size (depends on the above flag). */
    979     uint8_t             cbSGEntry;
    980 } BUSLOGICTASKSTATE;
     975    bool                           fIs24Bit;
     976    /** SCSI status code. */
     977    uint8_t                        u8ScsiSts;
     978} BUSLOGICREQ;
     979
     980#ifdef IN_RING3
     981/**
     982 * Memory buffer callback.
     983 *
     984 * @returns nothing.
     985 * @param   pThis    The LsiLogic controller instance.
     986 * @param   GCPhys   The guest physical address of the memory buffer.
     987 * @param   pSgBuf   The pointer to the host R3 S/G buffer.
     988 * @param   cbCopy   How many bytes to copy between the two buffers.
     989 * @param   pcbSkip  Initially contains the amount of bytes to skip
     990 *                   starting from the guest physical address before
     991 *                   accessing the S/G buffer and start copying data.
     992 *                   On return this contains the remaining amount if
     993 *                   cbCopy < *pcbSkip or 0 otherwise.
     994 */
     995typedef DECLCALLBACK(void) BUSLOGICR3MEMCOPYCALLBACK(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
     996                                                     size_t *pcbSkip);
     997/** Pointer to a memory copy buffer callback. */
     998typedef BUSLOGICR3MEMCOPYCALLBACK *PBUSLOGICR3MEMCOPYCALLBACK;
     999#endif
    9811000
    9821001#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    983 
    984 #define PDMIBASE_2_PBUSLOGICDEVICE(pInterface)     ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, IBase)) )
    985 #define PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ISCSIPort)) )
    986 #define PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ILed)) )
    987 #define PDMIBASE_2_PBUSLOGIC(pInterface)           ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, IBase)) )
    988 #define PDMILEDPORTS_2_PBUSLOGIC(pInterface)       ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, ILeds)) )
    9891002
    9901003
     
    11881201 * @returns nothing.
    11891202 * @param   pBusLogic                 Pointer to the BusLogic device instance.
    1190  * @param   pTaskState                Pointer to the task state with the mailbox to send.
     1203 * @param   GCPhysAddrCCB             The physical guest address of the CCB the mailbox is for.
     1204 * @param   pCCBGuet                  The command control block.
    11911205 * @param   uHostAdapterStatus        The host adapter status code to set.
    11921206 * @param   uDeviceStatus             The target device status to set.
    11931207 * @param   uMailboxCompletionCode    Completion status code to set in the mailbox.
    11941208 */
    1195 static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState,
    1196                                           uint8_t uHostAdapterStatus, uint8_t uDeviceStatus,
    1197                                           uint8_t uMailboxCompletionCode)
    1198 {
    1199     pTaskState->MailboxGuest.u.in.uHostAdapterStatus = uHostAdapterStatus;
    1200     pTaskState->MailboxGuest.u.in.uTargetDeviceStatus = uDeviceStatus;
    1201     pTaskState->MailboxGuest.u.in.uCompletionCode = uMailboxCompletionCode;
     1209static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB,
     1210                                          PCCBU pCCBGuest, uint8_t uHostAdapterStatus,
     1211                                          uint8_t uDeviceStatus, uint8_t uMailboxCompletionCode)
     1212{
     1213    Mailbox32 MbxIn;
     1214
     1215    MbxIn.u32PhysAddrCCB           = (uint32_t)GCPhysAddrCCB;
     1216    MbxIn.u.in.uHostAdapterStatus  = uHostAdapterStatus;
     1217    MbxIn.u.in.uTargetDeviceStatus = uDeviceStatus;
     1218    MbxIn.u.in.uCompletionCode     = uMailboxCompletionCode;
    12021219
    12031220    int rc = PDMCritSectEnter(&pBusLogic->CritSectIntr, VINF_SUCCESS);
     
    12061223    RTGCPHYS GCPhysAddrMailboxIncoming = pBusLogic->GCPhysAddrMailboxIncomingBase
    12071224                                       + (   pBusLogic->uMailboxIncomingPositionCurrent
    1208                                           * (pTaskState->fIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) );
     1225                                          * (pBusLogic->fMbxIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) );
    12091226
    12101227    if (uMailboxCompletionCode != BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND)
    12111228    {
    1212         RTGCPHYS GCPhysAddrCCB = pTaskState->MailboxGuest.u32PhysAddrCCB;
    12131229        LogFlowFunc(("Completing CCB %RGp hstat=%u, dstat=%u, outgoing mailbox at %RGp\n", GCPhysAddrCCB,
    12141230                     uHostAdapterStatus, uDeviceStatus, GCPhysAddrMailboxIncoming));
    12151231
    12161232        /* Update CCB. */
    1217         pTaskState->CommandControlBlockGuest.c.uHostAdapterStatus = uHostAdapterStatus;
    1218         pTaskState->CommandControlBlockGuest.c.uDeviceStatus      = uDeviceStatus;
     1233        pCCBGuest->c.uHostAdapterStatus = uHostAdapterStatus;
     1234        pCCBGuest->c.uDeviceStatus      = uDeviceStatus;
    12191235        /* Rewrite CCB up to the CDB; perhaps more than necessary. */
    12201236        PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
    1221                               &pTaskState->CommandControlBlockGuest, RT_OFFSETOF(CCBC, abCDB));
     1237                              pCCBGuest, RT_OFFSETOF(CCBC, abCDB));
    12221238    }
    12231239
    12241240# ifdef RT_STRICT
    12251241    uint8_t     uCode;
    1226     unsigned    uCodeOffs = pTaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
     1242    unsigned    uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
    12271243    PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming + uCodeOffs, &uCode, sizeof(uCode));
    12281244    Assert(uCode == BUSLOGIC_MAILBOX_INCOMING_COMPLETION_FREE);
     
    12301246
    12311247    /* Update mailbox. */
    1232     if (pTaskState->fIs24Bit)
     1248    if (pBusLogic->fMbxIs24Bit)
    12331249    {
    12341250        Mailbox24   Mbx24;
    12351251
    1236         Mbx24.uCmdState = pTaskState->MailboxGuest.u.in.uCompletionCode;
    1237         U32_TO_ADDR(Mbx24.aPhysAddrCCB, pTaskState->MailboxGuest.u32PhysAddrCCB);
     1252        Mbx24.uCmdState = MbxIn.u.in.uCompletionCode;
     1253        U32_TO_ADDR(Mbx24.aPhysAddrCCB, MbxIn.u32PhysAddrCCB);
    12381254        Log(("24-bit mailbox: completion code=%u, CCB at %RGp\n", Mbx24.uCmdState, (RTGCPHYS)ADDR_TO_U32(Mbx24.aPhysAddrCCB)));
    12391255        PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming, &Mbx24, sizeof(Mailbox24));
     
    12411257    else
    12421258    {
    1243         Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", pTaskState->MailboxGuest.u.in.uCompletionCode, (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB));
     1259        Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", MbxIn.u.in.uCompletionCode, GCPhysAddrCCB));
    12441260        PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming,
    1245                               &pTaskState->MailboxGuest, sizeof(Mailbox32));
     1261                              &MbxIn, sizeof(Mailbox32));
    12461262    }
    12471263
     
    13311347 * Allocate data buffer.
    13321348 *
    1333  * @param   pTaskState    Pointer to the task state.
     1349 * @param   pDevIns       PDM device instance.
     1350 * @param   fIs24Bit      Flag whether the 24bit SG format is used.
    13341351 * @param   GCSGList      Guest physical address of S/G list.
    13351352 * @param   cEntries      Number of list entries to read.
    13361353 * @param   pSGEList      Pointer to 32-bit S/G list storage.
    13371354 */
    1338 static void buslogicR3ReadSGEntries(PBUSLOGICTASKSTATE pTaskState, RTGCPHYS GCSGList, uint32_t cEntries, SGE32 *pSGEList)
    1339 {
    1340     PPDMDEVINS  pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
    1341     SGE24       aSGE24[32];
    1342     Assert(cEntries <= RT_ELEMENTS(aSGE24));
    1343 
     1355static void buslogicR3ReadSGEntries(PPDMDEVINS pDevIns, bool fIs24Bit, RTGCPHYS GCSGList,
     1356                                    uint32_t cEntries, SGE32 *pSGEList)
     1357{
    13441358    /* Read the S/G entries. Convert 24-bit entries to 32-bit format. */
    1345     if (pTaskState->fIs24Bit)
    1346     {
     1359    if (fIs24Bit)
     1360    {
     1361        SGE24 aSGE24[32];
     1362        Assert(cEntries <= RT_ELEMENTS(aSGE24));
     1363
    13471364        Log2(("Converting %u 24-bit S/G entries to 32-bit\n", cEntries));
    13481365        PDMDevHlpPhysRead(pDevIns, GCSGList, &aSGE24, cEntries * sizeof(SGE24));
     
    13581375
    13591376/**
    1360  * Allocate data buffer.
     1377 * Determines the size of th guest data buffer.
    13611378 *
    13621379 * @returns VBox status code.
    1363  * @param   pTaskState    Pointer to the task state.
    1364  */
    1365 static int buslogicR3DataBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
    1366 {
    1367     PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
    1368     uint32_t   cbDataCCB;
    1369     uint32_t   u32PhysAddrCCB;
     1380 * @param   pDevIns       PDM device instance.
     1381 * @param   pCCBGuest     The CCB of the guest.
     1382 * @param   fIs24Bit      Flag whether the 24bit SG format is used.
     1383 * @para    cbSGEntry     Size of one SG entry in bytes.
     1384 * @param   pcbBuf        Where to store the size of the guest data buffer on success.
     1385 */
     1386static int buslogicR3QueryDataBufferSize(PPDMDEVINS pDevIns, PCCBU pCCBGuest, bool fIs24Bit, size_t *pcbBuf)
     1387{
     1388    int rc = VINF_SUCCESS;
     1389    uint32_t cbDataCCB;
     1390    uint32_t u32PhysAddrCCB;
     1391    size_t cbBuf = 0;
    13701392
    13711393    /* Extract the data length and physical address from the CCB. */
    1372     if (pTaskState->fIs24Bit)
    1373     {
    1374         u32PhysAddrCCB  = ADDR_TO_U32(pTaskState->CommandControlBlockGuest.o.aPhysAddrData);
    1375         cbDataCCB       = LEN_TO_U32(pTaskState->CommandControlBlockGuest.o.acbData);
     1394    if (fIs24Bit)
     1395    {
     1396        u32PhysAddrCCB  = ADDR_TO_U32(pCCBGuest->o.aPhysAddrData);
     1397        cbDataCCB       = LEN_TO_U32(pCCBGuest->o.acbData);
    13761398    }
    13771399    else
    13781400    {
    1379         u32PhysAddrCCB  = pTaskState->CommandControlBlockGuest.n.u32PhysAddrData;
    1380         cbDataCCB       = pTaskState->CommandControlBlockGuest.n.cbData;
    1381     }
    1382 
    1383     if (   (pTaskState->CommandControlBlockGuest.c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)
     1401        u32PhysAddrCCB  = pCCBGuest->n.u32PhysAddrData;
     1402        cbDataCCB       = pCCBGuest->n.cbData;
     1403    }
     1404
     1405    if (   (pCCBGuest->c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)
    13841406        && cbDataCCB)
    13851407    {
    1386         /** @todo Check following assumption and what residual means. */
    13871408        /*
    13881409         * The BusLogic adapter can handle two different data buffer formats.
     
    13911412         * scatter gather list which describes the buffer.
    13921413         */
    1393         if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
    1394             || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
     1414        if (   (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
     1415            || (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
    13951416        {
    13961417            uint32_t cScatterGatherGCRead;
    13971418            uint32_t iScatterGatherEntry;
    13981419            SGE32    aScatterGatherReadGC[32]; /* A buffer for scatter gather list entries read from guest memory. */
    1399             uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
     1420            uint32_t cScatterGatherGCLeft = cbDataCCB / (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
    14001421            RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
    1401             size_t cbDataToTransfer = 0;
    14021422
    14031423            /* Count number of bytes to transfer. */
     
    14091429                cScatterGatherGCLeft -= cScatterGatherGCRead;
    14101430
    1411                 buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
     1431                buslogicR3ReadSGEntries(pDevIns, fIs24Bit, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
    14121432
    14131433                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
    1414                 {
    1415                     RTGCPHYS    GCPhysAddrDataBase;
    1416 
    1417                     Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
    1418 
    1419                     GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
    1420                     cbDataToTransfer += aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
    1421 
    1422                     Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n",
    1423                          __FUNCTION__, GCPhysAddrDataBase,
    1424                          aScatterGatherReadGC[iScatterGatherEntry].cbSegment));
    1425                 }
     1434                    cbBuf += aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
    14261435
    14271436                /* Set address to the next entries to read. */
    1428                 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
     1437                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
    14291438            } while (cScatterGatherGCLeft > 0);
    14301439
    1431             Log(("%s: cbDataToTransfer=%d\n", __FUNCTION__, cbDataToTransfer));
    1432 
    1433             /* Allocate buffer */
    1434             pTaskState->DataSeg.cbSeg = cbDataToTransfer;
    1435             pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
    1436             if (!pTaskState->DataSeg.pvSeg)
    1437                 return VERR_NO_MEMORY;
    1438 
    1439             /* Copy the data if needed */
    1440             if (   (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
    1441                 || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN))
    1442             {
    1443                 cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
    1444                 GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
    1445                 uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
    1446 
    1447                 do
    1448                 {
    1449                     cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
    1450                                             ? cScatterGatherGCLeft
    1451                                             : RT_ELEMENTS(aScatterGatherReadGC);
    1452                     cScatterGatherGCLeft -= cScatterGatherGCRead;
    1453 
    1454                     buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
    1455 
    1456                     for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
    1457                     {
    1458                         RTGCPHYS    GCPhysAddrDataBase;
    1459 
    1460                         Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
    1461 
    1462                         GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
    1463                         cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
    1464 
    1465                         Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
    1466 
    1467                         PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
    1468                         pbData += cbDataToTransfer;
    1469                     }
    1470 
    1471                     /* Set address to the next entries to read. */
    1472                     GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
    1473                 } while (cScatterGatherGCLeft > 0);
    1474             }
    1475 
    1476         }
    1477         else if (   pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
    1478                  || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
    1479         {
    1480             /* The buffer is not scattered. */
    1481             RTGCPHYS GCPhysAddrDataBase = u32PhysAddrCCB;
    1482 
    1483             AssertMsg(GCPhysAddrDataBase != 0, ("Physical address is 0\n"));
    1484 
    1485             pTaskState->DataSeg.cbSeg = cbDataCCB;
    1486             pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
    1487             if (!pTaskState->DataSeg.pvSeg)
    1488                 return VERR_NO_MEMORY;
    1489 
    1490             Log(("Non scattered buffer:\n"));
    1491             Log(("u32PhysAddrData=%#x\n", u32PhysAddrCCB));
    1492             Log(("cbData=%u\n", cbDataCCB));
    1493             Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase));
    1494 
    1495             /* Copy the data into the buffer. */
    1496             PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
    1497         }
    1498     }
    1499 
    1500     return VINF_SUCCESS;
    1501 }
    1502 
    1503 /**
    1504  * Free allocated resources used for the scatter gather list.
    1505  *
    1506  * @returns nothing.
    1507  * @param   pTaskState    Pointer to the task state.
    1508  */
    1509 static void buslogicR3DataBufferFree(PBUSLOGICTASKSTATE pTaskState)
    1510 {
    1511     PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
     1440            Log(("%s: cbBuf=%d\n", __FUNCTION__, cbBuf));
     1441        }
     1442        else if (   pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
     1443                 || pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
     1444            cbBuf = cbDataCCB;
     1445    }
     1446
     1447    if (RT_SUCCESS(rc))
     1448        *pcbBuf = cbBuf;
     1449
     1450    return rc;
     1451}
     1452
     1453/**
     1454 * Copy from guest to host memory worker.
     1455 *
     1456 * @copydoc{BUSLOGICR3MEMCOPYCALLBACK}
     1457 */
     1458static DECLCALLBACK(void) buslogicR3CopyBufferFromGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     1459                                                              size_t cbCopy, size_t *pcbSkip)
     1460{
     1461    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     1462    cbCopy   -= cbSkipped;
     1463    GCPhys   += cbSkipped;
     1464    *pcbSkip -= cbSkipped;
     1465
     1466    while (cbCopy)
     1467    {
     1468        size_t cbSeg = cbCopy;
     1469        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     1470
     1471        AssertPtr(pvSeg);
     1472        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     1473        GCPhys += cbSeg;
     1474        cbCopy -= cbSeg;
     1475    }
     1476}
     1477
     1478/**
     1479 * Copy from host to guest memory worker.
     1480 *
     1481 * @copydoc{BUSLOGICR3MEMCOPYCALLBACK}
     1482 */
     1483static DECLCALLBACK(void) buslogicR3CopyBufferToGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     1484                                                            size_t cbCopy, size_t *pcbSkip)
     1485{
     1486    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     1487    cbCopy   -= cbSkipped;
     1488    GCPhys   += cbSkipped;
     1489    *pcbSkip -= cbSkipped;
     1490
     1491    while (cbCopy)
     1492    {
     1493        size_t cbSeg = cbCopy;
     1494        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     1495
     1496        AssertPtr(pvSeg);
     1497        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     1498        GCPhys += cbSeg;
     1499        cbCopy -= cbSeg;
     1500    }
     1501}
     1502
     1503/**
     1504 * Walks the guest S/G buffer calling the given copy worker for every buffer.
     1505 *
     1506 * @returns The amout of bytes actually copied.
     1507 * @param   pThis                  Pointer to the Buslogic device state.
     1508 * @param   pReq                   Pointe to the request state.
     1509 * @param   pfnCopyWorker          The copy method to apply for each guest buffer.
     1510 * @param   pSgBuf                 The host S/G buffer.
     1511 * @param   cbSkip                 How many bytes to skip in advance before starting to copy.
     1512 * @param   cbCopy                 How many bytes to copy.
     1513 */
     1514static size_t buslogicR3SgBufWalker(PBUSLOGIC pThis, PBUSLOGICREQ pReq,
     1515                                    PBUSLOGICR3MEMCOPYCALLBACK pfnCopyWorker,
     1516                                    PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
     1517{
     1518    PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);
    15121519    uint32_t   cbDataCCB;
    15131520    uint32_t   u32PhysAddrCCB;
     1521    size_t     cbCopied = 0;
     1522
     1523    /*
     1524     * Add the amount to skip to the host buffer size to avoid a
     1525     * few conditionals later on.
     1526     */
     1527    cbCopy += cbSkip;
    15141528
    15151529    /* Extract the data length and physical address from the CCB. */
    1516     if (pTaskState->fIs24Bit)
    1517     {
    1518         u32PhysAddrCCB  = ADDR_TO_U32(pTaskState->CommandControlBlockGuest.o.aPhysAddrData);
    1519         cbDataCCB       = LEN_TO_U32(pTaskState->CommandControlBlockGuest.o.acbData);
     1530    if (pReq->fIs24Bit)
     1531    {
     1532        u32PhysAddrCCB  = ADDR_TO_U32(pReq->CCBGuest.o.aPhysAddrData);
     1533        cbDataCCB       = LEN_TO_U32(pReq->CCBGuest.o.acbData);
    15201534    }
    15211535    else
    15221536    {
    1523         u32PhysAddrCCB  = pTaskState->CommandControlBlockGuest.n.u32PhysAddrData;
    1524         cbDataCCB       = pTaskState->CommandControlBlockGuest.n.cbData;
     1537        u32PhysAddrCCB  = pReq->CCBGuest.n.u32PhysAddrData;
     1538        cbDataCCB       = pReq->CCBGuest.n.cbData;
    15251539    }
    15261540
     
    15291543     * returns no data, hence the buffer must be left alone!
    15301544     */
    1531     if (pTaskState->CommandControlBlockGuest.c.abCDB[0] == 0)
     1545    if (pReq->CCBGuest.c.abCDB[0] == 0)
    15321546        cbDataCCB = 0;
    15331547#endif
    15341548
    1535     LogFlowFunc(("pTaskState=%#p cbDataCCB=%u direction=%u cbSeg=%u\n", pTaskState, cbDataCCB,
    1536                  pTaskState->CommandControlBlockGuest.c.uDataDirection, pTaskState->DataSeg.cbSeg));
     1549    LogFlowFunc(("pReq=%#p cbDataCCB=%u direction=%u cbCopy=%zu\n", pReq, cbDataCCB,
     1550                 pReq->CCBGuest.c.uDataDirection, cbCopy));
    15371551
    15381552    if (   (cbDataCCB > 0)
    1539         && (   (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
    1540             || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)))
    1541     {
    1542         if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
    1543             || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
     1553        && (   pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN
     1554            || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT
     1555            || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN))
     1556    {
     1557        if (   (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
     1558            || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
    15441559        {
    15451560            uint32_t cScatterGatherGCRead;
    15461561            uint32_t iScatterGatherEntry;
    15471562            SGE32    aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
    1548             uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
     1563            uint32_t cScatterGatherGCLeft = cbDataCCB / (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
    15491564            RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
    1550             uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
    15511565
    15521566            do
     
    15571571                cScatterGatherGCLeft -= cScatterGatherGCRead;
    15581572
    1559                 buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
    1560 
    1561                 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
     1573                buslogicR3ReadSGEntries(pDevIns, pReq->fIs24Bit, GCPhysAddrScatterGatherCurrent,
     1574                                        cScatterGatherGCRead, aScatterGatherReadGC);
     1575
     1576                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead && cbCopy > 0; iScatterGatherEntry++)
    15621577                {
    1563                     RTGCPHYS    GCPhysAddrDataBase;
    1564                     size_t      cbDataToTransfer;
     1578                    RTGCPHYS GCPhysAddrDataBase;
     1579                    size_t   cbCopyThis;
    15651580
    15661581                    Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
    15671582
    15681583                    GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
    1569                     cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
    1570 
    1571                     Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
    1572 
    1573                     PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
    1574                     pbData += cbDataToTransfer;
     1584                    cbCopyThis = RT_MIN(cbCopy, aScatterGatherReadGC[iScatterGatherEntry].cbSegment);
     1585
     1586                    Log(("%s: GCPhysAddrDataBase=%RGp cbCopyThis=%zu\n", __FUNCTION__, GCPhysAddrDataBase, cbCopyThis));
     1587
     1588                    pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbCopyThis, &cbSkip);
     1589                    cbCopied += cbCopyThis;
     1590                    cbCopy   -= cbCopyThis;
    15751591                }
    15761592
    15771593                /* Set address to the next entries to read. */
    1578                 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
    1579             } while (cScatterGatherGCLeft > 0);
    1580 
    1581         }
    1582         else if (   pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
    1583                  || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
     1594                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
     1595            } while (   cScatterGatherGCLeft > 0
     1596                     && cbCopy > 0);
     1597
     1598        }
     1599        else if (   pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
     1600                 || pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
    15841601        {
    15851602            /* The buffer is not scattered. */
     
    15941611
    15951612            /* Copy the data into the guest memory. */
    1596             PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
    1597         }
    1598 
    1599     }
     1613            pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, RT_MIN(cbDataCCB, cbCopy), &cbSkip);
     1614            cbCopied += RT_MIN(cbDataCCB, cbCopy);
     1615        }
     1616    }
     1617
    16001618    /* Update residual data length. */
    1601     if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
    1602         || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
     1619    if (   (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
     1620        || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
    16031621    {
    16041622        uint32_t    cbResidual;
     
    16061624        /** @todo we need to get the actual transfer length from the VSCSI layer?! */
    16071625        cbResidual = 0; //LEN_TO_U32(pTaskState->CCBGuest.acbData) - ???;
    1608         if (pTaskState->fIs24Bit)
    1609             U32_TO_LEN(pTaskState->CommandControlBlockGuest.o.acbData, cbResidual);
     1626        if (pReq->fIs24Bit)
     1627            U32_TO_LEN(pReq->CCBGuest.o.acbData, cbResidual);
    16101628        else
    1611             pTaskState->CommandControlBlockGuest.n.cbData = cbResidual;
    1612     }
    1613 
    1614     RTMemFree(pTaskState->DataSeg.pvSeg);
    1615     pTaskState->DataSeg.pvSeg = NULL;
    1616     pTaskState->DataSeg.cbSeg = 0;
     1629            pReq->CCBGuest.n.cbData = cbResidual;
     1630    }
     1631
     1632    return cbCopied - RT_MIN(cbSkip, cbCopied);
     1633}
     1634
     1635/**
     1636 * Copies a data buffer into the S/G buffer set up by the guest.
     1637 *
     1638 * @returns Amount of bytes copied to the guest.
     1639 * @param   pThis          The LsiLogic controller device instance.
     1640 * @param   pReq           Request structure.
     1641 * @param   pSgBuf         The S/G buffer to copy from.
     1642 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     1643 * @param   cbCopy         How many bytes to copy.
     1644 */
     1645static size_t buslogicR3CopySgBufToGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf,
     1646                                         size_t cbSkip, size_t cbCopy)
     1647{
     1648    return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferToGuestWorker,
     1649                                 pSgBuf, cbSkip, cbCopy);
     1650}
     1651
     1652/**
     1653 * Copies the guest S/G buffer into a host data buffer.
     1654 *
     1655 * @returns Amount of bytes copied from the guest.
     1656 * @param   pThis          The LsiLogic controller device instance.
     1657 * @param   pReq           Request structure.
     1658 * @param   pSgBuf         The S/G buffer to copy into.
     1659 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     1660 * @param   cbCopy         How many bytes to copy.
     1661 */
     1662static size_t buslogicR3CopySgBufFromGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf,
     1663                                           size_t cbSkip, size_t cbCopy)
     1664{
     1665    return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferFromGuestWorker,
     1666                                 pSgBuf, cbSkip, cbCopy);
    16171667}
    16181668
     
    16351685 *
    16361686 * @returns nothing.
    1637  * @param   pTaskState   Pointer to the task state.
     1687 * @param   pReq         Pointer to the request state.
    16381688 * @param   fCopy        If sense data should be copied to guest memory.
    16391689 */
    1640 static void buslogicR3SenseBufferFree(PBUSLOGICTASKSTATE pTaskState, bool fCopy)
     1690static void buslogicR3SenseBufferFree(PBUSLOGICREQ pReq, bool fCopy)
    16411691{
    16421692    uint32_t    cbSenseBuffer;
    16431693
    1644     cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
     1694    cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData);
    16451695
    16461696    /* Copy the sense buffer into guest memory if requested. */
    16471697    if (fCopy && cbSenseBuffer)
    16481698    {
    1649         PPDMDEVINS  pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
     1699        PPDMDEVINS  pDevIns = pReq->pTargetDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
    16501700        RTGCPHYS    GCPhysAddrSenseBuffer;
    16511701
     
    16541704         * the CCB, right after the variable-length CDB.
    16551705         */
    1656         if (pTaskState->fIs24Bit)
    1657         {
    1658             GCPhysAddrSenseBuffer  = pTaskState->MailboxGuest.u32PhysAddrCCB;
    1659             GCPhysAddrSenseBuffer += pTaskState->CommandControlBlockGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB);
     1706        if (pReq->fIs24Bit)
     1707        {
     1708            GCPhysAddrSenseBuffer  = pReq->GCPhysAddrCCB;
     1709            GCPhysAddrSenseBuffer += pReq->CCBGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB);
    16601710        }
    16611711        else
    1662             GCPhysAddrSenseBuffer = pTaskState->CommandControlBlockGuest.n.u32PhysAddrSenseData;
    1663 
    1664         Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, pTaskState->pbSenseBuffer));
    1665         PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pTaskState->pbSenseBuffer, cbSenseBuffer);
    1666     }
    1667 
    1668     RTMemFree(pTaskState->pbSenseBuffer);
    1669     pTaskState->pbSenseBuffer = NULL;
     1712            GCPhysAddrSenseBuffer = pReq->CCBGuest.n.u32PhysAddrSenseData;
     1713
     1714        Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, pReq->pbSenseBuffer));
     1715        PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pReq->pbSenseBuffer, cbSenseBuffer);
     1716    }
     1717
     1718    RTMemFree(pReq->pbSenseBuffer);
     1719    pReq->pbSenseBuffer = NULL;
    16701720}
    16711721
     
    16741724 *
    16751725 * @returns VBox status code.
    1676  * @param   pTaskState    Pointer to the task state.
    1677  * @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary.
    1678  */
    1679 static int buslogicR3SenseBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
    1680 {
    1681     pTaskState->pbSenseBuffer = NULL;
    1682 
    1683     uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
     1726 * @param   pReq    Pointer to the task state.
     1727 */
     1728static int buslogicR3SenseBufferAlloc(PBUSLOGICREQ pReq)
     1729{
     1730    pReq->pbSenseBuffer = NULL;
     1731
     1732    uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData);
    16841733    if (cbSenseBuffer)
    16851734    {
    1686         pTaskState->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);
    1687         if (!pTaskState->pbSenseBuffer)
     1735        pReq->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);
     1736        if (!pReq->pbSenseBuffer)
    16881737            return VERR_NO_MEMORY;
    16891738    }
     
    24882537#ifdef IN_RING3
    24892538
    2490 static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pBusLogic)
    2491 {
    2492     int rc;
    2493     PBUSLOGICTASKSTATE pTaskState;
    2494     uint32_t           uTargetDevice;
    2495 
    2496     rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState);
    2497     AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
    2498 
    2499     pTaskState->fBIOS = true;
    2500 
    2501     rc = vboxscsiSetupRequest(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, &uTargetDevice);
     2539static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pThis)
     2540{
     2541    uint32_t uTargetDevice;
     2542    uint32_t uLun;
     2543    uint8_t *pbCdb;
     2544    size_t cbCdb;
     2545    size_t cbBuf;
     2546
     2547    int rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice);
    25022548    AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc);
    25032549
    2504     pTaskState->PDMScsiRequest.pvUser = pTaskState;
    2505 
    2506     pTaskState->CTX_SUFF(pTargetDevice) = &pBusLogic->aDeviceStates[uTargetDevice];
    2507 
    2508     if (!pTaskState->CTX_SUFF(pTargetDevice)->fPresent)
    2509     {
    2510         /* Device is not present. */
    2511         AssertMsg(pTaskState->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,
    2512                     ("Device is not present but command is not inquiry\n"));
    2513 
    2514         SCSIINQUIRYDATA ScsiInquiryData;
    2515 
    2516         memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA));
    2517         ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
    2518         ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
    2519 
    2520         memcpy(pBusLogic->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
    2521 
    2522         rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, SCSI_STATUS_OK);
    2523         AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
    2524 
    2525         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    2526     }
    2527     else
    2528     {
    2529         LogFlowFunc(("before increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests));
    2530         ASMAtomicIncU32(&pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests);
    2531         LogFlowFunc(("after increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests));
    2532 
    2533         rc = pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector,
    2534                                                                                         &pTaskState->PDMScsiRequest);
    2535         AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
    2536     }
     2550    if (   uTargetDevice < RT_ELEMENTS(pThis->aDeviceStates)
     2551        && pThis->aDeviceStates[uTargetDevice].pDrvBase)
     2552    {
     2553        PBUSLOGICDEVICE pTgtDev = &pThis->aDeviceStates[uTargetDevice];
     2554        PDMMEDIAEXIOREQ hIoReq;
     2555        PBUSLOGICREQ pReq;
     2556
     2557        rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
     2558                                                 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     2559        AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
     2560
     2561        pReq->fBIOS = true;
     2562        pReq->hIoReq = hIoReq;
     2563        pReq->pTargetDevice = pTgtDev;
     2564
     2565        ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     2566
     2567        rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
     2568                                                       pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN,
     2569                                                       cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
     2570        if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     2571        {
     2572            uint8_t u8ScsiSts = pReq->u8ScsiSts;
     2573            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
     2574            rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts);
     2575        }
     2576        else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     2577            rc = VINF_SUCCESS;
     2578
     2579        return rc;
     2580    }
     2581
     2582    /* Device is not present. */
     2583    AssertMsg(pbCdb[0] == SCSI_INQUIRY,
     2584              ("Device is not present but command is not inquiry\n"));
     2585
     2586    SCSIINQUIRYDATA ScsiInquiryData;
     2587
     2588    memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA));
     2589    ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
     2590    ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
     2591
     2592    memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
     2593
     2594    rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK);
     2595    AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
    25372596
    25382597    return rc;
     
    27152774}
    27162775
    2717 static void buslogicR3WarningDiskFull(PPDMDEVINS pDevIns)
    2718 {
    2719     int rc;
    2720     LogRel(("BusLogic#%d: Host disk full\n", pDevIns->iInstance));
    2721     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_DISKFULL",
    2722                                     N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
    2723     AssertRC(rc);
    2724 }
    2725 
    2726 static void buslogicR3WarningFileTooBig(PPDMDEVINS pDevIns)
    2727 {
    2728     int rc;
    2729     LogRel(("BusLogic#%d: File too big\n", pDevIns->iInstance));
    2730     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_FILETOOBIG",
    2731                                     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"));
    2732     AssertRC(rc);
    2733 }
    2734 
    2735 static void buslogicR3WarningISCSI(PPDMDEVINS pDevIns)
    2736 {
    2737     int rc;
    2738     LogRel(("BusLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
    2739     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_ISCSIDOWN",
    2740                                     N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
    2741     AssertRC(rc);
    2742 }
    2743 
    2744 static void buslogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc)
    2745 {
    2746     int rc2;
    2747     LogRel(("BusLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
    2748     rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_UNKNOWN",
    2749                                      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);
    2750     AssertRC(rc2);
    2751 }
    2752 
    2753 static void buslogicR3RedoSetWarning(PBUSLOGIC pThis, int rc)
    2754 {
    2755     if (rc == VERR_DISK_FULL)
    2756         buslogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns));
    2757     else if (rc == VERR_FILE_TOO_BIG)
    2758         buslogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns));
    2759     else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
    2760     {
    2761         /* iSCSI connection abort (first error) or failure to reestablish
    2762          * connection (second error). Pause VM. On resume we'll retry. */
    2763         buslogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns));
    2764     }
    2765     else if (rc != VERR_VD_DEK_MISSING)
    2766         buslogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
    2767 }
    2768 
    27692776
    27702777/**
     
    28412848}
    28422849
    2843 static DECLCALLBACK(int) buslogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
    2844                                                               int rcCompletion, bool fRedo, int rcReq)
    2845 {
    2846     RT_NOREF(pInterface);
    2847     int rc;
    2848     PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)pSCSIRequest->pvUser;
    2849     PBUSLOGICDEVICE pBusLogicDevice = pTaskState->CTX_SUFF(pTargetDevice);
    2850     PBUSLOGIC pBusLogic = pBusLogicDevice->CTX_SUFF(pBusLogic);
    2851 
    2852     LogFlowFunc(("before decrement %u\n", pBusLogicDevice->cOutstandingRequests));
    2853     ASMAtomicDecU32(&pBusLogicDevice->cOutstandingRequests);
    2854     LogFlowFunc(("after decrement %u\n", pBusLogicDevice->cOutstandingRequests));
    2855 
    2856     if (fRedo)
    2857     {
    2858         if (!pTaskState->fBIOS)
    2859         {
    2860             buslogicR3DataBufferFree(pTaskState);
    2861 
    2862             if (pTaskState->pbSenseBuffer)
    2863                 buslogicR3SenseBufferFree(pTaskState, false /* fCopy */);
    2864         }
    2865 
    2866         /* Add to the list. */
    2867         do
    2868         {
    2869             pTaskState->pRedoNext = ASMAtomicReadPtrT(&pBusLogic->pTasksRedoHead, PBUSLOGICTASKSTATE);
    2870         } while (!ASMAtomicCmpXchgPtr(&pBusLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
    2871 
    2872         /* Suspend the VM if not done already. */
    2873         if (!ASMAtomicXchgBool(&pBusLogic->fRedo, true))
    2874             buslogicR3RedoSetWarning(pBusLogic, rcReq);
     2850static int buslogicR3ReqComplete(PBUSLOGIC pThis, PBUSLOGICREQ pReq, int rcReq)
     2851{
     2852    RT_NOREF(rcReq);
     2853    PBUSLOGICDEVICE pTgtDev = pReq->pTargetDevice;
     2854
     2855    LogFlowFunc(("before decrement %u\n", pTgtDev->cOutstandingRequests));
     2856    ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
     2857    LogFlowFunc(("after decrement %u\n", pTgtDev->cOutstandingRequests));
     2858
     2859    if (pReq->fBIOS)
     2860    {
     2861        int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pReq->u8ScsiSts);
     2862        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
    28752863    }
    28762864    else
    28772865    {
    2878         if (pTaskState->fBIOS)
    2879         {
    2880             rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, pSCSIRequest, rcCompletion);
    2881             AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
    2882         }
     2866        if (pReq->pbSenseBuffer)
     2867            buslogicR3SenseBufferFree(pReq, (pReq->u8ScsiSts != SCSI_STATUS_OK));
     2868
     2869        if (pReq->u8ScsiSts == SCSI_STATUS_OK)
     2870            buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest,
     2871                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
     2872                                        BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
     2873                                        BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
     2874        else if (pReq->u8ScsiSts == SCSI_STATUS_CHECK_CONDITION)
     2875            buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest,
     2876                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
     2877                                        BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION,
     2878                                        BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    28832879        else
    2884         {
    2885             buslogicR3DataBufferFree(pTaskState);
    2886 
    2887             if (pTaskState->pbSenseBuffer)
    2888                 buslogicR3SenseBufferFree(pTaskState, (rcCompletion != SCSI_STATUS_OK));
    2889 
    2890             if (rcCompletion == SCSI_STATUS_OK)
    2891                 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
    2892                                             BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
    2893                                             BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    2894                                             BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
    2895             else if (rcCompletion == SCSI_STATUS_CHECK_CONDITION)
    2896                 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
    2897                                             BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
    2898                                             BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION,
    2899                                             BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    2900             else
    2901                 AssertMsgFailed(("invalid completion status %d\n", rcCompletion));
    2902         }
     2880            AssertMsgFailed(("invalid completion status %d\n", pReq->u8ScsiSts));
     2881    }
     2882
    29032883#ifdef LOG_ENABLED
    2904             buslogicR3DumpCCBInfo(&pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);
     2884    buslogicR3DumpCCBInfo(&pReq->CCBGuest, pReq->fIs24Bit);
    29052885#endif
    29062886
    2907         /* Remove task from the cache. */
    2908         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    2909     }
    2910 
    2911     if (pBusLogicDevice->cOutstandingRequests == 0 && pBusLogic->fSignalIdle)
    2912         PDMDevHlpAsyncNotificationCompleted(pBusLogic->pDevInsR3);
     2887    if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle)
     2888        PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
    29132889
    29142890    return VINF_SUCCESS;
    29152891}
    29162892
    2917 static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
     2893static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    29182894                                                       uint32_t *piInstance, uint32_t *piLUN)
    29192895{
    2920     PBUSLOGICDEVICE pBusLogicDevice = PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface);
     2896    PBUSLOGICDEVICE pBusLogicDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaPort);
    29212897    PPDMDEVINS pDevIns = pBusLogicDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
    29222898
     
    29322908}
    29332909
    2934 static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
     2910/**
     2911 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     2912 */
     2913static DECLCALLBACK(int) buslogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2914                                                    void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
     2915                                                    size_t cbCopy)
     2916{
     2917    RT_NOREF1(hIoReq);
     2918    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
     2919    PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc;
     2920
     2921    size_t cbCopied = 0;
     2922    if (RT_UNLIKELY(pReq->fBIOS))
     2923        cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy);
     2924    else
     2925        cbCopied = buslogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offDst, cbCopy);
     2926    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     2927}
     2928
     2929/**
     2930 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     2931 */
     2932static DECLCALLBACK(int) buslogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2933                                                  void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
     2934                                                  size_t cbCopy)
     2935{
     2936    RT_NOREF1(hIoReq);
     2937    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
     2938    PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc;
     2939
     2940    size_t cbCopied = 0;
     2941    if (RT_UNLIKELY(pReq->fBIOS))
     2942        cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy);
     2943    else
     2944        cbCopied = buslogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offSrc, cbCopy);
     2945    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     2946}
     2947
     2948/**
     2949 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     2950 */
     2951static DECLCALLBACK(int) buslogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2952                                                       void *pvIoReqAlloc, int rcReq)
     2953{
     2954    RT_NOREF(hIoReq);
     2955    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
     2956    buslogicR3ReqComplete(pTgtDev->CTX_SUFF(pBusLogic), (PBUSLOGICREQ)pvIoReqAlloc, rcReq);
     2957    return VINF_SUCCESS;
     2958}
     2959
     2960/**
     2961 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     2962 */
     2963static DECLCALLBACK(void) buslogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2964                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     2965{
     2966    RT_NOREF3(hIoReq, pvIoReqAlloc, enmState);
     2967    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
     2968
     2969    switch (enmState)
     2970    {
     2971        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
     2972        {
     2973            /* Make sure the request is not accounted for so the VM can suspend successfully. */
     2974            uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
     2975            if (!cTasksActive && pTgtDev->CTX_SUFF(pBusLogic)->fSignalIdle)
     2976                PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pBusLogic)->pDevInsR3);
     2977            break;
     2978        }
     2979        case PDMMEDIAEXIOREQSTATE_ACTIVE:
     2980            /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
     2981            ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     2982            break;
     2983        default:
     2984            AssertMsgFailed(("Invalid request state given %u\n", enmState));
     2985    }
     2986}
     2987
     2988/**
     2989 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     2990 */
     2991static DECLCALLBACK(void) buslogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
     2992{
     2993    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
     2994    PBUSLOGIC pThis = pTgtDev->CTX_SUFF(pBusLogic);
     2995
     2996    RT_NOREF(pThis); /** @todo */
     2997}
     2998
     2999static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB)
    29353000{
    29363001    int rc = VINF_SUCCESS;
    29373002    uint8_t uTargetIdCCB;
    2938     PBUSLOGICDEVICE pTargetDevice;
     3003    CCBU CCBGuest;
    29393004
    29403005    /* Fetch the CCB from guest memory. */
    29413006    /** @todo How much do we really have to read? */
    2942     RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
    29433007    PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
    2944                         &pTaskState->CommandControlBlockGuest, sizeof(CCB32));
    2945 
    2946     uTargetIdCCB = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;
     3008                      &CCBGuest, sizeof(CCB32));
     3009
     3010    uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId;
    29473011    if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates)))
    29483012    {
    2949         pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB];
    2950         pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
     3013        PBUSLOGICDEVICE pTgtDev = &pBusLogic->aDeviceStates[uTargetIdCCB];
    29513014
    29523015#ifdef LOG_ENABLED
    2953         buslogicR3DumpCCBInfo(&pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);
     3016        buslogicR3DumpCCBInfo(&CCBGuest, pBusLogic->fMbxIs24Bit);
    29543017#endif
    29553018
    2956         /* Alloc required buffers. */
    2957         rc = buslogicR3DataBufferAlloc(pTaskState);
    2958         AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));
    2959 
    2960         rc = buslogicR3SenseBufferAlloc(pTaskState);
    2961         AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
    2962 
    29633019        /* Check if device is present on bus. If not return error immediately and don't process this further. */
    2964         if (!pBusLogic->aDeviceStates[uTargetIdCCB].fPresent)
    2965         {
    2966             buslogicR3DataBufferFree(pTaskState);
    2967 
    2968             if (pTaskState->pbSenseBuffer)
    2969                 buslogicR3SenseBufferFree(pTaskState, true);
    2970 
    2971             buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
     3020        if (RT_LIKELY(pTgtDev->fPresent))
     3021        {
     3022            PDMMEDIAEXIOREQ hIoReq;
     3023            PBUSLOGICREQ pReq;
     3024            rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
     3025                                                     GCPhysAddrCCB, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     3026            if (RT_SUCCESS(rc))
     3027            {
     3028                pReq->pTargetDevice = pTgtDev;
     3029                pReq->GCPhysAddrCCB = GCPhysAddrCCB;
     3030                pReq->fBIOS         = false;
     3031                pReq->hIoReq        = hIoReq;
     3032                pReq->fIs24Bit      = pBusLogic->fMbxIs24Bit;
     3033
     3034                /* Make a copy of the CCB */
     3035                memcpy(&pReq->CCBGuest, &CCBGuest, sizeof(CCBGuest));
     3036
     3037                /* Alloc required buffers. */
     3038                rc = buslogicR3SenseBufferAlloc(pReq);
     3039                AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
     3040
     3041                size_t cbBuf = 0;
     3042                rc = buslogicR3QueryDataBufferSize(pBusLogic->CTX_SUFF(pDevIns), &pReq->CCBGuest, pReq->fIs24Bit, &cbBuf);
     3043                AssertRC(rc);
     3044
     3045                uint32_t uLun = pReq->fIs24Bit ? pReq->CCBGuest.o.uLogicalUnit
     3046                                               : pReq->CCBGuest.n.uLogicalUnit;
     3047
     3048                PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN;
     3049                size_t cbSense = buslogicR3ConvertSenseBufferLength(CCBGuest.c.cbSenseData);
     3050
     3051                if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
     3052                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE;
     3053                else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
     3054                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE;
     3055                else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
     3056                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE;
     3057
     3058                ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     3059                rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
     3060                                                               &pReq->CCBGuest.c.abCDB[0], pReq->CCBGuest.c.cbCDB,
     3061                                                               enmXferDir, cbBuf, pReq->pbSenseBuffer, cbSense,
     3062                                                               &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
     3063                if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3064                    buslogicR3ReqComplete(pBusLogic, pReq, rc);
     3065            }
     3066            else
     3067                buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
     3068                                              BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
     3069                                              BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
     3070                                              BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
     3071        }
     3072        else
     3073            buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
    29723074                                          BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
    29733075                                          BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    29743076                                          BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    2975 
    2976             RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    2977         }
    2978         else
    2979         {
    2980             /* Setup SCSI request. */
    2981             pTaskState->PDMScsiRequest.uLogicalUnit = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uLogicalUnit
    2982                                                                            : pTaskState->CommandControlBlockGuest.n.uLogicalUnit;
    2983 
    2984             if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)
    2985                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_UNKNOWN;
    2986             else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
    2987                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
    2988             else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
    2989                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE;
    2990             else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
    2991                 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE;
    2992             else
    2993                 AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.c.uDataDirection));
    2994 
    2995             pTaskState->PDMScsiRequest.cbCDB                 = pTaskState->CommandControlBlockGuest.c.cbCDB;
    2996             pTaskState->PDMScsiRequest.pbCDB                 = pTaskState->CommandControlBlockGuest.c.abCDB;
    2997             if (pTaskState->DataSeg.cbSeg)
    2998             {
    2999                 pTaskState->PDMScsiRequest.cbScatterGather       = (uint32_t)pTaskState->DataSeg.cbSeg;
    3000                 pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;
    3001                 pTaskState->PDMScsiRequest.paScatterGatherHead   = &pTaskState->DataSeg;
    3002             }
    3003             else
    3004             {
    3005                 pTaskState->PDMScsiRequest.cbScatterGather       = 0;
    3006                 pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;
    3007                 pTaskState->PDMScsiRequest.paScatterGatherHead   = NULL;
    3008             }
    3009             pTaskState->PDMScsiRequest.cbSenseBuffer         = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
    3010             pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pbSenseBuffer;
    3011             pTaskState->PDMScsiRequest.pvUser                = pTaskState;
    3012 
    3013             ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
    3014             rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
    3015             AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
    3016         }
    30173077    }
    30183078    else
    3019     {
    3020         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    3021 
    3022         buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
     3079        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
    30233080                                      BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER,
    30243081                                      BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    30253082                                      BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    3026     }
    30273083
    30283084    return rc;
    30293085}
    30303086
    3031 static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
    3032 {
    3033     int             rc = VINF_SUCCESS;
    3034     uint8_t         uTargetIdCCB;
    3035     PBUSLOGICDEVICE pTargetDevice;
    3036     RTGCPHYS        GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
     3087static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB)
     3088{
     3089    int      rc = VINF_SUCCESS;
     3090    uint8_t  uTargetIdCCB;
     3091    CCBU     CCBGuest;
    30373092
    30383093    PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
    3039                       &pTaskState->CommandControlBlockGuest, sizeof(CCB32));
    3040 
    3041     uTargetIdCCB = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;
     3094                      &CCBGuest, sizeof(CCB32));
     3095
     3096    uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId;
    30423097    if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates)))
    3043     {
    3044         pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB];
    3045         pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
    3046 
    3047         buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
     3098        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
    30483099                                      BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_ABORT_QUEUE_GENERATED,
    30493100                                      BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    30503101                                      BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND);
    3051 
    3052         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    3053     }
    30543102    else
    3055     {
    3056         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    3057 
    3058         buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
     3103        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
    30593104                                      BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER,
    30603105                                      BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
    30613106                                      BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
    3062     }
    30633107
    30643108    return rc;
     
    30713115 * @returns Mailbox guest physical address.
    30723116 * @param   pBusLogic    Pointer to the BusLogic instance data.
    3073  * @param   pTaskStat    Pointer to the task state being set up.
    3074  */
    3075 static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
     3117 * @param   pMbx         Pointer to the mailbox to read into.
     3118 */
     3119static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, PMailbox32 pMbx)
    30763120{
    30773121    RTGCPHYS    GCMailbox;
     
    30833127        GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox24));
    30843128        PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &Mbx24, sizeof(Mailbox24));
    3085         pTaskState->MailboxGuest.u32PhysAddrCCB    = ADDR_TO_U32(Mbx24.aPhysAddrCCB);
    3086         pTaskState->MailboxGuest.u.out.uActionCode = Mbx24.uCmdState;
     3129        pMbx->u32PhysAddrCCB    = ADDR_TO_U32(Mbx24.aPhysAddrCCB);
     3130        pMbx->u.out.uActionCode = Mbx24.uCmdState;
    30873131    }
    30883132    else
    30893133    {
    30903134        GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox32));
    3091         PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &pTaskState->MailboxGuest, sizeof(Mailbox32));
     3135        PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, pMbx, sizeof(Mailbox32));
    30923136    }
    30933137
     
    31033147static int buslogicR3ProcessMailboxNext(PBUSLOGIC pBusLogic)
    31043148{
    3105     PBUSLOGICTASKSTATE pTaskState = NULL;
    3106     RTGCPHYS           GCPhysAddrMailboxCurrent;
    3107     int rc;
    3108 
    3109     rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState);
    3110     AssertMsgReturn(RT_SUCCESS(rc) && (pTaskState != NULL), ("Failed to get task state from cache\n"), rc);
    3111 
    3112     pTaskState->fBIOS     = false;
    3113     pTaskState->fIs24Bit  = pBusLogic->fMbxIs24Bit;
    3114     pTaskState->cbSGEntry = pBusLogic->fMbxIs24Bit ? sizeof(SGE24) : sizeof(SGE32);
     3149    RTGCPHYS     GCPhysAddrMailboxCurrent;
     3150    Mailbox32    MailboxGuest;
     3151    int rc = VINF_SUCCESS;
    31153152
    31163153    if (!pBusLogic->fStrictRoundRobinMode)
     
    31223159        {
    31233160            /* Fetch mailbox from guest memory. */
    3124             GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic,pTaskState);
     3161            GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest);
    31253162
    31263163            /* Check the next mailbox. */
    31273164            buslogicR3OutgoingMailboxAdvance(pBusLogic);
    3128         } while (   pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE
     3165        } while (   MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE
    31293166                 && uMailboxPosCur != pBusLogic->uMailboxOutgoingPositionCurrent);
    31303167    }
     
    31323169    {
    31333170        /* Fetch mailbox from guest memory. */
    3134         GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic,pTaskState);
     3171        GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest);
    31353172    }
    31363173
     
    31413178     * log entry.
    31423179     */
    3143     if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE)
     3180    if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE)
    31443181    {
    31453182        Log(("No loaded mailbox left\n"));
    3146         RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    31473183        return VERR_NO_DATA;
    31483184    }
    31493185
    3150     LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB));
     3186    LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB));
    31513187#ifdef LOG_ENABLED
    3152     buslogicR3DumpMailboxInfo(&pTaskState->MailboxGuest, true);
     3188    buslogicR3DumpMailboxInfo(&MailboxGuest, true);
    31533189#endif
    31543190
    31553191    /* We got the mailbox, mark it as free in the guest. */
    31563192    uint8_t uActionCode = BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE;
    3157     unsigned uCodeOffs = pTaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
     3193    unsigned uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
    31583194    PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxCurrent + uCodeOffs, &uActionCode, sizeof(uActionCode));
    31593195
    3160     if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
    3161         rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, pTaskState);
    3162     else if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
     3196    if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
     3197        rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB);
     3198    else if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
    31633199    {
    31643200        LogFlow(("Aborting mailbox\n"));
    3165         rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, pTaskState);
     3201        rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB);
    31663202    }
    31673203    else
    3168         AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", pTaskState->MailboxGuest.u.out.uActionCode));
     3204        AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", MailboxGuest.u.out.uActionCode));
    31693205
    31703206    AssertRC(rc);
     
    31973233}
    31983234
    3199 /**
    3200  * Kicks the controller to process pending tasks after the VM was resumed
    3201  * or loaded from a saved state.
    3202  *
    3203  * @returns nothing.
    3204  * @param   pThis    The BusLogic device instance.
    3205  */
    3206 static void buslogicR3Kick(PBUSLOGIC pThis)
    3207 {
    3208     if (pThis->fRedo)
    3209     {
    3210         pThis->fRedo = false;
    3211         if (pThis->VBoxSCSI.fBusy)
    3212         {
    3213 
    3214             /* The BIOS had a request active when we got suspended. Resume it. */
    3215             int rc = buslogicR3PrepareBIOSSCSIRequest(pThis);
    3216             AssertRC(rc);
    3217         }
    3218         else
    3219         {
    3220             /* Queue all pending tasks again. */
    3221             PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
    3222 
    3223             pThis->pTasksRedoHead = NULL;
    3224 
    3225             while (pTaskState)
    3226             {
    3227                 PBUSLOGICTASKSTATE pCur = pTaskState;
    3228 
    3229                 int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pCur);
    3230                 AssertRC(rc);
    3231 
    3232                 pTaskState = pTaskState->pRedoNext;
    3233             }
    3234         }
    3235     }
    3236 }
    3237 
    32383235/** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
    32393236static DECLCALLBACK(int) buslogicR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
     
    32533250{
    32543251    PBUSLOGIC pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
     3252    uint32_t cReqsSuspended = 0;
    32553253
    32563254    /* Every device first. */
     
    32633261        SSMR3PutBool(pSSM, pDevice->fPresent);
    32643262        SSMR3PutU32(pSSM, pDevice->cOutstandingRequests);
     3263
     3264        if (pDevice->fPresent)
     3265            cReqsSuspended += pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
    32653266    }
    32663267    /* Now the main device state. */
     
    32923293    vboxscsiR3SaveExec(&pBusLogic->VBoxSCSI, pSSM);
    32933294
    3294     /*
    3295      * Save the physical addresses of the command control blocks of still pending tasks.
    3296      * They are processed again on resume.
    3297      *
    3298      * The number of pending tasks needs to be determined first.
    3299      */
    3300     uint32_t cTasks = 0;
    3301 
    3302     PBUSLOGICTASKSTATE pTaskState = pBusLogic->pTasksRedoHead;
    3303     if (pBusLogic->fRedo)
    3304     {
    3305         while (pTaskState)
    3306         {
    3307             cTasks++;
    3308             pTaskState = pTaskState->pRedoNext;
    3309         }
    3310     }
    3311     SSMR3PutU32(pSSM, cTasks);
    3312 
    3313     /* Write the address of every task now. */
    3314     pTaskState = pBusLogic->pTasksRedoHead;
    3315     while (pTaskState)
    3316     {
    3317         SSMR3PutU32(pSSM, pTaskState->MailboxGuest.u32PhysAddrCCB);
    3318         pTaskState = pTaskState->pRedoNext;
     3295    SSMR3PutU32(pSSM, cReqsSuspended);
     3296
     3297    /* Save the physical CCB address of all suspended requests. */
     3298    for (unsigned i = 0; i < RT_ELEMENTS(pBusLogic->aDeviceStates) && cReqsSuspended; i++)
     3299    {
     3300        PBUSLOGICDEVICE pDevice = &pBusLogic->aDeviceStates[i];
     3301        if (pDevice->fPresent)
     3302        {
     3303            uint32_t cThisReqsSuspended = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
     3304
     3305            cReqsSuspended -= cThisReqsSuspended;
     3306            if (cThisReqsSuspended)
     3307            {
     3308                PDMMEDIAEXIOREQ hIoReq;
     3309                PBUSLOGICREQ pReq;
     3310                int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq,
     3311                                                                           (void **)&pReq);
     3312                AssertRCBreak(rc);
     3313
     3314                for (;;)
     3315                {
     3316                    SSMR3PutU32(pSSM, (uint32_t)pReq->GCPhysAddrCCB);
     3317
     3318                    cThisReqsSuspended--;
     3319                    if (!cThisReqsSuspended)
     3320                        break;
     3321
     3322                    rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq,
     3323                                                                          &hIoReq, (void **)&pReq);
     3324                    AssertRCBreak(rc);
     3325                }
     3326            }
     3327        }
    33193328    }
    33203329
     
    33293338
    33303339    buslogicR3RegisterISARange(pThis, pThis->uISABaseCode);
    3331     buslogicR3Kick(pThis);
     3340
     3341    /* Kick of any requests we might need to redo. */
     3342    if (pThis->VBoxSCSI.fBusy)
     3343    {
     3344
     3345        /* The BIOS had a request active when we got suspended. Resume it. */
     3346        int rc = buslogicR3PrepareBIOSSCSIRequest(pThis);
     3347        AssertRC(rc);
     3348    }
     3349    else if (pThis->cReqsRedo)
     3350    {
     3351        for (unsigned i = 0; i < pThis->cReqsRedo; i++)
     3352        {
     3353            int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pThis->paGCPhysAddrCCBRedo[i]);
     3354            AssertRC(rc);
     3355        }
     3356
     3357        RTMemFree(pThis->paGCPhysAddrCCBRedo);
     3358        pThis->paGCPhysAddrCCBRedo = NULL;
     3359        pThis->cReqsRedo = 0;
     3360    }
     3361
    33323362    return VINF_SUCCESS;
    33333363}
     
    34013431    }
    34023432
    3403     if (pBusLogic->VBoxSCSI.fBusy)
    3404         pBusLogic->fRedo = true;
    3405 
    34063433    if (uVersion > BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING)
    34073434    {
     
    34123439
    34133440        if (cTasks)
    3414             pBusLogic->fRedo = true;
    3415 
    3416         for (uint32_t i = 0; i < cTasks; i++)
    3417         {
    3418             PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)RTMemCacheAlloc(pBusLogic->hTaskCache);
    3419             if (!pTaskState)
     3441        {
     3442            pBusLogic->paGCPhysAddrCCBRedo = (PRTGCPHYS)RTMemAllocZ(cTasks * sizeof(RTGCPHYS));
     3443            if (RT_LIKELY(pBusLogic->paGCPhysAddrCCBRedo))
    34203444            {
     3445                pBusLogic->cReqsRedo = cTasks;
     3446
     3447                for (uint32_t i = 0; i < cTasks; i++)
     3448                {
     3449                    uint32_t u32PhysAddrCCB;
     3450
     3451                    rc = SSMR3GetU32(pSSM, &u32PhysAddrCCB);
     3452                    if (RT_FAILURE(rc))
     3453                        break;
     3454
     3455                    pBusLogic->paGCPhysAddrCCBRedo[i] = u32PhysAddrCCB;
     3456                }
     3457            }
     3458            else
    34213459                rc = VERR_NO_MEMORY;
    3422                 break;
    3423             }
    3424 
    3425             rc = SSMR3GetU32(pSSM, &pTaskState->MailboxGuest.u32PhysAddrCCB);
    3426             if (RT_FAILURE(rc))
    3427             {
    3428                 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
    3429                 break;
    3430             }
    3431 
    3432             /* Link into the list. */
    3433             pTaskState->pRedoNext = pBusLogic->pTasksRedoHead;
    3434             pBusLogic->pTasksRedoHead = pTaskState;
    34353460        }
    34363461    }
     
    34583483static DECLCALLBACK(int) buslogicR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    34593484{
    3460     PBUSLOGICDEVICE pDevice = PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface);
     3485    PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, ILed);
    34613486    if (iLUN == 0)
    34623487    {
     
    34733498static DECLCALLBACK(void *) buslogicR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    34743499{
    3475     PBUSLOGICDEVICE pDevice = PDMIBASE_2_PBUSLOGICDEVICE(pInterface);
     3500    PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IBase);
    34763501    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase);
    3477     PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort);
     3502    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort);
     3503    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort);
    34783504    PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed);
    34793505    return NULL;
     
    34903516static DECLCALLBACK(int) buslogicR3StatusQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    34913517{
    3492     PBUSLOGIC pBusLogic = PDMILEDPORTS_2_PBUSLOGIC(pInterface);
     3518    PBUSLOGIC pBusLogic = RT_FROM_MEMBER(pInterface, BUSLOGIC, ILeds);
    34933519    if (iLUN < BUSLOGIC_MAX_DEVICES)
    34943520    {
     
    35053531static DECLCALLBACK(void *) buslogicR3StatusQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    35063532{
    3507     PBUSLOGIC pThis = PDMIBASE_2_PBUSLOGIC(pInterface);
     3533    PBUSLOGIC pThis = RT_FROM_MEMBER(pInterface, BUSLOGIC, IBase);
    35083534    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
    35093535    PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
     
    37363762
    37373763/**
    3738  * Common worker for ahciR3Suspend and ahciR3PowerOff.
    3739  */
    3740 static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns, bool fPowerOff)
     3764 * Common worker for buslogicR3Suspend and buslogicR3PowerOff.
     3765 */
     3766static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
    37413767{
    37423768    PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
     
    37483774    {
    37493775        ASMAtomicWriteBool(&pThis->fSignalIdle, false);
    3750 
    37513776        AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n"));
    3752 
    3753         if (pThis->fRedo)
    3754         {
    3755             if (fPowerOff)
    3756             {
    3757                 /* Free tasks which would have been queued again on resume. */
    3758                 PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
    3759 
    3760                 pThis->pTasksRedoHead = NULL;
    3761 
    3762                 while (pTaskState)
    3763                 {
    3764                     PBUSLOGICTASKSTATE pFree;
    3765 
    3766                     pFree = pTaskState;
    3767                     pTaskState = pTaskState->pRedoNext;
    3768 
    3769                     RTMemCacheFree(pThis->hTaskCache, pFree);
    3770                 }
    3771                 pThis->fRedo = false;
    3772             }
    3773             else if (pThis->VBoxSCSI.fBusy)
    3774             {
    3775                 /* Destroy the task because the BIOS interface has all necessary information. */
    3776                 Assert(pThis->pTasksRedoHead->fBIOS);
    3777                 Assert(!pThis->pTasksRedoHead->pRedoNext);
    3778 
    3779                 RTMemCacheFree(pThis->hTaskCache, pThis->pTasksRedoHead);
    3780                 pThis->pTasksRedoHead = NULL;
    3781             }
    3782         }
    37833777    }
    37843778}
     
    37923786{
    37933787    Log(("buslogicR3Suspend\n"));
    3794     buslogicR3SuspendOrPowerOff(pDevIns, false /* fPoweroff */);
    3795 }
    3796 
    3797 /**
    3798  * Resume notification.
    3799  *
    3800  * @param   pDevIns     The device instance data.
    3801  */
    3802 static DECLCALLBACK(void) buslogicR3Resume(PPDMDEVINS pDevIns)
    3803 {
    3804     Log(("buslogicR3Resume\n"));
    3805     PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
    3806     buslogicR3Kick(pThis);
    3807 }
    3808 
     3788    buslogicR3SuspendOrPowerOff(pDevIns);
     3789}
    38093790
    38103791/**
     
    38323813     * Zero some important members.
    38333814     */
    3834     pDevice->pDrvBase = NULL;
    3835     pDevice->fPresent = false;
    3836     pDevice->pDrvSCSIConnector = NULL;
     3815    pDevice->fPresent    = false;
     3816    pDevice->pDrvBase    = NULL;
     3817    pDevice->pDrvMedia   = NULL;
     3818    pDevice->pDrvMediaEx = NULL;
    38373819}
    38383820
     
    38593841    /* the usual paranoia */
    38603842    AssertRelease(!pDevice->pDrvBase);
    3861     AssertRelease(!pDevice->pDrvSCSIConnector);
     3843    AssertRelease(!pDevice->pDrvMedia);
     3844    AssertRelease(!pDevice->pDrvMediaEx);
    38623845    Assert(pDevice->iLUN == iLUN);
    38633846
    38643847    /*
    3865      * Try attach the block device and get the interfaces,
     3848     * Try attach the SCSI driver and get the interfaces,
    38663849     * required as well as optional.
    38673850     */
     
    38693852    if (RT_SUCCESS(rc))
    38703853    {
    3871         /* Get SCSI connector interface. */
    3872         pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
    3873         AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
     3854        /* Query the media interface. */
     3855        pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
     3856        AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
     3857                        ("BusLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
     3858                        VERR_PDM_MISSING_INTERFACE);
     3859
     3860        /* Get the extended media interface. */
     3861        pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
     3862        AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
     3863                        ("BusLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
     3864                        VERR_PDM_MISSING_INTERFACE);
     3865
     3866        rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ));
     3867        AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!"),
     3868                               pDevice->iLUN);
     3869
    38743870        pDevice->fPresent = true;
    38753871    }
     
    38793875    if (RT_FAILURE(rc))
    38803876    {
    3881         pDevice->pDrvBase = NULL;
    3882         pDevice->pDrvSCSIConnector = NULL;
     3877        pDevice->fPresent    = false;
     3878        pDevice->pDrvBase    = NULL;
     3879        pDevice->pDrvMedia   = NULL;
     3880        pDevice->pDrvMediaEx = NULL;
    38833881    }
    38843882    return rc;
     
    39453943{
    39463944    Log(("buslogicR3PowerOff\n"));
    3947     buslogicR3SuspendOrPowerOff(pDevIns, true /* fPoweroff */);
     3945    buslogicR3SuspendOrPowerOff(pDevIns);
    39483946}
    39493947
     
    39633961    PDMR3CritSectDelete(&pThis->CritSectIntr);
    39643962
    3965     /*
    3966      * Free all tasks which are still hanging around
    3967      * (Power off after the VM was suspended).
    3968      */
    3969     if (pThis->fRedo)
    3970     {
    3971         /* Free tasks which would have been queued again on resume. */
    3972         PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
    3973 
    3974         pThis->pTasksRedoHead = NULL;
    3975 
    3976         while (pTaskState)
    3977         {
    3978             PBUSLOGICTASKSTATE pFree;
    3979 
    3980             pFree = pTaskState;
    3981             pTaskState = pTaskState->pRedoNext;
    3982 
    3983             RTMemCacheFree(pThis->hTaskCache, pFree);
    3984         }
    3985         pThis->fRedo = false;
    3986     }
    3987 
    39883963    if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
    39893964    {
     
    39923967    }
    39933968
    3994     int rc = RTMemCacheDestroy(pThis->hTaskCache);
    3995     AssertMsgRC(rc, ("Destroying task cache failed rc=%Rrc\n", rc));
    3996 
    3997     return rc;
     3969    return VINF_SUCCESS;
    39983970}
    39993971
     
    40123984     * Init instance data (do early because of constructor).
    40133985     */
    4014     pThis->hTaskCache = NIL_RTMEMCACHE;
    40153986    pThis->pDevInsR3 = pDevIns;
    40163987    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     
    41134084        return PDMDEV_SET_ERROR(pDevIns, rc, N_("BusLogic cannot register ISA I/O handlers"));
    41144085
    4115     /* Initialize task cache. */
    4116     rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(BUSLOGICTASKSTATE), 0, UINT32_MAX,
    4117                           NULL, NULL, NULL, 0);
    4118     if (RT_FAILURE(rc))
    4119         return PDMDEV_SET_ERROR(pDevIns, rc,
    4120                                 N_("BusLogic: Failed to initialize task cache\n"));
    4121 
    41224086    /* Initialize task queue. */
    41234087    rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 5, 0,
     
    41634127        pDevice->pBusLogicRC = PDMINS_2_DATA_RCPTR(pDevIns);
    41644128        pDevice->Led.u32Magic = PDMLED_MAGIC;
    4165         pDevice->IBase.pfnQueryInterface           = buslogicR3DeviceQueryInterface;
    4166         pDevice->ISCSIPort.pfnSCSIRequestCompleted = buslogicR3DeviceSCSIRequestCompleted;
    4167         pDevice->ISCSIPort.pfnQueryDeviceLocation  = buslogicR3QueryDeviceLocation;
    4168         pDevice->ILed.pfnQueryStatusLed            = buslogicR3DeviceQueryStatusLed;
     4129        pDevice->IBase.pfnQueryInterface                 = buslogicR3DeviceQueryInterface;
     4130        pDevice->IMediaPort.pfnQueryDeviceLocation       = buslogicR3QueryDeviceLocation;
     4131        pDevice->IMediaExPort.pfnIoReqCompleteNotify     = buslogicR3IoReqCompleteNotify;
     4132        pDevice->IMediaExPort.pfnIoReqCopyFromBuf        = buslogicR3IoReqCopyFromBuf;
     4133        pDevice->IMediaExPort.pfnIoReqCopyToBuf          = buslogicR3IoReqCopyToBuf;
     4134        pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
     4135        pDevice->IMediaExPort.pfnIoReqStateChanged       = buslogicR3IoReqStateChanged;
     4136        pDevice->IMediaExPort.pfnMediumEjected           = buslogicR3MediumEjected;
     4137        pDevice->ILed.pfnQueryStatusLed                  = buslogicR3DeviceQueryStatusLed;
    41694138
    41704139        /* Attach SCSI driver. */
     
    41724141        if (RT_SUCCESS(rc))
    41734142        {
    4174             /* Get SCSI connector interface. */
    4175             pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
    4176             AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
     4143            /* Query the media interface. */
     4144            pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
     4145            AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
     4146                            ("Buslogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
     4147                            VERR_PDM_MISSING_INTERFACE);
     4148
     4149            /* Get the extended media interface. */
     4150            pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
     4151            AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
     4152                            ("Buslogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
     4153                            VERR_PDM_MISSING_INTERFACE);
     4154
     4155            rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ));
     4156            if (RT_FAILURE(rc))
     4157                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     4158                                           N_("Buslogic configuration error: LUN#%u: Failed to set I/O request size!"),
     4159                                           pDevice->iLUN);
    41774160
    41784161            pDevice->fPresent = true;
     
    41804163        else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    41814164        {
    4182             pDevice->pDrvBase = NULL;
    4183             pDevice->fPresent = false;
     4165            pDevice->fPresent    = false;
     4166            pDevice->pDrvBase    = NULL;
     4167            pDevice->pDrvMedia   = NULL;
     4168            pDevice->pDrvMediaEx = NULL;
    41844169            rc = VINF_SUCCESS;
    41854170            Log(("BusLogic: no driver attached to device %s\n", szName));
     
    42654250    buslogicR3Suspend,
    42664251    /* pfnResume */
    4267     buslogicR3Resume,
     4252    NULL,
    42684253    /* pfnAttach */
    42694254    buslogicR3Attach,
  • trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp

    r63690 r64224  
    8080*********************************************************************************************************************************/
    8181
    82 /**
    83  * I/O buffer copy worker.
     82/** Pointer to the device instance data of the LsiLogic emulation. */
     83typedef struct LSILOGICSCSI *PLSILOGICSCSI;
     84
     85#ifdef IN_RING3
     86/**
     87 * Memory buffer callback.
    8488 *
    8589 * @returns nothing.
    86  * @param   pDevIns     Device instance data.
    87  * @param   GCPhysIoBuf Guest physical address of the I/O buffer.
    88  * @param   pvBuf       R3 buffer pointer.
    89  * @param   cbCopy      How much to copy.
    90  */
    91 typedef DECLCALLBACK(void) FNLSILOGICIOBUFCOPY(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
    92                                                void *pvBuf, size_t cbCopy);
    93 /** Pointer to a I/O buffer copy worker. */
    94 typedef FNLSILOGICIOBUFCOPY *PFNLSILOGICIOBUFCOPY;
     90 * @param   pThis    The LsiLogic controller instance.
     91 * @param   GCPhys   The guest physical address of the memory buffer.
     92 * @param   pSgBuf   The pointer to the host R3 S/G buffer.
     93 * @param   cbCopy   How many bytes to copy between the two buffers.
     94 * @param   pcbSkip  Initially contains the amount of bytes to skip
     95 *                   starting from the guest physical address before
     96 *                   accessing the S/G buffer and start copying data.
     97 *                   On return this contains the remaining amount if
     98 *                   cbCopy < *pcbSkip or 0 otherwise.
     99 */
     100typedef DECLCALLBACK(void) LSILOGICR3MEMCOPYCALLBACK(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
     101                                                     size_t *pcbSkip);
     102/** Pointer to a memory copy buffer callback. */
     103typedef LSILOGICR3MEMCOPYCALLBACK *PLSILOGICR3MEMCOPYCALLBACK;
     104#endif
    95105
    96106/**
     
    138148{
    139149    /** Pointer to the owning lsilogic device instance. - R3 pointer */
    140     R3PTRTYPE(struct LSILOGICSCSI *)  pLsiLogicR3;
     150    R3PTRTYPE(PLSILOGICSCSI)      pLsiLogicR3;
    141151
    142152    /** LUN of the device. */
     
    151161    /** Our base interface. */
    152162    PDMIBASE                      IBase;
    153     /** SCSI port interface. */
    154     PDMISCSIPORT                  ISCSIPort;
     163    /** Media port interface. */
     164    PDMIMEDIAPORT                 IMediaPort;
     165    /** Extended media port interface. */
     166    PDMIMEDIAEXPORT               IMediaExPort;
    155167    /** Led interface. */
    156168    PDMILEDPORTS                  ILed;
    157169    /** Pointer to the attached driver's base interface. */
    158170    R3PTRTYPE(PPDMIBASE)          pDrvBase;
    159     /** Pointer to the underlying SCSI connector interface. */
    160     R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector;
     171    /** Pointer to the attached driver's media interface. */
     172    R3PTRTYPE(PPDMIMEDIA)         pDrvMedia;
     173    /** Pointer to the attached driver's extended media interface. */
     174    R3PTRTYPE(PPDMIMEDIAEX)       pDrvMediaEx;
    161175    /** The status LED state for this device. */
    162176    PDMLED                        Led;
     
    323337    VBOXSCSI                       VBoxSCSI;
    324338
    325     /** Cache for allocated tasks. */
    326     R3PTRTYPE(RTMEMCACHE)          hTaskCache;
    327339    /** Status LUN: The base interface. */
    328340    PDMIBASE                       IBase;
     
    375387
    376388} LSILOGISCSI;
    377 /** Pointer to the device instance data of the LsiLogic emulation. */
    378 typedef LSILOGICSCSI *PLSILOGICSCSI;
    379389
    380390/**
     
    384394typedef struct LSILOGICREQ
    385395{
     396    /** I/O request handle. */
     397    PDMMEDIAEXIOREQ            hIoReq;
    386398    /** Next in the redo list. */
    387399    PLSILOGICREQ               pRedoNext;
     
    390402    /** The message request from the guest. */
    391403    MptRequestUnion            GuestRequest;
    392     /** Reply message if the request produces one. */
    393     MptReplyUnion              IOCReply;
    394     /** SCSI request structure for the SCSI driver. */
    395     PDMSCSIREQUEST             PDMScsiRequest;
    396404    /** Address of the message request frame in guests memory.
    397405     *  Used to read the S/G entries in the second step. */
     
    401409    /** Chain offset */
    402410    uint32_t                   cChainOffset;
    403     /** Segment describing the I/O buffer. */
    404     RTSGSEG                    SegIoBuf;
    405     /** Additional memory allocation for this task. */
    406     void                      *pvAlloc;
    407     /** Siize of the allocation. */
    408     size_t                     cbAlloc;
    409     /** Number of times we had too much memory allocated for the request. */
    410     unsigned                   cAllocTooMuch;
    411411    /** Pointer to the sense buffer. */
    412412    uint8_t                    abSenseBuffer[18];
    413413    /** Flag whether the request was issued from the BIOS. */
    414414    bool                       fBIOS;
     415    /** SCSI status code. */
     416    uint8_t                    u8ScsiSts;
    415417} LSILOGICREQ;
    416418
     
    18571859
    18581860/**
     1861 * Copy from guest to host memory worker.
     1862 *
     1863 * @copydoc{LSILOGICR3MEMCOPYCALLBACK}
     1864 */
     1865static DECLCALLBACK(void) lsilogicR3CopyBufferFromGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     1866                                                              size_t cbCopy, size_t *pcbSkip)
     1867{
     1868    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     1869    cbCopy   -= cbSkipped;
     1870    GCPhys   += cbSkipped;
     1871    *pcbSkip -= cbSkipped;
     1872
     1873    while (cbCopy)
     1874    {
     1875        size_t cbSeg = cbCopy;
     1876        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     1877
     1878        AssertPtr(pvSeg);
     1879        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     1880        GCPhys += cbSeg;
     1881        cbCopy -= cbSeg;
     1882    }
     1883}
     1884
     1885/**
     1886 * Copy from host to guest memory worker.
     1887 *
     1888 * @copydoc{LSILOGICR3MEMCOPYCALLBACK}
     1889 */
     1890static DECLCALLBACK(void) lsilogicR3CopyBufferToGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     1891                                                            size_t cbCopy, size_t *pcbSkip)
     1892{
     1893    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     1894    cbCopy   -= cbSkipped;
     1895    GCPhys   += cbSkipped;
     1896    *pcbSkip -= cbSkipped;
     1897
     1898    while (cbCopy)
     1899    {
     1900        size_t cbSeg = cbCopy;
     1901        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     1902
     1903        AssertPtr(pvSeg);
     1904        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     1905        GCPhys += cbSeg;
     1906        cbCopy -= cbSeg;
     1907    }
     1908}
     1909
     1910/**
    18591911 * Walks the guest S/G buffer calling the given copy worker for every buffer.
    18601912 *
    1861  * @returns nothing.
    1862  * @param   pDevIns      Device instance data.
    1863  * @param   pLsiReq      LSI request state.
    1864  * @param   cbCopy       How much bytes to copy.
    1865  * @param   pfnIoBufCopy Copy worker to call.
    1866  */
    1867 static void lsilogicSgBufWalker(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy,
    1868                                 PFNLSILOGICIOBUFCOPY pfnIoBufCopy)
     1913 * @returns The amout of bytes actually copied.
     1914 * @param   pThis                  Pointer to the LsiLogic device state.
     1915 * @param   pLsiReq                LSI request state.
     1916 * @param   pfnCopyWorker          The copy method to apply for each guest buffer.
     1917 * @param   pSgBuf                 The host S/G buffer.
     1918 * @param   cbSkip                 How many bytes to skip in advance before starting to copy.
     1919 * @param   cbCopy                 How many bytes to copy.
     1920 */
     1921static size_t lsilogicSgBufWalker(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq,
     1922                                  PLSILOGICR3MEMCOPYCALLBACK pfnCopyWorker,
     1923                                  PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
    18691924{
    18701925    bool     fEndOfList = false;
     
    18721927    RTGCPHYS GCPhysSegmentStart = pLsiReq->GCPhysSgStart;
    18731928    uint32_t cChainOffsetNext = pLsiReq->cChainOffset;
    1874     uint8_t *pbBuf = (uint8_t *)pLsiReq->SegIoBuf.pvSeg;
     1929    PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);
     1930    size_t cbCopied = 0;
     1931
     1932    /*
     1933     * Add the amount to skip to the host buffer size to avoid a
     1934     * few conditionals later on.
     1935     */
     1936    cbCopy += cbSkip;
    18751937
    18761938    /* Go through the list until we reach the end. */
     
    19001962                && SGEntry.Simple32.fEndOfList
    19011963                && SGEntry.Simple32.fEndOfBuffer)
    1902                 return;
     1964                return cbCopied - RT_MIN(cbSkip, cbCopied);
    19031965
    19041966            uint32_t cbCopyThis           = SGEntry.Simple32.u24Length;
     
    19131975                GCPhysSgEntryNext += sizeof(MptSGEntrySimple32);
    19141976
    1915 
    1916             pfnIoBufCopy(pDevIns, GCPhysAddrDataBuffer, pbBuf, cbCopyThis);
    1917             pbBuf  += cbCopyThis;
     1977            pfnCopyWorker(pThis, GCPhysAddrDataBuffer, pSgBuf, cbCopyThis, &cbSkip);
    19181978            cbCopy -= cbCopyThis;
     1979            cbCopied += cbCopyThis;
    19191980
    19201981            /* Check if we reached the end of the list. */
     
    19472008        }
    19482009    } /* while (!fEndOfList) */
    1949 }
    1950 
    1951 static DECLCALLBACK(void) lsilogicCopyFromGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
    1952                                                 void *pvBuf, size_t cbCopy)
    1953 {
    1954     PDMDevHlpPhysRead(pDevIns, GCPhysIoBuf, pvBuf, cbCopy);
    1955 }
    1956 
    1957 static DECLCALLBACK(void) lsilogicCopyToGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
    1958                                               void *pvBuf, size_t cbCopy)
    1959 {
    1960     PDMDevHlpPCIPhysWrite(pDevIns, GCPhysIoBuf, pvBuf, cbCopy);
    1961 }
    1962 
    1963 /**
    1964  * Copy from a guest S/G buffer to the I/O buffer.
    1965  *
    1966  * @returns nothing.
    1967  * @param   pDevIns      Device instance data.
    1968  * @param   pLsiReq      Request data.
    1969  * @param   cbCopy       How much to copy over.
    1970  */
    1971 DECLINLINE(void) lsilogicCopyFromSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy)
    1972 {
    1973     lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyFromGuest);
    1974 }
    1975 
    1976 /**
    1977  * Copy from an I/O buffer to the guest S/G buffer.
    1978  *
    1979  * @returns nothing.
    1980  * @param   pDevIns      Device instance data.
    1981  * @param   pLsiReq      Request data.
    1982  * @param   cbCopy       How much to copy over.
    1983  */
    1984 DECLINLINE(void) lsilogicCopyToSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy)
    1985 {
    1986     lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyToGuest);
    1987 }
    1988 
    1989 /**
    1990  * Allocates memory for the given request using already allocated memory if possible.
    1991  *
    1992  * @returns Pointer to the memory or NULL on failure
    1993  * @param   pLsiReq     The request to allocate memory for.
    1994  * @param   cb          The amount of memory to allocate.
    1995  */
    1996 static void *lsilogicReqMemAlloc(PLSILOGICREQ pLsiReq, size_t cb)
    1997 {
    1998     if (pLsiReq->cbAlloc > cb)
    1999         pLsiReq->cAllocTooMuch++;
    2000     else if (pLsiReq->cbAlloc < cb)
    2001     {
    2002         if (pLsiReq->cbAlloc)
    2003             RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc);
    2004 
    2005         pLsiReq->cbAlloc = RT_ALIGN_Z(cb, _4K);
    2006         pLsiReq->pvAlloc = RTMemPageAlloc(pLsiReq->cbAlloc);
    2007         pLsiReq->cAllocTooMuch = 0;
    2008         if (RT_UNLIKELY(!pLsiReq->pvAlloc))
    2009             pLsiReq->cbAlloc = 0;
    2010     }
    2011 
    2012     return pLsiReq->pvAlloc;
    2013 }
    2014 
    2015 /**
    2016  * Frees memory allocated for the given request.
    2017  *
    2018  * @returns nothing.
    2019  * @param   pLsiReq     The request.
    2020  */
    2021 static void lsilogicReqMemFree(PLSILOGICREQ pLsiReq)
    2022 {
    2023     if (pLsiReq->cAllocTooMuch >= LSILOGIC_MAX_ALLOC_TOO_MUCH)
    2024     {
    2025         RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc);
    2026         pLsiReq->cbAlloc = 0;
    2027         pLsiReq->cAllocTooMuch = 0;
    2028     }
    2029 }
    2030 
    2031 /**
    2032  * Allocate I/O memory and copies the guest buffer for writes.
    2033  *
    2034  * @returns VBox status code.
    2035  * @param   pDevIns     The device instance.
    2036  * @param   pLsiReq     The request state.
    2037  * @param   cbTransfer  Amount of bytes to allocate.
    2038  */
    2039 static int lsilogicIoBufAllocate(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq,
    2040                                  size_t cbTransfer)
    2041 {
    2042     uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
    2043 
    2044     AssertMsg(   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
    2045               || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
    2046               || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE,
    2047               ("Allocating I/O memory for a non I/O request is not allowed\n"));
    2048 
    2049     pLsiReq->SegIoBuf.pvSeg = lsilogicReqMemAlloc(pLsiReq, cbTransfer);
    2050     if (!pLsiReq->SegIoBuf.pvSeg)
    2051         return VERR_NO_MEMORY;
    2052 
    2053     pLsiReq->SegIoBuf.cbSeg = cbTransfer;
    2054     if (   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
    2055         || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
    2056         lsilogicCopyFromSgBuf(pDevIns, pLsiReq, cbTransfer);
    2057 
    2058     return VINF_SUCCESS;
    2059 }
    2060 
    2061 /**
    2062  * Frees the I/O memory of the given request and updates the guest buffer if necessary.
    2063  *
    2064  * @returns nothing.
    2065  * @param   pDevIns      The device instance.
    2066  * @param   pLsiReq      The request state.
    2067  * @param   fCopyToGuest Flag whether to update the guest buffer if necessary.
    2068  *                       Nothing is copied if false even if the request was a read.
    2069  */
    2070 static void lsilogicIoBufFree(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq,
    2071                               bool fCopyToGuest)
    2072 {
    2073     uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
    2074 
    2075     AssertMsg(   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
    2076               || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
    2077               || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE,
    2078               ("Allocating I/O memory for a non I/O request is not allowed\n"));
    2079 
    2080     if (   (   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
    2081             || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
    2082         && fCopyToGuest)
    2083         lsilogicCopyToSgBuf(pDevIns, pLsiReq, pLsiReq->SegIoBuf.cbSeg);
    2084 
    2085     lsilogicReqMemFree(pLsiReq);
    2086     pLsiReq->SegIoBuf.pvSeg = NULL;
    2087     pLsiReq->SegIoBuf.cbSeg = 0;
    2088 }
     2010
     2011    return cbCopied - RT_MIN(cbSkip, cbCopied);
     2012}
     2013
     2014/**
     2015 * Copies a data buffer into the S/G buffer set up by the guest.
     2016 *
     2017 * @returns Amount of bytes copied to the guest.
     2018 * @param   pThis          The LsiLogic controller device instance.
     2019 * @param   pReq           Request structure.
     2020 * @param   pSgBuf         The S/G buffer to copy from.
     2021 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     2022 * @param   cbCopy         How many bytes to copy.
     2023 */
     2024static size_t lsilogicR3CopySgBufToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf,
     2025                                         size_t cbSkip, size_t cbCopy)
     2026{
     2027    return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferToGuestWorker,
     2028                               pSgBuf, cbSkip, cbCopy);
     2029}
     2030
     2031/**
     2032 * Copies the guest S/G buffer into a host data buffer.
     2033 *
     2034 * @returns Amount of bytes copied from the guest.
     2035 * @param   pThis          The LsiLogic controller device instance.
     2036 * @param   pReq           Request structure.
     2037 * @param   pSgBuf         The S/G buffer to copy into.
     2038 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     2039 * @param   cbCopy         How many bytes to copy.
     2040 */
     2041static size_t lsilogicR3CopySgBufFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf,
     2042                                           size_t cbSkip, size_t cbCopy)
     2043{
     2044    return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferFromGuestWorker,
     2045                               pSgBuf, cbSkip, cbCopy);
     2046}
     2047
     2048#if 0 /* unused */
     2049/**
     2050 * Copy a simple memory buffer to the guest memory buffer.
     2051 *
     2052 * @returns Amount of bytes copied to the guest.
     2053 * @param   pThis          The LsiLogic controller device instance.
     2054 * @param   pReq           Request structure.
     2055 * @param   pvSrc          The buffer to copy from.
     2056 * @param   cbSrc          How many bytes to copy.
     2057 * @param   cbSkip         How many bytes to skip initially.
     2058 */
     2059static size_t lsilogicR3CopyBufferToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, const void *pvSrc,
     2060                                          size_t cbSrc, size_t cbSkip)
     2061{
     2062    RTSGSEG Seg;
     2063    RTSGBUF SgBuf;
     2064    Seg.pvSeg = (void *)pvSrc;
     2065    Seg.cbSeg = cbSrc;
     2066    RTSgBufInit(&SgBuf, &Seg, 1);
     2067    return lsilogicR3CopySgBufToGuest(pThis, pReq, &SgBuf, cbSkip, cbSrc);
     2068}
     2069
     2070/**
     2071 * Copy a guest memry buffe into simple host memory buffer.
     2072 *
     2073 * @returns Amount of bytes copied to the guest.
     2074 * @param   pThis          The LsiLogic controller device instance.
     2075 * @param   pReq           Request structure.
     2076 * @param   pvSrc          The buffer to copy from.
     2077 * @param   cbSrc          How many bytes to copy.
     2078 * @param   cbSkip         How many bytes to skip initially.
     2079 */
     2080static size_t lsilogicR3CopyBufferFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, void *pvDst,
     2081                                            size_t cbDst, size_t cbSkip)
     2082{
     2083    RTSGSEG Seg;
     2084    RTSGBUF SgBuf;
     2085    Seg.pvSeg = (void *)pvDst;
     2086    Seg.cbSeg = cbDst;
     2087    RTSgBufInit(&SgBuf, &Seg, 1);
     2088    return lsilogicR3CopySgBufFromGuest(pThis, pReq, &SgBuf, cbSkip, cbDst);
     2089}
     2090#endif
    20892091
    20902092# ifdef LOG_ENABLED
     
    21122114# endif
    21132115
    2114 static void lsilogicR3WarningDiskFull(PPDMDEVINS pDevIns)
    2115 {
    2116     int rc;
    2117     LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance));
    2118     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
    2119                                     N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
    2120     AssertRC(rc);
    2121 }
    2122 
    2123 static void lsilogicR3WarningFileTooBig(PPDMDEVINS pDevIns)
    2124 {
    2125     int rc;
    2126     LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance));
    2127     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
    2128                                     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"));
    2129     AssertRC(rc);
    2130 }
    2131 
    2132 static void lsilogicR3WarningISCSI(PPDMDEVINS pDevIns)
    2133 {
    2134     int rc;
    2135     LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
    2136     rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
    2137                                     N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
    2138     AssertRC(rc);
    2139 }
    2140 
    2141 static void lsilogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc)
    2142 {
    2143     int rc2;
    2144     LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
    2145     rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
    2146                                      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);
    2147     AssertRC(rc2);
    2148 }
    2149 
    2150 static void lsilogicR3RedoSetWarning(PLSILOGICSCSI pThis, int rc)
    2151 {
    2152     if (rc == VERR_DISK_FULL)
    2153         lsilogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns));
    2154     else if (rc == VERR_FILE_TOO_BIG)
    2155         lsilogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns));
    2156     else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
    2157     {
    2158         /* iSCSI connection abort (first error) or failure to reestablish
    2159          * connection (second error). Pause VM. On resume we'll retry. */
    2160         lsilogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns));
    2161     }
    2162     else if (rc != VERR_VD_DEK_MISSING)
    2163         lsilogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
     2116/**
     2117 * Handles the completion of th given request.
     2118 *
     2119 * @returns nothing.
     2120 * @param   pThis                  Pointer to the LsiLogic device state.
     2121 * @param   pReq                   The request to complete.
     2122 * @param   rcReq                  Status code of the request.
     2123 */
     2124static void lsilogicR3ReqComplete(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, int rcReq)
     2125{
     2126    PLSILOGICDEVICE pTgtDev = pReq->pTargetDevice;
     2127
     2128    if (RT_UNLIKELY(pReq->fBIOS))
     2129    {
     2130        pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
     2131        int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, rcReq);
     2132        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
     2133    }
     2134    else
     2135    {
     2136        RTGCPHYS GCPhysAddrSenseBuffer;
     2137
     2138        GCPhysAddrSenseBuffer = pReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
     2139        GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32);
     2140
     2141        /* Copy the sense buffer over. */
     2142        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pReq->abSenseBuffer,
     2143                              RT_UNLIKELY(  pReq->GuestRequest.SCSIIO.u8SenseBufferLength
     2144                                          < sizeof(pReq->abSenseBuffer))
     2145                              ? pReq->GuestRequest.SCSIIO.u8SenseBufferLength
     2146                              : sizeof(pReq->abSenseBuffer));
     2147
     2148        if (RT_SUCCESS(rcReq) && RT_LIKELY(pReq->u8ScsiSts == SCSI_STATUS_OK))
     2149        {
     2150            uint32_t u32MsgCtx = pReq->GuestRequest.SCSIIO.u32MessageContext;
     2151
     2152            /* Free the request before posting completion. */
     2153            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
     2154            lsilogicR3FinishContextReply(pThis, u32MsgCtx);
     2155        }
     2156        else
     2157        {
     2158            MptReplyUnion IOCReply;
     2159            RT_ZERO(IOCReply);
     2160
     2161            /* The SCSI target encountered an error during processing post a reply. */
     2162            IOCReply.SCSIIOError.u8TargetID          = pReq->GuestRequest.SCSIIO.u8TargetID;
     2163            IOCReply.SCSIIOError.u8Bus               = pReq->GuestRequest.SCSIIO.u8Bus;
     2164            IOCReply.SCSIIOError.u8MessageLength     = 8;
     2165            IOCReply.SCSIIOError.u8Function          = pReq->GuestRequest.SCSIIO.u8Function;
     2166            IOCReply.SCSIIOError.u8CDBLength         = pReq->GuestRequest.SCSIIO.u8CDBLength;
     2167            IOCReply.SCSIIOError.u8SenseBufferLength = pReq->GuestRequest.SCSIIO.u8SenseBufferLength;
     2168            IOCReply.SCSIIOError.u8MessageFlags      = pReq->GuestRequest.SCSIIO.u8MessageFlags;
     2169            IOCReply.SCSIIOError.u32MessageContext   = pReq->GuestRequest.SCSIIO.u32MessageContext;
     2170            IOCReply.SCSIIOError.u8SCSIStatus        = pReq->u8ScsiSts;
     2171            IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
     2172            IOCReply.SCSIIOError.u16IOCStatus        = 0;
     2173            IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
     2174            IOCReply.SCSIIOError.u32TransferCount    = 0;
     2175            IOCReply.SCSIIOError.u32SenseCount       = sizeof(pReq->abSenseBuffer);
     2176            IOCReply.SCSIIOError.u32ResponseInfo     = 0;
     2177
     2178            /* Free the request before posting completion. */
     2179            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
     2180            lsilogicFinishAddressReply(pThis, &IOCReply, false);
     2181        }
     2182    }
     2183
     2184    ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
     2185
     2186    if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle)
     2187        PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
    21642188}
    21652189
     
    21722196 *
    21732197 * @returns VBox status code.
    2174  * @param   pThis       Pointer to the LsiLogic device state.
    2175  * @param   pLsiReq  Pointer to the task state data.
    2176  */
    2177 static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq)
    2178 {
     2198 * @param   pThis                  Pointer to the LsiLogic device state.
     2199 * @param   GCPhysMessageFrameAddr Guest physical address where the request is located.
     2200 * @param   pGuestReq              The request read fro th guest memory.
     2201 */
     2202static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, RTGCPHYS GCPhysMessageFrameAddr,
     2203                                          PMptRequestUnion pGuestReq)
     2204{
     2205    MptReplyUnion IOCReply;
    21792206    int rc = VINF_SUCCESS;
    21802207
    21812208# ifdef LOG_ENABLED
    2182     lsilogicR3DumpSCSIIORequest(&pLsiReq->GuestRequest.SCSIIO);
     2209    lsilogicR3DumpSCSIIORequest(&pGuestReq->SCSIIO);
    21832210# endif
    21842211
    2185     pLsiReq->fBIOS = false;
    2186     pLsiReq->GCPhysSgStart = pLsiReq->GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest);
    2187     pLsiReq->cChainOffset  = pLsiReq->GuestRequest.SCSIIO.u8ChainOffset;
    2188     if (pLsiReq->cChainOffset)
    2189         pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest);
    2190 
    2191     if (RT_LIKELY(   (pLsiReq->GuestRequest.SCSIIO.u8TargetID < pThis->cDeviceStates)
    2192                   && (pLsiReq->GuestRequest.SCSIIO.u8Bus == 0)))
    2193     {
    2194         PLSILOGICDEVICE pTargetDevice;
    2195         pTargetDevice = &pThis->paDeviceStates[pLsiReq->GuestRequest.SCSIIO.u8TargetID];
    2196 
    2197         if (pTargetDevice->pDrvBase)
    2198         {
    2199 
    2200             if (pLsiReq->GuestRequest.SCSIIO.u32DataLength)
     2212    if (RT_LIKELY(   (pGuestReq->SCSIIO.u8TargetID < pThis->cDeviceStates)
     2213                  && (pGuestReq->SCSIIO.u8Bus == 0)))
     2214    {
     2215        PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[pGuestReq->SCSIIO.u8TargetID];
     2216
     2217        if (pTgtDev->pDrvBase)
     2218        {
     2219            /* Allocate and prepare a new request. */
     2220            PDMMEDIAEXIOREQ hIoReq;
     2221            PLSILOGICREQ pLsiReq = NULL;
     2222            rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pLsiReq,
     2223                                                     pGuestReq->SCSIIO.u32MessageContext,
     2224                                                     PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     2225            if (RT_SUCCESS(rc))
    22012226            {
    2202 
    2203                 rc = lsilogicIoBufAllocate(pThis->CTX_SUFF(pDevIns), pLsiReq,
    2204                                                            pLsiReq->GuestRequest.SCSIIO.u32DataLength);
    2205                 AssertRC(rc); /** @todo Insufficient resources error. */
    2206             }
    2207 
    2208             /* Setup the SCSI request. */
    2209             pLsiReq->pTargetDevice                        = pTargetDevice;
    2210             pLsiReq->PDMScsiRequest.uLogicalUnit          = pLsiReq->GuestRequest.SCSIIO.au8LUN[1];
    2211 
    2212             uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
    2213 
    2214             if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
    2215                 pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_NONE;
    2216             else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE)
    2217                 pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_TO_DEVICE;
    2218             else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ)
    2219                 pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
    2220 
    2221             pLsiReq->PDMScsiRequest.cbCDB                 = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
    2222             pLsiReq->PDMScsiRequest.pbCDB                 = pLsiReq->GuestRequest.SCSIIO.au8CDB;
    2223             pLsiReq->PDMScsiRequest.cbScatterGather       = pLsiReq->GuestRequest.SCSIIO.u32DataLength;
    2224             if (pLsiReq->PDMScsiRequest.cbScatterGather)
    2225             {
    2226                 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 1;
    2227                 pLsiReq->PDMScsiRequest.paScatterGatherHead   = &pLsiReq->SegIoBuf;
     2227                pLsiReq->hIoReq                 = hIoReq;
     2228                pLsiReq->pTargetDevice          = pTgtDev;
     2229                pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
     2230                pLsiReq->fBIOS                  = false;
     2231                pLsiReq->GCPhysSgStart          = GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest);
     2232                pLsiReq->cChainOffset           = pGuestReq->SCSIIO.u8ChainOffset;
     2233                if (pLsiReq->cChainOffset)
     2234                    pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest);
     2235                memcpy(&pLsiReq->GuestRequest, pGuestReq, sizeof(MptRequestUnion));
     2236                RT_BZERO(&pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer));
     2237
     2238                PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN;
     2239                uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
     2240
     2241                if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
     2242                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE;
     2243                else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE)
     2244                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE;
     2245                else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ)
     2246                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE;
     2247
     2248                ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     2249                rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pLsiReq->hIoReq, pLsiReq->GuestRequest.SCSIIO.au8LUN[1],
     2250                                                               &pLsiReq->GuestRequest.SCSIIO.au8CDB[0], pLsiReq->GuestRequest.SCSIIO.u8CDBLength,
     2251                                                               enmXferDir, pLsiReq->GuestRequest.SCSIIO.u32DataLength,
     2252                                                               &pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer), &pLsiReq->u8ScsiSts,
     2253                                                               30 * RT_MS_1SEC);
     2254                if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     2255                    lsilogicR3ReqComplete(pThis, pLsiReq, rc);
     2256
     2257                return VINF_SUCCESS;
    22282258            }
    22292259            else
    2230             {
    2231                 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 0;
    2232                 pLsiReq->PDMScsiRequest.paScatterGatherHead   = NULL;
    2233             }
    2234             pLsiReq->PDMScsiRequest.cbSenseBuffer         = sizeof(pLsiReq->abSenseBuffer);
    2235             memset(pLsiReq->abSenseBuffer, 0, pLsiReq->PDMScsiRequest.cbSenseBuffer);
    2236             pLsiReq->PDMScsiRequest.pbSenseBuffer         = pLsiReq->abSenseBuffer;
    2237             pLsiReq->PDMScsiRequest.pvUser                = pLsiReq;
    2238 
    2239             ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
    2240             rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pLsiReq->PDMScsiRequest);
    2241             AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
    2242             return VINF_SUCCESS;
     2260                IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
    22432261        }
    22442262        else
    22452263        {
    22462264            /* Device is not present report SCSI selection timeout. */
    2247             pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
     2265            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
    22482266        }
    22492267    }
     
    22512269    {
    22522270        /* Report out of bounds target ID or bus. */
    2253         if (pLsiReq->GuestRequest.SCSIIO.u8Bus != 0)
    2254             pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;
     2271        if (pGuestReq->SCSIIO.u8Bus != 0)
     2272            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;
    22552273        else
    2256             pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;
     2274            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;
    22572275    }
    22582276
     
    22622280    {
    22632281        LogRel(("LsiLogic#%d: %d/%d (Bus/Target) doesn't exist\n", pThis->CTX_SUFF(pDevIns)->iInstance,
    2264                 pLsiReq->GuestRequest.SCSIIO.u8TargetID, pLsiReq->GuestRequest.SCSIIO.u8Bus));
     2282                pGuestReq->SCSIIO.u8TargetID, pGuestReq->SCSIIO.u8Bus));
    22652283        /* Log the CDB too  */
    22662284        LogRel(("LsiLogic#%d: Guest issued CDB {%#x",
    2267                 pThis->CTX_SUFF(pDevIns)->iInstance, pLsiReq->GuestRequest.SCSIIO.au8CDB[0]));
    2268         for (unsigned i = 1; i < pLsiReq->GuestRequest.SCSIIO.u8CDBLength; i++)
    2269             LogRel((", %#x", pLsiReq->GuestRequest.SCSIIO.au8CDB[i]));
     2285                pThis->CTX_SUFF(pDevIns)->iInstance, pGuestReq->SCSIIO.au8CDB[0]));
     2286        for (unsigned i = 1; i < pGuestReq->SCSIIO.u8CDBLength; i++)
     2287            LogRel((", %#x", pGuestReq->SCSIIO.au8CDB[i]));
    22702288        LogRel(("}\n"));
    22712289    }
    22722290
    22732291    /* The rest is equal to both errors. */
    2274     pLsiReq->IOCReply.SCSIIOError.u8TargetID          = pLsiReq->GuestRequest.SCSIIO.u8TargetID;
    2275     pLsiReq->IOCReply.SCSIIOError.u8Bus               = pLsiReq->GuestRequest.SCSIIO.u8Bus;
    2276     pLsiReq->IOCReply.SCSIIOError.u8MessageLength     = sizeof(MptSCSIIOErrorReply) / 4;
    2277     pLsiReq->IOCReply.SCSIIOError.u8Function          = pLsiReq->GuestRequest.SCSIIO.u8Function;
    2278     pLsiReq->IOCReply.SCSIIOError.u8CDBLength         = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
    2279     pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength;
    2280     pLsiReq->IOCReply.SCSIIOError.u32MessageContext   = pLsiReq->GuestRequest.SCSIIO.u32MessageContext;
    2281     pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus        = SCSI_STATUS_OK;
    2282     pLsiReq->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED;
    2283     pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
    2284     pLsiReq->IOCReply.SCSIIOError.u32TransferCount    = 0;
    2285     pLsiReq->IOCReply.SCSIIOError.u32SenseCount       = 0;
    2286     pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
    2287 
    2288     lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false);
    2289     RTMemCacheFree(pThis->hTaskCache, pLsiReq);
     2292    IOCReply.SCSIIOError.u8TargetID          = pGuestReq->SCSIIO.u8TargetID;
     2293    IOCReply.SCSIIOError.u8Bus               = pGuestReq->SCSIIO.u8Bus;
     2294    IOCReply.SCSIIOError.u8MessageLength     = sizeof(MptSCSIIOErrorReply) / 4;
     2295    IOCReply.SCSIIOError.u8Function          = pGuestReq->SCSIIO.u8Function;
     2296    IOCReply.SCSIIOError.u8CDBLength         = pGuestReq->SCSIIO.u8CDBLength;
     2297    IOCReply.SCSIIOError.u8SenseBufferLength = pGuestReq->SCSIIO.u8SenseBufferLength;
     2298    IOCReply.SCSIIOError.u32MessageContext   = pGuestReq->SCSIIO.u32MessageContext;
     2299    IOCReply.SCSIIOError.u8SCSIStatus        = SCSI_STATUS_OK;
     2300    IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED;
     2301    IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
     2302    IOCReply.SCSIIOError.u32TransferCount    = 0;
     2303    IOCReply.SCSIIOError.u32SenseCount       = 0;
     2304    IOCReply.SCSIIOError.u32ResponseInfo     = 0;
     2305
     2306    lsilogicFinishAddressReply(pThis, &IOCReply, false);
    22902307
    22912308    return rc;
     
    22942311
    22952312/**
    2296  * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
    2297  */
    2298 static DECLCALLBACK(int) lsilogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
    2299                                                               int rcCompletion, bool fRedo, int rcReq)
    2300 {
    2301     RT_NOREF(pInterface);
    2302     PLSILOGICREQ    pLsiReq         = (PLSILOGICREQ)pSCSIRequest->pvUser;
    2303     PLSILOGICDEVICE pLsiLogicDevice = pLsiReq->pTargetDevice;
    2304     PLSILOGICSCSI   pThis           = pLsiLogicDevice->CTX_SUFF(pLsiLogic);
    2305 
    2306     /* If the task failed but it is possible to redo it again after a suspend
    2307      * add it to the list. */
    2308     if (fRedo)
    2309     {
    2310         if (!pLsiReq->fBIOS && pLsiReq->PDMScsiRequest.cbScatterGather)
    2311             lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, false /* fCopyToGuest */);
    2312 
    2313         /* Add to the list. */
    2314         do
    2315         {
    2316             pLsiReq->pRedoNext = ASMAtomicReadPtrT(&pThis->pTasksRedoHead, PLSILOGICREQ);
    2317         } while (!ASMAtomicCmpXchgPtr(&pThis->pTasksRedoHead, pLsiReq, pLsiReq->pRedoNext));
    2318 
    2319         /* Suspend the VM if not done already. */
    2320         if (!ASMAtomicXchgBool(&pThis->fRedo, true))
    2321             lsilogicR3RedoSetWarning(pThis, rcReq);
    2322     }
    2323     else
    2324     {
    2325         if (RT_UNLIKELY(pLsiReq->fBIOS))
    2326         {
    2327             int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pSCSIRequest, rcCompletion);
    2328             AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
    2329         }
    2330         else
    2331         {
    2332             RTGCPHYS GCPhysAddrSenseBuffer;
    2333 
    2334             GCPhysAddrSenseBuffer = pLsiReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
    2335             GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32);
    2336 
    2337             /* Copy the sense buffer over. */
    2338             PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pLsiReq->abSenseBuffer,
    2339                                   RT_UNLIKELY(  pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength
    2340                                               < pLsiReq->PDMScsiRequest.cbSenseBuffer)
    2341                                   ? pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength
    2342                                   : pLsiReq->PDMScsiRequest.cbSenseBuffer);
    2343 
    2344             if (pLsiReq->PDMScsiRequest.cbScatterGather)
    2345                 lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, true /* fCopyToGuest */);
    2346 
    2347 
    2348             if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
    2349                 lsilogicR3FinishContextReply(pThis, pLsiReq->GuestRequest.SCSIIO.u32MessageContext);
    2350             else
    2351             {
    2352                 /* The SCSI target encountered an error during processing post a reply. */
    2353                 memset(&pLsiReq->IOCReply, 0, sizeof(MptReplyUnion));
    2354                 pLsiReq->IOCReply.SCSIIOError.u8TargetID          = pLsiReq->GuestRequest.SCSIIO.u8TargetID;
    2355                 pLsiReq->IOCReply.SCSIIOError.u8Bus               = pLsiReq->GuestRequest.SCSIIO.u8Bus;
    2356                 pLsiReq->IOCReply.SCSIIOError.u8MessageLength     = 8;
    2357                 pLsiReq->IOCReply.SCSIIOError.u8Function          = pLsiReq->GuestRequest.SCSIIO.u8Function;
    2358                 pLsiReq->IOCReply.SCSIIOError.u8CDBLength         = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
    2359                 pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength;
    2360                 pLsiReq->IOCReply.SCSIIOError.u8MessageFlags      = pLsiReq->GuestRequest.SCSIIO.u8MessageFlags;
    2361                 pLsiReq->IOCReply.SCSIIOError.u32MessageContext   = pLsiReq->GuestRequest.SCSIIO.u32MessageContext;
    2362                 pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
    2363                 pLsiReq->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
    2364                 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus        = 0;
    2365                 pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
    2366                 pLsiReq->IOCReply.SCSIIOError.u32TransferCount    = 0;
    2367                 pLsiReq->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pLsiReq->abSenseBuffer);
    2368                 pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
    2369 
    2370                 lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false);
    2371             }
    2372         }
    2373 
    2374         RTMemCacheFree(pThis->hTaskCache, pLsiReq);
    2375     }
    2376 
    2377     ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
    2378 
    2379     if (pLsiLogicDevice->cOutstandingRequests == 0 && pThis->fSignalIdle)
    2380         PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
    2381 
    2382     return VINF_SUCCESS;
    2383 }
    2384 
    2385 /**
    2386  * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation}
    2387  */
    2388 static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
     2313 * @interface_method_impl{PDMIMEDIA,pfnQueryDeviceLocation}
     2314 */
     2315static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
    23892316                                                       uint32_t *piInstance, uint32_t *piLUN)
    23902317{
    2391     PLSILOGICDEVICE pLsiLogicDevice = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, ISCSIPort);
    2392     PPDMDEVINS pDevIns = pLsiLogicDevice->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
     2318    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaPort);
     2319    PPDMDEVINS pDevIns = pTgtDev->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
    23932320
    23942321    AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
     
    23982325    *ppcszController = pDevIns->pReg->szName;
    23992326    *piInstance = pDevIns->iInstance;
    2400     *piLUN = pLsiLogicDevice->iLUN;
     2327    *piLUN = pTgtDev->iLUN;
    24012328
    24022329    return VINF_SUCCESS;
    24032330}
     2331
     2332
     2333/**
     2334 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     2335 */
     2336static DECLCALLBACK(int) lsilogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2337                                                    void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
     2338                                                    size_t cbCopy)
     2339{
     2340    RT_NOREF1(hIoReq);
     2341    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
     2342    PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc;
     2343
     2344    size_t cbCopied = 0;
     2345    if (RT_UNLIKELY(pReq->fBIOS))
     2346        cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy);
     2347    else
     2348        cbCopied = lsilogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offDst, cbCopy);
     2349    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     2350}
     2351
     2352/**
     2353 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     2354 */
     2355static DECLCALLBACK(int) lsilogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2356                                                  void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
     2357                                                  size_t cbCopy)
     2358{
     2359    RT_NOREF1(hIoReq);
     2360    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
     2361    PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc;
     2362
     2363    size_t cbCopied = 0;
     2364    if (RT_UNLIKELY(pReq->fBIOS))
     2365        cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy);
     2366    else
     2367        cbCopied = lsilogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offSrc, cbCopy);
     2368    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     2369}
     2370
     2371/**
     2372 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     2373 */
     2374static DECLCALLBACK(int) lsilogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2375                                                       void *pvIoReqAlloc, int rcReq)
     2376{
     2377    RT_NOREF(hIoReq);
     2378    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
     2379    lsilogicR3ReqComplete(pTgtDev->CTX_SUFF(pLsiLogic), (PLSILOGICREQ)pvIoReqAlloc, rcReq);
     2380    return VINF_SUCCESS;
     2381}
     2382
     2383/**
     2384 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     2385 */
     2386static DECLCALLBACK(void) lsilogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     2387                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     2388{
     2389    RT_NOREF3(hIoReq, pvIoReqAlloc, enmState);
     2390    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
     2391
     2392    switch (enmState)
     2393    {
     2394        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
     2395        {
     2396            /* Make sure the request is not accounted for so the VM can suspend successfully. */
     2397            uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
     2398            if (!cTasksActive && pTgtDev->CTX_SUFF(pLsiLogic)->fSignalIdle)
     2399                PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pLsiLogic)->pDevInsR3);
     2400            break;
     2401        }
     2402        case PDMMEDIAEXIOREQSTATE_ACTIVE:
     2403            /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
     2404            ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     2405            break;
     2406        default:
     2407            AssertMsgFailed(("Invalid request state given %u\n", enmState));
     2408    }
     2409}
     2410
     2411/**
     2412 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
     2413 */
     2414static DECLCALLBACK(void) lsilogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
     2415{
     2416    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
     2417    PLSILOGICSCSI pThis = pTgtDev->CTX_SUFF(pLsiLogic);
     2418
     2419    RT_NOREF(pThis); /** @todo */
     2420}
     2421
    24042422
    24052423/**
     
    38073825{
    38083826    int rc;
    3809     PLSILOGICREQ pLsiReq;
    3810     uint32_t           uTargetDevice;
    3811 
    3812     rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
    3813     AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
    3814 
    3815     pLsiReq->fBIOS = true;
    3816 
    3817     rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, &uTargetDevice);
     3827    uint32_t uTargetDevice;
     3828    uint32_t uLun;
     3829    uint8_t *pbCdb;
     3830    size_t cbCdb;
     3831    size_t cbBuf;
     3832
     3833    rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice);
    38183834    AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc);
    38193835
    3820     pLsiReq->PDMScsiRequest.pvUser = pLsiReq;
    3821 
    3822     if (uTargetDevice < pThis->cDeviceStates)
    3823     {
    3824         pLsiReq->pTargetDevice = &pThis->paDeviceStates[uTargetDevice];
    3825 
    3826         if (pLsiReq->pTargetDevice->pDrvBase)
    3827         {
    3828             ASMAtomicIncU32(&pLsiReq->pTargetDevice->cOutstandingRequests);
    3829 
    3830             rc = pLsiReq->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pLsiReq->pTargetDevice->pDrvSCSIConnector,
    3831                                                                                   &pLsiReq->PDMScsiRequest);
    3832             AssertMsgRCReturn(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc), rc);
    3833             return VINF_SUCCESS;
    3834         }
     3836    if (   uTargetDevice < pThis->cDeviceStates
     3837        && pThis->paDeviceStates[uTargetDevice].pDrvBase)
     3838    {
     3839        PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[uTargetDevice];
     3840        PDMMEDIAEXIOREQ hIoReq;
     3841        PLSILOGICREQ pReq;
     3842
     3843        rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
     3844                                                 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
     3845        AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
     3846
     3847        pReq->fBIOS = true;
     3848        pReq->hIoReq = hIoReq;
     3849        pReq->pTargetDevice = pTgtDev;
     3850
     3851        ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
     3852
     3853        rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
     3854                                                       pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN,
     3855                                                       cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
     3856        if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3857        {
     3858            uint8_t u8ScsiSts = pReq->u8ScsiSts;
     3859            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
     3860            rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts);
     3861        }
     3862        else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3863            rc = VINF_SUCCESS;
     3864
     3865        return rc;
    38353866    }
    38363867
    38373868    /* Device is not present. */
    3838     AssertMsg(pLsiReq->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,
    3839                 ("Device is not present but command is not inquiry\n"));
     3869    AssertMsg(pbCdb[0] == SCSI_INQUIRY,
     3870              ("Device is not present but command is not inquiry\n"));
    38403871
    38413872    SCSIINQUIRYDATA ScsiInquiryData;
     
    38473878    memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
    38483879
    3849     rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, SCSI_STATUS_OK);
     3880    rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK);
    38503881    AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
    38513882
    3852     RTMemCacheFree(pThis->hTaskCache, pLsiReq);
    38533883    return rc;
    38543884}
     
    42434273               && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite))
    42444274        {
     4275            MptRequestUnion GuestRequest;
    42454276            uint32_t  u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead];
    42464277            RTGCPHYS  GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr,
    42474278                                                                          (u32RequestMessageFrameDesc & ~0x07));
    42484279
    4249             PLSILOGICREQ pLsiReq;
    4250 
    4251             /* Get new task state. */
    4252             rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
    4253             AssertRC(rc);
    4254 
    4255             pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
    4256 
    42574280            /* Read the message header from the guest first. */
    4258             PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr));
     4281            PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, sizeof(MptMessageHdr));
    42594282
    42604283            /* Determine the size of the request. */
    42614284            uint32_t cbRequest = 0;
    4262 
    4263             switch (pLsiReq->GuestRequest.Header.u8Function)
     4285            switch (GuestRequest.Header.u8Function)
    42644286            {
    42654287                case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST:
     
    42984320                    break;
    42994321                default:
    4300                     AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function));
     4322                    AssertMsgFailed(("Unknown function issued %u\n", GuestRequest.Header.u8Function));
    43014323                    lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION);
    43024324            }
     
    43054327            {
    43064328                /* Read the complete message frame from guest memory now. */
    4307                 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest);
     4329                PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, cbRequest);
    43084330
    43094331                /* Handle SCSI I/O requests now. */
    4310                 if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
     4332                if (GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
    43114333                {
    4312                    rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq);
     4334                   rc = lsilogicR3ProcessSCSIIORequest(pThis, GCPhysMessageFrameAddr, &GuestRequest);
    43134335                   AssertRC(rc);
    43144336                }
     
    43164338                {
    43174339                    MptReplyUnion Reply;
    4318                     rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply);
     4340                    rc = lsilogicR3ProcessMessageRequest(pThis, &GuestRequest.Header, &Reply);
    43194341                    AssertRC(rc);
    4320                     RTMemCacheFree(pThis->hTaskCache, pLsiReq);
    43214342                }
    43224343
     
    43554376static void lsilogicR3Kick(PLSILOGICSCSI pThis)
    43564377{
    4357     if (   pThis->VBoxSCSI.fBusy
    4358         && !pThis->fBiosReqPending)
    4359         pThis->fBiosReqPending = true;
    4360 
    43614378    if (pThis->fNotificationSent)
    43624379    {
     
    44084425                  ("There are still outstanding requests on this device\n"));
    44094426        SSMR3PutU32(pSSM, pDevice->cOutstandingRequests);
    4410     }
     4427
     4428        /* Query all suspended requests and store them in the request queue. */
     4429        if (pDevice->pDrvMediaEx)
     4430        {
     4431            uint32_t cReqsRedo = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
     4432            if (cReqsRedo)
     4433            {
     4434                PDMMEDIAEXIOREQ hIoReq;
     4435                PLSILOGICREQ pReq;
     4436                int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq,
     4437                                                                           (void **)&pReq);
     4438                AssertRCBreak(rc);
     4439
     4440                for (;;)
     4441                {
     4442                    if (!pReq->fBIOS)
     4443                    {
     4444                        /* Write only the lower 32bit part of the address. */
     4445                        ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
     4446                                          pReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
     4447
     4448                        pThis->uRequestQueueNextEntryFreeWrite++;
     4449                        pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
     4450                    }
     4451                    else
     4452                    {
     4453                        AssertMsg(!pReq->pRedoNext, ("Only one BIOS task can be active!\n"));
     4454                        vboxscsiSetRequestRedo(&pThis->VBoxSCSI);
     4455                    }
     4456
     4457                    cReqsRedo--;
     4458                    if (!cReqsRedo)
     4459                        break;
     4460
     4461                    rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq,
     4462                                                                          &hIoReq, (void **)&pReq);
     4463                    AssertRCBreak(rc);
     4464                }
     4465            }
     4466        }
     4467    }
     4468
    44114469    /* Now the main device state. */
    44124470    SSMR3PutU32   (pSSM, pThis->enmState);
     
    49244982
    49254983    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase);
    4926     PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort);
     4984    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort);
     4985    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort);
    49274986    PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed);
    49284987    return NULL;
     
    50245083
    50255084        AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n"));
    5026 
    5027         if (pThis->fRedo)
    5028         {
    5029             /*
    5030              * We have tasks which we need to redo. Put the message frame addresses
    5031              * into the request queue (we save the requests).
    5032              * Guest execution is suspended at this point so there is no race between us and
    5033              * lsilogicRegisterWrite.
    5034              */
    5035             PLSILOGICREQ pLsiReq = pThis->pTasksRedoHead;
    5036 
    5037             pThis->pTasksRedoHead = NULL;
    5038 
    5039             while (pLsiReq)
    5040             {
    5041                 PLSILOGICREQ pFree;
    5042 
    5043                 if (!pLsiReq->fBIOS)
    5044                 {
    5045                     /* Write only the lower 32bit part of the address. */
    5046                     ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
    5047                                       pLsiReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
    5048 
    5049                     pThis->uRequestQueueNextEntryFreeWrite++;
    5050                     pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
    5051                 }
    5052                 else
    5053                 {
    5054                     AssertMsg(!pLsiReq->pRedoNext, ("Only one BIOS task can be active!\n"));
    5055                     vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest);
    5056                 }
    5057 
    5058                 pThis->fNotificationSent = true;
    5059 
    5060                 pFree = pLsiReq;
    5061                 pLsiReq = pLsiReq->pRedoNext;
    5062 
    5063                 RTMemCacheFree(pThis->hTaskCache, pFree);
    5064             }
    5065             pThis->fRedo = false;
    5066         }
    50675085    }
    50685086}
     
    51135131     */
    51145132    pDevice->pDrvBase = NULL;
    5115     pDevice->pDrvSCSIConnector = NULL;
     5133    pDevice->pDrvMedia = NULL;
     5134    pDevice->pDrvMediaEx = NULL;
    51165135}
    51175136
     
    51345153    /* the usual paranoia */
    51355154    AssertRelease(!pDevice->pDrvBase);
    5136     AssertRelease(!pDevice->pDrvSCSIConnector);
     5155    AssertRelease(!pDevice->pDrvMedia);
     5156    AssertRelease(!pDevice->pDrvMediaEx);
    51375157    Assert(pDevice->iLUN == iLUN);
    51385158
     
    51445164    if (RT_SUCCESS(rc))
    51455165    {
    5146         /* Get SCSI connector interface. */
    5147         pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
    5148         AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
     5166        /* Query the media interface. */
     5167        pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
     5168        AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
     5169                        ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
     5170                        VERR_PDM_MISSING_INTERFACE);
     5171
     5172        /* Get the extended media interface. */
     5173        pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
     5174        AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
     5175                        ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
     5176                        VERR_PDM_MISSING_INTERFACE);
     5177
     5178        rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ));
     5179        AssertMsgRCReturn(rc, ("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"),
     5180                               pDevice->iLUN);
    51495181    }
    51505182    else
     
    51545186    {
    51555187        pDevice->pDrvBase = NULL;
    5156         pDevice->pDrvSCSIConnector = NULL;
     5188        pDevice->pDrvMedia = NULL;
     5189        pDevice->pDrvMediaEx = NULL;
    51575190    }
    51585191    return rc;
     
    52475280    pThis->paDeviceStates = NULL;
    52485281
    5249     /* Destroy task cache. */
    5250     if (pThis->hTaskCache != NIL_RTMEMCACHE)
    5251     {
    5252         int rc = RTMemCacheDestroy(pThis->hTaskCache); AssertRC(rc);
    5253         pThis->hTaskCache = NIL_RTMEMCACHE;
    5254     }
    5255 
    52565282    if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
    52575283    {
     
    52785304     * Initialize enought of the state to make the destructure not trip up.
    52795305     */
    5280     pThis->hTaskCache  = NIL_RTMEMCACHE;
    52815306    pThis->hEvtProcess = NIL_SUPSEMEVENT;
    52825307    pThis->fBiosReqPending = false;
     
    54835508        return rc;
    54845509
    5485     /*
    5486      * Allocate task cache.
    5487      */
    5488     rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(LSILOGICREQ), 0, UINT32_MAX,
    5489                           NULL, NULL, NULL, 0);
    5490     if (RT_FAILURE(rc))
    5491         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Cannot create task cache"));
    5492 
    54935510    if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
    54945511        pThis->cDeviceStates = pThis->cPorts * LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX;
     
    55255542
    55265543        /* Initialize static parts of the device. */
    5527         pDevice->iLUN                              = i;
    5528         pDevice->pLsiLogicR3                       = pThis;
    5529         pDevice->Led.u32Magic                      = PDMLED_MAGIC;
    5530         pDevice->IBase.pfnQueryInterface           = lsilogicR3DeviceQueryInterface;
    5531         pDevice->ISCSIPort.pfnSCSIRequestCompleted = lsilogicR3DeviceSCSIRequestCompleted;
    5532         pDevice->ISCSIPort.pfnQueryDeviceLocation  = lsilogicR3QueryDeviceLocation;
    5533         pDevice->ILed.pfnQueryStatusLed            = lsilogicR3DeviceQueryStatusLed;
     5544        pDevice->iLUN                                    = i;
     5545        pDevice->pLsiLogicR3                             = pThis;
     5546        pDevice->Led.u32Magic                            = PDMLED_MAGIC;
     5547        pDevice->IBase.pfnQueryInterface                 = lsilogicR3DeviceQueryInterface;
     5548        pDevice->IMediaPort.pfnQueryDeviceLocation       = lsilogicR3QueryDeviceLocation;
     5549        pDevice->IMediaExPort.pfnIoReqCompleteNotify     = lsilogicR3IoReqCompleteNotify;
     5550        pDevice->IMediaExPort.pfnIoReqCopyFromBuf        = lsilogicR3IoReqCopyFromBuf;
     5551        pDevice->IMediaExPort.pfnIoReqCopyToBuf          = lsilogicR3IoReqCopyToBuf;
     5552        pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
     5553        pDevice->IMediaExPort.pfnIoReqStateChanged       = lsilogicR3IoReqStateChanged;
     5554        pDevice->IMediaExPort.pfnMediumEjected           = lsilogicR3MediumEjected;
     5555        pDevice->ILed.pfnQueryStatusLed                  = lsilogicR3DeviceQueryStatusLed;
    55345556
    55355557        RTStrPrintf(szName, sizeof(szName), "Device%u", i);
     
    55395561        if (RT_SUCCESS(rc))
    55405562        {
    5541             /* Get SCSI connector interface. */
    5542             pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
    5543             AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
     5563            /* Query the media interface. */
     5564            pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
     5565            AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
     5566                            ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
     5567                            VERR_PDM_MISSING_INTERFACE);
     5568
     5569            /* Get the extended media interface. */
     5570            pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
     5571            AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
     5572                            ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
     5573                            VERR_PDM_MISSING_INTERFACE);
     5574
     5575            rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ));
     5576            if (RT_FAILURE(rc))
     5577                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     5578                                           N_("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"),
     5579                                           pDevice->iLUN);
    55445580        }
    55455581        else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp

    r63657 r64224  
    277277 * @returns VBox status code.
    278278 * @param   pVBoxSCSI      Pointer to the SCSI state.
    279  * @param   pScsiRequest   Pointer to a scsi request to setup.
     279 * @paam    puLun          Where to store the LUN on success.
     280 * @param   ppbCdb         Where to store the pointer to the CDB on success.
     281 * @param   pcbCdb         Where to store the size of the CDB on success.
     282 * @param   pcbBuf         Where to store th size of the data buffer on success.
    280283 * @param   puTargetDevice Where to store the target device ID.
    281284 */
    282 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice)
     285int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb,
     286                         size_t *pcbCdb, size_t *pcbBuf, uint32_t *puTargetDevice)
    283287{
    284288    int rc = VINF_SUCCESS;
    285289
    286     LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p puTargetDevice=%#p\n", pVBoxSCSI, pScsiRequest, puTargetDevice));
     290    LogFlowFunc(("pVBoxSCSI=%#p puTargetDevice=%#p\n", pVBoxSCSI, puTargetDevice));
    287291
    288292    AssertMsg(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, ("Invalid state %u\n", pVBoxSCSI->enmState));
     
    301305    }
    302306
    303     /* Allocate scatter gather element. */
    304     pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
    305     if (!pScsiRequest->paScatterGatherHead)
    306     {
    307         RTMemFree(pVBoxSCSI->pbBuf);
    308         pVBoxSCSI->pbBuf = NULL;
    309         return VERR_NO_MEMORY;
    310     }
    311 
    312     /* Allocate sense buffer. */
    313     pScsiRequest->cbSenseBuffer = 18;
    314     pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer);
    315 
    316     pScsiRequest->cbCDB = pVBoxSCSI->cbCDB;
    317     pScsiRequest->pbCDB = pVBoxSCSI->abCDB;
    318     pScsiRequest->uLogicalUnit = 0;
    319     pScsiRequest->cbScatterGather = pVBoxSCSI->cbBuf;
    320     pScsiRequest->cScatterGatherEntries = 1;
    321 
    322     pScsiRequest->paScatterGatherHead[0].cbSeg = pVBoxSCSI->cbBuf;
    323     pScsiRequest->paScatterGatherHead[0].pvSeg = pVBoxSCSI->pbBuf;
    324 
     307    *puLun = 0;
     308    *ppbCdb = &pVBoxSCSI->abCDB[0];
     309    *pcbCdb = pVBoxSCSI->cbCDB;
     310    *pcbBuf = pVBoxSCSI->cbBuf;
    325311    *puTargetDevice = pVBoxSCSI->uTargetDevice;
    326312
     
    332318 * is ready at the incoming data port.
    333319 */
    334 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion)
    335 {
    336     LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p\n", pVBoxSCSI, pScsiRequest));
    337     RTMemFree(pScsiRequest->paScatterGatherHead);
    338     RTMemFree(pScsiRequest->pbSenseBuffer);
     320int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion)
     321{
     322    LogFlowFunc(("pVBoxSCSI=%#p\n", pVBoxSCSI));
    339323
    340324    if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE)
     
    346330
    347331    return VINF_SUCCESS;
     332}
     333
     334size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
     335{
     336    AssertPtrReturn(pVBoxSCSI->pbBuf, 0);
     337    AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0);
     338
     339    void *pvBuf = pVBoxSCSI->pbBuf + cbSkip;
     340    return RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy);
     341}
     342
     343size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
     344{
     345    AssertPtrReturn(pVBoxSCSI->pbBuf, 0);
     346    AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0);
     347
     348    void *pvBuf = pVBoxSCSI->pbBuf + cbSkip;
     349    return RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy);
    348350}
    349351
     
    452454}
    453455
    454 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest)
     456void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI)
    455457{
    456458    AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n"));
    457 
    458     RTMemFree(pScsiRequest->paScatterGatherHead);
    459     RTMemFree(pScsiRequest->pbSenseBuffer);
    460459
    461460    if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.h

    r62506 r64224  
    136136int vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value);
    137137int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal);
    138 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice);
    139 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion);
    140 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
     138int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb, size_t *pcbCdb,
     139                         size_t *pcbBuf, uint32_t *puTargetDevice);
     140int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion);
     141size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy);
     142size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy);
     143void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI);
    141144int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
    142145                        uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb);
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r64176 r64224  
    17311731    GEN_CHECK_OFF(BUSLOGICDEVICE, iLUN);
    17321732    GEN_CHECK_OFF(BUSLOGICDEVICE, IBase);
    1733     GEN_CHECK_OFF(BUSLOGICDEVICE, ISCSIPort);
     1733    GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaPort);
     1734    GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaExPort);
    17341735    GEN_CHECK_OFF(BUSLOGICDEVICE, ILed);
    17351736    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvBase);
    1736     GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvSCSIConnector);
     1737    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMedia);
     1738    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMediaEx);
    17371739    GEN_CHECK_OFF(BUSLOGICDEVICE, Led);
    17381740    GEN_CHECK_OFF(BUSLOGICDEVICE, cOutstandingRequests);
     
    17731775    GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueRC);
    17741776    GEN_CHECK_OFF(BUSLOGIC, CritSectIntr);
    1775     GEN_CHECK_OFF(BUSLOGIC, hTaskCache);
    17761777    GEN_CHECK_OFF(BUSLOGIC, VBoxSCSI);
    17771778    GEN_CHECK_OFF(BUSLOGIC, aDeviceStates);
     
    17811782    GEN_CHECK_OFF(BUSLOGIC, pLedsConnector);
    17821783    GEN_CHECK_OFF(BUSLOGIC, fSignalIdle);
    1783     GEN_CHECK_OFF(BUSLOGIC, fRedo);
    17841784    GEN_CHECK_OFF(BUSLOGIC, fWrkThreadSleeping);
    17851785    GEN_CHECK_OFF(BUSLOGIC, fBiosReqPending);
    1786     GEN_CHECK_OFF(BUSLOGIC, pTasksRedoHead);
    17871786    GEN_CHECK_OFF(BUSLOGIC, pSupDrvSession);
    17881787    GEN_CHECK_OFF(BUSLOGIC, hEvtProcess);
     1788    GEN_CHECK_OFF(BUSLOGIC, paGCPhysAddrCCBRedo);
     1789    GEN_CHECK_OFF(BUSLOGIC, cReqsRedo);
    17891790# ifdef LOG_ENABLED
    17901791    GEN_CHECK_OFF(BUSLOGIC, cInMailboxesReady);
     
    18521853    GEN_CHECK_OFF(LSILOGICSCSI, enmCtrlType);
    18531854    GEN_CHECK_OFF(LSILOGICSCSI, VBoxSCSI);
    1854     GEN_CHECK_OFF(LSILOGICSCSI, hTaskCache);
    18551855    GEN_CHECK_OFF(LSILOGICSCSI, IBase);
    18561856    GEN_CHECK_OFF(LSILOGICSCSI, ILeds);
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