Index: trunk/src/VBox/Devices/Serial/DrvCharNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvCharNew.cpp	(revision 73711)
+++ trunk/src/VBox/Devices/Serial/DrvCharNew.cpp	(revision 73712)
@@ -59,9 +59,11 @@
     /** Flag to notify the receive thread it should terminate. */
     volatile bool               fShutdown;
+    /** Flag whether data is available from the device/driver above as notified by the driver. */
+    volatile bool               fAvailWrExt;
+    /** Internal copy of the flag which gets reset when there is no data anymore. */
+    bool                        fAvailWrInt;
     /** I/O thread. */
     PPDMTHREAD                  pThrdIo;
 
-    /** Amount of data available for sending from the device/driver above. */
-    volatile size_t             cbAvailWr;
     /** Small send buffer. */
     uint8_t                     abTxBuf[16];
@@ -112,12 +114,12 @@
  * @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify}
  */
-static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
-{
-    LogFlowFunc(("pInterface=%#p cbAvail=%zu\n", pInterface, cbAvail));
+static DECLCALLBACK(int) drvCharDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface)
+{
+    LogFlowFunc(("pInterface=%#p\n", pInterface));
     PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ISerialConnector);
 
     int rc = VINF_SUCCESS;
-    size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
-    if (!cbAvailOld)
+    bool fAvailOld = ASMAtomicXchgBool(&pThis->fAvailWrExt, true);
+    if (!fAvailOld)
         rc = pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
 
@@ -219,8 +221,11 @@
         uint32_t fEvts = 0;
 
+        if (!pThis->fAvailWrInt)
+            pThis->fAvailWrInt = ASMAtomicXchgBool(&pThis->fAvailWrExt, false);
+
         if (   !pThis->cbRemaining
             && pThis->pDrvStream->pfnRead)
             fEvts |= RTPOLL_EVT_READ;
-        if (   pThis->cbAvailWr
+        if (   pThis->fAvailWrInt
             || pThis->cbTxUsed)
             fEvts |= RTPOLL_EVT_WRITE;
@@ -232,8 +237,8 @@
             if (fEvtsRecv & RTPOLL_EVT_WRITE)
             {
-                if (pThis->cbAvailWr)
+                if (pThis->fAvailWrInt)
                 {
                     /* Stuff as much data into the TX buffer as we can. */
-                    size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
+                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
                     size_t cbFetched = 0;
                     rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
@@ -242,12 +247,9 @@
 
                     if (cbFetched > 0)
-                    {
-                        ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
                         pThis->cbTxUsed  += cbFetched;
-                    }
                     else
                     {
-                        /* The guest reset the send queue and there is no data available anymore. */
-                        pThis->cbAvailWr = 0;
+                        /* There is no data available anymore. */
+                        pThis->fAvailWrInt = false;
                     }
                 }
@@ -331,5 +333,6 @@
 
     /* Reset TX and RX buffers. */
-    pThis->cbAvailWr   = 0;
+    pThis->fAvailWrExt = false;
+    pThis->fAvailWrInt = false;
     pThis->cbTxUsed    = 0;
     pThis->cbRemaining = 0;
Index: trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 73711)
+++ trunk/src/VBox/Devices/Serial/DrvHostSerialNew.cpp	(revision 73712)
@@ -63,6 +63,8 @@
     char                        *pszDevicePath;
 
-    /** Amount of data available for sending from the device/driver above. */
-    volatile size_t             cbAvailWr;
+    /** Flag whether data is available from the device/driver above as notified by the driver. */
+    volatile bool               fAvailWrExt;
+    /** Internal copy of the flag which gets reset when there is no data anymore. */
+    bool                        fAvailWrInt;
     /** Small send buffer. */
     uint8_t                     abTxBuf[16];
@@ -187,11 +189,11 @@
 
 /** @interface_method_impl{PDMISERIALCONNECTOR,pfnDataAvailWrNotify} */
-static DECLCALLBACK(int) drvHostSerialDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface, size_t cbAvail)
+static DECLCALLBACK(int) drvHostSerialDataAvailWrNotify(PPDMISERIALCONNECTOR pInterface)
 {
     PDRVHOSTSERIAL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTSERIAL, ISerialConnector);
 
     int rc = VINF_SUCCESS;
-    size_t cbAvailOld = ASMAtomicAddZ(&pThis->cbAvailWr, cbAvail);
-    if (!cbAvailOld)
+    bool fAvailOld = ASMAtomicXchgBool(&pThis->fAvailWrExt, true);
+    if (!fAvailOld)
         rc = RTSerialPortEvtPollInterrupt(pThis->hSerialPort);
 
