Index: trunk/src/VBox/Devices/Serial/DrvCharNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvCharNew.cpp	(revision 73330)
+++ trunk/src/VBox/Devices/Serial/DrvCharNew.cpp	(revision 73331)
@@ -114,4 +114,5 @@
 static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
 {
+    LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail));
     PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
 
@@ -130,4 +131,5 @@
 static DECLCALLBACK(int) drvCharReadRdr(PPDMISERIALCONNECTOR pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead)
 {
+    LogFlowFunc(("pInterface=%#p pvBuf=%#p cbRead=%zu pcbRead=%#p\n", pInterface, pvBuf, cbRead, pcbRead));
     PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
     int rc = VINF_SUCCESS;
@@ -136,4 +138,6 @@
     size_t cbToRead = RT_MIN(cbRead, pThis->cbRemaining);
     memcpy(pvBuf, pThis->pbBuf, cbToRead);
+
+    pThis->pbBuf += cbToRead;
     *pcbRead = cbToRead;
     size_t cbOld = ASMAtomicSubZ(&pThis->cbRemaining, cbToRead);
@@ -142,4 +146,5 @@
     STAM_COUNTER_ADD(&pThis->StatBytesRead, cbToRead);
 
+    LogFlowFunc(("-> %Rrc\n", rc));
     return rc;
 }
@@ -230,5 +235,5 @@
                 {
                     /* Stuff as much data into the TX buffer as we can. */
-                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
+                    size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
                     size_t cbFetched = 0;
                     rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
@@ -239,5 +244,5 @@
                     {
                         ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
-                        pThis->cbTxUsed += cbFetched;
+                        pThis->cbTxUsed  += cbFetched;
                     }
                     else
@@ -281,8 +286,12 @@
                     break;
                 }
-                pThis->pbBuf = &pThis->abBuffer[0];
-                ASMAtomicWriteZ(&pThis->cbRemaining, cbRead);
-                /* Notify the upper device/driver. */
-                rc = pThis->pDrvSerialPort->pfnDataAvailRdrNotify(pThis->pDrvSerialPort, cbRead);
+
+                if (cbRead)
+                {
+                    pThis->pbBuf = &pThis->abBuffer[0];
+                    ASMAtomicWriteZ(&pThis->cbRemaining, cbRead);
+                    /* Notify the upper device/driver. */
+                    rc = pThis->pDrvSerialPort->pfnDataAvailRdrNotify(pThis->pDrvSerialPort, cbRead);
+                }
             }
         }
Index: trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 73330)
+++ trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 73331)
@@ -394,5 +394,5 @@
                 {
                     /* Stuff as much data into the TX buffer as we can. */
-                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
+                    size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
                     size_t cbFetched = 0;
                     rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
@@ -403,5 +403,5 @@
                     {
                         ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
-                        pThis->cbTxUsed += cbFetched;
+                        pThis->cbTxUsed  += cbFetched;
                     }
                     else
Index: trunk/src/VBox/Devices/Serial/UartCore.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/UartCore.cpp	(revision 73330)
+++ trunk/src/VBox/Devices/Serial/UartCore.cpp	(revision 73331)
@@ -614,5 +614,11 @@
     while (cbFilled < cbFill)
     {
-        size_t cbThisRead = RT_MIN(cbFill - cbFilled, (uint8_t)(pFifo->cbMax - pFifo->offWrite));
+        size_t cbThisRead = cbFill - cbFilled;
+
+        if (pFifo->offRead <= pFifo->offWrite)
+            cbThisRead = RT_MIN(cbThisRead, (uint8_t)(pFifo->cbMax - pFifo->offWrite));
+        else
+            cbThisRead = RT_MIN(cbThisRead, (uint8_t)(pFifo->offRead - pFifo->offWrite));
+
         size_t cbRead = 0;
         int rc = pThis->pDrvSerial->pfnReadRdr(pThis->pDrvSerial, &pFifo->abBuf[pFifo->offWrite], cbThisRead, &cbRead);
@@ -670,4 +676,40 @@
     else
         uartR3ByteFetch(pThis);
+}
+
+
+/**
+ * Reset the transmit/receive related bits to the standard values
+ * (after a detach/attach/reset event).
+ *
+ * @returns nothing.
+ * @param   pThis               The serial port instance.
+ */
+static void uartR3XferReset(PUARTCORE pThis)
+{
+    pThis->uRegLsr = UART_REG_LSR_THRE | UART_REG_LSR_TEMT;
+
+    uartFifoClear(&pThis->FifoXmit);
+    uartFifoClear(&pThis->FifoRecv);
+    uartR3ParamsUpdate(pThis);
+    uartIrqUpdate(pThis);
+
+    if (pThis->pDrvSerial)
+    {
+        /* Set the modem lines to reflect the current state. */
+        int rc = pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/);
+        if (RT_FAILURE(rc))
+            LogRel(("Serial#%d: Failed to set modem lines with %Rrc during reset\n",
+                    pThis->pDevInsR3->iInstance, rc));
+
+        uint32_t fStsLines = 0;
+        rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines);
+        if (RT_SUCCESS(rc))
+            uartR3StsLinesUpdate(pThis, fStsLines);
+        else
+            LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n",
+                    pThis->pDevInsR3->iInstance, rc));
+    }
+
 }
 #endif
@@ -1600,27 +1642,7 @@
     pThis->FifoXmit.cbMax = 16;
     pThis->FifoRecv.cbMax = 16;
-    uartFifoClear(&pThis->FifoXmit);
-    uartFifoClear(&pThis->FifoRecv);
     pThis->FifoRecv.cbItl = 1;
 
-    uartR3ParamsUpdate(pThis);
-    uartIrqUpdate(pThis);
-
-    if (pThis->pDrvSerial)
-    {
-        /* Set the modem lines to reflect the current state. */
-        int rc = pThis->pDrvSerial->pfnChgModemLines(pThis->pDrvSerial, false /*fRts*/, false /*fDtr*/);
-        if (RT_FAILURE(rc))
-            LogRel(("Serial#%d: Failed to set modem lines with %Rrc during reset\n",
-                    pThis->pDevInsR3->iInstance, rc));
-
-        uint32_t fStsLines = 0;
-        rc = pThis->pDrvSerial->pfnQueryStsLines(pThis->pDrvSerial, &fStsLines);
-        if (RT_SUCCESS(rc))
-            uartR3StsLinesUpdate(pThis, fStsLines);
-        else
-            LogRel(("Serial#%d: Failed to query status line status with %Rrc during reset\n",
-                    pThis->pDevInsR3->iInstance, rc));
-    }
+    uartR3XferReset(pThis);
 }
 
@@ -1637,4 +1659,5 @@
             return VERR_PDM_MISSING_INTERFACE;
         }
+        uartR3XferReset(pThis);
     }
     else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
@@ -1643,4 +1666,5 @@
         pThis->pDrvSerial = NULL;
         rc = VINF_SUCCESS;
+        uartR3XferReset(pThis);
         LogRel(("Serial#%d: no unit\n", pThis->pDevInsR3->iInstance));
     }
@@ -1657,4 +1681,5 @@
     pThis->pDrvBase   = NULL;
     pThis->pDrvSerial = NULL;
+    uartR3XferReset(pThis);
 }
 
