Index: /trunk/include/VBox/pdmifs.h
===================================================================
--- /trunk/include/VBox/pdmifs.h	(revision 28100)
+++ /trunk/include/VBox/pdmifs.h	(revision 28101)
@@ -1505,4 +1505,14 @@
      */
     DECLR3CALLBACKMEMBER(int, pfnNotifyStatusLinesChanged,(PPDMICHARPORT pInterface, uint32_t fNewStatusLines));
+    
+    /**
+     * Notify the device when the driver buffer is full.
+     *
+     * @returns VBox status code.
+     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
+     * @param   fFull           Buffer full.
+     * @thread  Any thread.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnNotifyBufferFull,(PPDMICHARPORT pInterface, bool fFull));
 
     /**
Index: /trunk/src/VBox/Devices/Serial/DevSerial.cpp
===================================================================
--- /trunk/src/VBox/Devices/Serial/DevSerial.cpp	(revision 28100)
+++ /trunk/src/VBox/Devices/Serial/DevSerial.cpp	(revision 28101)
@@ -274,8 +274,6 @@
             s->divider = (s->divider & 0xff00) | val;
             serial_update_parameters(s);
-        } else {
+        } else if (s->lsr & UART_LSR_THRE) {
             s->thr_ipending = 0;
-            s->lsr &= ~UART_LSR_THRE;
-            serial_update_irq(s);
             ch = val;
             if (RT_LIKELY(s->pDrvChar))
@@ -286,8 +284,7 @@
             }
             s->thr_ipending = 1;
-            s->lsr |= UART_LSR_THRE;
-            s->lsr |= UART_LSR_TEMT;
             serial_update_irq(s);
-        }
+        } else
+            Log(("serial: THR not EMPTY!\n"));
         break;
     case 1:
@@ -508,4 +505,23 @@
 }
 
+static DECLCALLBACK(int) serialNotifyBufferFull(PPDMICHARPORT pInterface, bool fFull)
+{
+    SerialState *pThis = PDMICHARPORT_2_SERIALSTATE(pInterface);
+    PDMCritSectEnter(&pThis->CritSect, VERR_PERMISSION_DENIED);
+    if (fFull)
+    {
+        pThis->lsr &= ~UART_LSR_THRE;
+    }
+    else
+    {
+        pThis->thr_ipending = 1;
+        pThis->lsr |= UART_LSR_THRE;
+        pThis->lsr |= UART_LSR_TEMT;
+    }
+    serial_update_irq(pThis);
+    PDMCritSectLeave(&pThis->CritSect);
+    return VINF_SUCCESS;
+}
+
 static DECLCALLBACK(int) serialNotifyBreak(PPDMICHARPORT pInterface)
 {
@@ -798,4 +814,5 @@
     pThis->ICharPort.pfnNotifyRead               = serialNotifyRead;
     pThis->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
+    pThis->ICharPort.pfnNotifyBufferFull         = serialNotifyBufferFull;
     pThis->ICharPort.pfnNotifyBreak              = serialNotifyBreak;
 
Index: /trunk/src/VBox/Devices/Serial/DrvChar.cpp
===================================================================
--- /trunk/src/VBox/Devices/Serial/DrvChar.cpp	(revision 28100)
+++ /trunk/src/VBox/Devices/Serial/DrvChar.cpp	(revision 28101)
@@ -81,4 +81,5 @@
     uint32_t volatile           iSendQueueHead;
     uint32_t                    iSendQueueTail;
+    uint32_t                    cEntries;
 
     uintptr_t                   AlignmentPadding;
@@ -118,13 +119,16 @@
     LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
 
-    for (uint32_t i=0;i<cbWrite;i++)
-    {
-        uint32_t idx = pThis->iSendQueueHead;
-
-        pThis->aSendQueue[idx] = pBuffer[i];
-        idx = (idx + 1) & CHAR_MAX_SEND_QUEUE_MASK;
+    for (uint32_t i=0; i<cbWrite; i++)
+    {
+        uint32_t iOld = pThis->iSendQueueHead;
+        uint32_t iNew = (iOld + 1) & CHAR_MAX_SEND_QUEUE_MASK;
+
+        pThis->aSendQueue[iOld] = pBuffer[i];
 
         STAM_COUNTER_INC(&pThis->StatBytesWritten);
-        ASMAtomicXchgU32(&pThis->iSendQueueHead, idx);
+        ASMAtomicXchgU32(&pThis->iSendQueueHead, iNew);
+        ASMAtomicIncU32(&pThis->cEntries);
+        if (pThis->cEntries > CHAR_MAX_SEND_QUEUE_MASK / 2)
+            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, true);
     }
     RTSemEventSignal(pThis->SendSem);
@@ -174,4 +178,5 @@
 
             rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed);
+            pThis->pDrvCharPort->pfnNotifyBufferFull(pThis->pDrvCharPort, false);
             if (RT_SUCCESS(rc))
             {
@@ -179,4 +184,5 @@
                 pThis->iSendQueueTail++;
                 pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK;
+                ASMAtomicDecU32(&pThis->cEntries);
             }
             else if (rc == VERR_TIMEOUT)