@@ -376,6 +378,9 @@
         uint32_t fEvtFlags = RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED | RTSERIALPORT_EVT_F_BREAK_DETECTED;
 
+        if (!pThis->fAvailWrInt)
+            pThis->fAvailWrInt = ASMAtomicXchgBool(&pThis->fAvailWrExt, false);
+
         /* Wait until there is room again if there is anyting to send. */
-        if (   pThis->cbAvailWr
+        if (   pThis->fAvailWrInt
             || pThis->cbTxUsed)
             fEvtFlags |= RTSERIALPORT_EVT_F_DATA_TX;
@@ -391,8 +396,8 @@
             if (fEvtsRecv & RTSERIALPORT_EVT_F_DATA_TX)
             {
-                if (pThis->cbAvailWr)
+                if (pThis->fAvailWrInt)
                 {
                     /* Stuff as much data into the TX buffer as we can. */
-                    size_t cbToFetch = RT_MIN(RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed, pThis->cbAvailWr);
+                    size_t cbToFetch = RT_ELEMENTS(pThis->abTxBuf) - pThis->cbTxUsed;
                     size_t cbFetched = 0;
                     rc = pThis->pDrvSerialPort->pfnReadWr(pThis->pDrvSerialPort, &pThis->abTxBuf[pThis->cbTxUsed], cbToFetch,
@@ -401,12 +406,9 @@
 
                     if (cbFetched > 0)
-                    {
-                        ASMAtomicSubZ(&pThis->cbAvailWr, cbFetched);
-                        pThis->cbTxUsed  += cbFetched;
-                    }
+                        pThis->cbTxUsed += cbFetched;
                     else
                     {
-                        /* The guest reset the send queue and there is no data available anymore. */
-                        pThis->cbAvailWr = 0;
+                        /* There is no data available anymore. */
+                        pThis->fAvailWrInt = false;
                     }
                 }
@@ -565,5 +567,6 @@
     pThis->pDrvIns                               = pDrvIns;
     pThis->hSerialPort                           = NIL_RTSERIALPORT;
-    pThis->cbAvailWr                             = 0;
+    pThis->fAvailWrExt                           = false;
+    pThis->fAvailWrInt                           = false;
     pThis->cbTxUsed                              = 0;
     pThis->offWrite                              = 0;
Index: trunk/src/VBox/Devices/Serial/UartCore.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/UartCore.cpp	(revision 73711)
+++ trunk/src/VBox/Devices/Serial/UartCore.cpp	(revision 73712)
@@ -70,5 +70,5 @@
 # define UART_REG_IIR_ID_SET(a_Val)          (((a_Val) << 1) & UART_REG_IIR_ID_MASK)
 /** Gets the interrupt identification from the given IIR register value. */
-# define UART_REG_IIR_ID_GET(a_Val)          (((a_Val) >> 1) & UART_REG_IIR_ID_MASK)
+# define UART_REG_IIR_ID_GET(a_Val)          (((a_Val) & UART_REG_IIR_ID_MASK) >> 1)
 /** Receiver Line Status interrupt. */
 #  define UART_REG_IIR_ID_RCL                0x3
@@ -337,4 +337,67 @@
 
 
+/**
+ * Returns the amount of bytes stored in the given FIFO.
+ *
+ * @retrusn Amount of bytes stored in the FIFO.
+ * @param   pFifo               The FIFO.
+ */
+DECLINLINE(size_t) uartFifoUsedGet(PUARTFIFO pFifo)
+{
+    return pFifo->cbUsed;
+}
+
+
+/**
+ * Puts a new character into the given FIFO.
+ *
+ * @returns Flag whether the FIFO overflowed.
+ * @param   pFifo               The FIFO to put the data into.
+ * @param   fOvrWr              Flag whether to overwrite data if the FIFO is full.
+ * @param   bData               The data to add.
+ */
+DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData)
+{
+    if (fOvrWr || pFifo->cbUsed < pFifo->cbMax)
+    {
+        pFifo->abBuf[pFifo->offWrite] = bData;
+        pFifo->offWrite = (pFifo->offWrite + 1) % pFifo->cbMax;
+    }
+
+    bool fOverFlow = false;
+    if (pFifo->cbUsed < pFifo->cbMax)
+        pFifo->cbUsed++;
+    else
+    {
+        fOverFlow = true;
+        if (fOvrWr) /* Advance the read position to account for the lost character. */
+           pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
+    }
+
+    return fOverFlow;
+}
+
+
+/**
+ * Returns the next character in the FIFO.
+ *
+ * @return Next byte in the FIFO.
+ * @param   pFifo               The FIFO to get data from.
+ */
+DECLINLINE(uint8_t) uartFifoGet(PUARTFIFO pFifo)
+{
+    uint8_t bRet = 0;
+
+    if (pFifo->cbUsed)
+    {
+        bRet = pFifo->abBuf[pFifo->offRead];
+        pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
+        pFifo->cbUsed--;
+    }
+
+    return bRet;
+}
+
+
 #ifdef IN_RING3
 /**
@@ -365,57 +428,4 @@
 
 
-/**
- * Puts a new character into the given FIFO.
- *
- * @returns Flag whether the FIFO overflowed.
- * @param   pFifo               The FIFO to put the data into.
- * @param   fOvrWr              Flag whether to overwrite data if the FIFO is full.
- * @param   bData               The data to add.
- */
-DECLINLINE(bool) uartFifoPut(PUARTFIFO pFifo, bool fOvrWr, uint8_t bData)
-{
-    if (fOvrWr || pFifo->cbUsed < pFifo->cbMax)
-    {
-        pFifo->abBuf[pFifo->offWrite] = bData;
-        pFifo->offWrite = (pFifo->offWrite + 1) % pFifo->cbMax;
-    }
-
-    bool fOverFlow = false;
-    if (pFifo->cbUsed < pFifo->cbMax)
-        pFifo->cbUsed++;
-    else
-    {
-        fOverFlow = true;
-        if (fOvrWr) /* Advance the read position to account for the lost character. */
-           pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
-    }
-
-    return fOverFlow;
-}
-#endif
-
-
-/**
- * Returns the next character in the FIFO.
- *
- * @return Next byte in the FIFO.
- * @param   pFifo               The FIFO to get data from.
- */
-DECLINLINE(uint8_t) uartFifoGet(PUARTFIFO pFifo)
-{
-    uint8_t bRet = 0;
-
-    if (pFifo->cbUsed)
-    {
-        bRet = pFifo->abBuf[pFifo->offRead];
-        pFifo->offRead = (pFifo->offRead + 1) % pFifo->cbMax;
-        pFifo->cbUsed--;
-    }
-
-    return bRet;
-}
-
-
-#ifdef IN_RING3
 /**
  * Tries to copy the requested amount of data from the given FIFO into the provided buffer.
@@ -748,5 +758,11 @@
         {
 #ifndef IN_RING3
-            rc = VINF_IOM_R3_IOPORT_WRITE;
+            if (!uartFifoUsedGet(&pThis->FifoXmit))
+                rc = VINF_IOM_R3_IOPORT_WRITE;
+            else
+            {
+                uartFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);
+                UART_REG_CLR(pThis->uRegLsr, UART_REG_LSR_THRE | UART_REG_LSR_TEMT);
+            }
 #else
             uartFifoPut(&pThis->FifoXmit, true /*fOvrWr*/, uVal);
@@ -754,7 +770,8 @@
             pThis->fThreEmptyPending = false;
             uartIrqUpdate(pThis);
-            if (pThis->pDrvSerial)
+            if (   pThis->pDrvSerial
+                && uartFifoUsedGet(&pThis->FifoXmit) == 1)
             {
-                int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);
+                int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial);
                 if (RT_FAILURE(rc2))
                     LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", pThis->pDevInsR3->iInstance, rc2));
@@ -776,5 +793,5 @@
                 if (pThis->pDrvSerial)
                 {
-                    int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial, 1);
+                    int rc2 = pThis->pDrvSerial->pfnDataAvailWrNotify(pThis->pDrvSerial);
                     if (RT_FAILURE(rc2))
                         LogRelMax(10, ("Serial#%d: Failed to send data with %Rrc\n", pThis->pDevInsR3->iInstance, rc2));
@@ -821,4 +838,8 @@
         else
             pThis->uRegIer = uVal & UART_REG_IER_MASK_WR_16750;
+
+        if (pThis->uRegLsr & UART_REG_LSR_THRE)
+            pThis->fThreEmptyPending = true;
+
         uartIrqUpdate(pThis);
     }
@@ -1657,5 +1678,5 @@
     pThis->uRegScr        = 0;
     pThis->fIrqCtiPending = false;
-    pThis->fThreEmptyPending = false;
+    pThis->fThreEmptyPending = true;
 
     /* Standard FIFO size for 15550A. */
