Index: trunk/src/VBox/Devices/Serial/DevSerialNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DevSerialNew.cpp	(revision 72130)
+++ trunk/src/VBox/Devices/Serial/DevSerialNew.cpp	(revision 72132)
@@ -64,5 +64,5 @@
 # define UART_REG_IIR_ID_MASK                0x0e
 /** Sets the interrupt identification to the given value. */
-# define UART_REG_IIR_ID_SET(a_Val)          (((a_Val) & UART_REG_IIR_ID_MASK) << 1)
+# define UART_REG_IIR_ID_SET(a_Val)          (((a_Val) << 1) & UART_REG_IIR_ID_MASK)
 /** Receiver Line Status interrupt. */
 #  define UART_REG_IIR_ID_RCL                0x3
@@ -304,4 +304,6 @@
 static void serialIrqUpdate(PDEVSERIAL pThis)
 {
+    LogFlowFunc(("pThis=%#p\n", pThis));
+
     /*
      * The interrupt uses a priority scheme, only the interrupt with the
@@ -327,13 +329,17 @@
     else if (   (pThis->uRegMsr & UART_REG_MSR_BITS_IIR_MS)
              && (pThis->uRegIer & UART_REG_IER_EDSSI))
-        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_MSR_BITS_IIR_MS);
+        uRegIirNew = UART_REG_IIR_ID_SET(UART_REG_IIR_ID_MS);
 
     /** @todo Character timeout indication for FIFO mode. */
 
-    LogFlowFunc(("uRegIirNew=%#x uRegIir=%#x\n", uRegIirNew, pThis->uRegIir));
+    LogFlowFunc(("    uRegIirNew=%#x uRegIir=%#x\n", uRegIirNew, pThis->uRegIir));
 
     /* Change interrupt only if the interrupt status really changed from the previous value. */
     if (uRegIirNew != (pThis->uRegIir & UART_REG_IIR_CHANGED_MASK))
     {
+        LogFlow(("    Interrupt source changed from %#x -> %#x (IRQ %d -> %d)\n",
+                 pThis->uRegIir, uRegIirNew,
+                 pThis->uRegIir == UART_REG_IIR_IP_NO_INT ? 0 : 1,
+                 uRegIirNew == UART_REG_IIR_IP_NO_INT ? 0 : 1));
         if (uRegIirNew == UART_REG_IIR_IP_NO_INT)
             PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 0);
@@ -341,4 +347,6 @@
             PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->uIrq, 1);
     }
+    else
+        LogFlow(("    No change in interrupt source\n"));
 
     if (pThis->uRegFcr & UART_REG_FCR_FIFO_EN)
@@ -482,5 +490,5 @@
 #else
                 pThis->uRegThr = uVal;
-                UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE);
+                UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);
                 if (pThis->pDrvSerial)
                 {
@@ -756,4 +764,62 @@
 
 
+#ifdef LOG_ENABLED
+/**
+ * Converts the register index into a sensible memnonic.
+ *
+ * @returns Register memnonic.
+ * @param   pThis               The serial port instance.
+ * @param   idxReg              Register index.
+ * @param   fWrite              Flag whether the register gets written.
+ */
+DECLINLINE(const char *) serialRegIdx2Str(PDEVSERIAL pThis, uint8_t idxReg, bool fWrite)
+{
+    const char *psz = "INV";
+
+    switch (idxReg)
+    {
+        /*case UART_REG_THR_DLL_INDEX:*/
+        case UART_REG_RBR_DLL_INDEX:
+            if (pThis->uRegLcr & UART_REG_LCR_DLAB)
+                psz = "DLL";
+            else if (fWrite)
+                psz = "THR";
+            else
+                psz = "RBR";
+            break;
+        case UART_REG_IER_DLM_INDEX:
+            if (pThis->uRegLcr & UART_REG_LCR_DLAB)
+                psz = "DLM";
+            else
+                psz = "IER";
+            break;
+        /*case UART_REG_IIR_INDEX:*/
+        case UART_REG_FCR_INDEX:
+            if (fWrite)
+                psz = "FCR";
+            else
+                psz = "IIR";
+            break;
+        case UART_REG_LCR_INDEX:
+            psz = "LCR";
+            break;
+        case UART_REG_MCR_INDEX:
+            psz = "MCR";
+            break;
+        case UART_REG_LSR_INDEX:
+            psz = "LSR";
+            break;
+        case UART_REG_MSR_INDEX:
+            psz = "MSR";
+            break;
+        case UART_REG_SCR_INDEX:
+            psz = "SCR";
+            break;
+    }
+
+    return psz;
+}
+#endif
+
 /* -=-=-=-=-=-=-=-=- I/O Port Access Handlers -=-=-=-=-=-=-=-=- */
 
@@ -767,6 +833,7 @@
     RT_NOREF_PV(pvUser);
 
-    LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop u32=%#x cb=%u\n",
-                 pDevIns, pvUser, uPort, u32, cb));
+    uint8_t idxReg = uPort & 0x7;
+    LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u\n",
+                 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, true /*fWrite*/), u32, cb));
 
     AssertMsgReturn(cb == 1, ("uPort=%#x cb=%d u32=%#x\n", uPort, cb, u32), VINF_SUCCESS);
