Index: /trunk/include/VBox/pdmifs.h
===================================================================
--- /trunk/include/VBox/pdmifs.h	(revision 32982)
+++ /trunk/include/VBox/pdmifs.h	(revision 32983)
@@ -2639,10 +2639,17 @@
      * @param   pSCSIRequest  Pointer to the finished SCSI request.
      * @param   rcCompletion  SCSI_STATUS_* code for the completed request.
-     */
-     DECLR3CALLBACKMEMBER(int, pfnSCSIRequestCompleted, (PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion));
+     * @param   fRedo         Flag whether the request can to be redone
+     *                        when it failed.
+     * @param   rcReq         The status code the request completed with (VERR_*)
+     *                        Should be only used to choose the correct error message
+     *                        displayed to the user if the error can be fixed by him
+     *                        (fRedo is true).
+     */
+     DECLR3CALLBACKMEMBER(int, pfnSCSIRequestCompleted, (PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
+                                                         int rcCompletion, bool fRedo, int rcReq));
 
 } PDMISCSIPORT;
 /** PDMISCSIPORT interface ID. */
-#define PDMISCSIPORT_IID                        "0f894add-714d-4a77-818e-a32fe3586ba4"
+#define PDMISCSIPORT_IID                        "9d185b3b-1051-41f6-83ad-2a2a23f04e40"
 
 
Index: /trunk/include/VBox/scsi.h
===================================================================
--- /trunk/include/VBox/scsi.h	(revision 32982)
+++ /trunk/include/VBox/scsi.h	(revision 32983)
@@ -179,4 +179,5 @@
 /* additional sense keys */
 #define SCSI_ASC_NONE                               0x00
+#define SCSI_ASC_WRITE_ERROR                        0x0c
 #define SCSI_ASC_READ_ERROR                         0x11
 #define SCSI_ASC_ILLEGAL_OPCODE                     0x20
Index: /trunk/include/VBox/vscsi.h
===================================================================
--- /trunk/include/VBox/vscsi.h	(revision 32982)
+++ /trunk/include/VBox/vscsi.h	(revision 32983)
@@ -135,4 +135,6 @@
                                                void *pvVScsiDeviceUser,
                                                void *pvVScsiReqUser,
+                                               int rcScsiCode,
+                                               bool fRedoPossible,
                                                int rcReq);
 /** Pointer to a virtual SCSI request completed callback. */
@@ -253,6 +255,9 @@
  *                                  the LUN is called by the virtual SCSI layer.
  * @param   rcIoReq                 The status code the I/O request completed with.
- */
-VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq);
+ * @param   fRedoPossible           Flag whether it is possible to redo the request.
+ *                                  If true setting any sense code will be omitted
+ *                                  in case of an error to not alter the device state.
+ */
+VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible);
 
 /**
Index: /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/DevBusLogic.cpp	(revision 32983)
@@ -2013,5 +2013,6 @@
 }
 
-static DECLCALLBACK(int) buslogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
+static DECLCALLBACK(int) buslogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
+                                                            int rcCompletion, bool fRedo, int rcReq)
 {
     int rc;
Index: /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp	(revision 32983)
@@ -103,4 +103,7 @@
 } LSILOGICDEVICE, *PLSILOGICDEVICE;
 
+/** Pointer to a task state. */
+typedef struct LSILOGICTASKSTATE *PLSILOGICTASKSTATE;
+
 /**
  * Device instance data for the emulated
@@ -290,4 +293,8 @@
      * a port is entering the idle state. */
     bool volatile                  fSignalIdle;
+    /** Flag whether we have tasks which need to be processed again- */
+    bool volatile                  fRedo;
+    /** List of tasks which can be redone. */
+    R3PTRTYPE(volatile PLSILOGICTASKSTATE) pTasksRedoHead;
 
 } LSILOGISCSI, *PLSILOGICSCSI;
