Index: /trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp	(revision 65035)
+++ /trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp	(revision 65036)
@@ -108,5 +108,7 @@
     /** Whether we use a memory mapped file instead of our
      *  own allocated PCM buffer below. */
-    bool                fMemMapped;
+    /** @todo The memory mapped code seems to be utterly broken.
+     *        Needs investigation! */
+    bool                fMMIO;
 #endif
     /** Own PCM buffer in case memory mapping is unavailable. */
@@ -303,4 +305,11 @@
         }
 #endif
+
+        /* Check access mode (input or output). */
+        bool fIn = ((fOpen & O_ACCMODE) == O_RDONLY);
+
+        LogRel2(("OSS: Requested %RU16 %s fragments, %RU32 bytes each\n",
+                 pReq->cFragments, fIn ? "input" : "output", pReq->cbFragmentSize));
+
         int mmmmssss = (pReq->cFragments << 16) | lsbindex(pReq->cbFragmentSize);
         if (ioctl(hFile, SNDCTL_DSP_SETFRAGMENT, &mmmmssss))
@@ -311,7 +320,4 @@
             break;
         }
-
-        /* Check access mode (input or output). */
-        bool fIn = ((fOpen & O_ACCMODE) == O_RDONLY);
 
         audio_buf_info abinfo;
@@ -331,4 +337,7 @@
             pObt->cbFragmentSize = abinfo.fragsize;
 
+            LogRel2(("OSS: Got %RU16 %s fragments, %RU32 bytes each\n",
+                     pObt->cFragments, fIn ? "input" : "output", pObt->cbFragmentSize));
+
             *phFile = hFile;
         }
@@ -356,13 +365,6 @@
     POSSAUDIOSTREAMOUT pStreamOut = (POSSAUDIOSTREAMOUT)pStream;
 
-#ifdef RT_OS_L4
-    return VINF_SUCCESS;
-#else
-    if (!pStreamOut->fMemMapped)
-        return VINF_SUCCESS;
-#endif
-
     int rc = VINF_SUCCESS;