@@ -774,5 +841,5 @@
     int rc = VINF_SUCCESS;
     uint8_t uVal = (uint8_t)u32;
-    switch (uPort & 0x7)
+    switch (idxReg)
     {
         case UART_REG_THR_DLL_INDEX:
@@ -815,6 +882,7 @@
         return VERR_IOM_IOPORT_UNUSED;
 
+    uint8_t idxReg = uPort & 0x7;
     int rc = VINF_SUCCESS;
-    switch (uPort & 0x7)
+    switch (idxReg)
     {
         case UART_REG_RBR_DLL_INDEX:
@@ -846,6 +914,6 @@
     }
 
-    LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop u32=%#x cb=%u -> %Rrc\n",
-                 pDevIns, pvUser, uPort, *pu32, cb, rc));
+    LogFlowFunc(("pDevIns=%#p pvUser=%#p uPort=%RTiop{%s} u32=%#x cb=%u -> %Rrc\n",
+                 pDevIns, pvUser, uPort, serialRegIdx2Str(pThis, idxReg, false /*fWrite*/), *pu32, cb, rc));
     return rc;
 }
@@ -862,4 +930,5 @@
 static DECLCALLBACK(int) serialR3DataAvailRdrNotify(PPDMISERIALPORT pInterface, size_t cbAvail)
 {
+    LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail));
     PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);
 
@@ -869,4 +938,5 @@
     if (!cbAvailOld)
     {
+        LogFlow(("    cbAvailRdr=0 -> cbAvailRdr=%zu\n", cbAvail));
         PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
         size_t cbRead = 0;
@@ -877,4 +947,6 @@
         PDMCritSectLeave(&pThis->CritSect);
     }
+    else
+        LogFlow(("    cbAvailOld=%zu\n", cbAvailOld));
     return VINF_SUCCESS;
 }
@@ -886,4 +958,5 @@
 static DECLCALLBACK(int) serialR3DataSentNotify(PPDMISERIALPORT pInterface)
 {
+    LogFlowFunc(("pInterface=%#p\n", pInterface));
     PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);
 
@@ -902,4 +975,5 @@
 static DECLCALLBACK(int) serialR3ReadWr(PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead)
 {
+    LogFlowFunc(("pInterface=%#p pvBuf=%#p cbRead=%zu pcbRead=%#p\n", pInterface, pvBuf, cbRead, pcbRead));
     PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);
 
@@ -922,4 +996,5 @@
     }
 
+    LogFlowFunc(("-> VINF_SUCCESS{*pcbRead=%zu}\n", *pcbRead));
     PDMCritSectLeave(&pThis->CritSect);
     return VINF_SUCCESS;
@@ -932,4 +1007,5 @@
 static DECLCALLBACK(int) serialR3NotifyStsLinesChanged(PPDMISERIALPORT pInterface, uint32_t fNewStatusLines)
 {
+    LogFlowFunc(("pInterface=%#p fNewStatusLines=%#x\n", pInterface, fNewStatusLines));
     PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);
 