@@ -325,4 +332,6 @@
 typedef struct LSILOGICTASKSTATE
 {
+    /** Next in the redo list. */
+    PLSILOGICTASKSTATE         pRedoNext;
     /** Target device. */
     PLSILOGICDEVICE            pTargetDevice;
@@ -360,5 +369,5 @@
     /** Flag whether the request was issued from the BIOS. */
     bool                       fBIOS;
-} LSILOGICTASKSTATE, *PLSILOGICTASKSTATE;
+} LSILOGICTASKSTATE;
 
 #ifndef VBOX_DEVICE_STRUCT_TESTCASE
@@ -1893,4 +1902,56 @@
 #endif
 
+static void lsilogicWarningDiskFull(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 lsilogicWarningFileTooBig(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 lsilogicWarningISCSI(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 lsilogicWarningUnknown(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 lsilogicRedoSetWarning(PLSILOGICSCSI pThis, int rc)
+{
+    if (rc == VERR_DISK_FULL)
+        lsilogicWarningDiskFull(pThis->CTX_SUFF(pDevIns));
+    else if (rc == VERR_FILE_TOO_BIG)
+        lsilogicWarningFileTooBig(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. */
+        lsilogicWarningISCSI(pThis->CTX_SUFF(pDevIns));
+    }
+    else
+        lsilogicWarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
+}
+
 /**
  * Processes a SCSI I/O request by setting up the request
@@ -2019,14 +2080,7 @@
 }
 
-/**
- * Called upon completion of the request from the SCSI driver below.
- * This function frees all allocated ressources and notifies the guest
- * that the process finished by asserting an interrupt.
- *
- * @returns VBox status code.
- * @param   pInterface    Pointer to the interface the called funtion belongs to.
- * @param   pSCSIRequest  Pointer to the SCSI request which finished.
- */
-static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
+
+static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
+                                                            int rcCompletion, bool fRedo, int rcReq)
 {
     PLSILOGICTASKSTATE pTaskState      = (PLSILOGICTASKSTATE)pSCSIRequest->pvUser;
@@ -2034,57 +2088,77 @@
     PLSILOGICSCSI      pLsiLogic       = 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 (!pTaskState->fBIOS)
+            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
+
+        /* Add to the list. */
+        do
+        {
+            pTaskState->pRedoNext = ASMAtomicReadPtrT(&pLsiLogic->pTasksRedoHead, PLSILOGICTASKSTATE);
+        } while (!ASMAtomicCmpXchgPtr(&pLsiLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
+
+        /* Suspend the VM if not done already. */
+        if (!ASMAtomicXchgBool(&pLsiLogic->fRedo, true))
+            lsilogicRedoSetWarning(pLsiLogic, rcReq);
+    }
+    else
+    {
+        if (RT_UNLIKELY(pTaskState->fBIOS))
+        {
+            int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
+            AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
+        }
+        else
+        {
+#if 0
+            lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
+#else
+            RTGCPHYS GCPhysAddrSenseBuffer;
+
+            GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
+            GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
+
+            /* Copy the sense buffer over. */
+            PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
+                                 RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
+                               ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
+                               : pTaskState->PDMScsiRequest.cbSenseBuffer);
+#endif
+            lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
+
+
+            if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
+                lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
+            else
+            {
+                /* The SCSI target encountered an error during processing post a reply. */
+                memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
+                pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
+                pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
+                pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
+                pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
+                pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
+                pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
+                pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
+                pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
+                pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
+                pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
+                pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
+                pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
+                pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
+                pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
+                pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
+
+                lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
+            }
+        }
+
+        RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
+    }
+
     ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
-
-    if (RT_UNLIKELY(pTaskState->fBIOS))
-    {
-        int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
-        AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
-    }
-    else
-    {
-#if 0
-        lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
-#else
-        RTGCPHYS GCPhysAddrSenseBuffer;
-
-        GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
-        GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
-
-        /* Copy the sense buffer over. */
-        PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
-                             RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
-                           ? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
-                           : pTaskState->PDMScsiRequest.cbSenseBuffer);
-#endif
-        lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
-
-
-        if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
-            lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
-        else
-        {
-            /* The SCSI target encountered an error during processing post a reply. */
-            memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
-            pTaskState->IOCReply.SCSIIOError.u8TargetID          = pTaskState->GuestRequest.SCSIIO.u8TargetID;
-            pTaskState->IOCReply.SCSIIOError.u8Bus               = pTaskState->GuestRequest.SCSIIO.u8Bus;
-            pTaskState->IOCReply.SCSIIOError.u8MessageLength     = 8;
-            pTaskState->IOCReply.SCSIIOError.u8Function          = pTaskState->GuestRequest.SCSIIO.u8Function;
-            pTaskState->IOCReply.SCSIIOError.u8CDBLength         = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
-            pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
-            pTaskState->IOCReply.SCSIIOError.u8MessageFlags      = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
-            pTaskState->IOCReply.SCSIIOError.u32MessageContext   = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
-            pTaskState->IOCReply.SCSIIOError.u8SCSIStatus        = rcCompletion;
-            pTaskState->IOCReply.SCSIIOError.u8SCSIState         = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
-            pTaskState->IOCReply.SCSIIOError.u16IOCStatus        = 0;
-            pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo       = 0;
-            pTaskState->IOCReply.SCSIIOError.u32TransferCount    = 0;
-            pTaskState->IOCReply.SCSIIOError.u32SenseCount       = sizeof(pTaskState->abSenseBuffer);
-            pTaskState->IOCReply.SCSIIOError.u32ResponseInfo     = 0;
-
-            lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
-        }
-    }
-
-    RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
 
     if (pLsiLogicDevice->cOutstandingRequests == 0 && pLsiLogic->fSignalIdle)
@@ -3974,4 +4048,29 @@
 }
 
+/**
+ * Kicks the controller to process pending tasks after the VM was resumed
+ * or loaded from a saved state.
+ *
+ * @returns nothing.
+ * @param   pThis    The LsiLogic device instance.
+ */
+static void lsilogicKick(PLSILOGICSCSI pThis)
+{
+    if (pThis->fNotificationSend)
+    {
+        /* Send a notifier to the PDM queue that there are pending requests. */
+        PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pNotificationQueue));
+        AssertMsg(pItem, ("Allocating item for queue failed\n"));
+        PDMQueueInsert(pThis->CTX_SUFF(pNotificationQueue), (PPDMQUEUEITEMCORE)pItem);
+    }
+    else if (pThis->VBoxSCSI.fBusy)
+    {
+        /* The BIOS had a request active when we got suspended. Resume it. */
+        int rc = lsilogicPrepareBIOSSCSIRequest(pThis);
+        AssertRC(rc);
+    }
+
+}
+
 static DECLCALLBACK(int) lsilogicLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
 {
@@ -4138,8 +4237,16 @@
     SSMR3PutBool  (pSSM, pLsiLogic->VBoxSCSI.fBusy);
     SSMR3PutU8    (pSSM, pLsiLogic->VBoxSCSI.enmState);
-    if (pLsiLogic->VBoxSCSI.cbCDB)
+    if (pLsiLogic->VBoxSCSI.cbBuf)
         SSMR3PutMem(pSSM, pLsiLogic->VBoxSCSI.pBuf, pLsiLogic->VBoxSCSI.cbBuf);
 
     return SSMR3PutU32(pSSM, ~0);
+}
+
+static DECLCALLBACK(int) lsilogicLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
+
+    lsilogicKick(pThis);
+    return VINF_SUCCESS;
 }
 
