Index: /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp	(revision 64223)
+++ /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp	(revision 64224)
@@ -112,12 +112,16 @@
     /** Our base interface. */
     PDMIBASE                      IBase;
-    /** SCSI port interface. */
-    PDMISCSIPORT                  ISCSIPort;
+    /** Media port interface. */
+    PDMIMEDIAPORT                 IMediaPort;
+    /** Extended media port interface. */
+    PDMIMEDIAEXPORT               IMediaExPort;
     /** Led interface. */
     PDMILEDPORTS                  ILed;
     /** Pointer to the attached driver's base interface. */
     R3PTRTYPE(PPDMIBASE)          pDrvBase;
-    /** Pointer to the underlying SCSI connector interface. */
-    R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector;
+    /** Pointer to the attached driver's media interface. */
+    R3PTRTYPE(PPDMIMEDIA)         pDrvMedia;
+    /** Pointer to the attached driver's extended media interface. */
+    R3PTRTYPE(PPDMIMEDIAEX)       pDrvMediaEx;
     /** The status LED state for this device. */
     PDMLED                        Led;
@@ -313,5 +317,5 @@
 
 /** Pointer to a task state structure. */
-typedef struct BUSLOGICTASKSTATE *PBUSLOGICTASKSTATE;
+typedef struct BUSLOGICREQ *PBUSLOGICREQ;
 
 /**
@@ -436,7 +440,4 @@
     PDMCRITSECT                     CritSectIntr;
 
-    /** Cache for task states. */
-    R3PTRTYPE(RTMEMCACHE)           hTaskCache;
-
     /** Device state for BIOS access. */
     VBOXSCSI                        VBoxSCSI;
@@ -460,6 +461,4 @@
      * a port is entering the idle state. */
     bool volatile                   fSignalIdle;
-    /** Flag whether we have tasks which need to be processed again. */
-    bool volatile                   fRedo;
     /** Flag whether the worker thread is sleeping. */
     volatile bool                   fWrkThreadSleeping;
@@ -467,6 +466,4 @@
      * worker thread needs to process. */
     volatile bool                   fBiosReqPending;
-    /** List of tasks which can be redone. */
-    R3PTRTYPE(volatile PBUSLOGICTASKSTATE) pTasksRedoHead;
 
     /** The support driver session handle. */
@@ -477,10 +474,15 @@
     SUPSEMEVENT                     hEvtProcess;
 
+    /** Pointer to the array of addresses to redo. */
+    R3PTRTYPE(PRTGCPHYS)            paGCPhysAddrCCBRedo;
+    /** Number of addresses the redo array holds. */
+    uint32_t                        cReqsRedo;
+
 #ifdef LOG_ENABLED
+    volatile uint32_t               cInMailboxesReady;
+#else
 # if HC_ARCH_BITS == 64
     uint32_t                        Alignment4;
 # endif
-
-    volatile uint32_t               cInMailboxesReady;
 #endif
 
@@ -956,35 +958,46 @@
  * Task state for a CCB request.
  */
-typedef struct BUSLOGICTASKSTATE
-{
-    /** Next in the redo list. */
-    PBUSLOGICTASKSTATE             pRedoNext;
+typedef struct BUSLOGICREQ
+{
+    /** PDM extended media interface I/O request hande. */
+    PDMMEDIAEXIOREQ                hIoReq;
     /** Device this task is assigned to. */
-    R3PTRTYPE(PBUSLOGICDEVICE)     pTargetDeviceR3;
+    PBUSLOGICDEVICE                pTargetDevice;
     /** The command control block from the guest. */
-    CCBU                CommandControlBlockGuest;
-    /** Mailbox read from guest memory. */
-    Mailbox32           MailboxGuest;
-    /** The SCSI request we pass to the underlying SCSI engine. */
-    PDMSCSIREQUEST      PDMScsiRequest;
-    /** Data buffer segment */
-    RTSGSEG             DataSeg;
+    CCBU                           CCBGuest;
+    /** Guest physical address of th CCB. */
+    RTGCPHYS                       GCPhysAddrCCB;
     /** Pointer to the R3 sense buffer. */
-    uint8_t            *pbSenseBuffer;
+    uint8_t                        *pbSenseBuffer;
     /** Flag whether this is a request from the BIOS. */
-    bool                fBIOS;
+    bool                           fBIOS;
     /** 24-bit request flag (default is 32-bit). */
-    bool                fIs24Bit;
-    /** S/G entry size (depends on the above flag). */
-    uint8_t             cbSGEntry;
-} BUSLOGICTASKSTATE;
+    bool                           fIs24Bit;
+    /** SCSI status code. */
+    uint8_t                        u8ScsiSts;
+} BUSLOGICREQ;
+
+#ifdef IN_RING3
+/**
+ * Memory buffer callback.
+ *
+ * @returns nothing.
+ * @param   pThis    The LsiLogic controller instance.
+ * @param   GCPhys   The guest physical address of the memory buffer.
+ * @param   pSgBuf   The pointer to the host R3 S/G buffer.
+ * @param   cbCopy   How many bytes to copy between the two buffers.
+ * @param   pcbSkip  Initially contains the amount of bytes to skip
+ *                   starting from the guest physical address before
+ *                   accessing the S/G buffer and start copying data.
+ *                   On return this contains the remaining amount if
+ *                   cbCopy < *pcbSkip or 0 otherwise.
+ */
+typedef DECLCALLBACK(void) BUSLOGICR3MEMCOPYCALLBACK(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
+                                                     size_t *pcbSkip);
+/** Pointer to a memory copy buffer callback. */
+typedef BUSLOGICR3MEMCOPYCALLBACK *PBUSLOGICR3MEMCOPYCALLBACK;
+#endif
 
 #ifndef VBOX_DEVICE_STRUCT_TESTCASE
-
-#define PDMIBASE_2_PBUSLOGICDEVICE(pInterface)     ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, IBase)) )
-#define PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ISCSIPort)) )
-#define PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ILed)) )
-#define PDMIBASE_2_PBUSLOGIC(pInterface)           ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, IBase)) )
-#define PDMILEDPORTS_2_PBUSLOGIC(pInterface)       ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, ILeds)) )
 
 
@@ -1188,16 +1201,20 @@
  * @returns nothing.
  * @param   pBusLogic                 Pointer to the BusLogic device instance.
- * @param   pTaskState                Pointer to the task state with the mailbox to send.
+ * @param   GCPhysAddrCCB             The physical guest address of the CCB the mailbox is for.
+ * @param   pCCBGuet                  The command control block.
  * @param   uHostAdapterStatus        The host adapter status code to set.
  * @param   uDeviceStatus             The target device status to set.
  * @param   uMailboxCompletionCode    Completion status code to set in the mailbox.
  */
-static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState,
-                                          uint8_t uHostAdapterStatus, uint8_t uDeviceStatus,
-                                          uint8_t uMailboxCompletionCode)
-{
-    pTaskState->MailboxGuest.u.in.uHostAdapterStatus = uHostAdapterStatus;
-    pTaskState->MailboxGuest.u.in.uTargetDeviceStatus = uDeviceStatus;
-    pTaskState->MailboxGuest.u.in.uCompletionCode = uMailboxCompletionCode;
+static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB,
+                                          PCCBU pCCBGuest, uint8_t uHostAdapterStatus,
+                                          uint8_t uDeviceStatus, uint8_t uMailboxCompletionCode)
+{
+    Mailbox32 MbxIn;
+
+    MbxIn.u32PhysAddrCCB           = (uint32_t)GCPhysAddrCCB;
+    MbxIn.u.in.uHostAdapterStatus  = uHostAdapterStatus;
+    MbxIn.u.in.uTargetDeviceStatus = uDeviceStatus;
+    MbxIn.u.in.uCompletionCode     = uMailboxCompletionCode;
 
     int rc = PDMCritSectEnter(&pBusLogic->CritSectIntr, VINF_SUCCESS);
@@ -1206,23 +1223,22 @@
     RTGCPHYS GCPhysAddrMailboxIncoming = pBusLogic->GCPhysAddrMailboxIncomingBase
                                        + (   pBusLogic->uMailboxIncomingPositionCurrent
-                                          * (pTaskState->fIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) );
+                                          * (pBusLogic->fMbxIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) );
 
     if (uMailboxCompletionCode != BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND)
     {
-        RTGCPHYS GCPhysAddrCCB = pTaskState->MailboxGuest.u32PhysAddrCCB;
         LogFlowFunc(("Completing CCB %RGp hstat=%u, dstat=%u, outgoing mailbox at %RGp\n", GCPhysAddrCCB,
                      uHostAdapterStatus, uDeviceStatus, GCPhysAddrMailboxIncoming));
 
         /* Update CCB. */
-        pTaskState->CommandControlBlockGuest.c.uHostAdapterStatus = uHostAdapterStatus;
-        pTaskState->CommandControlBlockGuest.c.uDeviceStatus      = uDeviceStatus;
+        pCCBGuest->c.uHostAdapterStatus = uHostAdapterStatus;
+        pCCBGuest->c.uDeviceStatus      = uDeviceStatus;
         /* Rewrite CCB up to the CDB; perhaps more than necessary. */
         PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
-                              &pTaskState->CommandControlBlockGuest, RT_OFFSETOF(CCBC, abCDB));
+                              pCCBGuest, RT_OFFSETOF(CCBC, abCDB));
     }
 
 # ifdef RT_STRICT
     uint8_t     uCode;
-    unsigned    uCodeOffs = pTaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
+    unsigned    uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
     PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming + uCodeOffs, &uCode, sizeof(uCode));
     Assert(uCode == BUSLOGIC_MAILBOX_INCOMING_COMPLETION_FREE);
@@ -1230,10 +1246,10 @@
 
     /* Update mailbox. */
-    if (pTaskState->fIs24Bit)
+    if (pBusLogic->fMbxIs24Bit)
     {
         Mailbox24   Mbx24;
 
-        Mbx24.uCmdState = pTaskState->MailboxGuest.u.in.uCompletionCode;
-        U32_TO_ADDR(Mbx24.aPhysAddrCCB, pTaskState->MailboxGuest.u32PhysAddrCCB);
+        Mbx24.uCmdState = MbxIn.u.in.uCompletionCode;
+        U32_TO_ADDR(Mbx24.aPhysAddrCCB, MbxIn.u32PhysAddrCCB);
         Log(("24-bit mailbox: completion code=%u, CCB at %RGp\n", Mbx24.uCmdState, (RTGCPHYS)ADDR_TO_U32(Mbx24.aPhysAddrCCB)));
         PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming, &Mbx24, sizeof(Mailbox24));
@@ -1241,7 +1257,7 @@
     else
     {
-        Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", pTaskState->MailboxGuest.u.in.uCompletionCode, (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB));
+        Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", MbxIn.u.in.uCompletionCode, GCPhysAddrCCB));
         PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming,
-                              &pTaskState->MailboxGuest, sizeof(Mailbox32));
+                              &MbxIn, sizeof(Mailbox32));
     }
 
@@ -1331,18 +1347,19 @@
  * Allocate data buffer.
  *
- * @param   pTaskState    Pointer to the task state.
+ * @param   pDevIns       PDM device instance.
+ * @param   fIs24Bit      Flag whether the 24bit SG format is used.
  * @param   GCSGList      Guest physical address of S/G list.
  * @param   cEntries      Number of list entries to read.
  * @param   pSGEList      Pointer to 32-bit S/G list storage.
  */