@@ -946,4 +1022,5 @@
 static DECLCALLBACK(int) serialR3NotifyBrk(PPDMISERIALPORT pInterface)
 {
+    LogFlowFunc(("pInterface=%#p\n", pInterface));
     PDEVSERIAL pThis = RT_FROM_MEMBER(pInterface, DEVSERIAL, ISerialPort);
 
Index: trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 72130)
+++ trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 72132)
@@ -46,5 +46,5 @@
  * Char driver instance data.
  *
- * @implements  PDMICHARCONNECTOR
+ * @implements  PDMISERIALCONNECTOR
  */
 typedef struct DRVHOSTSERIAL
@@ -76,4 +76,6 @@
     /** Current offset into the read buffer. */
     volatile uint32_t           offRead;
+    /** Current amount of data in the buffer. */
+    volatile size_t             cbReadBuf;
 
     /** Read/write statistics */
@@ -103,14 +105,12 @@
 DECLINLINE(size_t) drvHostSerialReadBufGetWrite(PDRVHOSTSERIAL pThis, void **ppv)
 {
-    uint32_t offRead  = ASMAtomicReadU32(&pThis->offRead);
-    uint32_t offWrite = ASMAtomicReadU32(&pThis->offWrite);
-
     if (ppv)
-        *ppv = &pThis->abReadBuf[offWrite];
-
-    if (offWrite >= offRead)
-        return sizeof(pThis->abReadBuf) - offWrite;
-    else
-        return offRead - offWrite - 1; /* Leave one byte free. */
+        *ppv = &pThis->abReadBuf[pThis->offWrite];
+
+    size_t cbFree = sizeof(pThis->abReadBuf) - ASMAtomicReadZ(&pThis->cbReadBuf);
+    if (cbFree)
+        cbFree = RT_MIN(cbFree, sizeof(pThis->abReadBuf) - pThis->offWrite);
+
+    return cbFree;
 }
 
@@ -125,14 +125,12 @@
 DECLINLINE(size_t) drvHostSerialReadBufGetRead(PDRVHOSTSERIAL pThis, void **ppv)
 {
-    uint32_t offRead  = ASMAtomicReadU32(&pThis->offRead);
-    uint32_t offWrite = ASMAtomicReadU32(&pThis->offWrite);
-
     if (ppv)
-        *ppv = &pThis->abReadBuf[offRead];
-
-    if (offWrite < offRead)
-        return sizeof(pThis->abReadBuf) - offRead;
-    else
-        return offWrite - offRead;
+        *ppv = &pThis->abReadBuf[pThis->offRead];
+
+    size_t cbUsed = ASMAtomicReadZ(&pThis->cbReadBuf);
+    if (cbUsed)
+        cbUsed = RT_MIN(cbUsed, sizeof(pThis->abReadBuf) - pThis->offRead);
+
+    return cbUsed;
 }
 
@@ -150,4 +148,5 @@
     offWrite = (offWrite + cbAdv) % sizeof(pThis->abReadBuf);
     ASMAtomicWriteU32(&pThis->offWrite, offWrite);
+    ASMAtomicAddZ(&pThis->cbReadBuf, cbAdv);
 }
 
@@ -165,4 +164,5 @@
     offRead = (offRead + cbAdv) % sizeof(pThis->abReadBuf);
     ASMAtomicWriteU32(&pThis->offRead, offRead);
+    ASMAtomicSubZ(&pThis->cbReadBuf, cbAdv);
 }
 
@@ -228,4 +228,7 @@
 
     *pcbRead = cbReadAll;
+    /* Kick the I/O thread if there is nothing to read to recalculate the poll flags. */
+    if (!drvHostSerialReadBufGetRead(pThis, NULL))
+        rc = RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
 
     STAM_COUNTER_ADD(&pThis->StatBytesRead, cbReadAll);
@@ -549,4 +552,5 @@
      * Init basic data members and interfaces.
      */
+    pThis->pDrvIns                               = pDrvIns;
     pThis->hSerialPort                           = NIL_RTSERIALPORT;
     pThis->cbAvailWr                             = 0;
@@ -554,4 +558,5 @@
     pThis->offWrite                              = 0;
     pThis->offRead                               = 0;
+    pThis->cbReadBuf                             = 0;
     /* IBase. */
     pDrvIns->IBase.pfnQueryInterface             = drvHostSerialQueryInterface;