@@ -4412,7 +4519,7 @@
     SSMR3GetBool(pSSM, (bool *)&pLsiLogic->VBoxSCSI.fBusy);
     SSMR3GetU8  (pSSM, (uint8_t *)&pLsiLogic->VBoxSCSI.enmState);
-    if (pLsiLogic->VBoxSCSI.cbCDB)
-    {
-        pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbCDB);
+    if (pLsiLogic->VBoxSCSI.cbBuf)
+    {
+        pLsiLogic->VBoxSCSI.pBuf = (uint8_t *)RTMemAllocZ(pLsiLogic->VBoxSCSI.cbBuf);
         if (!pLsiLogic->VBoxSCSI.pBuf)
         {
@@ -4553,5 +4660,50 @@
         PDMDevHlpSetAsyncNotification(pDevIns, lsilogicR3IsAsyncSuspendOrPowerOffDone);
     else
+    {
         ASMAtomicWriteBool(&pThis->fSignalIdle, false);
+
+        AssertMsg(!pThis->fNotificationSend, ("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.
+             */
+            PLSILOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
+
+            pThis->pTasksRedoHead = NULL;
+
+            while (pTaskState)
+            {
+                PLSILOGICTASKSTATE pFree;
+
+                if (!pTaskState->fBIOS)
+                {
+                    /* Write only the lower 32bit part of the address. */
+                    ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
+                                      pTaskState->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
+
+                    pThis->uRequestQueueNextEntryFreeWrite++;
+                    pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
+
+                    pThis->fNotificationSend = true;
+                }
+                else
+                {
+                    AssertMsg(!pTaskState->pRedoNext, ("Only one BIOS task can be active!\n"));
+                    vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pTaskState->PDMScsiRequest);
+                }
+
+                pFree = pTaskState;
+                pTaskState = pTaskState->pRedoNext;
+
+                RTMemCacheFree(pThis->hTaskCache, pFree);
+            }
+            pThis->fRedo = false;
+        }
+    }
 }
 
@@ -4565,4 +4717,18 @@
     Log(("lsilogicSuspend\n"));
     lsilogicR3SuspendOrPowerOff(pDevIns);
+}
+
+/**
+ * Resume notification.
+ *
+ * @param   pDevIns     The device instance data.
+ */
+static DECLCALLBACK(void) lsilogicResume(PPDMDEVINS pDevIns)
+{
+    PLSILOGICSCSI pThis = PDMINS_2_DATA(pDevIns, PLSILOGICSCSI);
+
+    Log(("lsilogicResume\n"));
+
+    lsilogicKick(pThis);
 }
 