-    int mask;
+
     switch (enmStreamCmd)
     {
@@ -370,8 +372,8 @@
         case PDMAUDIOSTREAMCMD_RESUME:
         {
-            DrvAudioHlpClearBuf(&pStreamOut->Props,
-                                pStreamOut->pvBuf, pStreamOut->cbBuf, AudioMixBufSize(&pStream->MixBuf));
-
-            mask = PCM_ENABLE_OUTPUT;
+            DrvAudioHlpClearBuf(&pStreamOut->Props, pStreamOut->pvBuf, pStreamOut->cbBuf,
+                                AUDIOMIXBUF_B2S(&pStream->MixBuf, pStreamOut->cbBuf));
+
+            int mask = PCM_ENABLE_OUTPUT;
             if (ioctl(pStreamOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
             {
@@ -386,5 +388,5 @@
         case PDMAUDIOSTREAMCMD_PAUSE:
         {
-            mask = 0;
+            int mask = 0;
             if (ioctl(pStreamOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
             {
@@ -423,5 +425,6 @@
  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
  */
-static DECLCALLBACK(int) drvHostOSSAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
+static DECLCALLBACK(int) drvHostOSSAudioStreamCapture(PPDMIHOSTAUDIO pInterface,
+                                                      PPDMAUDIOSTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
 {
     RT_NOREF(pInterface, cbBuf, pvBuf);
@@ -542,5 +545,5 @@
 
 #ifndef RT_OS_L4
-    if (pStrm->fMemMapped)
+    if (pStrm->fMMIO)
     {
         if (pStrm->pvBuf)
@@ -554,5 +557,5 @@
                 pStrm->cbBuf      = 0;
 
-                pStrm->fMemMapped = false;
+                pStrm->fMMIO      = false;
             }
             else
@@ -671,5 +674,5 @@
             pCfgAcq->enmFormat     = obtStream.enmFormat;
             pCfgAcq->uHz           = obtStream.uFreq;
-            pCfgAcq->cChannels     = pCfgReq->cChannels; /** @todo r=andy Why not using obtStream? */
+            pCfgAcq->cChannels     = obtStream.cChannels;
             pCfgAcq->enmEndianness = obtStream.enmENDIANNESS;
 
@@ -738,10 +741,10 @@
         reqStream.cbFragmentSize = s_OSSConf.fragsize;
 
-        rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY | O_NONBLOCK, &reqStream, &obtStream, &hFile);
+        rc = ossStreamOpen(s_OSSConf.devpath_out, O_WRONLY, &reqStream, &obtStream, &hFile);
         if (RT_SUCCESS(rc))
         {
             pCfgAcq->enmFormat     = obtStream.enmFormat;
             pCfgAcq->uHz           = obtStream.uFreq;
-            pCfgAcq->cChannels     = pCfgReq->cChannels; /** @todo r=andy Why not using obtStream? */
+            pCfgAcq->cChannels     = obtStream.cChannels;
             pCfgAcq->enmEndianness = obtStream.enmENDIANNESS;
 
@@ -761,7 +764,9 @@
         if (RT_SUCCESS(rc))
         {
-            pStrm->fMemMapped = false;
-
-            size_t cbSamples =  cSamples << pStrm->Props.cShift;
+            pStrm->fMMIO = false;
+
+            size_t cbSample = (1 << pStrm->Props.cShift);
+
+            size_t cbSamples = cSamples * cbSample;
             Assert(cbSamples);
 
@@ -795,5 +800,8 @@
                         }
                         else
-                            pStrm->fMemMapped = true;
+                        {
+                            pStrm->fMMIO = true;
+                            LogRel(("OSS: Using MMIO\n"));
+                        }
                     }
 
@@ -811,5 +819,5 @@
             /* Memory mapping failed above? Try allocating an own buffer. */
 #ifndef RT_OS_L4
-            if (!pStrm->fMemMapped)
+            if (!pStrm->fMMIO)
             {
 #endif
@@ -844,5 +852,7 @@
  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
  */
-static DECLCALLBACK(int) drvHostOSSAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
+static DECLCALLBACK(int) drvHostOSSAudioStreamPlay(PPDMIHOSTAUDIO pInterface,
+                                                   PPDMAUDIOSTREAM pStream, const void *pvBuf, uint32_t cbBuf,
+                                                   uint32_t *pcbWritten)
 {
     RT_NOREF(pInterface, cbBuf, pvBuf);
@@ -852,6 +862,9 @@
 
     int rc = VINF_SUCCESS;
-    uint32_t cbReadTotal = 0;
+    uint32_t cbWrittenTotal = 0;
+
+#ifndef RT_OS_L4
     count_info cntinfo;
+#endif
 
     do
@@ -859,9 +872,9 @@
         size_t cbBufSize = AudioMixBufSizeBytes(&pStream->MixBuf);
 
-        uint32_t cLive = AudioMixBufLive(&pStream->MixBuf);
-        uint32_t cToRead;
+        uint32_t csLive = AudioMixBufLive(&pStream->MixBuf);
+        uint32_t csToRead;
 
 #ifndef RT_OS_L4
-        if (pStrm->fMemMapped)
+        if (pStrm->fMMIO)
         {
             /* Get current playback pointer. */
@@ -869,6 +882,5 @@
             if (!rc2)
             {
-                LogRel(("OSS: Failed to retrieve current playback pointer: %s\n",
-                        strerror(errno)));
+                LogRel(("OSS: Failed to retrieve current playback pointer: %s\n", strerror(errno)));
                 rc = RTErrConvertFromErrno(errno);
                 break;
@@ -886,6 +898,6 @@
             Assert(cbData);
 
-            cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, cbData),
-                             cLive);
+            csToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, cbData),
+                             csLive);
         }
         else
@@ -903,5 +915,5 @@
             if ((size_t)abinfo.bytes > cbBufSize)
             {
-                LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBufSize));
+                LogRel2(("OSS: Warning: Too big output size (%d > %zu), limiting to %zu\n", abinfo.bytes, cbBufSize, cbBufSize));
                 abinfo.bytes = cbBufSize;
                 /* Keep going. */
@@ -910,42 +922,58 @@
             if (abinfo.bytes < 0)
             {
-                LogFlowFunc(("Warning: Invalid available size, size=%d, bufsize=%zu\n", abinfo.bytes, cbBufSize));
+                LogRel2(("OSS: Warning: Invalid available size (%d vs. %zu)\n", abinfo.bytes, cbBufSize));
                 rc = VERR_INVALID_PARAMETER;
                 break;
             }
 
-            cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, abinfo.bytes), cLive);
-            if (!cToRead)
+            csToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, abinfo.fragments * abinfo.fragsize), csLive);
+            if (!csToRead)
                 break;
 #ifndef RT_OS_L4
         }
 #endif
-        size_t cbToRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cToRead);
-        LogFlowFunc(("cbToRead=%zu\n", cbToRead));
-
-        uint32_t cRead, cbRead;
+        size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pStream->MixBuf, csToRead), pStrm->cbBuf);
+
+        uint32_t csRead, cbRead;
         while (cbToRead)
         {
-            rc = AudioMixBufReadCirc(&pStream->MixBuf, pStrm->pvBuf, cbToRead, &cRead);
+            rc = AudioMixBufReadCirc(&pStream->MixBuf, pStrm->pvBuf, cbToRead, &csRead);
             if (RT_FAILURE(rc))
                 break;
 
-            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
-            ssize_t cbWritten = write(pStrm->hFile, pStrm->pvBuf, cbRead);
-            if (cbWritten == -1)
-            {
-                LogRel(("OSS: Failed writing output data: %s\n", strerror(errno)));
-                rc = RTErrConvertFromErrno(errno);
-                break;
+            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, csRead);
+
+            uint32_t cbChunk    = cbRead;
+            uint32_t cbChunkOff = 0;
+            while (cbChunk)
+            {
+                ssize_t cbChunkWritten = write(pStrm->hFile, (uint8_t *)pStrm->pvBuf + cbChunkOff, RT_MIN(cbChunk, 4096));
+                if (cbChunkWritten < 0)
+                {
+                    LogRel(("OSS: Failed writing output data: %s\n", strerror(errno)));
+                    rc = RTErrConvertFromErrno(errno);
+                    break;
+                }
+
+                if (cbChunkWritten & pStrm->Props.uAlign)
+                {
+                    LogRel(("OSS: Misaligned write (written %z, expected %RU32)\n", cbChunkWritten, cbChunk));
+                    break;
+                }
+
+                cbChunkOff += cbChunkWritten;
+                Assert(cbChunkOff <= cbRead);
+                Assert(cbChunk    >= cbChunkWritten);
+                cbChunk    -= cbChunkWritten;
             }
 
             Assert(cbToRead >= cbRead);
-            cbToRead    -= cbRead;
-            cbReadTotal += cbRead;
+            cbToRead       -= cbRead;
+            cbWrittenTotal += cbRead;
         }
 
 #ifndef RT_OS_L4
         /* Update read pointer. */
-        if (pStrm->fMemMapped)
+        if (pStrm->fMMIO)
             pStrm->old_optr = cntinfo.ptr;
 #endif
@@ -955,12 +983,10 @@
     if (RT_SUCCESS(rc))
     {
-        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal);
-        if (cReadTotal)
-            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
+        uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbWrittenTotal);
+        if (cWrittenTotal)
+            AudioMixBufFinish(&pStream->MixBuf, cWrittenTotal);
 
         if (pcbWritten)
-            *pcbWritten = cReadTotal;
-
-        LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes), rc=%Rrc\n", cReadTotal, cbReadTotal, rc));
+            *pcbWritten = cbWrittenTotal;
     }
 
@@ -994,5 +1020,6 @@
  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
  */
-static DECLCALLBACK(int) drvHostOSSAudioStreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
+static DECLCALLBACK(int) drvHostOSSAudioStreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
+                                                     PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
 {
     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
@@ -1032,5 +1059,6 @@
  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
  */
-static DECLCALLBACK(int) drvHostOSSAudioStreamControl(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
+static DECLCALLBACK(int) drvHostOSSAudioStreamControl(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
+                                                      PDMAUDIOSTREAMCMD enmStreamCmd)
 {
     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