-static void buslogicR3ReadSGEntries(PBUSLOGICTASKSTATE pTaskState, RTGCPHYS GCSGList, uint32_t cEntries, SGE32 *pSGEList)
-{
-    PPDMDEVINS  pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
-    SGE24       aSGE24[32];
-    Assert(cEntries <= RT_ELEMENTS(aSGE24));
-
+static void buslogicR3ReadSGEntries(PPDMDEVINS pDevIns, bool fIs24Bit, RTGCPHYS GCSGList,
+                                    uint32_t cEntries, SGE32 *pSGEList)
+{
     /* Read the S/G entries. Convert 24-bit entries to 32-bit format. */
-    if (pTaskState->fIs24Bit)
-    {
+    if (fIs24Bit)
+    {
+        SGE24 aSGE24[32];
+        Assert(cEntries <= RT_ELEMENTS(aSGE24));
+
         Log2(("Converting %u 24-bit S/G entries to 32-bit\n", cEntries));
         PDMDevHlpPhysRead(pDevIns, GCSGList, &aSGE24, cEntries * sizeof(SGE24));
@@ -1358,31 +1375,35 @@
 
 /**
- * Allocate data buffer.
+ * Determines the size of th guest data buffer.
  *
  * @returns VBox status code.
- * @param   pTaskState    Pointer to the task state.
- */
-static int buslogicR3DataBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
-{
-    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
-    uint32_t   cbDataCCB;
-    uint32_t   u32PhysAddrCCB;
+ * @param   pDevIns       PDM device instance.
+ * @param   pCCBGuest     The CCB of the guest.
+ * @param   fIs24Bit      Flag whether the 24bit SG format is used.
+ * @para    cbSGEntry     Size of one SG entry in bytes.
+ * @param   pcbBuf        Where to store the size of the guest data buffer on success.
+ */
+static int buslogicR3QueryDataBufferSize(PPDMDEVINS pDevIns, PCCBU pCCBGuest, bool fIs24Bit, size_t *pcbBuf)
+{
+    int rc = VINF_SUCCESS;
+    uint32_t cbDataCCB;
+    uint32_t u32PhysAddrCCB;
+    size_t cbBuf = 0;
 
     /* Extract the data length and physical address from the CCB. */
-    if (pTaskState->fIs24Bit)
-    {
-        u32PhysAddrCCB  = ADDR_TO_U32(pTaskState->CommandControlBlockGuest.o.aPhysAddrData);
-        cbDataCCB       = LEN_TO_U32(pTaskState->CommandControlBlockGuest.o.acbData);
+    if (fIs24Bit)
+    {
+        u32PhysAddrCCB  = ADDR_TO_U32(pCCBGuest->o.aPhysAddrData);
+        cbDataCCB       = LEN_TO_U32(pCCBGuest->o.acbData);
     }
     else
     {
-        u32PhysAddrCCB  = pTaskState->CommandControlBlockGuest.n.u32PhysAddrData;
-        cbDataCCB       = pTaskState->CommandControlBlockGuest.n.cbData;
-    }
-
-    if (   (pTaskState->CommandControlBlockGuest.c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)
+        u32PhysAddrCCB  = pCCBGuest->n.u32PhysAddrData;
+        cbDataCCB       = pCCBGuest->n.cbData;
+    }
+
+    if (   (pCCBGuest->c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)
         && cbDataCCB)
     {
-        /** @todo Check following assumption and what residual means. */
         /*
          * The BusLogic adapter can handle two different data buffer formats.
@@ -1391,13 +1412,12 @@
          * scatter gather list which describes the buffer.
          */
-        if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
-            || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
+        if (   (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
+            || (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
         {
             uint32_t cScatterGatherGCRead;
             uint32_t iScatterGatherEntry;
             SGE32    aScatterGatherReadGC[32]; /* A buffer for scatter gather list entries read from guest memory. */
-            uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
+            uint32_t cScatterGatherGCLeft = cbDataCCB / (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
             RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
-            size_t cbDataToTransfer = 0;
 
             /* Count number of bytes to transfer. */
@@ -1409,118 +1429,112 @@
                 cScatterGatherGCLeft -= cScatterGatherGCRead;
 
-                buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
+                buslogicR3ReadSGEntries(pDevIns, fIs24Bit, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
 
                 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
-                {
-                    RTGCPHYS    GCPhysAddrDataBase;
-
-                    Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
-
-                    GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
-                    cbDataToTransfer += aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
-
-                    Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n",
-                         __FUNCTION__, GCPhysAddrDataBase,
-                         aScatterGatherReadGC[iScatterGatherEntry].cbSegment));
-                }
+                    cbBuf += aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
 
                 /* Set address to the next entries to read. */
-                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
+                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
             } while (cScatterGatherGCLeft > 0);
 
-            Log(("%s: cbDataToTransfer=%d\n", __FUNCTION__, cbDataToTransfer));
-
-            /* Allocate buffer */
-            pTaskState->DataSeg.cbSeg = cbDataToTransfer;
-            pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
-            if (!pTaskState->DataSeg.pvSeg)
-                return VERR_NO_MEMORY;
-
-            /* Copy the data if needed */
-            if (   (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
-                || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN))
-            {
-                cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
-                GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
-                uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
-
-                do
-                {
-                    cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
-                                            ? cScatterGatherGCLeft
-                                            : RT_ELEMENTS(aScatterGatherReadGC);
-                    cScatterGatherGCLeft -= cScatterGatherGCRead;
-
-                    buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
-
-                    for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
-                    {
-                        RTGCPHYS    GCPhysAddrDataBase;
-
-                        Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
-
-                        GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
-                        cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
-
-                        Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
-
-                        PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
-                        pbData += cbDataToTransfer;
-                    }
-
-                    /* Set address to the next entries to read. */
-                    GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
-                } while (cScatterGatherGCLeft > 0);
-            }
-
-        }
-        else if (   pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
-                 || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
-        {
-            /* The buffer is not scattered. */
-            RTGCPHYS GCPhysAddrDataBase = u32PhysAddrCCB;
-
-            AssertMsg(GCPhysAddrDataBase != 0, ("Physical address is 0\n"));
-
-            pTaskState->DataSeg.cbSeg = cbDataCCB;
-            pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
-            if (!pTaskState->DataSeg.pvSeg)
-                return VERR_NO_MEMORY;
-
-            Log(("Non scattered buffer:\n"));
-            Log(("u32PhysAddrData=%#x\n", u32PhysAddrCCB));
-            Log(("cbData=%u\n", cbDataCCB));
-            Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase));
-
-            /* Copy the data into the buffer. */
-            PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
-        }
-    }
-
-    return VINF_SUCCESS;
-}
-
-/**
- * Free allocated resources used for the scatter gather list.
- *
- * @returns nothing.
- * @param   pTaskState    Pointer to the task state.
- */
-static void buslogicR3DataBufferFree(PBUSLOGICTASKSTATE pTaskState)
-{
-    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
+            Log(("%s: cbBuf=%d\n", __FUNCTION__, cbBuf));
+        }
+        else if (   pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
+                 || pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
+            cbBuf = cbDataCCB;
+    }
+
+    if (RT_SUCCESS(rc))
+        *pcbBuf = cbBuf;
+
+    return rc;
+}
+
+/**
+ * Copy from guest to host memory worker.
+ *
+ * @copydoc{BUSLOGICR3MEMCOPYCALLBACK}
+ */
+static DECLCALLBACK(void) buslogicR3CopyBufferFromGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
+                                                              size_t cbCopy, size_t *pcbSkip)
+{
+    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
+    cbCopy   -= cbSkipped;
+    GCPhys   += cbSkipped;
+    *pcbSkip -= cbSkipped;
+
+    while (cbCopy)
+    {
+        size_t cbSeg = cbCopy;
+        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
+
+        AssertPtr(pvSeg);
+        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
+        GCPhys += cbSeg;
+        cbCopy -= cbSeg;
+    }
+}
+
+/**
+ * Copy from host to guest memory worker.
+ *
+ * @copydoc{BUSLOGICR3MEMCOPYCALLBACK}
+ */
+static DECLCALLBACK(void) buslogicR3CopyBufferToGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
+                                                            size_t cbCopy, size_t *pcbSkip)
+{
+    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
+    cbCopy   -= cbSkipped;
+    GCPhys   += cbSkipped;
+    *pcbSkip -= cbSkipped;
+
+    while (cbCopy)
+    {
+        size_t cbSeg = cbCopy;
+        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
+
+        AssertPtr(pvSeg);
+        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
+        GCPhys += cbSeg;
+        cbCopy -= cbSeg;
+    }
+}
+
+/**
+ * Walks the guest S/G buffer calling the given copy worker for every buffer.
+ *
+ * @returns The amout of bytes actually copied.
+ * @param   pThis                  Pointer to the Buslogic device state.
+ * @param   pReq                   Pointe to the request state.
+ * @param   pfnCopyWorker          The copy method to apply for each guest buffer.
+ * @param   pSgBuf                 The host S/G buffer.
+ * @param   cbSkip                 How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy                 How many bytes to copy.
+ */
+static size_t buslogicR3SgBufWalker(PBUSLOGIC pThis, PBUSLOGICREQ pReq,
+                                    PBUSLOGICR3MEMCOPYCALLBACK pfnCopyWorker,
+                                    PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
+{
+    PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);
     uint32_t   cbDataCCB;
     uint32_t   u32PhysAddrCCB;
+    size_t     cbCopied = 0;
+
+    /*
+     * Add the amount to skip to the host buffer size to avoid a
+     * few conditionals later on.
+     */
+    cbCopy += cbSkip;
 
     /* Extract the data length and physical address from the CCB. */
-    if (pTaskState->fIs24Bit)
-    {
-        u32PhysAddrCCB  = ADDR_TO_U32(pTaskState->CommandControlBlockGuest.o.aPhysAddrData);
-        cbDataCCB       = LEN_TO_U32(pTaskState->CommandControlBlockGuest.o.acbData);
+    if (pReq->fIs24Bit)
+    {
+        u32PhysAddrCCB  = ADDR_TO_U32(pReq->CCBGuest.o.aPhysAddrData);
+        cbDataCCB       = LEN_TO_U32(pReq->CCBGuest.o.acbData);
     }
     else
     {
-        u32PhysAddrCCB  = pTaskState->CommandControlBlockGuest.n.u32PhysAddrData;
-        cbDataCCB       = pTaskState->CommandControlBlockGuest.n.cbData;
+        u32PhysAddrCCB  = pReq->CCBGuest.n.u32PhysAddrData;
+        cbDataCCB       = pReq->CCBGuest.n.cbData;
     }
 
@@ -1529,24 +1543,24 @@
      * returns no data, hence the buffer must be left alone!
      */
-    if (pTaskState->CommandControlBlockGuest.c.abCDB[0] == 0)
+    if (pReq->CCBGuest.c.abCDB[0] == 0)
         cbDataCCB = 0;
 #endif
 
-    LogFlowFunc(("pTaskState=%#p cbDataCCB=%u direction=%u cbSeg=%u\n", pTaskState, cbDataCCB,
-                 pTaskState->CommandControlBlockGuest.c.uDataDirection, pTaskState->DataSeg.cbSeg));
+    LogFlowFunc(("pReq=%#p cbDataCCB=%u direction=%u cbCopy=%zu\n", pReq, cbDataCCB,
+                 pReq->CCBGuest.c.uDataDirection, cbCopy));
 
     if (   (cbDataCCB > 0)
-        && (   (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
-            || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)))
-    {
-        if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
-            || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
+        && (   pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN
+            || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT
+            || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN))
+    {
+        if (   (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
+            || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
         {
             uint32_t cScatterGatherGCRead;
             uint32_t iScatterGatherEntry;
             SGE32    aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
-            uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;
+            uint32_t cScatterGatherGCLeft = cbDataCCB / (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
             RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB;
-            uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
 
             do
@@ -1557,29 +1571,32 @@
                 cScatterGatherGCLeft -= cScatterGatherGCRead;
 
-                buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);
-
-                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
+                buslogicR3ReadSGEntries(pDevIns, pReq->fIs24Bit, GCPhysAddrScatterGatherCurrent,
+                                        cScatterGatherGCRead, aScatterGatherReadGC);
+
+                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead && cbCopy > 0; iScatterGatherEntry++)
                 {
-                    RTGCPHYS    GCPhysAddrDataBase;
-                    size_t      cbDataToTransfer;
+                    RTGCPHYS GCPhysAddrDataBase;
+                    size_t   cbCopyThis;
 
                     Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
 
                     GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
-                    cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
-
-                    Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
-
-                    PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
-                    pbData += cbDataToTransfer;
+                    cbCopyThis = RT_MIN(cbCopy, aScatterGatherReadGC[iScatterGatherEntry].cbSegment);
+
+                    Log(("%s: GCPhysAddrDataBase=%RGp cbCopyThis=%zu\n", __FUNCTION__, GCPhysAddrDataBase, cbCopyThis));
+
+                    pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbCopyThis, &cbSkip);
+                    cbCopied += cbCopyThis;
+                    cbCopy   -= cbCopyThis;
                 }
 
                 /* Set address to the next entries to read. */
-                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;
-            } while (cScatterGatherGCLeft > 0);
-
-        }
-        else if (   pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
-                 || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
+                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32));
+            } while (   cScatterGatherGCLeft > 0
+                     && cbCopy > 0);
+
+        }
+        else if (   pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB
+                 || pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
         {
             /* The buffer is not scattered. */
@@ -1594,11 +1611,12 @@
 
             /* Copy the data into the guest memory. */
-            PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
-        }
-
-    }
+            pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, RT_MIN(cbDataCCB, cbCopy), &cbSkip);
+            cbCopied += RT_MIN(cbDataCCB, cbCopy);
+        }
+    }
+
     /* Update residual data length. */
-    if (   (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
-        || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
+    if (   (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)
+        || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
     {
         uint32_t    cbResidual;
@@ -1606,13 +1624,45 @@
         /** @todo we need to get the actual transfer length from the VSCSI layer?! */
         cbResidual = 0; //LEN_TO_U32(pTaskState->CCBGuest.acbData) - ???;
-        if (pTaskState->fIs24Bit)
-            U32_TO_LEN(pTaskState->CommandControlBlockGuest.o.acbData, cbResidual);
+        if (pReq->fIs24Bit)
+            U32_TO_LEN(pReq->CCBGuest.o.acbData, cbResidual);
         else
-            pTaskState->CommandControlBlockGuest.n.cbData = cbResidual;
-    }
-
-    RTMemFree(pTaskState->DataSeg.pvSeg);
-    pTaskState->DataSeg.pvSeg = NULL;
-    pTaskState->DataSeg.cbSeg = 0;
+            pReq->CCBGuest.n.cbData = cbResidual;
+    }
+
+    return cbCopied - RT_MIN(cbSkip, cbCopied);
+}
+
+/**
+ * Copies a data buffer into the S/G buffer set up by the guest.
+ *
+ * @returns Amount of bytes copied to the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pSgBuf         The S/G buffer to copy from.
+ * @param   cbSkip         How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy         How many bytes to copy.
+ */
+static size_t buslogicR3CopySgBufToGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf,
+                                         size_t cbSkip, size_t cbCopy)
+{
+    return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferToGuestWorker,
+                                 pSgBuf, cbSkip, cbCopy);
+}
+
+/**
+ * Copies the guest S/G buffer into a host data buffer.
+ *
+ * @returns Amount of bytes copied from the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pSgBuf         The S/G buffer to copy into.
+ * @param   cbSkip         How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy         How many bytes to copy.
+ */
+static size_t buslogicR3CopySgBufFromGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf,
+                                           size_t cbSkip, size_t cbCopy)
+{
+    return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferFromGuestWorker,
+                                 pSgBuf, cbSkip, cbCopy);
 }
 
@@ -1635,17 +1685,17 @@
  *
  * @returns nothing.
- * @param   pTaskState   Pointer to the task state.
+ * @param   pReq         Pointer to the request state.
  * @param   fCopy        If sense data should be copied to guest memory.
  */
-static void buslogicR3SenseBufferFree(PBUSLOGICTASKSTATE pTaskState, bool fCopy)
+static void buslogicR3SenseBufferFree(PBUSLOGICREQ pReq, bool fCopy)
 {
     uint32_t    cbSenseBuffer;
 
-    cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
+    cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData);
 
     /* Copy the sense buffer into guest memory if requested. */
     if (fCopy && cbSenseBuffer)
     {
-        PPDMDEVINS  pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
+        PPDMDEVINS  pDevIns = pReq->pTargetDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
         RTGCPHYS    GCPhysAddrSenseBuffer;
 
@@ -1654,18 +1704,18 @@
          * the CCB, right after the variable-length CDB.
          */
-        if (pTaskState->fIs24Bit)
-        {
-            GCPhysAddrSenseBuffer  = pTaskState->MailboxGuest.u32PhysAddrCCB;
-            GCPhysAddrSenseBuffer += pTaskState->CommandControlBlockGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB);
+        if (pReq->fIs24Bit)
+        {
+            GCPhysAddrSenseBuffer  = pReq->GCPhysAddrCCB;
+            GCPhysAddrSenseBuffer += pReq->CCBGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB);
         }
         else
-            GCPhysAddrSenseBuffer = pTaskState->CommandControlBlockGuest.n.u32PhysAddrSenseData;
-
-        Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, pTaskState->pbSenseBuffer));
-        PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pTaskState->pbSenseBuffer, cbSenseBuffer);
-    }
-
-    RTMemFree(pTaskState->pbSenseBuffer);
-    pTaskState->pbSenseBuffer = NULL;
+            GCPhysAddrSenseBuffer = pReq->CCBGuest.n.u32PhysAddrSenseData;
+
+        Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, pReq->pbSenseBuffer));
+        PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pReq->pbSenseBuffer, cbSenseBuffer);
+    }
+
+    RTMemFree(pReq->pbSenseBuffer);
+    pReq->pbSenseBuffer = NULL;
 }
 
@@ -1674,16 +1724,15 @@
  *
  * @returns VBox status code.
- * @param   pTaskState    Pointer to the task state.
- * @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary.
- */
-static int buslogicR3SenseBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
-{
-    pTaskState->pbSenseBuffer = NULL;
-
-    uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
+ * @param   pReq    Pointer to the task state.
+ */
+static int buslogicR3SenseBufferAlloc(PBUSLOGICREQ pReq)
+{
+    pReq->pbSenseBuffer = NULL;
+
+    uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData);
     if (cbSenseBuffer)
     {
-        pTaskState->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);
-        if (!pTaskState->pbSenseBuffer)
+        pReq->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);
+        if (!pReq->pbSenseBuffer)
             return VERR_NO_MEMORY;
     }
@@ -2488,51 +2537,61 @@
 #ifdef IN_RING3
 
-static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pBusLogic)
-{
-    int rc;
-    PBUSLOGICTASKSTATE pTaskState;
-    uint32_t           uTargetDevice;
-
-    rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState);
-    AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
-
-    pTaskState->fBIOS = true;
-
-    rc = vboxscsiSetupRequest(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, &uTargetDevice);
+static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pThis)
+{
+    uint32_t uTargetDevice;
+    uint32_t uLun;
+    uint8_t *pbCdb;
+    size_t cbCdb;
+    size_t cbBuf;
+
+    int rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice);
     AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc);
 