@@ -5034,6 +5200,8 @@
 
     /* Register save state handlers. */
-    rc = PDMDevHlpSSMRegister3(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis),
-                               lsilogicLiveExec, lsilogicSaveExec, lsilogicLoadExec);
+    rc = PDMDevHlpSSMRegisterEx(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
+                                NULL, lsilogicLiveExec, NULL,
+                                NULL, lsilogicSaveExec, NULL,
+                                NULL, lsilogicLoadExec, lsilogicLoadDone);
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register save state handlers"));
@@ -5097,5 +5265,5 @@
     lsilogicSuspend,
     /* pfnResume */
-    NULL,
+    lsilogicResume,
     /* pfnAttach */
     lsilogicAttach,
@@ -5153,5 +5321,5 @@
     lsilogicSuspend,
     /* pfnResume */
-    NULL,
+    lsilogicResume,
     /* pfnAttach */
     lsilogicAttach,
Index: /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 32983)
@@ -112,4 +112,15 @@
 #define PDMIBLOCKASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) )
 
+static int drvscsiIsRedoPossible(int rc)
+{
+    if (   rc == VERR_DISK_FULL
+        || rc == VERR_FILE_TOO_BIG
+        || rc == VERR_BROKEN_PIPE
+        || rc == VERR_NET_CONNECTION_REFUSED)
+        return true;
+
+    return false;
+}
+
 static int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq)
 {
@@ -152,5 +163,5 @@
                     pThis->pLed->Actual.s.fReading = 0;
                     if (RT_FAILURE(rc))
-                        AssertMsgFailed(("%s: Failed to read data %Rrc\n", __FUNCTION__, rc));
+                        break;
                     STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess);
                 }
@@ -162,5 +173,5 @@
                     pThis->pLed->Actual.s.fWriting = 0;
                     if (RT_FAILURE(rc))
-                        AssertMsgFailed(("%s: Failed to write data %Rrc\n", __FUNCTION__, rc));
+                        break;
                     STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess);
                 }
@@ -179,5 +190,8 @@
     }
 
