Index: /trunk/src/VBox/Devices/Audio/DevHDA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 65017)
+++ /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 65018)
@@ -4647,4 +4647,5 @@
     {
         int rc2;
+        uint32_t cbDMA = 0;
 
         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
@@ -4656,29 +4657,39 @@
              */
 
-            uint8_t  abFIFO[HDA_FIFO_MAX + 1];
-            uint32_t cbProcessed = 0;
+            uint8_t abFIFO[HDA_FIFO_MAX + 1];
+            size_t  offFIFO = 0;
 
             /* Do one DMA transfer with FIFOS size at a time. */
-            rc2 = hdaStreamDoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), (uint32_t)pStream->u16FIFOS /* cbToProcess */,
-                                 &cbProcessed);
+            rc2 = hdaStreamDoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), (uint32_t)pStream->u16FIFOS /* cbToProcess */, &cbDMA);
             AssertRC(rc2);
 
-            if (cbProcessed)
+            uint32_t cbDMALeft = cbDMA;
+
+            while (   cbDMALeft
+                   && RTCircBufFree(pCircBuf))
             {
                 void *pvDst;
                 size_t cbDst;
 
-                Assert(pStream->u16FIFOS);
-                RTCircBufAcquireWriteBlock(pCircBuf, cbProcessed, &pvDst, &cbDst);
+                RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvDst, &cbDst);
 
                 if (cbDst)
                 {
-                    Assert(cbDst == cbProcessed);
-                    memcpy(pvDst, abFIFO, cbDst);
+                    memcpy(pvDst, abFIFO + offFIFO, cbDst);
+
+                    offFIFO += cbDst;
+                    Assert(offFIFO <= sizeof(abFIFO));
                 }
 
                 RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
+
+                Assert(cbDst <= cbDMALeft);
+                cbDMALeft -= (uint32_t)cbDst;
             }
 
+#ifdef DEBUG_andy
+            AssertMsg(cbDMALeft == 0, ("%RU32 bytes of DMA data left, CircBuf=%zu/%zu\n",
+                                       cbDMALeft, RTCircBufUsed(pCircBuf), RTCircBufSize(pCircBuf)));
+#endif
             /*
              * Process backends.
@@ -4692,7 +4703,19 @@
                 hdaStreamAsyncIONotify(pThis, pStream);
 #else
+                /* Read audio data from the HDA stream and write to the backends. */
                 rc2 = hdaStreamRead(pThis, pStream, cbUsed, NULL /* pcbRead */);
                 AssertRC(rc2);
 #endif
+            }
+
+            /* All DMA transfers done for now? */
+            if (   !cbDMA
+#ifndef VBOX_WITH_AUDIO_AC97_ASYNC_IO
+            /* All data read *and* processed for now? */
+                && RTCircBufUsed(pCircBuf) == 0
+#endif
+               )
+            {
+                fDone = true;
             }
 
@@ -4701,7 +4724,4 @@
             AssertRC(rc2);
 #endif
-            if (!cbProcessed)
-                fDone = true;
-
             STAM_PROFILE_STOP(&pThis->StatOut, a);
         }
@@ -4721,4 +4741,5 @@
             AssertRC(rc2);
 
+            /* Write read data from the backend to the HDA stream. */
             rc2 = hdaStreamWrite(pThis, pStream, pStream->u16FIFOS, NULL /* pcbWritten */);
             AssertRC(rc2);
@@ -4733,16 +4754,14 @@
             RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc);
 
-            uint32_t cbProcessed = 0;
-
             if (cbSrc)
             {
                 /* Do one DMA transfer with FIFOS size at a time. */
-                rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbProcessed);
+                rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbDMA);
                 AssertRC(rc2);
             }
 
-            RTCircBufReleaseReadBlock(pCircBuf, cbProcessed);
-
-            if (!cbProcessed)
+            RTCircBufReleaseReadBlock(pCircBuf, cbDMA);
+
+            if (!cbDMA)
                 fDone = true;
 
Index: /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 65017)
+++ /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 65018)
@@ -66,4 +66,7 @@
 /** Default timer frequency (in Hz). */
 #define AC97_TIMER_HZ       100
+
+/** Maximum FIFO size (in bytes). */
+#define AC97_FIFO_MAX       256
 
 #define AC97_SR_FIFOE RT_BIT(4)          /* rwc, FIFO error. */
@@ -473,4 +476,5 @@
 static int                ichac97StreamReOpen(PAC97STATE pThis, PAC97STREAM pStream);
 static int                ichac97StreamClose(PAC97STATE pThis, PAC97STREAM pStream);
+static void               ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStream);
 
 static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
@@ -691,4 +695,6 @@
     pRegs->lvi      = 0;
 
+    ichac97StreamReset(pThis, pStream);
+
     ichac97StreamEnable(pThis, pStream, false /* fEnable */);
 
@@ -913,4 +919,8 @@
         int rc2 = AudioMixerSinkWrite(pDstMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);
         AssertRC(rc2);
+
+#ifdef DEBUG_andy
+        Assert(cbWritten == cbSrc);
+#endif
     }
 