-    pTaskState->PDMScsiRequest.pvUser = pTaskState;
-
-    pTaskState->CTX_SUFF(pTargetDevice) = &pBusLogic->aDeviceStates[uTargetDevice];
-
-    if (!pTaskState->CTX_SUFF(pTargetDevice)->fPresent)
-    {
-        /* Device is not present. */
-        AssertMsg(pTaskState->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,
-                    ("Device is not present but command is not inquiry\n"));
-
-        SCSIINQUIRYDATA ScsiInquiryData;
-
-        memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA));
-        ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
-        ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
-
-        memcpy(pBusLogic->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
-
-        rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, SCSI_STATUS_OK);
-        AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
-
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-    }
-    else
-    {
-        LogFlowFunc(("before increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests));
-        ASMAtomicIncU32(&pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests);
-        LogFlowFunc(("after increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests));
-
-        rc = pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector,
-                                                                                        &pTaskState->PDMScsiRequest);
-        AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
-    }
+    if (   uTargetDevice < RT_ELEMENTS(pThis->aDeviceStates)
+        && pThis->aDeviceStates[uTargetDevice].pDrvBase)
+    {
+        PBUSLOGICDEVICE pTgtDev = &pThis->aDeviceStates[uTargetDevice];
+        PDMMEDIAEXIOREQ hIoReq;
+        PBUSLOGICREQ pReq;
+
+        rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
+                                                 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
+        AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
+
+        pReq->fBIOS = true;
+        pReq->hIoReq = hIoReq;
+        pReq->pTargetDevice = pTgtDev;
+
+        ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+
+        rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
+                                                       pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN,
+                                                       cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
+        if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+        {
+            uint8_t u8ScsiSts = pReq->u8ScsiSts;
+            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
+            rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts);
+        }
+        else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+            rc = VINF_SUCCESS;
+
+        return rc;
+    }
+
+    /* Device is not present. */
+    AssertMsg(pbCdb[0] == SCSI_INQUIRY,
+              ("Device is not present but command is not inquiry\n"));
+
+    SCSIINQUIRYDATA ScsiInquiryData;
+
+    memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA));
+    ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
+    ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
+
+    memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
+
+    rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK);
+    AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
 
     return rc;
@@ -2715,56 +2774,4 @@
 }
 
-static void buslogicR3WarningDiskFull(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("BusLogic#%d: Host disk full\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_DISKFULL",
-                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
-    AssertRC(rc);
-}
-
-static void buslogicR3WarningFileTooBig(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("BusLogic#%d: File too big\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_FILETOOBIG",
-                                    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"));
-    AssertRC(rc);
-}
-
-static void buslogicR3WarningISCSI(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("BusLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_ISCSIDOWN",
-                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
-    AssertRC(rc);
-}
-
-static void buslogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc)
-{
-    int rc2;
-    LogRel(("BusLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
-    rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_UNKNOWN",
-                                     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);
-    AssertRC(rc2);
-}
-
-static void buslogicR3RedoSetWarning(PBUSLOGIC pThis, int rc)
-{
-    if (rc == VERR_DISK_FULL)
-        buslogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns));
-    else if (rc == VERR_FILE_TOO_BIG)
-        buslogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns));
-    else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
-    {
-        /* iSCSI connection abort (first error) or failure to reestablish
-         * connection (second error). Pause VM. On resume we'll retry. */
-        buslogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns));
-    }
-    else if (rc != VERR_VD_DEK_MISSING)
-        buslogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
-}
-
 
 /**
@@ -2841,82 +2848,51 @@
 }
 
-static DECLCALLBACK(int) buslogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
-                                                              int rcCompletion, bool fRedo, int rcReq)
-{
-    RT_NOREF(pInterface);
-    int rc;
-    PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)pSCSIRequest->pvUser;
-    PBUSLOGICDEVICE pBusLogicDevice = pTaskState->CTX_SUFF(pTargetDevice);
-    PBUSLOGIC pBusLogic = pBusLogicDevice->CTX_SUFF(pBusLogic);
-
-    LogFlowFunc(("before decrement %u\n", pBusLogicDevice->cOutstandingRequests));
-    ASMAtomicDecU32(&pBusLogicDevice->cOutstandingRequests);
-    LogFlowFunc(("after decrement %u\n", pBusLogicDevice->cOutstandingRequests));
-
-    if (fRedo)
-    {
-        if (!pTaskState->fBIOS)
-        {
-            buslogicR3DataBufferFree(pTaskState);
-
-            if (pTaskState->pbSenseBuffer)
-                buslogicR3SenseBufferFree(pTaskState, false /* fCopy */);
-        }
-
-        /* Add to the list. */
-        do
-        {
-            pTaskState->pRedoNext = ASMAtomicReadPtrT(&pBusLogic->pTasksRedoHead, PBUSLOGICTASKSTATE);
-        } while (!ASMAtomicCmpXchgPtr(&pBusLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
-
-        /* Suspend the VM if not done already. */
-        if (!ASMAtomicXchgBool(&pBusLogic->fRedo, true))
-            buslogicR3RedoSetWarning(pBusLogic, rcReq);
+static int buslogicR3ReqComplete(PBUSLOGIC pThis, PBUSLOGICREQ pReq, int rcReq)
+{
+    RT_NOREF(rcReq);
+    PBUSLOGICDEVICE pTgtDev = pReq->pTargetDevice;
+
+    LogFlowFunc(("before decrement %u\n", pTgtDev->cOutstandingRequests));
+    ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
+    LogFlowFunc(("after decrement %u\n", pTgtDev->cOutstandingRequests));
+
+    if (pReq->fBIOS)
+    {
+        int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pReq->u8ScsiSts);
+        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
     }
     else
     {
-        if (pTaskState->fBIOS)
-        {
-            rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, pSCSIRequest, rcCompletion);
-            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
-        }
+        if (pReq->pbSenseBuffer)
+            buslogicR3SenseBufferFree(pReq, (pReq->u8ScsiSts != SCSI_STATUS_OK));
+
+        if (pReq->u8ScsiSts == SCSI_STATUS_OK)
+            buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest,
+                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
+                                        BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
+                                        BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
+        else if (pReq->u8ScsiSts == SCSI_STATUS_CHECK_CONDITION)
+            buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest,
+                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
+                                        BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION,
+                                        BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
         else
-        {
-            buslogicR3DataBufferFree(pTaskState);
-
-            if (pTaskState->pbSenseBuffer)
-                buslogicR3SenseBufferFree(pTaskState, (rcCompletion != SCSI_STATUS_OK));
-
-            if (rcCompletion == SCSI_STATUS_OK)
-                buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
-                                            BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
-                                            BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
-                                            BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR);
-            else if (rcCompletion == SCSI_STATUS_CHECK_CONDITION)
-                buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
-                                            BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
-                                            BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION,
-                                            BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
-            else
-                AssertMsgFailed(("invalid completion status %d\n", rcCompletion));
-        }
+            AssertMsgFailed(("invalid completion status %d\n", pReq->u8ScsiSts));
+    }
+
 #ifdef LOG_ENABLED
-            buslogicR3DumpCCBInfo(&pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);
+    buslogicR3DumpCCBInfo(&pReq->CCBGuest, pReq->fIs24Bit);
 #endif
 
-        /* Remove task from the cache. */
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-    }
-
-    if (pBusLogicDevice->cOutstandingRequests == 0 && pBusLogic->fSignalIdle)
-        PDMDevHlpAsyncNotificationCompleted(pBusLogic->pDevInsR3);
+    if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle)
+        PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
 
     return VINF_SUCCESS;
 }
 
-static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
+static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
                                                        uint32_t *piInstance, uint32_t *piLUN)
 {
-    PBUSLOGICDEVICE pBusLogicDevice = PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface);
+    PBUSLOGICDEVICE pBusLogicDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaPort);
     PPDMDEVINS pDevIns = pBusLogicDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
 
@@ -2932,133 +2908,201 @@
 }
 
-static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
+ */
+static DECLCALLBACK(int) buslogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                    void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
+                                                    size_t cbCopy)
+{
+    RT_NOREF1(hIoReq);
+    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
+    PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc;
+
+    size_t cbCopied = 0;
+    if (RT_UNLIKELY(pReq->fBIOS))
+        cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy);
+    else
+        cbCopied = buslogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offDst, cbCopy);
+    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
+ */
+static DECLCALLBACK(int) buslogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                  void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
+                                                  size_t cbCopy)
+{
+    RT_NOREF1(hIoReq);
+    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
+    PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc;
+
+    size_t cbCopied = 0;
+    if (RT_UNLIKELY(pReq->fBIOS))
+        cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy);
+    else
+        cbCopied = buslogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offSrc, cbCopy);
+    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
+ */
+static DECLCALLBACK(int) buslogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                       void *pvIoReqAlloc, int rcReq)
+{
+    RT_NOREF(hIoReq);
+    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
+    buslogicR3ReqComplete(pTgtDev->CTX_SUFF(pBusLogic), (PBUSLOGICREQ)pvIoReqAlloc, rcReq);
+    return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
+ */
+static DECLCALLBACK(void) buslogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
+{
+    RT_NOREF3(hIoReq, pvIoReqAlloc, enmState);
+    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
+
+    switch (enmState)
+    {
+        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
+        {
+            /* Make sure the request is not accounted for so the VM can suspend successfully. */
+            uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
+            if (!cTasksActive && pTgtDev->CTX_SUFF(pBusLogic)->fSignalIdle)
+                PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pBusLogic)->pDevInsR3);
+            break;
+        }
+        case PDMMEDIAEXIOREQSTATE_ACTIVE:
+            /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
+            ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+            break;
+        default:
+            AssertMsgFailed(("Invalid request state given %u\n", enmState));
+    }
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
+ */
+static DECLCALLBACK(void) buslogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
+{
+    PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort);
+    PBUSLOGIC pThis = pTgtDev->CTX_SUFF(pBusLogic);
+
+    RT_NOREF(pThis); /** @todo */
+}
+
+static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB)
 {
     int rc = VINF_SUCCESS;
     uint8_t uTargetIdCCB;
-    PBUSLOGICDEVICE pTargetDevice;
+    CCBU CCBGuest;
 
     /* Fetch the CCB from guest memory. */
     /** @todo How much do we really have to read? */
-    RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
     PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
-                        &pTaskState->CommandControlBlockGuest, sizeof(CCB32));
-
-    uTargetIdCCB = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;
+                      &CCBGuest, sizeof(CCB32));
+
+    uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId;
     if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates)))
     {
-        pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB];
-        pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
+        PBUSLOGICDEVICE pTgtDev = &pBusLogic->aDeviceStates[uTargetIdCCB];
 
 #ifdef LOG_ENABLED
-        buslogicR3DumpCCBInfo(&pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);
+        buslogicR3DumpCCBInfo(&CCBGuest, pBusLogic->fMbxIs24Bit);
 #endif
 
-        /* Alloc required buffers. */
-        rc = buslogicR3DataBufferAlloc(pTaskState);
-        AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));
-
-        rc = buslogicR3SenseBufferAlloc(pTaskState);
-        AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
-
         /* Check if device is present on bus. If not return error immediately and don't process this further. */
-        if (!pBusLogic->aDeviceStates[uTargetIdCCB].fPresent)
-        {
-            buslogicR3DataBufferFree(pTaskState);
-
-            if (pTaskState->pbSenseBuffer)
-                buslogicR3SenseBufferFree(pTaskState, true);
-
-            buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
+        if (RT_LIKELY(pTgtDev->fPresent))
+        {
+            PDMMEDIAEXIOREQ hIoReq;
+            PBUSLOGICREQ pReq;
+            rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
+                                                     GCPhysAddrCCB, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
+            if (RT_SUCCESS(rc))
+            {
+                pReq->pTargetDevice = pTgtDev;
+                pReq->GCPhysAddrCCB = GCPhysAddrCCB;
+                pReq->fBIOS         = false;
+                pReq->hIoReq        = hIoReq;
+                pReq->fIs24Bit      = pBusLogic->fMbxIs24Bit;
+
+                /* Make a copy of the CCB */
+                memcpy(&pReq->CCBGuest, &CCBGuest, sizeof(CCBGuest));
+
+                /* Alloc required buffers. */
+                rc = buslogicR3SenseBufferAlloc(pReq);
+                AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
+
+                size_t cbBuf = 0;
+                rc = buslogicR3QueryDataBufferSize(pBusLogic->CTX_SUFF(pDevIns), &pReq->CCBGuest, pReq->fIs24Bit, &cbBuf);
+                AssertRC(rc);
+
+                uint32_t uLun = pReq->fIs24Bit ? pReq->CCBGuest.o.uLogicalUnit
+                                               : pReq->CCBGuest.n.uLogicalUnit;
+
+                PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN;
+                size_t cbSense = buslogicR3ConvertSenseBufferLength(CCBGuest.c.cbSenseData);
+
+                if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE;
+                else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE;
+                else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE;
+
+                ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+                rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
+                                                               &pReq->CCBGuest.c.abCDB[0], pReq->CCBGuest.c.cbCDB,
+                                                               enmXferDir, cbBuf, pReq->pbSenseBuffer, cbSense,
+                                                               &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
+                if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+                    buslogicR3ReqComplete(pBusLogic, pReq, rc);
+            }
+            else
+                buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
+                                              BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
+                                              BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
+                                              BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
+        }
+        else
+            buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
                                           BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
                                           BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
                                           BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
-
-            RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-        }
-        else
-        {
-            /* Setup SCSI request. */
-            pTaskState->PDMScsiRequest.uLogicalUnit = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uLogicalUnit
-                                                                           : pTaskState->CommandControlBlockGuest.n.uLogicalUnit;
-
-            if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)
-                pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_UNKNOWN;
-            else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
-                pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
-            else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
-                pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE;
-            else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)
-                pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE;
-            else
-                AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.c.uDataDirection));
-
-            pTaskState->PDMScsiRequest.cbCDB                 = pTaskState->CommandControlBlockGuest.c.cbCDB;
-            pTaskState->PDMScsiRequest.pbCDB                 = pTaskState->CommandControlBlockGuest.c.abCDB;
-            if (pTaskState->DataSeg.cbSeg)
-            {
-                pTaskState->PDMScsiRequest.cbScatterGather       = (uint32_t)pTaskState->DataSeg.cbSeg;
-                pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;
-                pTaskState->PDMScsiRequest.paScatterGatherHead   = &pTaskState->DataSeg;
-            }
-            else
-            {
-                pTaskState->PDMScsiRequest.cbScatterGather       = 0;
-                pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;
-                pTaskState->PDMScsiRequest.paScatterGatherHead   = NULL;
-            }
-            pTaskState->PDMScsiRequest.cbSenseBuffer         = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);
-            pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pbSenseBuffer;
-            pTaskState->PDMScsiRequest.pvUser                = pTaskState;
-
-            ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
-            rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
-            AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
-        }
     }
     else
-    {
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-
-        buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
+        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
                                       BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER,
                                       BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
                                       BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
-    }
 
     return rc;
 }
 
-static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
-{
-    int             rc = VINF_SUCCESS;
-    uint8_t         uTargetIdCCB;
-    PBUSLOGICDEVICE pTargetDevice;
-    RTGCPHYS        GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
+static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB)
+{
+    int      rc = VINF_SUCCESS;
+    uint8_t  uTargetIdCCB;
+    CCBU     CCBGuest;
 
     PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
-                      &pTaskState->CommandControlBlockGuest, sizeof(CCB32));
-
-    uTargetIdCCB = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;
+                      &CCBGuest, sizeof(CCB32));
+
+    uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId;
     if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates)))
-    {
-        pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB];
-        pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice;
-
-        buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
+        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
                                       BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_ABORT_QUEUE_GENERATED,
                                       BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
                                       BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND);
-
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-    }
     else
-    {
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-
-        buslogicR3SendIncomingMailbox(pBusLogic, pTaskState,
+        buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest,
                                       BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER,
                                       BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD,
                                       BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR);
-    }
 
     return rc;
@@ -3071,7 +3115,7 @@
  * @returns Mailbox guest physical address.
  * @param   pBusLogic    Pointer to the BusLogic instance data.
