Index: /trunk/include/VBox/vscsi.h
===================================================================
--- /trunk/include/VBox/vscsi.h	(revision 64653)
+++ /trunk/include/VBox/vscsi.h	(revision 64654)
@@ -231,5 +231,6 @@
                                                int rcScsiCode,
                                                bool fRedoPossible,
-                                               int rcReq);
+                                               int rcReq,
+                                               size_t cbXfer);
 /** Pointer to a virtual SCSI request completed callback. */
 typedef FNVSCSIREQCOMPLETED *PFNVSCSIREQCOMPLETED;
Index: /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 64653)
+++ /trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 64654)
@@ -73,4 +73,6 @@
     /** Where to store the SCSI status code. */
     uint8_t                  *pu8ScsiSts;
+    /** Transfer size determined by the VSCSI layer. */
+    size_t                   cbXfer;
     /** Start of the request data for the device above us. */
     uint8_t                  abAlloc[1];
@@ -786,5 +788,8 @@
     PDRVSCSIREQ pReq = (PDRVSCSIREQ)hIoReq;
 
-    *pcbResidual = *pReq->pu8ScsiSts == SCSI_STATUS_OK ? 0 : pReq->cbBuf; /** @todo: Implement properly. */
+    if (pReq->cbXfer <= pReq->cbBuf)
+        *pcbResidual = pReq->cbBuf - pReq->cbXfer;
+    else
+        *pcbResidual = 0; /* Overflow/Underrun error. */
     return VINF_SUCCESS;
 }
@@ -796,5 +801,5 @@
     PDRVSCSIREQ pReq = (PDRVSCSIREQ)hIoReq;
 
-    *pcbXfer = pReq->cbBuf; /** @todo: Implement properly. */
+    *pcbXfer = pReq->cbXfer;
     return VINF_SUCCESS;
 }
@@ -950,5 +955,6 @@
 
 static DECLCALLBACK(void) drvscsiIoReqVScsiReqCompleted(VSCSIDEVICE hVScsiDevice, void *pVScsiDeviceUser,
-                                                        void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible, int rcReq)
+                                                        void *pVScsiReqUser, int rcScsiCode, bool fRedoPossible,
+                                                        int rcReq, size_t cbXfer)
 {
     RT_NOREF2(hVScsiDevice, fRedoPossible);
@@ -979,4 +985,5 @@
 
     *pReq->pu8ScsiSts = (uint8_t)rcScsiCode;
+    pReq->cbXfer      = cbXfer;
     int rc = pThis->pDevMediaExPort->pfnIoReqCompleteNotify(pThis->pDevMediaExPort, (PDMMEDIAEXIOREQ)pReq,
                                                             &pReq->abAlloc[0], rcReq);
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp	(revision 64653)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp	(revision 64654)
@@ -67,4 +67,5 @@
                 SCSIINQUIRYDATA ScsiInquiryReply;
 
+                vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[3]));
                 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
                 ScsiInquiryReply.cbAdditional = 31;
@@ -85,5 +86,6 @@
              * to return an error.
              */
-            if (vscsiBE2HU32(&pVScsiReq->pbCDB[6]) < 16)
+            vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU32(&pVScsiReq->pbCDB[6]));
+            if (pVScsiReq->cbXfer < 16)
                 *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
             else
@@ -113,4 +115,6 @@
         case SCSI_REQUEST_SENSE:
         {
+            vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]);
+
             /* Descriptor format sense data is not supported and results in an error. */
             if ((pVScsiReq->pbCDB[1] & 0x1) != 0)
@@ -179,5 +183,5 @@
     pVScsiDevice->pfnVScsiReqCompleted(pVScsiDevice, pVScsiDevice->pvVScsiDeviceUser,
                                        pVScsiReq->pvVScsiReqUser, rcScsiCode, fRedoPossible,
-                                       rcReq);
+                                       rcReq, pVScsiReq->cbXfer);
 
     RTMemCacheFree(pVScsiDevice->hCacheReq, pVScsiReq);