@@ -1179,10 +1189,10 @@
     bool fDone = false;
 
-    LogFunc(("[SD%RU8] Started\n", pStream->u8Strm));
+    Log3Func(("[SD%RU8] Started\n", pStream->u8Strm));
 
     while (!fDone)
     {
         int rc2;
-        uint32_t cbProcessed = 0;
+        uint32_t cbDMA = 0;
 
         if (pStream->u8Strm == AC97SOUNDSOURCE_PO_INDEX) /* Output. */
@@ -1193,19 +1203,41 @@
              * Read from DMA.
              */
-
-            void *pvDst;
-            size_t cbDst;
-
-            RTCircBufAcquireWriteBlock(pCircBuf, 256 /** @todo */, &pvDst, &cbDst);
-
-            if (cbDst)
+            uint8_t abFIFO[AC97_FIFO_MAX + 1];
+            size_t  offFIFO = 0;
+
+            /* Do one DMA transfer with FIFOS size at a time. */
+            rc2 = ichac97DoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), AC97_FIFO_MAX /** @todo FIFOS? */, &cbDMA);
+            AssertRC(rc2);
+
+            uint32_t cbDMALeft = cbDMA;
+
+            while (   cbDMALeft
+                   && RTCircBufFree(pCircBuf))
             {
-                /* Do one DMA transfer with FIFOS size at a time. */
-                rc2 = ichac97DoDMA(pThis, pStream, pvDst, (uint32_t)cbDst, (uint32_t)cbDst /* cbToProcess */, &cbProcessed);
-                AssertRC(rc2);
+                Log3Func(("[SD%RU8] cbLeft=%RU32\n", pStream->u8Strm, cbDMALeft));
+
+                void *pvDst;
+                size_t cbDst;
+
+                RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvDst, &cbDst);
+
+                if (cbDst)
+                {
+                    memcpy(pvDst, abFIFO + offFIFO, cbDst);
+
+                    offFIFO += cbDst;
+                    Assert(offFIFO <= sizeof(abFIFO));
+                }
+
+                RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
+
+                Assert(cbDst <= cbDMALeft);
+                cbDMALeft -= (uint32_t)cbDst;
             }
 
-            RTCircBufReleaseWriteBlock(pCircBuf, cbProcessed);
-
+#ifdef DEBUG_andy
+            AssertMsg(cbDMALeft == 0, ("%RU32 bytes of DMA data left, CircBuf=%zu/%zu\n",
+                                       cbDMALeft, RTCircBufUsed(pCircBuf), RTCircBufSize(pCircBuf)));
+#endif
             /*
              * Process backends.
@@ -1216,4 +1248,6 @@
             if (cbUsed)
             {
+                Log3Func(("[SD%RU8] cbUsed=%RU32\n", pStream->u8Strm, cbUsed));
+
 #ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
                 /* Let the asynchronous thread know that there is some new data to process. */
@@ -1221,5 +1255,5 @@
 #else
                 /* Read audio data from the AC'97 stream and write to the backends. */
-                rc2 = ichac97StreamRead(pThis, pStream, pMixSink, cbProcessed, NULL /* pcbRead */);
+                rc2 = ichac97StreamRead(pThis, pStream, pMixSink, cbUsed, NULL /* pcbRead */);
                 AssertRC(rc2);
 #endif
@@ -1227,5 +1261,5 @@
 
             /* All DMA transfers done for now? */
-            if (   !cbProcessed
+            if (   !cbDMA
 #ifndef VBOX_WITH_AUDIO_AC97_ASYNC_IO
             /* All data read *and* processed for now? */
@@ -1266,5 +1300,4 @@
              * Write to DMA.
              */
-
             void *pvSrc;
             size_t cbSrc;
@@ -1275,12 +1308,12 @@
             {
                 /* Do one DMA transfer with FIFOS size at a time. */
-                rc2 = ichac97DoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbProcessed);
+                rc2 = ichac97DoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbDMA);
                 AssertRC(rc2);
             }
 
-            RTCircBufReleaseReadBlock(pCircBuf, cbProcessed);
+            RTCircBufReleaseReadBlock(pCircBuf, cbDMA);
 
             /* All DMA transfers done for now? */
-            if (!cbProcessed)
+            if (!cbDMA)
                 fDone = true;
 
@@ -1616,5 +1649,5 @@
     AssertPtrReturnVoid(pStream);
 
-    LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
+    LogFunc(("[SD%RU8] Reset\n", pStream->u8Strm));
 
 #ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
@@ -1984,6 +2017,8 @@
                         uint32_t cbToProcess, uint32_t *pcbProcessed)
 {
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+    AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
+    AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
+    AssertPtrReturn(pvBuf,             VERR_INVALID_POINTER);
+    AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER);
     /* pcbProcessed is optional. */
 
@@ -2101,4 +2136,5 @@
         {
             cbTotal     += cbChunk;
+            Assert(cbTotal <= cbToProcess);
             Assert(cbLeft >= cbChunk);
             cbLeft      -= cbChunk;