- * @param   pTaskStat    Pointer to the task state being set up.
- */
-static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState)
+ * @param   pMbx         Pointer to the mailbox to read into.
+ */
+static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, PMailbox32 pMbx)
 {
     RTGCPHYS    GCMailbox;
@@ -3083,11 +3127,11 @@
         GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox24));
         PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &Mbx24, sizeof(Mailbox24));
-        pTaskState->MailboxGuest.u32PhysAddrCCB    = ADDR_TO_U32(Mbx24.aPhysAddrCCB);
-        pTaskState->MailboxGuest.u.out.uActionCode = Mbx24.uCmdState;
+        pMbx->u32PhysAddrCCB    = ADDR_TO_U32(Mbx24.aPhysAddrCCB);
+        pMbx->u.out.uActionCode = Mbx24.uCmdState;
     }
     else
     {
         GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox32));
-        PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &pTaskState->MailboxGuest, sizeof(Mailbox32));
+        PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, pMbx, sizeof(Mailbox32));
     }
 
@@ -3103,14 +3147,7 @@
 static int buslogicR3ProcessMailboxNext(PBUSLOGIC pBusLogic)
 {
-    PBUSLOGICTASKSTATE pTaskState = NULL;
-    RTGCPHYS           GCPhysAddrMailboxCurrent;
-    int rc;
-
-    rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState);
-    AssertMsgReturn(RT_SUCCESS(rc) && (pTaskState != NULL), ("Failed to get task state from cache\n"), rc);
-
-    pTaskState->fBIOS     = false;
-    pTaskState->fIs24Bit  = pBusLogic->fMbxIs24Bit;
-    pTaskState->cbSGEntry = pBusLogic->fMbxIs24Bit ? sizeof(SGE24) : sizeof(SGE32);
+    RTGCPHYS     GCPhysAddrMailboxCurrent;
+    Mailbox32    MailboxGuest;
+    int rc = VINF_SUCCESS;
 
     if (!pBusLogic->fStrictRoundRobinMode)
@@ -3122,9 +3159,9 @@
         {
             /* Fetch mailbox from guest memory. */
-            GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic,pTaskState);
+            GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest);
 
             /* Check the next mailbox. */
             buslogicR3OutgoingMailboxAdvance(pBusLogic);
-        } while (   pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE
+        } while (   MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE
                  && uMailboxPosCur != pBusLogic->uMailboxOutgoingPositionCurrent);
     }
@@ -3132,5 +3169,5 @@
     {
         /* Fetch mailbox from guest memory. */
-        GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic,pTaskState);
+        GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest);
     }
 
@@ -3141,30 +3178,29 @@
      * log entry.
      */
-    if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE)
+    if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE)
     {
         Log(("No loaded mailbox left\n"));
-        RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
         return VERR_NO_DATA;
     }
 
-    LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB));
+    LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB));
 #ifdef LOG_ENABLED
-    buslogicR3DumpMailboxInfo(&pTaskState->MailboxGuest, true);
+    buslogicR3DumpMailboxInfo(&MailboxGuest, true);
 #endif
 
     /* We got the mailbox, mark it as free in the guest. */
     uint8_t uActionCode = BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE;
-    unsigned uCodeOffs = pTaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
+    unsigned uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);
     PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxCurrent + uCodeOffs, &uActionCode, sizeof(uActionCode));
 
-    if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
-        rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, pTaskState);
-    else if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
+    if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
+        rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB);
+    else if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)
     {
         LogFlow(("Aborting mailbox\n"));
-        rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, pTaskState);
+        rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB);
     }
     else
-        AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", pTaskState->MailboxGuest.u.out.uActionCode));
+        AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", MailboxGuest.u.out.uActionCode));
 
     AssertRC(rc);
@@ -3197,43 +3233,4 @@
 }
 
-/**
- * Kicks the controller to process pending tasks after the VM was resumed
- * or loaded from a saved state.
- *
- * @returns nothing.
- * @param   pThis    The BusLogic device instance.
- */
-static void buslogicR3Kick(PBUSLOGIC pThis)
-{
-    if (pThis->fRedo)
-    {
-        pThis->fRedo = false;
-        if (pThis->VBoxSCSI.fBusy)
-        {
-
-            /* The BIOS had a request active when we got suspended. Resume it. */
-            int rc = buslogicR3PrepareBIOSSCSIRequest(pThis);
-            AssertRC(rc);
-        }
-        else
-        {
-            /* Queue all pending tasks again. */
-            PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
-
-            pThis->pTasksRedoHead = NULL;
-
-            while (pTaskState)
-            {
-                PBUSLOGICTASKSTATE pCur = pTaskState;
-
-                int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pCur);
-                AssertRC(rc);
-
-                pTaskState = pTaskState->pRedoNext;
-            }
-        }
-    }
-}
-
 /** @callback_method_impl{FNSSMDEVLIVEEXEC}  */
 static DECLCALLBACK(int) buslogicR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
@@ -3253,4 +3250,5 @@
 {
     PBUSLOGIC pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
+    uint32_t cReqsSuspended = 0;
 
     /* Every device first. */
@@ -3263,4 +3261,7 @@
         SSMR3PutBool(pSSM, pDevice->fPresent);
         SSMR3PutU32(pSSM, pDevice->cOutstandingRequests);
+
+        if (pDevice->fPresent)
+            cReqsSuspended += pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
     }
     /* Now the main device state. */
@@ -3292,29 +3293,37 @@
     vboxscsiR3SaveExec(&pBusLogic->VBoxSCSI, pSSM);
 
-    /*
-     * Save the physical addresses of the command control blocks of still pending tasks.
-     * They are processed again on resume.
-     *
-     * The number of pending tasks needs to be determined first.
-     */
-    uint32_t cTasks = 0;
-
-    PBUSLOGICTASKSTATE pTaskState = pBusLogic->pTasksRedoHead;
-    if (pBusLogic->fRedo)
-    {
-        while (pTaskState)
-        {
-            cTasks++;
-            pTaskState = pTaskState->pRedoNext;
-        }
-    }
-    SSMR3PutU32(pSSM, cTasks);
-
-    /* Write the address of every task now. */
-    pTaskState = pBusLogic->pTasksRedoHead;
-    while (pTaskState)
-    {
-        SSMR3PutU32(pSSM, pTaskState->MailboxGuest.u32PhysAddrCCB);
-        pTaskState = pTaskState->pRedoNext;
+    SSMR3PutU32(pSSM, cReqsSuspended);
+
+    /* Save the physical CCB address of all suspended requests. */
+    for (unsigned i = 0; i < RT_ELEMENTS(pBusLogic->aDeviceStates) && cReqsSuspended; i++)
+    {
+        PBUSLOGICDEVICE pDevice = &pBusLogic->aDeviceStates[i];
+        if (pDevice->fPresent)
+        {
+            uint32_t cThisReqsSuspended = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
+
+            cReqsSuspended -= cThisReqsSuspended;
+            if (cThisReqsSuspended)
+            {
+                PDMMEDIAEXIOREQ hIoReq;
+                PBUSLOGICREQ pReq;
+                int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq,
+                                                                           (void **)&pReq);
+                AssertRCBreak(rc);
+
+                for (;;)
+                {
+                    SSMR3PutU32(pSSM, (uint32_t)pReq->GCPhysAddrCCB);
+
+                    cThisReqsSuspended--;
+                    if (!cThisReqsSuspended)
+                        break;
+
+                    rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq,
+                                                                          &hIoReq, (void **)&pReq);
+                    AssertRCBreak(rc);
+                }
+            }
+        }
     }
 
@@ -3329,5 +3338,26 @@
 
     buslogicR3RegisterISARange(pThis, pThis->uISABaseCode);
-    buslogicR3Kick(pThis);
+
+    /* Kick of any requests we might need to redo. */
+    if (pThis->VBoxSCSI.fBusy)
+    {
+
+        /* The BIOS had a request active when we got suspended. Resume it. */
+        int rc = buslogicR3PrepareBIOSSCSIRequest(pThis);
+        AssertRC(rc);
+    }
+    else if (pThis->cReqsRedo)
+    {
+        for (unsigned i = 0; i < pThis->cReqsRedo; i++)
+        {
+            int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pThis->paGCPhysAddrCCBRedo[i]);
+            AssertRC(rc);
+        }
+
+        RTMemFree(pThis->paGCPhysAddrCCBRedo);
+        pThis->paGCPhysAddrCCBRedo = NULL;
+        pThis->cReqsRedo = 0;
+    }
+
     return VINF_SUCCESS;
 }
@@ -3401,7 +3431,4 @@
     }
 
-    if (pBusLogic->VBoxSCSI.fBusy)
-        pBusLogic->fRedo = true;
-
     if (uVersion > BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING)
     {
@@ -3412,25 +3439,23 @@
 
         if (cTasks)
-            pBusLogic->fRedo = true;
-
-        for (uint32_t i = 0; i < cTasks; i++)
-        {
-            PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)RTMemCacheAlloc(pBusLogic->hTaskCache);
-            if (!pTaskState)
+        {
+            pBusLogic->paGCPhysAddrCCBRedo = (PRTGCPHYS)RTMemAllocZ(cTasks * sizeof(RTGCPHYS));
+            if (RT_LIKELY(pBusLogic->paGCPhysAddrCCBRedo))
             {
+                pBusLogic->cReqsRedo = cTasks;
+
+                for (uint32_t i = 0; i < cTasks; i++)
+                {
+                    uint32_t u32PhysAddrCCB;
+
+                    rc = SSMR3GetU32(pSSM, &u32PhysAddrCCB);
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    pBusLogic->paGCPhysAddrCCBRedo[i] = u32PhysAddrCCB;
+                }
+            }
+            else
                 rc = VERR_NO_MEMORY;
-                break;
-            }
-
-            rc = SSMR3GetU32(pSSM, &pTaskState->MailboxGuest.u32PhysAddrCCB);
-            if (RT_FAILURE(rc))
-            {
-                RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);
-                break;
-            }
-
-            /* Link into the list. */
-            pTaskState->pRedoNext = pBusLogic->pTasksRedoHead;
-            pBusLogic->pTasksRedoHead = pTaskState;
         }
     }
@@ -3458,5 +3483,5 @@
 static DECLCALLBACK(int) buslogicR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
 {
-    PBUSLOGICDEVICE pDevice = PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface);
+    PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, ILed);
     if (iLUN == 0)
     {
@@ -3473,7 +3498,8 @@
 static DECLCALLBACK(void *) buslogicR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
 {
-    PBUSLOGICDEVICE pDevice = PDMIBASE_2_PBUSLOGICDEVICE(pInterface);
+    PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IBase);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase);
-    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed);
     return NULL;
@@ -3490,5 +3516,5 @@
 static DECLCALLBACK(int) buslogicR3StatusQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
 {
-    PBUSLOGIC pBusLogic = PDMILEDPORTS_2_PBUSLOGIC(pInterface);
+    PBUSLOGIC pBusLogic = RT_FROM_MEMBER(pInterface, BUSLOGIC, ILeds);
     if (iLUN < BUSLOGIC_MAX_DEVICES)
     {
@@ -3505,5 +3531,5 @@
 static DECLCALLBACK(void *) buslogicR3StatusQueryInterface(PPDMIBASE pInterface, const char *pszIID)
 {
-    PBUSLOGIC pThis = PDMIBASE_2_PBUSLOGIC(pInterface);
+    PBUSLOGIC pThis = RT_FROM_MEMBER(pInterface, BUSLOGIC, IBase);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
@@ -3736,7 +3762,7 @@
 
 /**
- * Common worker for ahciR3Suspend and ahciR3PowerOff.
- */
-static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns, bool fPowerOff)
+ * Common worker for buslogicR3Suspend and buslogicR3PowerOff.
+ */
+static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
 {
     PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
@@ -3748,37 +3774,5 @@
     {
         ASMAtomicWriteBool(&pThis->fSignalIdle, false);
-
         AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n"));
-
-        if (pThis->fRedo)
-        {
-            if (fPowerOff)
-            {
-                /* Free tasks which would have been queued again on resume. */
-                PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
-
-                pThis->pTasksRedoHead = NULL;
-
-                while (pTaskState)
-                {
-                    PBUSLOGICTASKSTATE pFree;
-
-                    pFree = pTaskState;
-                    pTaskState = pTaskState->pRedoNext;
-
-                    RTMemCacheFree(pThis->hTaskCache, pFree);
-                }
-                pThis->fRedo = false;
-            }
-            else if (pThis->VBoxSCSI.fBusy)
-            {
-                /* Destroy the task because the BIOS interface has all necessary information. */
-                Assert(pThis->pTasksRedoHead->fBIOS);
-                Assert(!pThis->pTasksRedoHead->pRedoNext);
-
-                RTMemCacheFree(pThis->hTaskCache, pThis->pTasksRedoHead);
-                pThis->pTasksRedoHead = NULL;
-            }
-        }
     }
 }
@@ -3792,19 +3786,6 @@
 {
     Log(("buslogicR3Suspend\n"));
-    buslogicR3SuspendOrPowerOff(pDevIns, false /* fPoweroff */);
-}
-
-/**
- * Resume notification.
- *
- * @param   pDevIns     The device instance data.
- */
-static DECLCALLBACK(void) buslogicR3Resume(PPDMDEVINS pDevIns)
-{
-    Log(("buslogicR3Resume\n"));
-    PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC);
-    buslogicR3Kick(pThis);
-}
-
+    buslogicR3SuspendOrPowerOff(pDevIns);
+}
 
 /**
@@ -3832,7 +3813,8 @@
      * Zero some important members.
      */
-    pDevice->pDrvBase = NULL;
-    pDevice->fPresent = false;
-    pDevice->pDrvSCSIConnector = NULL;
+    pDevice->fPresent    = false;
+    pDevice->pDrvBase    = NULL;
+    pDevice->pDrvMedia   = NULL;
+    pDevice->pDrvMediaEx = NULL;
 }
 
@@ -3859,9 +3841,10 @@
     /* the usual paranoia */
     AssertRelease(!pDevice->pDrvBase);
-    AssertRelease(!pDevice->pDrvSCSIConnector);
+    AssertRelease(!pDevice->pDrvMedia);
+    AssertRelease(!pDevice->pDrvMediaEx);
     Assert(pDevice->iLUN == iLUN);
 
     /*
-     * Try attach the block device and get the interfaces,
+     * Try attach the SCSI driver and get the interfaces,
      * required as well as optional.
      */
@@ -3869,7 +3852,20 @@
     if (RT_SUCCESS(rc))
     {
-        /* Get SCSI connector interface. */
-        pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
-        AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
+        /* Query the media interface. */
+        pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
+        AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
+                        ("BusLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
+                        VERR_PDM_MISSING_INTERFACE);
+
+        /* Get the extended media interface. */
+        pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
+        AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
+                        ("BusLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
+                        VERR_PDM_MISSING_INTERFACE);
+
+        rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ));
+        AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!"),
+                               pDevice->iLUN);
+
         pDevice->fPresent = true;
     }
@@ -3879,6 +3875,8 @@
     if (RT_FAILURE(rc))
     {
-        pDevice->pDrvBase = NULL;
-        pDevice->pDrvSCSIConnector = NULL;
+        pDevice->fPresent    = false;
+        pDevice->pDrvBase    = NULL;
+        pDevice->pDrvMedia   = NULL;
+        pDevice->pDrvMediaEx = NULL;
     }
     return rc;
@@ -3945,5 +3943,5 @@
 {
     Log(("buslogicR3PowerOff\n"));
-    buslogicR3SuspendOrPowerOff(pDevIns, true /* fPoweroff */);
+    buslogicR3SuspendOrPowerOff(pDevIns);
 }
 