-    VSCSIIoReqCompleted(hVScsiIoReq, rc);
+    if (RT_SUCCESS(rc))
+        VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
+    else
+        VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
 
     return VINF_SUCCESS;
@@ -208,5 +222,8 @@
         AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
 
-    VSCSIIoReqCompleted(hVScsiIoReq, rc);
+    if (RT_SUCCESS(rc))
+        VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
+    else
+        VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
 
     return VINF_SUCCESS;
@@ -296,5 +313,5 @@
                 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
 
-            VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS);
+            VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
         }
         else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
@@ -309,5 +326,5 @@
                 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
 
-            VSCSIIoReqCompleted(hVScsiIoReq, rc);
+            VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
             rc = VINF_SUCCESS;
         }
@@ -326,5 +343,6 @@
 
 static void drvscsiVScsiReqCompleted(VSCSIDEVICE hVScsiDevice, void *pVScsiDeviceUser,
-                                     void *pVScsiReqUser, int rcReq)
+                                     void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible,
+                                     int rcReq)
 {
     PDRVSCSI pThis = (PDRVSCSI)pVScsiDeviceUser;
@@ -333,5 +351,5 @@
 
     pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, (PPDMSCSIREQUEST)pVScsiReqUser,
-                                                 rcReq);
+                                                 rcScsiCode, fRedoPossible, rcReq);
 
     if (RT_UNLIKELY(pThis->fDummySignal) && !pThis->StatIoDepth)
Index: /trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp	(revision 32983)
@@ -316,5 +316,5 @@
     }
     /* Notify device that request finished. */
-    rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK);
+    rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK, false, VINF_SUCCESS);
     AssertMsgRC(rc, ("Notifying device above failed rc=%Rrc\n", rc));
 
Index: /trunk/src/VBox/Devices/Storage/UsbMsd.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/UsbMsd.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/UsbMsd.cpp	(revision 32983)
@@ -746,5 +746,6 @@
  * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted}
  */
-static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
+static DECLCALLBACK(int) usbMsdLun0ScsiRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
+                                                        int rcCompletion, bool fRedo, int rcReq)
 {
     PUSBMSD     pThis = RT_FROM_MEMBER(pInterface, USBMSD, Lun0.IScsiPort);
@@ -894,5 +895,5 @@
     pReq->ScsiReqSense[13] = 0; /* Should be ASCQ but it has the same value for success. */
 
-    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION);
+    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
     return VINF_SUCCESS;
 }
@@ -946,5 +947,5 @@
 
     /* Do normal completion.  */
-    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK);
+    usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
     return VINF_SUCCESS;
 }
@@ -1274,5 +1275,5 @@
                 LogFlow(("usbMsdHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
 
-                usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK);
+                usbMsdLun0ScsiRequestCompleted(&pThis->Lun0.IScsiPort, &pReq->ScsiReq, SCSI_STATUS_OK, false, VINF_SUCCESS);
                 return VINF_SUCCESS;
             }
Index: /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp	(revision 32983)
@@ -271,5 +271,7 @@
     if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
     {
-        Assert(!pVBoxSCSI->pBuf);
+        if (pVBoxSCSI->pBuf)
+            RTMemFree(pVBoxSCSI->pBuf);
+
         pVBoxSCSI->pBuf = (uint8_t *)RTMemAllocZ(pVBoxSCSI->cbBuf);
         if (!pVBoxSCSI->pBuf)
@@ -277,5 +279,5 @@
     }
 
-    /** Allocate scatter gather element. */
+    /* Allocate scatter gather element. */
     pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */
     if (!pScsiRequest->paScatterGatherHead)
@@ -286,5 +288,5 @@
     }
 
-    /** Allocate sense buffer. */
+    /* Allocate sense buffer. */
     pScsiRequest->cbSenseBuffer = 18;
     pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer);
@@ -385,2 +387,15 @@
 }
 