@@ -391,4 +395,5 @@
     pVScsiReq->cbSense        = cbSense;
     pVScsiReq->pvVScsiReqUser = pvVScsiReqUser;
+    pVScsiReq->cbXfer         = 0;
     RTSgBufInit(&pVScsiReq->SgBuf, paSGList, cSGListEntries);
 
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h	(revision 64653)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h	(revision 64654)
@@ -119,4 +119,6 @@
     /** Opaque user data associated with this request */
     void                *pvVScsiReqUser;
+    /** Transfer size determined from the CDB. */
+    size_t               cbXfer;
 } VSCSIREQINT;
 
@@ -149,5 +151,5 @@
             PCRTSGSEG      paSeg;
         } Io;
-        /** Unmape request. */
+        /** Unmap request. */
         struct
         {
@@ -442,4 +444,16 @@
 
 /**
+ * Sets the transfer size for the given request.
+ *
+ * @returns nothing.
+ * @param   pVScsiReq     The SCSI request.
+ * @param   cbXfer        The transfer size for the request.
+ */
+DECLINLINE(void) vscsiReqSetXferSize(PVSCSIREQINT pVScsiReq, size_t cbXfer)
+{
+    pVScsiReq->cbXfer = cbXfer;
+}
+
+/**
  * Wrapper for the set I/O request allocation size I/O callback.
  *
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp	(revision 64653)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp	(revision 64654)
@@ -887,4 +887,5 @@
                 SCSIINQUIRYDATA ScsiInquiryReply;
 
+                vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[3]));
                 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));
 
@@ -908,4 +909,5 @@
                 uint8_t aReply[8];
                 memset(aReply, 0, sizeof(aReply));
+                vscsiReqSetXferSize(pVScsiReq, sizeof(aReply));
 
                 /*
@@ -929,4 +931,5 @@
                 bool    fValid = false;
 
+                vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]);
                 memset(aReply, 0, sizeof(aReply));
                 aReply[0] = 4; /* Reply length 4. */
@@ -959,5 +962,6 @@
             case SCSI_MODE_SENSE_10:
             {
-                size_t cbMax = vscsiBE2HU32(&pVScsiReq->pbCDB[7]);
+                size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 rcReq = vscsiLunMmcModeSense10(pVScsiLunMmc, pVScsiReq, cbMax);
                 break;
@@ -976,4 +980,5 @@
             {
                 /** @todo implement!! */
+                vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]);
                 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
                 break;
@@ -1012,4 +1017,6 @@
             {
                 uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
+
+                vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[6]));
 
                 switch (uDataMode)
@@ -1064,4 +1071,6 @@
                 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
                 uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
+
+                vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[7]));
 
                 switch (uPageCode)
@@ -1100,4 +1109,6 @@
                         vscsiH2BEU32(&aReply[8], pVScsiLunMmc->cbSector);
                         /* Leave the rest 0 */
+
+                        vscsiReqSetXferSize(pVScsiReq, sizeof(aReply));
                         RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
                         rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
@@ -1126,4 +1137,6 @@
                 cbMax  = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
                 fMSF   = (pVScsiReq->pbCDB[1] >> 1) & 1;