@@ -3963,27 +3961,4 @@
     PDMR3CritSectDelete(&pThis->CritSectIntr);
 
-    /*
-     * Free all tasks which are still hanging around
-     * (Power off after the VM was suspended).
-     */
-    if (pThis->fRedo)
-    {
-        /* Free tasks which would have been queued again on resume. */
-        PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
-
-        pThis->pTasksRedoHead = NULL;
-
-        while (pTaskState)
-        {
-            PBUSLOGICTASKSTATE pFree;
-
-            pFree = pTaskState;
-            pTaskState = pTaskState->pRedoNext;
-
-            RTMemCacheFree(pThis->hTaskCache, pFree);
-        }
-        pThis->fRedo = false;
-    }
-
     if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
     {
@@ -3992,8 +3967,5 @@
     }
 
-    int rc = RTMemCacheDestroy(pThis->hTaskCache);
-    AssertMsgRC(rc, ("Destroying task cache failed rc=%Rrc\n", rc));
-
-    return rc;
+    return VINF_SUCCESS;
 }
 
@@ -4012,5 +3984,4 @@
      * Init instance data (do early because of constructor).
      */
-    pThis->hTaskCache = NIL_RTMEMCACHE;
     pThis->pDevInsR3 = pDevIns;
     pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
@@ -4113,11 +4084,4 @@
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("BusLogic cannot register ISA I/O handlers"));
 
-    /* Initialize task cache. */
-    rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(BUSLOGICTASKSTATE), 0, UINT32_MAX,
-                          NULL, NULL, NULL, 0);
-    if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("BusLogic: Failed to initialize task cache\n"));
-
     /* Initialize task queue. */
     rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 5, 0,
@@ -4163,8 +4127,13 @@
         pDevice->pBusLogicRC = PDMINS_2_DATA_RCPTR(pDevIns);
         pDevice->Led.u32Magic = PDMLED_MAGIC;
-        pDevice->IBase.pfnQueryInterface           = buslogicR3DeviceQueryInterface;
-        pDevice->ISCSIPort.pfnSCSIRequestCompleted = buslogicR3DeviceSCSIRequestCompleted;
-        pDevice->ISCSIPort.pfnQueryDeviceLocation  = buslogicR3QueryDeviceLocation;
-        pDevice->ILed.pfnQueryStatusLed            = buslogicR3DeviceQueryStatusLed;
+        pDevice->IBase.pfnQueryInterface                 = buslogicR3DeviceQueryInterface;
+        pDevice->IMediaPort.pfnQueryDeviceLocation       = buslogicR3QueryDeviceLocation;
+        pDevice->IMediaExPort.pfnIoReqCompleteNotify     = buslogicR3IoReqCompleteNotify;
+        pDevice->IMediaExPort.pfnIoReqCopyFromBuf        = buslogicR3IoReqCopyFromBuf;
+        pDevice->IMediaExPort.pfnIoReqCopyToBuf          = buslogicR3IoReqCopyToBuf;
+        pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
+        pDevice->IMediaExPort.pfnIoReqStateChanged       = buslogicR3IoReqStateChanged;
+        pDevice->IMediaExPort.pfnMediumEjected           = buslogicR3MediumEjected;
+        pDevice->ILed.pfnQueryStatusLed                  = buslogicR3DeviceQueryStatusLed;
 
         /* Attach SCSI driver. */
@@ -4172,7 +4141,21 @@
         if (RT_SUCCESS(rc))
         {
-            /* Get SCSI connector interface. */
-            pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
-            AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
+            /* Query the media interface. */
+            pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
+            AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
+                            ("Buslogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
+                            VERR_PDM_MISSING_INTERFACE);
+
+            /* Get the extended media interface. */
+            pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
+            AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
+                            ("Buslogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
+                            VERR_PDM_MISSING_INTERFACE);
+
+            rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ));
+            if (RT_FAILURE(rc))
+                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+                                           N_("Buslogic configuration error: LUN#%u: Failed to set I/O request size!"),
+                                           pDevice->iLUN);
 
             pDevice->fPresent = true;
@@ -4180,6 +4163,8 @@
         else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
         {
-            pDevice->pDrvBase = NULL;
-            pDevice->fPresent = false;
+            pDevice->fPresent    = false;
+            pDevice->pDrvBase    = NULL;
+            pDevice->pDrvMedia   = NULL;
+            pDevice->pDrvMediaEx = NULL;
             rc = VINF_SUCCESS;
             Log(("BusLogic: no driver attached to device %s\n", szName));
@@ -4265,5 +4250,5 @@
     buslogicR3Suspend,
     /* pfnResume */
-    buslogicR3Resume,
+    NULL,
     /* pfnAttach */
     buslogicR3Attach,
Index: /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 64223)
+++ /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 64224)
@@ -80,17 +80,27 @@
 *********************************************************************************************************************************/
 
-/**
- * I/O buffer copy worker.
+/** Pointer to the device instance data of the LsiLogic emulation. */
+typedef struct LSILOGICSCSI *PLSILOGICSCSI;
+
+#ifdef IN_RING3
+/**
+ * Memory buffer callback.
  *
  * @returns nothing.
- * @param   pDevIns     Device instance data.
- * @param   GCPhysIoBuf Guest physical address of the I/O buffer.
- * @param   pvBuf       R3 buffer pointer.
- * @param   cbCopy      How much to copy.
- */
-typedef DECLCALLBACK(void) FNLSILOGICIOBUFCOPY(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
-                                               void *pvBuf, size_t cbCopy);
-/** Pointer to a I/O buffer copy worker. */
-typedef FNLSILOGICIOBUFCOPY *PFNLSILOGICIOBUFCOPY;
+ * @param   pThis    The LsiLogic controller instance.
+ * @param   GCPhys   The guest physical address of the memory buffer.
+ * @param   pSgBuf   The pointer to the host R3 S/G buffer.
+ * @param   cbCopy   How many bytes to copy between the two buffers.
+ * @param   pcbSkip  Initially contains the amount of bytes to skip
+ *                   starting from the guest physical address before
+ *                   accessing the S/G buffer and start copying data.
+ *                   On return this contains the remaining amount if
+ *                   cbCopy < *pcbSkip or 0 otherwise.
+ */
+typedef DECLCALLBACK(void) LSILOGICR3MEMCOPYCALLBACK(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
+                                                     size_t *pcbSkip);
+/** Pointer to a memory copy buffer callback. */
+typedef LSILOGICR3MEMCOPYCALLBACK *PLSILOGICR3MEMCOPYCALLBACK;
+#endif
 
 /**
@@ -138,5 +148,5 @@
 {
     /** Pointer to the owning lsilogic device instance. - R3 pointer */
-    R3PTRTYPE(struct LSILOGICSCSI *)  pLsiLogicR3;
+    R3PTRTYPE(PLSILOGICSCSI)      pLsiLogicR3;
 
     /** LUN of the device. */
@@ -151,12 +161,16 @@
     /** Our base interface. */
     PDMIBASE                      IBase;
-    /** SCSI port interface. */
-    PDMISCSIPORT                  ISCSIPort;
+    /** Media port interface. */
+    PDMIMEDIAPORT                 IMediaPort;
+    /** Extended media port interface. */
+    PDMIMEDIAEXPORT               IMediaExPort;
     /** Led interface. */
     PDMILEDPORTS                  ILed;
     /** Pointer to the attached driver's base interface. */
     R3PTRTYPE(PPDMIBASE)          pDrvBase;
-    /** Pointer to the underlying SCSI connector interface. */
-    R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector;
+    /** Pointer to the attached driver's media interface. */
+    R3PTRTYPE(PPDMIMEDIA)         pDrvMedia;
+    /** Pointer to the attached driver's extended media interface. */
+    R3PTRTYPE(PPDMIMEDIAEX)       pDrvMediaEx;
     /** The status LED state for this device. */
     PDMLED                        Led;
@@ -323,6 +337,4 @@
     VBOXSCSI                       VBoxSCSI;
 
-    /** Cache for allocated tasks. */
-    R3PTRTYPE(RTMEMCACHE)          hTaskCache;
     /** Status LUN: The base interface. */
     PDMIBASE                       IBase;
@@ -375,6 +387,4 @@
 
 } LSILOGISCSI;
-/** Pointer to the device instance data of the LsiLogic emulation. */
-typedef LSILOGICSCSI *PLSILOGICSCSI;
 
 /**
@@ -384,4 +394,6 @@
 typedef struct LSILOGICREQ
 {
+    /** I/O request handle. */
+    PDMMEDIAEXIOREQ            hIoReq;
     /** Next in the redo list. */
     PLSILOGICREQ               pRedoNext;
@@ -390,8 +402,4 @@
     /** The message request from the guest. */
     MptRequestUnion            GuestRequest;
-    /** Reply message if the request produces one. */
-    MptReplyUnion              IOCReply;
-    /** SCSI request structure for the SCSI driver. */
-    PDMSCSIREQUEST             PDMScsiRequest;
     /** Address of the message request frame in guests memory.
      *  Used to read the S/G entries in the second step. */
@@ -401,16 +409,10 @@
     /** Chain offset */
     uint32_t                   cChainOffset;
-    /** Segment describing the I/O buffer. */
-    RTSGSEG                    SegIoBuf;
-    /** Additional memory allocation for this task. */
-    void                      *pvAlloc;
-    /** Siize of the allocation. */
-    size_t                     cbAlloc;
-    /** Number of times we had too much memory allocated for the request. */
-    unsigned                   cAllocTooMuch;
     /** Pointer to the sense buffer. */
     uint8_t                    abSenseBuffer[18];
     /** Flag whether the request was issued from the BIOS. */
     bool                       fBIOS;
+    /** SCSI status code. */
+    uint8_t                    u8ScsiSts;
 } LSILOGICREQ;
 
@@ -1857,14 +1859,67 @@
 
 /**
+ * Copy from guest to host memory worker.
+ *
+ * @copydoc{LSILOGICR3MEMCOPYCALLBACK}
+ */
+static DECLCALLBACK(void) lsilogicR3CopyBufferFromGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
+                                                              size_t cbCopy, size_t *pcbSkip)
+{
+    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
+    cbCopy   -= cbSkipped;
+    GCPhys   += cbSkipped;
+    *pcbSkip -= cbSkipped;
+
+    while (cbCopy)
+    {
+        size_t cbSeg = cbCopy;
+        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
+
+        AssertPtr(pvSeg);
+        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
+        GCPhys += cbSeg;
+        cbCopy -= cbSeg;
+    }
+}
+
+/**
+ * Copy from host to guest memory worker.
+ *
+ * @copydoc{LSILOGICR3MEMCOPYCALLBACK}
+ */
+static DECLCALLBACK(void) lsilogicR3CopyBufferToGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
+                                                            size_t cbCopy, size_t *pcbSkip)
+{
+    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
+    cbCopy   -= cbSkipped;
+    GCPhys   += cbSkipped;
+    *pcbSkip -= cbSkipped;
+
+    while (cbCopy)
+    {
+        size_t cbSeg = cbCopy;
+        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
+
+        AssertPtr(pvSeg);
+        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
+        GCPhys += cbSeg;
+        cbCopy -= cbSeg;
+    }
+}
+
+/**
  * Walks the guest S/G buffer calling the given copy worker for every buffer.
  *
- * @returns nothing.
- * @param   pDevIns      Device instance data.
- * @param   pLsiReq      LSI request state.
- * @param   cbCopy       How much bytes to copy.
- * @param   pfnIoBufCopy Copy worker to call.
- */
-static void lsilogicSgBufWalker(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy,
-                                PFNLSILOGICIOBUFCOPY pfnIoBufCopy)
+ * @returns The amout of bytes actually copied.
+ * @param   pThis                  Pointer to the LsiLogic device state.
+ * @param   pLsiReq                LSI request state.
+ * @param   pfnCopyWorker          The copy method to apply for each guest buffer.
+ * @param   pSgBuf                 The host S/G buffer.
+ * @param   cbSkip                 How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy                 How many bytes to copy.
+ */
+static size_t lsilogicSgBufWalker(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq,
+                                  PLSILOGICR3MEMCOPYCALLBACK pfnCopyWorker,
+                                  PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
 {
     bool     fEndOfList = false;
@@ -1872,5 +1927,12 @@
     RTGCPHYS GCPhysSegmentStart = pLsiReq->GCPhysSgStart;
     uint32_t cChainOffsetNext = pLsiReq->cChainOffset;
-    uint8_t *pbBuf = (uint8_t *)pLsiReq->SegIoBuf.pvSeg;
+    PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);
+    size_t cbCopied = 0;
+
+    /*
+     * Add the amount to skip to the host buffer size to avoid a
+     * few conditionals later on.
+     */
+    cbCopy += cbSkip;
 
     /* Go through the list until we reach the end. */
@@ -1900,5 +1962,5 @@
                 && SGEntry.Simple32.fEndOfList
                 && SGEntry.Simple32.fEndOfBuffer)
-                return;
+                return cbCopied - RT_MIN(cbSkip, cbCopied);
 
             uint32_t cbCopyThis           = SGEntry.Simple32.u24Length;
@@ -1913,8 +1975,7 @@
                 GCPhysSgEntryNext += sizeof(MptSGEntrySimple32);
 
-
-            pfnIoBufCopy(pDevIns, GCPhysAddrDataBuffer, pbBuf, cbCopyThis);
-            pbBuf  += cbCopyThis;
+            pfnCopyWorker(pThis, GCPhysAddrDataBuffer, pSgBuf, cbCopyThis, &cbSkip);
             cbCopy -= cbCopyThis;
+            cbCopied += cbCopyThis;
 
             /* Check if we reached the end of the list. */
@@ -1947,144 +2008,85 @@
         }
     } /* while (!fEndOfList) */