+void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest)
+{
+    AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n"));
+
+    RTMemFree(pScsiRequest->paScatterGatherHead);
+    RTMemFree(pScsiRequest->pbSenseBuffer);
+
+    if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE)
+    {
+        AssertPtr(pVBoxSCSI->pBuf);
+    }
+}
+
Index: /trunk/src/VBox/Devices/Storage/VBoxSCSI.h
===================================================================
--- /trunk/src/VBox/Devices/Storage/VBoxSCSI.h	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VBoxSCSI.h	(revision 32983)
@@ -124,4 +124,5 @@
 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice);
 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
+void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest);
 int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister,
                         RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb);
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp	(revision 32983)
@@ -109,18 +109,11 @@
 }
 
-/**
- * Completesa SCSI request and calls the completion handler.
- *
- * @returns nothing.
- * @param   pVScsiDevice    The virtual SCSI device.
- * @param   pVScsiReq       The request which completed.
- * @param   rcReq           The status code
- *                          One of the SCSI_STATUS_* #defines.
- */
+
 void vscsiDeviceReqComplete(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVScsiReq,
-                            int rcReq)
+                            int rcScsiCode, bool fRedoPossible, int rcReq)
 {
     pVScsiDevice->pfnVScsiReqCompleted(pVScsiDevice, pVScsiDevice->pvVScsiDeviceUser,
-                                       pVScsiReq->pvVScsiReqUser, rcReq);
+                                       pVScsiReq->pvVScsiReqUser, rcScsiCode, fRedoPossible,
+                                       rcReq);
 
     RTMemCacheFree(pVScsiDevice->hCacheReq, pVScsiReq);
@@ -294,10 +287,10 @@
 
             vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq,
-                                   SCSI_STATUS_CHECK_CONDITION);
+                                   SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS);
         }
     }
     else
         vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq,
-                               rcReq);
+                               rcReq, false, VINF_SUCCESS);
 
     return rc;
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h	(revision 32983)
@@ -189,9 +189,11 @@
  * @param   pVScsiDevice    The virtual SCSI device.
  * @param   pVScsiReq       The request which completed.
- * @param   rcReq           The status code
+ * @param   rcScsiCode      The status code
  *                          One of the SCSI_STATUS_* #defines.
+ * @param   fRedoPossible   Flag whether redo is possible.
+ * @param   rcReq           Informational return code of the request.
  */
 void vscsiDeviceReqComplete(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVScsiReq,
-                            int rcReq);
+                            int rcScsiCode, bool fRedoPossible, int rcReq);
 
 /**
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp	(revision 32983)
@@ -93,5 +93,5 @@
 
 
-VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq)
+VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible)
 {
     PVSCSIIOREQINT pVScsiIoReq = hVScsiIoReq;
@@ -115,4 +115,15 @@
     if (RT_SUCCESS(rcIoReq))
         rcReq = vscsiReqSenseOkSet(pVScsiReq);
+    else if (!fRedoPossible)
+    {
+        /** @todo Not 100% correct for the write case as the 0x00 ASCQ for write errors
+         * is not used for SBC devices. */
+        rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_MEDIUM_ERROR,
+                                      pVScsiIoReq->enmTxDir == VSCSIIOREQTXDIR_READ
+                                      ? SCSI_ASC_READ_ERROR
+                                      : SCSI_ASC_WRITE_ERROR);
+    }
+    else
+        rcReq = SCSI_STATUS_CHECK_CONDITION;
 
     /* Free the I/O request */
@@ -120,5 +131,5 @@
 
     /* Notify completion of the SCSI request. */
-    vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
+    vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, fRedoPossible, rcIoReq);
 
     return VINF_SUCCESS;
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp	(revision 32982)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp	(revision 32983)
@@ -302,5 +302,5 @@
         {
             rcReq = vscsiReqSenseErrorSet(pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
-            vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
+            vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
         }
         else
@@ -317,5 +317,5 @@
     }
     else /* Request completed */
-        vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq);
+        vscsiDeviceReqComplete(pVScsiLun->pVScsiDevice, pVScsiReq, rcReq, false, VINF_SUCCESS);
 
     return rc;