+
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 switch (format)
                 {
@@ -1145,9 +1158,9 @@
             {
                 /* Only supporting polled mode at the moment. */
+                size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
+
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 if (pVScsiReq->pbCDB[1] & 0x1)
-                {
-                    size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
                     rcReq = vscsiLunMmcGetEventStatusNotification(pVScsiLunMmc, pVScsiReq, cbMax);
-                }
                 else
                     rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00);
@@ -1159,4 +1172,5 @@
                 uint8_t aReply[8];
 
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 vscsiH2BEU16(&aReply[0], 0);
                 /* no current LBA */
@@ -1175,4 +1189,5 @@
                 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
 
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 memset(aReply, '\0', sizeof(aReply));
                 vscsiH2BEU16(&aReply[0], 32);
@@ -1195,4 +1210,7 @@
             case SCSI_READ_TRACK_INFORMATION:
             {
+                size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
+
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 /* Accept address/number type of 1 only, and only track 1 exists. */
                 if ((pVScsiReq->pbCDB[1] & 0x03) != 1 || vscsiBE2HU32(&pVScsiReq->pbCDB[2]) != 1)
@@ -1201,5 +1219,4 @@
                 else
                 {
-                    size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
                     uint8_t aReply[36];
                     RT_ZERO(aReply);
@@ -1224,4 +1241,5 @@
             {
                 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]);
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 rcReq = vscsiLunMmcGetConfiguration(pVScsiLunMmc, pVScsiReq, cbMax);
                 break;
@@ -1230,4 +1248,5 @@
             {
                 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[8]);
+                vscsiReqSetXferSize(pVScsiReq, cbMax);
                 rcReq = vscsiLunMmcReadDvdStructure(pVScsiLunMmc, pVScsiReq, cbMax);
                 break;
@@ -1244,4 +1263,5 @@
                  __FUNCTION__, uLbaStart, cSectorTransfer));
 
+        vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * pVScsiLunMmc->cbSector);
         if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunMmc->cSectors))
         {
Index: /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp	(revision 64653)
+++ /trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp	(revision 64654)
@@ -203,4 +203,6 @@
         case SCSI_INQUIRY:
         {
+            vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[3]));
+
             /* Check for EVPD bit. */
             if (pVScsiReq->pbCDB[1] & 0x1)
@@ -244,4 +246,6 @@
             uint8_t aReply[8];
             memset(aReply, 0, sizeof(aReply));
+
+            vscsiReqSetXferSize(pVScsiReq, sizeof(aReply));
 
             /*
@@ -265,4 +269,5 @@
             bool    fValid = false;
 
+            vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]);
             memset(aReply, 0, sizeof(aReply));
             aReply[0] = 4; /* Reply length 4. */
@@ -302,4 +307,6 @@
             size_t  cbList = pVScsiReq->pbCDB[4];
 
+            vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]);
+
             /* Copy the parameters. */
             cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abParms[0], sizeof(abParms));
@@ -392,4 +399,6 @@
         {
             uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f;
+
+            vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[6]));
 
             switch (uDataMode)
@@ -423,4 +432,5 @@
         case SCSI_START_STOP_UNIT:
         {
+            vscsiReqSetXferSize(pVScsiReq, 0);
             rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
             break;
@@ -430,4 +440,6 @@
             uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f;
             uint8_t uSubPageCode = pVScsiReq->pbCDB[3];
+
+            vscsiReqSetXferSize(pVScsiReq, vscsiBE2HU16(&pVScsiReq->pbCDB[7]));
 
             switch (uPageCode)
@@ -468,4 +480,5 @@
                     /* Leave the rest 0 */
 
+                    vscsiReqSetXferSize(pVScsiReq, sizeof(aReply));
                     RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply));
                     rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq);
@@ -486,4 +499,5 @@
 
                 /* Copy the header. */
+                vscsiReqSetXferSize(pVScsiReq, cbList);
                 cbCopied = RTSgBufCopyToBuf(&pVScsiReq->SgBuf, &abHdr[0], sizeof(abHdr));
 
@@ -546,4 +560,6 @@
                  __FUNCTION__, uLbaStart, cSectorTransfer));
 
+        vscsiReqSetXferSize(pVScsiReq, cSectorTransfer * 512);
+
         if (RT_UNLIKELY(uLbaStart + cSectorTransfer > pVScsiLunSbc->cSectors))
         {
@@ -569,7 +585,8 @@
         }
     }
-    else if (pVScsiReq->pbCDB[0] ==  SCSI_SYNCHRONIZE_CACHE)
+    else if (pVScsiReq->pbCDB[0] == SCSI_SYNCHRONIZE_CACHE)
     {
         /* Enqueue flush */
+        vscsiReqSetXferSize(pVScsiReq, 0);
         rc = vscsiIoReqFlushEnqueue(pVScsiLun, pVScsiReq);
     }