-}
-
-static DECLCALLBACK(void) lsilogicCopyFromGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
-                                                void *pvBuf, size_t cbCopy)
-{
-    PDMDevHlpPhysRead(pDevIns, GCPhysIoBuf, pvBuf, cbCopy);
-}
-
-static DECLCALLBACK(void) lsilogicCopyToGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf,
-                                              void *pvBuf, size_t cbCopy)
-{
-    PDMDevHlpPCIPhysWrite(pDevIns, GCPhysIoBuf, pvBuf, cbCopy);
-}
-
-/**
- * Copy from a guest S/G buffer to the I/O buffer.
- *
- * @returns nothing.
- * @param   pDevIns      Device instance data.
- * @param   pLsiReq      Request data.
- * @param   cbCopy       How much to copy over.
- */
-DECLINLINE(void) lsilogicCopyFromSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy)
-{
-    lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyFromGuest);
-}
-
-/**
- * Copy from an I/O buffer to the guest S/G buffer.
- *
- * @returns nothing.
- * @param   pDevIns      Device instance data.
- * @param   pLsiReq      Request data.
- * @param   cbCopy       How much to copy over.
- */
-DECLINLINE(void) lsilogicCopyToSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy)
-{
-    lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyToGuest);
-}
-
-/**
- * Allocates memory for the given request using already allocated memory if possible.
- *
- * @returns Pointer to the memory or NULL on failure
- * @param   pLsiReq     The request to allocate memory for.
- * @param   cb          The amount of memory to allocate.
- */
-static void *lsilogicReqMemAlloc(PLSILOGICREQ pLsiReq, size_t cb)
-{
-    if (pLsiReq->cbAlloc > cb)
-        pLsiReq->cAllocTooMuch++;
-    else if (pLsiReq->cbAlloc < cb)
-    {
-        if (pLsiReq->cbAlloc)
-            RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc);
-
-        pLsiReq->cbAlloc = RT_ALIGN_Z(cb, _4K);
-        pLsiReq->pvAlloc = RTMemPageAlloc(pLsiReq->cbAlloc);
-        pLsiReq->cAllocTooMuch = 0;
-        if (RT_UNLIKELY(!pLsiReq->pvAlloc))
-            pLsiReq->cbAlloc = 0;
-    }
-
-    return pLsiReq->pvAlloc;
-}
-
-/**
- * Frees memory allocated for the given request.
- *
- * @returns nothing.
- * @param   pLsiReq     The request.
- */
-static void lsilogicReqMemFree(PLSILOGICREQ pLsiReq)
-{
-    if (pLsiReq->cAllocTooMuch >= LSILOGIC_MAX_ALLOC_TOO_MUCH)
-    {
-        RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc);
-        pLsiReq->cbAlloc = 0;
-        pLsiReq->cAllocTooMuch = 0;
-    }
-}
-
-/**
- * Allocate I/O memory and copies the guest buffer for writes.
- *
- * @returns VBox status code.
- * @param   pDevIns     The device instance.
- * @param   pLsiReq     The request state.
- * @param   cbTransfer  Amount of bytes to allocate.
- */
-static int lsilogicIoBufAllocate(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq,
-                                 size_t cbTransfer)
-{
-    uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
-
-    AssertMsg(   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
-              || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
-              || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE,
-              ("Allocating I/O memory for a non I/O request is not allowed\n"));
-
-    pLsiReq->SegIoBuf.pvSeg = lsilogicReqMemAlloc(pLsiReq, cbTransfer);
-    if (!pLsiReq->SegIoBuf.pvSeg)
-        return VERR_NO_MEMORY;
-
-    pLsiReq->SegIoBuf.cbSeg = cbTransfer;
-    if (   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
-        || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
-        lsilogicCopyFromSgBuf(pDevIns, pLsiReq, cbTransfer);
-
-    return VINF_SUCCESS;
-}
-
-/**
- * Frees the I/O memory of the given request and updates the guest buffer if necessary.
- *
- * @returns nothing.
- * @param   pDevIns      The device instance.
- * @param   pLsiReq      The request state.
- * @param   fCopyToGuest Flag whether to update the guest buffer if necessary.
- *                       Nothing is copied if false even if the request was a read.
- */
-static void lsilogicIoBufFree(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq,
-                              bool fCopyToGuest)
-{
-    uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
-
-    AssertMsg(   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE
-              || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
-              || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE,
-              ("Allocating I/O memory for a non I/O request is not allowed\n"));
-
-    if (   (   uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ
-            || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
-        && fCopyToGuest)
-        lsilogicCopyToSgBuf(pDevIns, pLsiReq, pLsiReq->SegIoBuf.cbSeg);
-
-    lsilogicReqMemFree(pLsiReq);
-    pLsiReq->SegIoBuf.pvSeg = NULL;
-    pLsiReq->SegIoBuf.cbSeg = 0;
-}
+
+    return cbCopied - RT_MIN(cbSkip, cbCopied);
+}
+
+/**
+ * Copies a data buffer into the S/G buffer set up by the guest.
+ *
+ * @returns Amount of bytes copied to the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pSgBuf         The S/G buffer to copy from.
+ * @param   cbSkip         How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy         How many bytes to copy.
+ */
+static size_t lsilogicR3CopySgBufToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf,
+                                         size_t cbSkip, size_t cbCopy)
+{
+    return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferToGuestWorker,
+                               pSgBuf, cbSkip, cbCopy);
+}
+
+/**
+ * Copies the guest S/G buffer into a host data buffer.
+ *
+ * @returns Amount of bytes copied from the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pSgBuf         The S/G buffer to copy into.
+ * @param   cbSkip         How many bytes to skip in advance before starting to copy.
+ * @param   cbCopy         How many bytes to copy.
+ */
+static size_t lsilogicR3CopySgBufFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf,
+                                           size_t cbSkip, size_t cbCopy)
+{
+    return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferFromGuestWorker,
+                               pSgBuf, cbSkip, cbCopy);
+}
+
+#if 0 /* unused */
+/**
+ * Copy a simple memory buffer to the guest memory buffer.
+ *
+ * @returns Amount of bytes copied to the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pvSrc          The buffer to copy from.
+ * @param   cbSrc          How many bytes to copy.
+ * @param   cbSkip         How many bytes to skip initially.
+ */
+static size_t lsilogicR3CopyBufferToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, const void *pvSrc,
+                                          size_t cbSrc, size_t cbSkip)
+{
+    RTSGSEG Seg;
+    RTSGBUF SgBuf;
+    Seg.pvSeg = (void *)pvSrc;
+    Seg.cbSeg = cbSrc;
+    RTSgBufInit(&SgBuf, &Seg, 1);
+    return lsilogicR3CopySgBufToGuest(pThis, pReq, &SgBuf, cbSkip, cbSrc);
+}
+
+/**
+ * Copy a guest memry buffe into simple host memory buffer.
+ *
+ * @returns Amount of bytes copied to the guest.
+ * @param   pThis          The LsiLogic controller device instance.
+ * @param   pReq           Request structure.
+ * @param   pvSrc          The buffer to copy from.
+ * @param   cbSrc          How many bytes to copy.
+ * @param   cbSkip         How many bytes to skip initially.
+ */
+static size_t lsilogicR3CopyBufferFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, void *pvDst,
+                                            size_t cbDst, size_t cbSkip)
+{
+    RTSGSEG Seg;
+    RTSGBUF SgBuf;
+    Seg.pvSeg = (void *)pvDst;
+    Seg.cbSeg = cbDst;
+    RTSgBufInit(&SgBuf, &Seg, 1);
+    return lsilogicR3CopySgBufFromGuest(pThis, pReq, &SgBuf, cbSkip, cbDst);
+}
+#endif
 
 # ifdef LOG_ENABLED
@@ -2112,54 +2114,76 @@
 # endif
 
-static void lsilogicR3WarningDiskFull(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
-                                    N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
-    AssertRC(rc);
-}
-
-static void lsilogicR3WarningFileTooBig(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
-                                    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"));
-    AssertRC(rc);
-}
-
-static void lsilogicR3WarningISCSI(PPDMDEVINS pDevIns)
-{
-    int rc;
-    LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
-    rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
-                                    N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
-    AssertRC(rc);
-}
-
-static void lsilogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc)
-{
-    int rc2;
-    LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
-    rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
-                                     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);
-    AssertRC(rc2);
-}
-
-static void lsilogicR3RedoSetWarning(PLSILOGICSCSI pThis, int rc)
-{
-    if (rc == VERR_DISK_FULL)
-        lsilogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns));
-    else if (rc == VERR_FILE_TOO_BIG)
-        lsilogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns));
-    else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
-    {
-        /* iSCSI connection abort (first error) or failure to reestablish
-         * connection (second error). Pause VM. On resume we'll retry. */
-        lsilogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns));
-    }
-    else if (rc != VERR_VD_DEK_MISSING)
-        lsilogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
+/**
+ * Handles the completion of th given request.
+ *
+ * @returns nothing.
+ * @param   pThis                  Pointer to the LsiLogic device state.
+ * @param   pReq                   The request to complete.
+ * @param   rcReq                  Status code of the request.
+ */
+static void lsilogicR3ReqComplete(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, int rcReq)
+{
+    PLSILOGICDEVICE pTgtDev = pReq->pTargetDevice;
+
+    if (RT_UNLIKELY(pReq->fBIOS))
+    {
+        pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
+        int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, rcReq);
+        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
+    }
+    else
+    {
+        RTGCPHYS GCPhysAddrSenseBuffer;
+
+        GCPhysAddrSenseBuffer = pReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
+        GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32);
+
+        /* Copy the sense buffer over. */
+        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pReq->abSenseBuffer,
+                              RT_UNLIKELY(  pReq->GuestRequest.SCSIIO.u8SenseBufferLength
+                                          < sizeof(pReq->abSenseBuffer))
+                              ? pReq->GuestRequest.SCSIIO.u8SenseBufferLength
+                              : sizeof(pReq->abSenseBuffer));
+
+        if (RT_SUCCESS(rcReq) && RT_LIKELY(pReq->u8ScsiSts == SCSI_STATUS_OK))
+        {
+            uint32_t u32MsgCtx = pReq->GuestRequest.SCSIIO.u32MessageContext;
+
+            /* Free the request before posting completion. */
+            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
+            lsilogicR3FinishContextReply(pThis, u32MsgCtx);
+        }
+        else
+        {
+            MptReplyUnion IOCReply;
+            RT_ZERO(IOCReply);
+
+            /* The SCSI target encountered an error during processing post a reply. */
+            IOCReply.SCSIIOError.u8TargetID          = pReq->GuestRequest.SCSIIO.u8TargetID;
+            IOCReply.SCSIIOError.u8Bus               = pReq->GuestRequest.SCSIIO.u8Bus;
+            IOCReply.SCSIIOError.u8MessageLength     = 8;
+            IOCReply.SCSIIOError.u8Function          = pReq->GuestRequest.SCSIIO.u8Function;
+            IOCReply.SCSIIOError.u8CDBLength         = pReq->GuestRequest.SCSIIO.u8CDBLength;
+            IOCReply.SCSIIOError.u8SenseBufferLength = pReq->GuestRequest.SCSIIO.u8SenseBufferLength;
+            IOCReply.SCSIIOError.u8MessageFlags      = pReq->GuestRequest.SCSIIO.u8MessageFlags;
+            IOCReply.SCSIIOError.u32MessageContext   = pReq->GuestRequest.SCSIIO.u32MessageContext;
+            IOCReply.SCSIIOError.u8SCSIStatus        = pReq->u8ScsiSts;
+            IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
+            IOCReply.SCSIIOError.u16IOCStatus        = 0;
+            IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
+            IOCReply.SCSIIOError.u32TransferCount    = 0;
+            IOCReply.SCSIIOError.u32SenseCount       = sizeof(pReq->abSenseBuffer);
+            IOCReply.SCSIIOError.u32ResponseInfo     = 0;
+
+            /* Free the request before posting completion. */
+            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
+            lsilogicFinishAddressReply(pThis, &IOCReply, false);
+        }
+    }
+
+    ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
+
+    if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle)
+        PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
 }
 
@@ -2172,78 +2196,72 @@
  *
  * @returns VBox status code.
- * @param   pThis       Pointer to the LsiLogic device state.
- * @param   pLsiReq  Pointer to the task state data.
- */
-static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq)
-{
+ * @param   pThis                  Pointer to the LsiLogic device state.
+ * @param   GCPhysMessageFrameAddr Guest physical address where the request is located.
+ * @param   pGuestReq              The request read fro th guest memory.
+ */
+static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, RTGCPHYS GCPhysMessageFrameAddr,
+                                          PMptRequestUnion pGuestReq)
+{
+    MptReplyUnion IOCReply;
     int rc = VINF_SUCCESS;
 
 # ifdef LOG_ENABLED
-    lsilogicR3DumpSCSIIORequest(&pLsiReq->GuestRequest.SCSIIO);
+    lsilogicR3DumpSCSIIORequest(&pGuestReq->SCSIIO);
 # endif
 
-    pLsiReq->fBIOS = false;
-    pLsiReq->GCPhysSgStart = pLsiReq->GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest);
-    pLsiReq->cChainOffset  = pLsiReq->GuestRequest.SCSIIO.u8ChainOffset;
-    if (pLsiReq->cChainOffset)
-        pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest);
-
-    if (RT_LIKELY(   (pLsiReq->GuestRequest.SCSIIO.u8TargetID < pThis->cDeviceStates)
-                  && (pLsiReq->GuestRequest.SCSIIO.u8Bus == 0)))
-    {
-        PLSILOGICDEVICE pTargetDevice;
-        pTargetDevice = &pThis->paDeviceStates[pLsiReq->GuestRequest.SCSIIO.u8TargetID];
-
-        if (pTargetDevice->pDrvBase)
-        {
-
-            if (pLsiReq->GuestRequest.SCSIIO.u32DataLength)
+    if (RT_LIKELY(   (pGuestReq->SCSIIO.u8TargetID < pThis->cDeviceStates)
+                  && (pGuestReq->SCSIIO.u8Bus == 0)))
+    {
+        PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[pGuestReq->SCSIIO.u8TargetID];
+
+        if (pTgtDev->pDrvBase)
+        {
+            /* Allocate and prepare a new request. */
+            PDMMEDIAEXIOREQ hIoReq;
+            PLSILOGICREQ pLsiReq = NULL;
+            rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pLsiReq,
+                                                     pGuestReq->SCSIIO.u32MessageContext,
+                                                     PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
+            if (RT_SUCCESS(rc))
             {
-
-                rc = lsilogicIoBufAllocate(pThis->CTX_SUFF(pDevIns), pLsiReq,
-                                                           pLsiReq->GuestRequest.SCSIIO.u32DataLength);
-                AssertRC(rc); /** @todo Insufficient resources error. */
-            }
-
-            /* Setup the SCSI request. */
-            pLsiReq->pTargetDevice                        = pTargetDevice;
-            pLsiReq->PDMScsiRequest.uLogicalUnit          = pLsiReq->GuestRequest.SCSIIO.au8LUN[1];
-
-            uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
-
-            if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
-                pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_NONE;
-            else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE)
-                pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_TO_DEVICE;
-            else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ)
-                pLsiReq->PDMScsiRequest.uDataDirection    = PDMSCSIREQUESTTXDIR_FROM_DEVICE;
-
-            pLsiReq->PDMScsiRequest.cbCDB                 = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
-            pLsiReq->PDMScsiRequest.pbCDB                 = pLsiReq->GuestRequest.SCSIIO.au8CDB;
-            pLsiReq->PDMScsiRequest.cbScatterGather       = pLsiReq->GuestRequest.SCSIIO.u32DataLength;
-            if (pLsiReq->PDMScsiRequest.cbScatterGather)
-            {
-                pLsiReq->PDMScsiRequest.cScatterGatherEntries = 1;
-                pLsiReq->PDMScsiRequest.paScatterGatherHead   = &pLsiReq->SegIoBuf;
+                pLsiReq->hIoReq                 = hIoReq;
+                pLsiReq->pTargetDevice          = pTgtDev;
+                pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
+                pLsiReq->fBIOS                  = false;
+                pLsiReq->GCPhysSgStart          = GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest);
+                pLsiReq->cChainOffset           = pGuestReq->SCSIIO.u8ChainOffset;
+                if (pLsiReq->cChainOffset)
+                    pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest);
+                memcpy(&pLsiReq->GuestRequest, pGuestReq, sizeof(MptRequestUnion));
+                RT_BZERO(&pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer));
+
+                PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN;
+                uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control);
+
+                if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE;
+                else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE;
+                else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ)
+                    enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE;
+
+                ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+                rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pLsiReq->hIoReq, pLsiReq->GuestRequest.SCSIIO.au8LUN[1],
+                                                               &pLsiReq->GuestRequest.SCSIIO.au8CDB[0], pLsiReq->GuestRequest.SCSIIO.u8CDBLength,
+                                                               enmXferDir, pLsiReq->GuestRequest.SCSIIO.u32DataLength,
+                                                               &pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer), &pLsiReq->u8ScsiSts,
+                                                               30 * RT_MS_1SEC);
+                if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+                    lsilogicR3ReqComplete(pThis, pLsiReq, rc);
+
+                return VINF_SUCCESS;
             }
             else
-            {
-                pLsiReq->PDMScsiRequest.cScatterGatherEntries = 0;
-                pLsiReq->PDMScsiRequest.paScatterGatherHead   = NULL;
-            }
-            pLsiReq->PDMScsiRequest.cbSenseBuffer         = sizeof(pLsiReq->abSenseBuffer);
-            memset(pLsiReq->abSenseBuffer, 0, pLsiReq->PDMScsiRequest.cbSenseBuffer);
-            pLsiReq->PDMScsiRequest.pbSenseBuffer         = pLsiReq->abSenseBuffer;
-            pLsiReq->PDMScsiRequest.pvUser                = pLsiReq;
-
-            ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);
-            rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pLsiReq->PDMScsiRequest);
-            AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));
-            return VINF_SUCCESS;
+                IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
         }
         else
         {
             /* Device is not present report SCSI selection timeout. */
-            pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
+            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;
         }
     }
@@ -2251,8 +2269,8 @@
     {
         /* Report out of bounds target ID or bus. */
-        if (pLsiReq->GuestRequest.SCSIIO.u8Bus != 0)
-            pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;
+        if (pGuestReq->SCSIIO.u8Bus != 0)
+            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;
         else
-            pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;
+            IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;
     }
 
@@ -2262,30 +2280,29 @@
     {
         LogRel(("LsiLogic#%d: %d/%d (Bus/Target) doesn't exist\n", pThis->CTX_SUFF(pDevIns)->iInstance,
-                pLsiReq->GuestRequest.SCSIIO.u8TargetID, pLsiReq->GuestRequest.SCSIIO.u8Bus));
+                pGuestReq->SCSIIO.u8TargetID, pGuestReq->SCSIIO.u8Bus));
         /* Log the CDB too  */
         LogRel(("LsiLogic#%d: Guest issued CDB {%#x",
-                pThis->CTX_SUFF(pDevIns)->iInstance, pLsiReq->GuestRequest.SCSIIO.au8CDB[0]));
-        for (unsigned i = 1; i < pLsiReq->GuestRequest.SCSIIO.u8CDBLength; i++)
-            LogRel((", %#x", pLsiReq->GuestRequest.SCSIIO.au8CDB[i]));
+                pThis->CTX_SUFF(pDevIns)->iInstance, pGuestReq->SCSIIO.au8CDB[0]));
+        for (unsigned i = 1; i < pGuestReq->SCSIIO.u8CDBLength; i++)
+            LogRel((", %#x", pGuestReq->SCSIIO.au8CDB[i]));
         LogRel(("}\n"));
     }
 
     /* The rest is equal to both errors. */
-    pLsiReq->IOCReply.SCSIIOError.u8TargetID          = pLsiReq->GuestRequest.SCSIIO.u8TargetID;
-    pLsiReq->IOCReply.SCSIIOError.u8Bus               = pLsiReq->GuestRequest.SCSIIO.u8Bus;
-    pLsiReq->IOCReply.SCSIIOError.u8MessageLength     = sizeof(MptSCSIIOErrorReply) / 4;
-    pLsiReq->IOCReply.SCSIIOError.u8Function          = pLsiReq->GuestRequest.SCSIIO.u8Function;
-    pLsiReq->IOCReply.SCSIIOError.u8CDBLength         = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
-    pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength;
-    pLsiReq->IOCReply.SCSIIOError.u32MessageContext   = pLsiReq->GuestRequest.SCSIIO.u32MessageContext;
-    pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus        = SCSI_STATUS_OK;
-    pLsiReq->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED;
-    pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
-    pLsiReq->IOCReply.SCSIIOError.u32TransferCount    = 0;
-    pLsiReq->IOCReply.SCSIIOError.u32SenseCount       = 0;
-    pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
-
-    lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false);
-    RTMemCacheFree(pThis->hTaskCache, pLsiReq);
+    IOCReply.SCSIIOError.u8TargetID          = pGuestReq->SCSIIO.u8TargetID;
+    IOCReply.SCSIIOError.u8Bus               = pGuestReq->SCSIIO.u8Bus;
+    IOCReply.SCSIIOError.u8MessageLength     = sizeof(MptSCSIIOErrorReply) / 4;
+    IOCReply.SCSIIOError.u8Function          = pGuestReq->SCSIIO.u8Function;
+    IOCReply.SCSIIOError.u8CDBLength         = pGuestReq->SCSIIO.u8CDBLength;
+    IOCReply.SCSIIOError.u8SenseBufferLength = pGuestReq->SCSIIO.u8SenseBufferLength;
+    IOCReply.SCSIIOError.u32MessageContext   = pGuestReq->SCSIIO.u32MessageContext;
+    IOCReply.SCSIIOError.u8SCSIStatus        = SCSI_STATUS_OK;
+    IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED;
+    IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
+    IOCReply.SCSIIOError.u32TransferCount    = 0;
+    IOCReply.SCSIIOError.u32SenseCount       = 0;
+    IOCReply.SCSIIOError.u32ResponseInfo     = 0;
+
+    lsilogicFinishAddressReply(pThis, &IOCReply, false);
 
     return rc;
@@ -2294,101 +2311,11 @@
 
 /**
- * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
- */
-static DECLCALLBACK(int) lsilogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
-                                                              int rcCompletion, bool fRedo, int rcReq)
-{
-    RT_NOREF(pInterface);
-    PLSILOGICREQ    pLsiReq         = (PLSILOGICREQ)pSCSIRequest->pvUser;
-    PLSILOGICDEVICE pLsiLogicDevice = pLsiReq->pTargetDevice;
-    PLSILOGICSCSI   pThis           = pLsiLogicDevice->CTX_SUFF(pLsiLogic);
-
-    /* If the task failed but it is possible to redo it again after a suspend
-     * add it to the list. */
-    if (fRedo)
-    {
-        if (!pLsiReq->fBIOS && pLsiReq->PDMScsiRequest.cbScatterGather)
-            lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, false /* fCopyToGuest */);
-
-        /* Add to the list. */
-        do
-        {
-            pLsiReq->pRedoNext = ASMAtomicReadPtrT(&pThis->pTasksRedoHead, PLSILOGICREQ);
-        } while (!ASMAtomicCmpXchgPtr(&pThis->pTasksRedoHead, pLsiReq, pLsiReq->pRedoNext));
-
-        /* Suspend the VM if not done already. */
-        if (!ASMAtomicXchgBool(&pThis->fRedo, true))
-            lsilogicR3RedoSetWarning(pThis, rcReq);
-    }
-    else
-    {
-        if (RT_UNLIKELY(pLsiReq->fBIOS))
-        {
-            int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pSCSIRequest, rcCompletion);
-            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
-        }
-        else
-        {
-            RTGCPHYS GCPhysAddrSenseBuffer;
-
-            GCPhysAddrSenseBuffer = pLsiReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
-            GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32);
-
-            /* Copy the sense buffer over. */
-            PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pLsiReq->abSenseBuffer,
-                                  RT_UNLIKELY(  pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength
-                                              < pLsiReq->PDMScsiRequest.cbSenseBuffer)
-                                  ? pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength
-                                  : pLsiReq->PDMScsiRequest.cbSenseBuffer);
-
-            if (pLsiReq->PDMScsiRequest.cbScatterGather)
-                lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, true /* fCopyToGuest */);
-
-
-            if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
-                lsilogicR3FinishContextReply(pThis, pLsiReq->GuestRequest.SCSIIO.u32MessageContext);
-            else
-            {
-                /* The SCSI target encountered an error during processing post a reply. */
-                memset(&pLsiReq->IOCReply, 0, sizeof(MptReplyUnion));
-                pLsiReq->IOCReply.SCSIIOError.u8TargetID          = pLsiReq->GuestRequest.SCSIIO.u8TargetID;
-                pLsiReq->IOCReply.SCSIIOError.u8Bus               = pLsiReq->GuestRequest.SCSIIO.u8Bus;
-                pLsiReq->IOCReply.SCSIIOError.u8MessageLength     = 8;
-                pLsiReq->IOCReply.SCSIIOError.u8Function          = pLsiReq->GuestRequest.SCSIIO.u8Function;
-                pLsiReq->IOCReply.SCSIIOError.u8CDBLength         = pLsiReq->GuestRequest.SCSIIO.u8CDBLength;
-                pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength;
-                pLsiReq->IOCReply.SCSIIOError.u8MessageFlags      = pLsiReq->GuestRequest.SCSIIO.u8MessageFlags;
-                pLsiReq->IOCReply.SCSIIOError.u32MessageContext   = pLsiReq->GuestRequest.SCSIIO.u32MessageContext;
-                pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
-                pLsiReq->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
-                pLsiReq->IOCReply.SCSIIOError.u16IOCStatus        = 0;
-                pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
-                pLsiReq->IOCReply.SCSIIOError.u32TransferCount    = 0;
-                pLsiReq->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pLsiReq->abSenseBuffer);
-                pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
-
-                lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false);
-            }
-        }
-
-        RTMemCacheFree(pThis->hTaskCache, pLsiReq);
-    }
-
-    ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
-
-    if (pLsiLogicDevice->cOutstandingRequests == 0 && pThis->fSignalIdle)
-        PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3);
-
-    return VINF_SUCCESS;
-}
-
-/**
- * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation}
- */
-static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
+ * @interface_method_impl{PDMIMEDIA,pfnQueryDeviceLocation}
+ */
+static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
                                                        uint32_t *piInstance, uint32_t *piLUN)
 {
-    PLSILOGICDEVICE pLsiLogicDevice = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, ISCSIPort);
-    PPDMDEVINS pDevIns = pLsiLogicDevice->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaPort);
+    PPDMDEVINS pDevIns = pTgtDev->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
 
     AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
@@ -2398,8 +2325,99 @@
     *ppcszController = pDevIns->pReg->szName;
     *piInstance = pDevIns->iInstance;
-    *piLUN = pLsiLogicDevice->iLUN;
+    *piLUN = pTgtDev->iLUN;
 
     return VINF_SUCCESS;
 }
+
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
+ */
+static DECLCALLBACK(int) lsilogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                    void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
+                                                    size_t cbCopy)
+{
+    RT_NOREF1(hIoReq);
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
+    PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc;
+
+    size_t cbCopied = 0;
+    if (RT_UNLIKELY(pReq->fBIOS))
+        cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy);
+    else
+        cbCopied = lsilogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offDst, cbCopy);
+    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
+ */
+static DECLCALLBACK(int) lsilogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                  void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
+                                                  size_t cbCopy)
+{
+    RT_NOREF1(hIoReq);
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
+    PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc;
+
+    size_t cbCopied = 0;
+    if (RT_UNLIKELY(pReq->fBIOS))
+        cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy);
+    else
+        cbCopied = lsilogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offSrc, cbCopy);
+    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
+ */
+static DECLCALLBACK(int) lsilogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                       void *pvIoReqAlloc, int rcReq)
+{
+    RT_NOREF(hIoReq);
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
+    lsilogicR3ReqComplete(pTgtDev->CTX_SUFF(pLsiLogic), (PLSILOGICREQ)pvIoReqAlloc, rcReq);
+    return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
+ */
+static DECLCALLBACK(void) lsilogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+                                                      void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
+{
+    RT_NOREF3(hIoReq, pvIoReqAlloc, enmState);
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
+
+    switch (enmState)
+    {
+        case PDMMEDIAEXIOREQSTATE_SUSPENDED:
+        {
+            /* Make sure the request is not accounted for so the VM can suspend successfully. */
+            uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests);
+            if (!cTasksActive && pTgtDev->CTX_SUFF(pLsiLogic)->fSignalIdle)
+                PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pLsiLogic)->pDevInsR3);
+            break;
+        }
+        case PDMMEDIAEXIOREQSTATE_ACTIVE:
+            /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
+            ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+            break;
+        default:
+            AssertMsgFailed(("Invalid request state given %u\n", enmState));
+    }
+}
+
+/**
+ * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
+ */
+static DECLCALLBACK(void) lsilogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
+{
+    PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort);
+    PLSILOGICSCSI pThis = pTgtDev->CTX_SUFF(pLsiLogic);
+
+    RT_NOREF(pThis); /** @todo */
+}
+
 
 /**
@@ -3807,35 +3825,48 @@
 {
     int rc;
-    PLSILOGICREQ pLsiReq;
-    uint32_t           uTargetDevice;
-
-    rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
-    AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
-
-    pLsiReq->fBIOS = true;
-
-    rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, &uTargetDevice);
+    uint32_t uTargetDevice;
+    uint32_t uLun;
+    uint8_t *pbCdb;
+    size_t cbCdb;
+    size_t cbBuf;
+
+    rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice);
     AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc);
 
-    pLsiReq->PDMScsiRequest.pvUser = pLsiReq;
-
-    if (uTargetDevice < pThis->cDeviceStates)
-    {
-        pLsiReq->pTargetDevice = &pThis->paDeviceStates[uTargetDevice];
-
-        if (pLsiReq->pTargetDevice->pDrvBase)
-        {
-            ASMAtomicIncU32(&pLsiReq->pTargetDevice->cOutstandingRequests);
-
-            rc = pLsiReq->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pLsiReq->pTargetDevice->pDrvSCSIConnector,
-                                                                                  &pLsiReq->PDMScsiRequest);
-            AssertMsgRCReturn(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc), rc);
-            return VINF_SUCCESS;
-        }
+    if (   uTargetDevice < pThis->cDeviceStates
+        && pThis->paDeviceStates[uTargetDevice].pDrvBase)
+    {
+        PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[uTargetDevice];
+        PDMMEDIAEXIOREQ hIoReq;
+        PLSILOGICREQ pReq;
+
+        rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq,
+                                                 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
+        AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc);
+
+        pReq->fBIOS = true;
+        pReq->hIoReq = hIoReq;
+        pReq->pTargetDevice = pTgtDev;
+
+        ASMAtomicIncU32(&pTgtDev->cOutstandingRequests);
+
+        rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun,
+                                                       pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN,
+                                                       cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC);
+        if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+        {
+            uint8_t u8ScsiSts = pReq->u8ScsiSts;
+            pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq);
+            rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts);
+        }
+        else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
+            rc = VINF_SUCCESS;
+
+        return rc;
     }
 
     /* Device is not present. */
-    AssertMsg(pLsiReq->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,
-                ("Device is not present but command is not inquiry\n"));
+    AssertMsg(pbCdb[0] == SCSI_INQUIRY,
+              ("Device is not present but command is not inquiry\n"));
 
     SCSIINQUIRYDATA ScsiInquiryData;
@@ -3847,8 +3878,7 @@
     memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5);
 
-    rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, SCSI_STATUS_OK);
+    rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK);
     AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc);
 
-    RTMemCacheFree(pThis->hTaskCache, pLsiReq);
     return rc;
 }
@@ -4243,23 +4273,15 @@
                && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite))
         {
+            MptRequestUnion GuestRequest;
             uint32_t  u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead];
             RTGCPHYS  GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr,
                                                                           (u32RequestMessageFrameDesc & ~0x07));
 
-            PLSILOGICREQ pLsiReq;
-
-            /* Get new task state. */
-            rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);
-            AssertRC(rc);
-
-            pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;
-
             /* Read the message header from the guest first. */
-            PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr));
+            PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, sizeof(MptMessageHdr));
 
             /* Determine the size of the request. */
             uint32_t cbRequest = 0;
-
-            switch (pLsiReq->GuestRequest.Header.u8Function)
+            switch (GuestRequest.Header.u8Function)
             {
                 case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST:
@@ -4298,5 +4320,5 @@
                     break;
                 default:
-                    AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function));
+                    AssertMsgFailed(("Unknown function issued %u\n", GuestRequest.Header.u8Function));
                     lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION);
             }
@@ -4305,10 +4327,10 @@
             {
                 /* Read the complete message frame from guest memory now. */
-                PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest);
+                PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, cbRequest);
 
                 /* Handle SCSI I/O requests now. */
-                if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
+                if (GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)
                 {
-                   rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq);
+                   rc = lsilogicR3ProcessSCSIIORequest(pThis, GCPhysMessageFrameAddr, &GuestRequest);
                    AssertRC(rc);
                 }
@@ -4316,7 +4338,6 @@
                 {
                     MptReplyUnion Reply;
-                    rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply);
+                    rc = lsilogicR3ProcessMessageRequest(pThis, &GuestRequest.Header, &Reply);
                     AssertRC(rc);
-                    RTMemCacheFree(pThis->hTaskCache, pLsiReq);
                 }
 
@@ -4355,8 +4376,4 @@
 static void lsilogicR3Kick(PLSILOGICSCSI pThis)
 {
-    if (   pThis->VBoxSCSI.fBusy
-        && !pThis->fBiosReqPending)
-        pThis->fBiosReqPending = true;
-
     if (pThis->fNotificationSent)
     {
@@ -4408,5 +4425,46 @@
                   ("There are still outstanding requests on this device\n"));
         SSMR3PutU32(pSSM, pDevice->cOutstandingRequests);
-    }
+
+        /* Query all suspended requests and store them in the request queue. */
+        if (pDevice->pDrvMediaEx)
+        {
+            uint32_t cReqsRedo = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx);
+            if (cReqsRedo)
+            {
+                PDMMEDIAEXIOREQ hIoReq;
+                PLSILOGICREQ pReq;
+                int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq,
+                                                                           (void **)&pReq);
+                AssertRCBreak(rc);
+
+                for (;;)
+                {
+                    if (!pReq->fBIOS)
+                    {
+                        /* Write only the lower 32bit part of the address. */
+                        ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
+                                          pReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
+
+                        pThis->uRequestQueueNextEntryFreeWrite++;
+                        pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
+                    }
+                    else
+                    {
+                        AssertMsg(!pReq->pRedoNext, ("Only one BIOS task can be active!\n"));
+                        vboxscsiSetRequestRedo(&pThis->VBoxSCSI);
+                    }
+
+                    cReqsRedo--;
+                    if (!cReqsRedo)
+                        break;
+
+                    rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq,
+                                                                          &hIoReq, (void **)&pReq);
+                    AssertRCBreak(rc);
+                }
+            }
+        }
+    }
+
     /* Now the main device state. */
     SSMR3PutU32   (pSSM, pThis->enmState);
@@ -4924,5 +4982,6 @@
 
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase);
-    PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort);
     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed);
     return NULL;
@@ -5024,45 +5083,4 @@
 
         AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n"));
-
-        if (pThis->fRedo)
-        {
-            /*
-             * We have tasks which we need to redo. Put the message frame addresses
-             * into the request queue (we save the requests).
-             * Guest execution is suspended at this point so there is no race between us and
-             * lsilogicRegisterWrite.
-             */
-            PLSILOGICREQ pLsiReq = pThis->pTasksRedoHead;
-
-            pThis->pTasksRedoHead = NULL;
-
-            while (pLsiReq)
-            {
-                PLSILOGICREQ pFree;
-
-                if (!pLsiReq->fBIOS)
-                {
-                    /* Write only the lower 32bit part of the address. */
-                    ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
-                                      pLsiReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
-
-                    pThis->uRequestQueueNextEntryFreeWrite++;
-                    pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
-                }
-                else
-                {
-                    AssertMsg(!pLsiReq->pRedoNext, ("Only one BIOS task can be active!\n"));
-                    vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest);
-                }
-
-                pThis->fNotificationSent = true;
-
-                pFree = pLsiReq;
-                pLsiReq = pLsiReq->pRedoNext;
-
-                RTMemCacheFree(pThis->hTaskCache, pFree);
-            }
-            pThis->fRedo = false;
-        }
     }
 }
@@ -5113,5 +5131,6 @@
      */
     pDevice->pDrvBase = NULL;
-    pDevice->pDrvSCSIConnector = NULL;
+    pDevice->pDrvMedia = NULL;
+    pDevice->pDrvMediaEx = NULL;
 }
 
@@ -5134,5 +5153,6 @@
     /* the usual paranoia */
     AssertRelease(!pDevice->pDrvBase);
-    AssertRelease(!pDevice->pDrvSCSIConnector);
+    AssertRelease(!pDevice->pDrvMedia);
+    AssertRelease(!pDevice->pDrvMediaEx);
     Assert(pDevice->iLUN == iLUN);
 
@@ -5144,7 +5164,19 @@
     if (RT_SUCCESS(rc))
     {
-        /* Get SCSI connector interface. */
-        pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
-        AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
+        /* Query the media interface. */
+        pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
+        AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
+                        ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
+                        VERR_PDM_MISSING_INTERFACE);
+
+        /* Get the extended media interface. */
+        pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
+        AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
+                        ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
+                        VERR_PDM_MISSING_INTERFACE);
+
+        rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ));
+        AssertMsgRCReturn(rc, ("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"),
+                               pDevice->iLUN);
     }
     else
@@ -5154,5 +5186,6 @@
     {
         pDevice->pDrvBase = NULL;
-        pDevice->pDrvSCSIConnector = NULL;
+        pDevice->pDrvMedia = NULL;
+        pDevice->pDrvMediaEx = NULL;
     }
     return rc;
@@ -5247,11 +5280,4 @@
     pThis->paDeviceStates = NULL;
 
-    /* Destroy task cache. */
-    if (pThis->hTaskCache != NIL_RTMEMCACHE)
-    {
-        int rc = RTMemCacheDestroy(pThis->hTaskCache); AssertRC(rc);
-        pThis->hTaskCache = NIL_RTMEMCACHE;
-    }
-
     if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
     {
@@ -5278,5 +5304,4 @@
      * Initialize enought of the state to make the destructure not trip up.
      */
-    pThis->hTaskCache  = NIL_RTMEMCACHE;
     pThis->hEvtProcess = NIL_SUPSEMEVENT;
     pThis->fBiosReqPending = false;
@@ -5483,12 +5508,4 @@
         return rc;
 
-    /*
-     * Allocate task cache.
-     */
-    rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(LSILOGICREQ), 0, UINT32_MAX,
-                          NULL, NULL, NULL, 0);
-    if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Cannot create task cache"));
-
     if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
         pThis->cDeviceStates = pThis->cPorts * LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX;
@@ -5525,11 +5542,16 @@
 
         /* Initialize static parts of the device. */
-        pDevice->iLUN                              = i;
-        pDevice->pLsiLogicR3                       = pThis;
-        pDevice->Led.u32Magic                      = PDMLED_MAGIC;
-        pDevice->IBase.pfnQueryInterface           = lsilogicR3DeviceQueryInterface;
-        pDevice->ISCSIPort.pfnSCSIRequestCompleted = lsilogicR3DeviceSCSIRequestCompleted;
-        pDevice->ISCSIPort.pfnQueryDeviceLocation  = lsilogicR3QueryDeviceLocation;
-        pDevice->ILed.pfnQueryStatusLed            = lsilogicR3DeviceQueryStatusLed;
+        pDevice->iLUN                                    = i;
+        pDevice->pLsiLogicR3                             = pThis;
+        pDevice->Led.u32Magic                            = PDMLED_MAGIC;
+        pDevice->IBase.pfnQueryInterface                 = lsilogicR3DeviceQueryInterface;
+        pDevice->IMediaPort.pfnQueryDeviceLocation       = lsilogicR3QueryDeviceLocation;
+        pDevice->IMediaExPort.pfnIoReqCompleteNotify     = lsilogicR3IoReqCompleteNotify;
+        pDevice->IMediaExPort.pfnIoReqCopyFromBuf        = lsilogicR3IoReqCopyFromBuf;
+        pDevice->IMediaExPort.pfnIoReqCopyToBuf          = lsilogicR3IoReqCopyToBuf;
+        pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
+        pDevice->IMediaExPort.pfnIoReqStateChanged       = lsilogicR3IoReqStateChanged;
+        pDevice->IMediaExPort.pfnMediumEjected           = lsilogicR3MediumEjected;
+        pDevice->ILed.pfnQueryStatusLed                  = lsilogicR3DeviceQueryStatusLed;
 
         RTStrPrintf(szName, sizeof(szName), "Device%u", i);
@@ -5539,7 +5561,21 @@
         if (RT_SUCCESS(rc))
         {
-            /* Get SCSI connector interface. */
-            pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR);
-            AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
+            /* Query the media interface. */
+            pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA);
+            AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia),
+                            ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN),
+                            VERR_PDM_MISSING_INTERFACE);
+
+            /* Get the extended media interface. */
+            pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX);
+            AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx),
+                            ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN),
+                            VERR_PDM_MISSING_INTERFACE);
+
+            rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ));
+            if (RT_FAILURE(rc))
+                return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
+                                           N_("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"),
+                                           pDevice->iLUN);
         }
         else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
Index: /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp	(revision 64223)
+++ /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp	(revision 64224)
@@ -277,12 +277,16 @@
  * @returns VBox status code.
  * @param   pVBoxSCSI      Pointer to the SCSI state.
- * @param   pScsiRequest   Pointer to a scsi request to setup.
+ * @paam    puLun          Where to store the LUN on success.
+ * @param   ppbCdb         Where to store the pointer to the CDB on success.
+ * @param   pcbCdb         Where to store the size of the CDB on success.
+ * @param   pcbBuf         Where to store th size of the data buffer on success.
  * @param   puTargetDevice Where to store the target device ID.
  */
-int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice)
+int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb,
+                         size_t *pcbCdb, size_t *pcbBuf, uint32_t *puTargetDevice)
 {
     int rc = VINF_SUCCESS;
 
-    LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p puTargetDevice=%#p\n", pVBoxSCSI, pScsiRequest, puTargetDevice));
+    LogFlowFunc(("pVBoxSCSI=%#p puTargetDevice=%#p\n", pVBoxSCSI, puTargetDevice));
 
     AssertMsg(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, ("Invalid state %u\n", pVBoxSCSI->enmState));
@@ -301,26 +305,8 @@
     }
 
-    /* Allocate scatter gather element. */
-    pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
-    if (!pScsiRequest->paScatterGatherHead)
-    {
-        RTMemFree(pVBoxSCSI->pbBuf);
-        pVBoxSCSI->pbBuf = NULL;
-        return VERR_NO_MEMORY;
-    }
-
-    /* Allocate sense buffer. */
-    pScsiRequest->cbSenseBuffer = 18;
-    pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer);
-
-    pScsiRequest->cbCDB = pVBoxSCSI->cbCDB;
-    pScsiRequest->pbCDB = pVBoxSCSI->abCDB;
-    pScsiRequest->uLogicalUnit = 0;
-    pScsiRequest->cbScatterGather = pVBoxSCSI->cbBuf;
-    pScsiRequest->cScatterGatherEntries = 1;
-
-    pScsiRequest->paScatterGatherHead[0].cbSeg = pVBoxSCSI->cbBuf;
-    pScsiRequest->paScatterGatherHead[0].pvSeg = pVBoxSCSI->pbBuf;
-
+    *puLun = 0;
+    *ppbCdb = &pVBoxSCSI->abCDB[0];
+    *pcbCdb = pVBoxSCSI->cbCDB;
+    *pcbBuf = pVBoxSCSI->cbBuf;
     *puTargetDevice = pVBoxSCSI->uTargetDevice;
 
@@ -332,9 +318,7 @@
  * is ready at the incoming data port.
  */
-int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion)
-{
-    LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p\n", pVBoxSCSI, pScsiRequest));
-    RTMemFree(pScsiRequest->paScatterGatherHead);
-    RTMemFree(pScsiRequest->pbSenseBuffer);
+int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion)
+{
+    LogFlowFunc(("pVBoxSCSI=%#p\n", pVBoxSCSI));
 
     if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE)
@@ -346,4 +330,22 @@
 
     return VINF_SUCCESS;
+}
+
+size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
+{
+    AssertPtrReturn(pVBoxSCSI->pbBuf, 0);
+    AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0);
+
+    void *pvBuf = pVBoxSCSI->pbBuf + cbSkip;
+    return RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy);
+}
+
+size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
+{
+    AssertPtrReturn(pVBoxSCSI->pbBuf, 0);
+    AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0);
+
+    void *pvBuf = pVBoxSCSI->pbBuf + cbSkip;
+    return RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy);
 }
 
@@ -452,10 +454,7 @@
 }
 
-void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest)
+void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI)
 {
     AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n"));
-
-    RTMemFree(pScsiRequest->paScatterGatherHead);
-    RTMemFree(pScsiRequest->pbSenseBuffer);
 
     if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
Index: /trunk/src/VBox/Devices/Storage/VBoxSCSI.h
===================================================================
--- /trunk/src/VBox/Devices/Storage/VBoxSCSI.h	(revision 64223)
+++ /trunk/src/VBox/Devices/Storage/VBoxSCSI.h	(revision 64224)
@@ -136,7 +136,10 @@
 int vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value);
 int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal);
-int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice);
-int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion);
-void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
+int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb, size_t *pcbCdb,
+                         size_t *pcbBuf, uint32_t *puTargetDevice);
+int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion);
+size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy);
+size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy);
+void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI);
 int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
                         uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb);
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 64223)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 64224)
@@ -1731,8 +1731,10 @@
     GEN_CHECK_OFF(BUSLOGICDEVICE, iLUN);
     GEN_CHECK_OFF(BUSLOGICDEVICE, IBase);
-    GEN_CHECK_OFF(BUSLOGICDEVICE, ISCSIPort);
+    GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaPort);
+    GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaExPort);
     GEN_CHECK_OFF(BUSLOGICDEVICE, ILed);
     GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvBase);
-    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvSCSIConnector);
+    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMedia);
+    GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMediaEx);
     GEN_CHECK_OFF(BUSLOGICDEVICE, Led);
     GEN_CHECK_OFF(BUSLOGICDEVICE, cOutstandingRequests);
@@ -1773,5 +1775,4 @@
     GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueRC);
     GEN_CHECK_OFF(BUSLOGIC, CritSectIntr);
-    GEN_CHECK_OFF(BUSLOGIC, hTaskCache);
     GEN_CHECK_OFF(BUSLOGIC, VBoxSCSI);
     GEN_CHECK_OFF(BUSLOGIC, aDeviceStates);
@@ -1781,10 +1782,10 @@
     GEN_CHECK_OFF(BUSLOGIC, pLedsConnector);
     GEN_CHECK_OFF(BUSLOGIC, fSignalIdle);
-    GEN_CHECK_OFF(BUSLOGIC, fRedo);
     GEN_CHECK_OFF(BUSLOGIC, fWrkThreadSleeping);
     GEN_CHECK_OFF(BUSLOGIC, fBiosReqPending);
-    GEN_CHECK_OFF(BUSLOGIC, pTasksRedoHead);
     GEN_CHECK_OFF(BUSLOGIC, pSupDrvSession);
     GEN_CHECK_OFF(BUSLOGIC, hEvtProcess);
+    GEN_CHECK_OFF(BUSLOGIC, paGCPhysAddrCCBRedo);
+    GEN_CHECK_OFF(BUSLOGIC, cReqsRedo);
 # ifdef LOG_ENABLED
     GEN_CHECK_OFF(BUSLOGIC, cInMailboxesReady);
@@ -1852,5 +1853,4 @@
     GEN_CHECK_OFF(LSILOGICSCSI, enmCtrlType);
     GEN_CHECK_OFF(LSILOGICSCSI, VBoxSCSI);
-    GEN_CHECK_OFF(LSILOGICSCSI, hTaskCache);
     GEN_CHECK_OFF(LSILOGICSCSI, IBase);
     GEN_CHECK_OFF(LSILOGICSCSI, ILeds);
