VirtualBox

Changeset 67429 in vbox


Ignore:
Timestamp:
Jun 15, 2017 4:23:13 PM (8 years ago)
Author:
vboxsync
Message:

Audio/DevHDA: More forward porting / integration stuff. WIP.

Location:
trunk/src/VBox/Devices
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r67265 r67429  
    814814 *
    815815 * @returns Amount of bytes ready to be read from the sink.
    816  * @param   pSink               Sink to return number of available samples for.
     816 * @param   pSink               Sink to return number of available bytes for.
    817817 */
    818818uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink)
     
    826826        return 0;
    827827
    828     uint32_t cbReadable;
     828    uint32_t cbReadable = 0;
    829829
    830830#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    831831# error "Implement me!"
    832832#else
    833     /* Get the time delta and calculate the bytes that need to be processed.
    834      *
    835      * Example for 16 bit, 44.1KhZ, stereo:
    836      * 16 bits per sample x 44.100 samples per second = 705.600 bits per second x 2 channels
    837      *     = 1.411.200 bits per second of stereo.
    838      */
    839     uint64_t tsDeltaMS  = RTTimeMilliTS() - pSink->tsLastUpdatedMS;
    840 
    841     cbReadable = ((DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8) / 1000 /* s to ms */) * tsDeltaMS;
    842 
    843     Log3Func(("[%s] Bitrate is %RU32 bytes/s -> %RU64ms / %RU32 bytes elapsed\n",
    844               pSink->pszName, DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8, tsDeltaMS, cbReadable));
     833    /* The hosts sets the pace --
     834     * so we try to find the maximum of readable data of all connected streams to this sink. */
     835    PAUDMIXSTREAM pMixStream;
     836    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     837    {
     838        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     839        {
     840            Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName));
     841            continue;
     842        }
     843
     844        cbReadable = RT_MAX(cbReadable,
     845                            pMixStream->pConn->pfnStreamGetReadable(pMixStream->pConn, pMixStream->pStream));
     846
     847        break; /** @todo For now we only support recording by the first stream added. */
     848    }
    845849#endif
    846850
     
    858862 *
    859863 * @returns Amount of bytes ready to be written to the sink.
    860  * @param   pSink               Sink to return number of available samples for.
     864 * @param   pSink               Sink to return number of available bytes for.
    861865 */
    862866uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink)
     
    870874        return 0;
    871875
    872     uint32_t cbWritable;
    873 
    874876    if (   !(pSink->fStatus & AUDMIXSINK_STS_RUNNING)
    875877        || pSink->fStatus & AUDMIXSINK_STS_PENDING_DISABLE)
    876878    {
    877         cbWritable = 0;
    878     }
    879     else
    880     {
     879        return 0;
     880    }
     881
     882    uint32_t cbWritable = 0;
     883
    881884#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
    882885# error "Implement me!"
    883886#else
    884         /* Get the time delta and calculate the bytes that need to be processed.
    885          *
    886          * Example for 16 bit, 44.1KhZ, stereo:
    887          * 16 bits per sample x 44.100 samples per second = 705.600 bits per second x 2 channels
    888          *     = 1.411.200 bits per second of stereo.
    889          */
    890         uint64_t tsDeltaMS  = RTTimeMilliTS() - pSink->tsLastUpdatedMS;
    891 
    892         cbWritable = ((DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8) / 1000 /* s to ms */) * tsDeltaMS;
    893 
    894         Log3Func(("[%s] Bitrate is %RU32 bytes/s -> %RU64ms / %RU32 bytes elapsed\n",
    895                   pSink->pszName, DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8, tsDeltaMS, cbWritable));
     887    /* The hosts sets the pace --
     888     * so we try to find the minimum of writable data to all connected streams to this sink. */
     889    PAUDMIXSTREAM pMixStream;
     890    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     891    {
     892        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     893        {
     894            Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName));
     895            continue;
     896        }
     897
     898        const uint32_t cbWritableStream = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream);
     899
     900        if (cbWritable < cbWritableStream)
     901            cbWritable = cbWritableStream;
     902
     903        break; /** @todo For now the first stream sets the pace. */
     904    }
    896905#endif
    897     }
    898906
    899907    Log3Func(("[%s] cbWritable=%RU32\n", pSink->pszName, cbWritable));
  • trunk/src/VBox/Devices/Audio/DevHDA.cpp

    r67425 r67429  
    2626#define LOG_GROUP LOG_GROUP_DEV_HDA
    2727#include <VBox/log.h>
     28
    2829#include <VBox/vmm/pdmdev.h>
    2930#include <VBox/vmm/pdmaudioifs.h>
     
    7374 * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */
    7475//# define HDA_USE_DMA_ACCESS_HANDLER_WRITING
     76
     77/* Useful to debug the device' timing. */
     78//#define HDA_DEBUG_TIMING
     79
     80/* To debug silence coming from the guest in form of audio gaps.
     81 * Very crude implementation for now. */
     82//#define HDA_DEBUG_SILENCE
    7583
    7684#if defined(VBOX_WITH_HP_HDA)
     
    103111#endif
    104112
    105 /** Default timer frequency (in Hz). */
     113/** Default timer frequency (in Hz).
     114 *
     115 *  Note: Keep in mind that the Hz rate has nothing to do with samples rates
     116 *        or DMA / interrupt timing -- it's purely needed in order to drive
     117 *        the data flow at a constant (and sufficient) rate.
     118 *
     119 *        Lowering this value can ask for trouble, as backends then can run
     120 *        into data underruns. */
    106121#define HDA_TIMER_HZ            200
    107122
     
    159174     | (((iss)   & 0xF)  << 8)  \
    160175     | (((bss)   & 0x1F) << 3)  \
    161      | (((bds)   & 0x3)  << 1)  \
     176     | (((bds)   & 0x3)  << 2)  \
    162177     | ((b64sup) & 1))
    163178
     
    10251040static int           hdaStreamRead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);
    10261041//static int           hdaStreamWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten);
     1042static void          hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fAsync);
    10271043# ifdef HDA_USE_DMA_ACCESS_HANDLER
    10281044static bool          hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
     
    13281344}
    13291345
    1330 
     1346/**
     1347 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
     1348 * updating its associated LPIB register and DMA position buffer (if enabled).
     1349 *
     1350 * @returns Set LPIB value.
     1351 * @param   pThis               HDA state.
     1352 * @param   pStream             HDA stream to update read / write position for.
     1353 */
    13311354DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
    13321355{
     
    13491372    {
    13501373        int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    1351                                         (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)),
     1374                                        pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
    13521375                                        (void *)&u32LPIB, sizeof(uint32_t));
    13531376        AssertRC(rc2);
     
    13841407    AssertRC(rc2);
    13851408}
    1386 
    1387 #if 0
    1388 /**
    1389  * Fetches the next BDLE to use for a stream.
    1390  *
    1391  * @return  IPRT status code.
    1392  */
    1393 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream, bool *pfWrapAround)
    1394 {
    1395     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1396     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1397 
    1398     NOREF(pThis);
    1399 
    1400     Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
    1401 
    1402     LogFlowFuncEnter();
    1403 
    1404 # ifdef LOG_ENABLED
    1405     uint32_t const uOldBDLE = pStream->State.uCurBDLE;
    1406 # endif
    1407 
    1408     PHDABDLE pBDLE       = &pStream->State.BDLE;
    1409     bool     fWrapAround = false;
    1410 
    1411     AssertMsg(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize, ("BDLE not finished yet: %R[bdle]\n", pBDLE));
    1412 
    1413     /*
    1414      * Switch to the next BDLE entry and do a wrap around
    1415      * if we reached the end of the Buffer Descriptor List (BDL).
    1416      */
    1417     pStream->State.uCurBDLE++;
    1418     if (pStream->State.uCurBDLE == pStream->u16LVI + 1)
    1419     {
    1420         pStream->State.uCurBDLE = 0;
    1421         fWrapAround = true;
    1422     }
    1423 
    1424     Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
    1425 
    1426     /* Fetch the next BDLE entry. */
    1427     int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    1428     if (RT_SUCCESS(rc))
    1429     {
    1430         LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",
    1431                      pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));
    1432 
    1433         if (pfWrapAround)
    1434             *pfWrapAround = fWrapAround;
    1435     }
    1436 
    1437     return rc;
    1438 }
    1439 #endif
    14401409
    14411410
     
    16261595    return VINF_SUCCESS;
    16271596}
     1597
     1598#ifdef IN_RING3
     1599/**
     1600 * Reschedules pending interrupts for all audio streams which have complete
     1601 * audio periods but did not have the chance to issue their (pending) interrupts yet.
     1602 *
     1603 * @param   pThis               The HDA device state.
     1604 */
     1605static void hdaReschedulePendingInterrupts(PHDASTATE pThis)
     1606{
     1607    bool fInterrupt = false;
     1608
     1609    for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
     1610    {
     1611        PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
     1612
     1613        if (   hdaStreamPeriodIsComplete    (&pStream->State.Period)
     1614            && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period)
     1615            && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
     1616        {
     1617            fInterrupt = true;
     1618            break;
     1619        }
     1620    }
     1621
     1622    LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
     1623
     1624    if (fInterrupt)
     1625    {
     1626#ifndef DEBUG
     1627        hdaProcessInterrupt(pThis);
     1628#else
     1629        hdaProcessInterrupt(pThis, __FUNCTION__);
     1630#endif
     1631    }
     1632}
     1633#endif
    16281634
    16291635/**
     
    18621868    if (RT_FAILURE(rc))
    18631869        AssertRCReturn(rc, rc);
     1870
    18641871    return rc;
    18651872}
     
    20072014    HDA_STREAM_REG(pThis, CBL,   uSD) = 0;
    20082015    HDA_STREAM_REG(pThis, LVI,   uSD) = 0;
    2009     HDA_STREAM_REG(pThis, FMT,   uSD) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ,
    2010                                                        HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT,
    2011                                                        HDA_SDFMT_CHAN_STEREO);
     2016    HDA_STREAM_REG(pThis, FMT,   uSD) = 0;
    20122017    HDA_STREAM_REG(pThis, BDPU,  uSD) = 0;
    20132018    HDA_STREAM_REG(pThis, BDPL,  uSD) = 0;
     
    20322037#endif
    20332038
     2039    /* Report that we're done resetting this stream. */
     2040    HDA_STREAM_REG(pThis, CTL,   uSD) = 0;
     2041
    20342042    LogFunc(("[SD%RU8] Reset\n", uSD));
    20352043
     
    22222230
    22232231# endif /* defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND) */
    2224 
    2225 # if 0 /* currently unused */
    2226 static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout)
    2227 {
    2228     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2229 
    2230     LogFlowFunc(("[SD%RU8]: msTimeout=%RU32\n", pStream->u8SD, msTimeout));
    2231     return RTSemEventWait(pStream->State.hStateChangedEvent, msTimeout);
    2232 }
    2233 # endif /* currently unused */
    2234 
    22352232#endif /* IN_RING3 */
    22362233
     
    23632360static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    23642361{
    2365     const uint8_t  u8Strm  = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
    2366     uint32_t       u32LPIB = HDA_STREAM_REG(pThis, LPIB, u8Strm);
     2362    const uint8_t  uSD     = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
     2363    uint32_t       u32LPIB = HDA_STREAM_REG(pThis, LPIB, uSD);
    23672364#ifdef LOG_ENABLED
    2368     const uint32_t u32CBL  = HDA_STREAM_REG(pThis, CBL,  u8Strm);
    2369     LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, u32CBL));
     2365    const uint32_t u32CBL  = HDA_STREAM_REG(pThis, CBL,  uSD);
     2366    LogFlowFunc(("[SD%RU8] LPIB=%RU32, CBL=%RU32\n", uSD, u32LPIB, u32CBL));
    23702367#endif
    23712368
     
    25802577{
    25812578#ifdef IN_RING3
    2582     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2583         return VINF_SUCCESS;
    2584 
    25852579    PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, CBL, iReg));
    25862580    if (!pStream)
     
    25922586
    25932587    pStream->u32CBL = u32Value;
    2594 
    2595     /* Reset BDLE state. */
    2596     RT_ZERO(pStream->State.BDLE);
    2597     pStream->State.uCurBDLE = 0;
    25982588
    25992589    int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
     
    26082598#endif /* IN_RING3 */
    26092599}
    2610 
    2611 #ifdef IN_RING3
    2612 /**
    2613  * Reschedules pending interrupts for all audio streams which have complete
    2614  * audio periods but did not have the chance to issue their (pending) interrupts yet.
    2615  *
    2616  * @param   pThis               The HDA device state.
    2617  */
    2618 static void hdaReschedulePendingInterrupts(PHDASTATE pThis)
    2619 {
    2620     bool fInterrupt = false;
    2621 
    2622     for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
    2623     {
    2624         PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
    2625 
    2626         if (   hdaStreamPeriodIsComplete    (&pStream->State.Period)
    2627             && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period)
    2628             && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
    2629         {
    2630             fInterrupt = true;
    2631             break;
    2632         }
    2633     }
    2634 
    2635     LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
    2636 
    2637     if (fInterrupt)
    2638     {
    2639 #ifndef DEBUG
    2640         hdaProcessInterrupt(pThis);
    2641 #else
    2642         hdaProcessInterrupt(pThis, __FUNCTION__);
    2643 #endif
    2644     }
    2645 }
    2646 #endif
    26472600
    26482601static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     
    26662619    LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
    26672620             uSD, fRun, fInRun, fReset, fInReset, u32Value));
    2668 
    2669     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    2670         return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    26712621
    26722622    /*
     
    28372787    }
    28382788# endif
    2839 
    2840     /* Reset BDLE state. */
    2841     RT_ZERO(pStream->State.BDLE);
    2842     pStream->State.uCurBDLE = 0;
    28432789
    28442790    int rc2 = hdaRegWriteU16(pThis, iReg, u32Value);
     
    33193265{
    33203266#ifdef IN_RING3
    3321     if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    3322         return VINF_SUCCESS;
    3323 
    33243267    int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
    33253268    AssertRC(rc2);
     
    33323275    pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
    33333276                                      HDA_STREAM_REG(pThis, BDPU, uSD));
    3334     AssertMsg(pStream->u64BDLBase, ("BDL base invalid\n"));
    3335 
    3336     /* Reset BDLE state. */
    3337     RT_ZERO(pStream->State.BDLE);
    3338     pStream->State.uCurBDLE = 0;
    33393277
    33403278# ifdef HDA_USE_DMA_ACCESS_HANDLER
     
    34653403        case HDA_REG_DPLBASE:
    34663404        {
    3467             pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
    3468             pThis->u64DPBase |= pThis->au32Regs[iRegMem];
     3405            pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK;
     3406            Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */
    34693407
    34703408            /* Also make sure to handle the DMA position enable bit. */
    3471             pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));
    3472             LogRel2(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));
     3409            pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);
     3410            LogRel(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));
    34733411            break;
    34743412        }
    34753413        case HDA_REG_DPUBASE:
    3476             pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
    3477             pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
     3414            pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]);
    34783415            break;
    34793416        default:
     
    37333670    /** @todo Compare u16Entry with LVI. */
    37343671
    3735     int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + u16Entry * sizeof(HDABDLEDESC),
     3672    int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
    37363673                               &pBDLE->Desc, sizeof(pBDLE->Desc));
    3737     if (RT_FAILURE(rc))
    3738         return rc;
    3739 
    3740     /* Set internal state. */
    3741     pBDLE->State.u32BufOff   = 0;
    3742     pBDLE->State.u32BDLIndex = u16Entry;
     3674
     3675    if (RT_SUCCESS(rc))
     3676    {
     3677        /* Reset internal state. */
     3678        RT_ZERO(pBDLE->State);
     3679        pBDLE->State.u32BDLIndex = u16Entry;
     3680    }
     3681
     3682    Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc));
     3683
    37433684
    37443685    return VINF_SUCCESS;
    37453686}
    3746 
    3747 /**
    3748  * Tells whether a given BDLE is complete or not.
    3749  *
    3750  * @return  true if BDLE is complete, false if not.
    3751  * @param   pBDLE               BDLE to retrieve status for.
    3752  */
    3753 static bool hdaBDLEIsComplete(PHDABDLE pBDLE)
    3754 {
    3755     bool fIsComplete = false;
    3756 
    3757     if (   !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */
    3758         || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))
    3759     {
    3760         Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);
    3761         fIsComplete = true;
    3762     }
    3763 
    3764     Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
    3765 
    3766     return fIsComplete;
    3767 }
    3768 
    3769 /**
    3770  * Tells whether a given BDLE needs an interrupt or not.
    3771  *
    3772  * @return  true if BDLE needs an interrupt, false if not.
    3773  * @param   pBDLE               BDLE to retrieve status for.
    3774  */
    3775 static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)
    3776 {
    3777     return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);
    3778 }
    3779 
    3780 #if 0
    3781 /**
    3782  * Returns the number of outstanding stream data bytes which need to be processed
    3783  * by the DMA engine assigned to this stream.
    3784  *
    3785  * @return Number of bytes for the DMA engine to process.
    3786  */
    3787 DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbMax)
    3788 {
    3789     AssertPtrReturn(pThis,   0);
    3790     AssertPtrReturn(pStream, 0);
    3791     AssertReturn   (cbMax,   0);
    3792 
    3793     PHDABDLE pBDLE = &pStream->State.BDLE;
    3794 
    3795     uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    3796     Assert(u32LPIB <= pStream->u32CBL);
    3797 
    3798     /* Do we have space left in the CBL at all? */
    3799     uint32_t cbData = pStream->u32CBL - u32LPIB;
    3800 
    3801     /* Limit to the available free space of the current BDLE. */
    3802     cbData = RT_MIN(cbData, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    3803 
    3804     /* Make sure we only transfer as many bytes as requested. */
    3805     cbData = RT_MIN(cbData, cbMax);
    3806 
    3807     if (pBDLE->State.cbBelowFIFOW)
    3808     {
    3809         /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?
    3810          * No need to read data from DMA then. */
    3811         if (cbData > pBDLE->State.cbBelowFIFOW)
    3812         {
    3813             /* Subtract the amount of bytes that still would fit in the stream's FIFO
    3814              * and therefore do not need to be processed by DMA. */
    3815             cbData -= pBDLE->State.cbBelowFIFOW;
    3816         }
    3817     }
    3818 
    3819     AssertMsg((cbData % 2 == 0), ("Transfer size invalid: %RU32\n", cbData));
    3820 
    3821     Log3Func(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbData=%RU32, %R[bdle]\n", pStream->u8SD,
    3822               pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS,
    3823               cbData, pBDLE));
    3824 
    3825     return cbData;
    3826 }
    3827 
    3828 DECLINLINE(void) hdaBDLEUpdate(PHDABDLE pBDLE, uint32_t cbData, uint32_t cbProcessed)
    3829 {
    3830     AssertPtrReturnVoid(pBDLE);
    3831 
    3832     if (!cbData || !cbProcessed)
    3833         return;
    3834 
    3835     Assert(pBDLE->Desc.u32BufSize >= cbProcessed);
    3836 
    3837     /* Fewer than cbBelowFIFOW bytes were copied.
    3838      * Probably we need to move the buffer, but it is rather hard to imagine a situation
    3839      * where it might happen. */
    3840     AssertMsg((cbProcessed == pBDLE->State.cbBelowFIFOW + cbData), /* we assume that we write the entire buffer including unreported bytes */
    3841               ("cbProcessed=%RU32 != pBDLE->State.cbBelowFIFOW=%RU32 + cbData=%RU32\n",
    3842               cbProcessed, pBDLE->State.cbBelowFIFOW, cbData));
    3843 
    3844 #if 0
    3845     if (   pBDLE->State.cbBelowFIFOW
    3846         && pBDLE->State.cbBelowFIFOW <= cbWritten)
    3847     {
    3848         LogFlowFunc(("BDLE(cbUnderFifoW:%RU32, off:%RU32, size:%RU32)\n",
    3849                      pBDLE->State.cbBelowFIFOW, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize));
    3850     }
    3851 #endif
    3852 
    3853     pBDLE->State.cbBelowFIFOW -= RT_MIN(pBDLE->State.cbBelowFIFOW, cbProcessed);
    3854     Assert(pBDLE->State.cbBelowFIFOW == 0);
    3855 
    3856     /* We always increment the position of DMA buffer counter because we're always reading
    3857      * into an intermediate buffer. */
    3858     Assert(pBDLE->Desc.u32BufSize >= (pBDLE->State.u32BufOff + cbProcessed));
    3859     pBDLE->State.u32BufOff += cbProcessed;
    3860 
    3861     LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE));
    3862 }
    3863 #endif
    38643687
    38653688#ifdef IN_RING3
     
    39313754}
    39323755
     3756
    39333757/**
    39343758 * Destroys a given stream mapping.
     
    39463770    }
    39473771}
     3772
    39483773
    39493774/**
     
    39723797#endif /* IN_RING3 */
    39733798
    3974 #if 0
    3975 DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStream)
    3976 {
    3977     AssertPtrReturn(pThis,   false);
    3978     AssertPtrReturn(pStream, false);
    3979 
    3980     PHDABDLE pBDLE   = &pStream->State.BDLE;
    3981     uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    3982 
    3983     /* Did we reach the CBL (Cyclic Buffer List) limit? */
    3984     bool fCBLLimitReached = u32LPIB >= pStream->u32CBL;
    3985 
    3986     /* Do we need to use the next BDLE entry? Either because we reached
    3987      * the CBL limit or our internal DMA buffer is full. */
    3988     bool fNeedsNextBDLE   = (   fCBLLimitReached
    3989                              || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize));
    3990 
    3991     Assert(u32LPIB                <= pStream->u32CBL);
    3992     Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
    3993 
    3994     LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, fCBLLimitReached=%RTbool, fNeedsNextBDLE=%RTbool, %R[bdle]\n",
    3995                  pStream->u8SD, u32LPIB, pStream->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE));
    3996 
    3997     return fNeedsNextBDLE;
    3998 }
    3999 #endif
    40003799
    40013800/**
     
    40163815    }
    40173816
    4018     PHDABDLE pBDLE = &pStream->State.BDLE;
    4019 
    4020     uint32_t cbFree = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    4021 
    4022     Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 -> cbFree=%RU32 %R[bdle]\n", pStream->u8SD,
    4023               HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbFree, pBDLE));
    4024     return cbFree;
    4025 }
     3817    /* Determine how much for the current BDL entry we have left to transfer. */
     3818    PHDABDLE pBDLE  = &pStream->State.BDLE;
     3819    const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
     3820
     3821    /* Determine how much we (still) can stuff in the stream's internal FIFO.  */
     3822    const uint32_t cbCircBuf   = (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
     3823
     3824    uint32_t cbToTransfer = cbBDLE;
     3825
     3826    /* Make sure that we don't transfer more than our FIFO can hold at the moment.
     3827     * As the host sets the overall pace it needs to process some of the FIFO data first before
     3828     * we can issue a new DMA data transfer. */
     3829    if (cbToTransfer > cbCircBuf)
     3830        cbToTransfer = cbCircBuf;
     3831
     3832    Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD,
     3833              HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE));
     3834    return cbToTransfer;
     3835}
     3836
    40263837
    40273838DECLINLINE(void) hdaStreamTransferInc(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)
     
    40413852}
    40423853
    4043 #if 0
    4044 DECLINLINE(void) hdaStreamTransferUpdate(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)
    4045 {
    4046     AssertPtrReturnVoid(pThis);
    4047     AssertPtrReturnVoid(pStream);
    4048 
    4049     if (!cbInc) /* Nothing to do? Bail out early. */
    4050         return;
    4051 
    4052     /*
    4053      * If we're below the FIFO watermark (SDFIFOW), it's expected that HDA
    4054      * doesn't fetch anything via DMA, so just update LPIB.
    4055      * (ICH6 datasheet 18.2.38).
    4056      */
    4057     PHDABDLE pBDLE = &pStream->State.BDLE;
    4058     if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */
    4059     {
    4060         uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc;
    4061 
    4062         Log3Func(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
    4063                   pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), u32LPIB, pStream->u32CBL));
    4064 
    4065         hdaStreamUpdateLPIB(pThis, pStream, u32LPIB);
    4066     }
    4067 }
    4068 
    4069 static bool hdaBDLEIsComplete(PHDABDLE pBDLE, bool *pfInterrupt)
    4070 {
    4071     AssertPtrReturn(pBDLE, true);
    4072 
    4073     bool fInterrupt  = false;
    4074     bool fIsComplete = false;
    4075 
    4076     /* Check if the current BDLE entry is complete (full). */
    4077     if (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize)
    4078     {
    4079         Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
    4080 
    4081         if (/* IOC (Interrupt On Completion) bit set? */
    4082                pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC
    4083             /* All data put into the DMA FIFO? */
    4084             && pBDLE->State.cbBelowFIFOW == 0
    4085            )
    4086         {
    4087             fInterrupt = true;
    4088         }
    4089 
    4090         fIsComplete = true;
    4091     }
    4092 
    4093     if (pfInterrupt)
    4094         *pfInterrupt = fInterrupt;
    4095 
    4096     LogFlowFunc(("%R[bdle] fIsComplete=%RTbool, fInterrupt=%RTbool\n", pBDLE, fIsComplete, fInterrupt));
    4097 
    4098     return fIsComplete;
    4099 }
    4100 #endif
    41013854
    41023855/**
     
    48454598
    48464599/**
     4600 * Tells whether a given BDLE is complete or not.
     4601 *
     4602 * @return  true if BDLE is complete, false if not.
     4603 * @param   pBDLE               BDLE to retrieve status for.
     4604 */
     4605static bool hdaBDLEIsComplete(PHDABDLE pBDLE)
     4606{
     4607    bool fIsComplete = false;
     4608
     4609    if (   !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */
     4610        || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))
     4611    {
     4612        Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);
     4613        fIsComplete = true;
     4614    }
     4615
     4616    Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
     4617
     4618    return fIsComplete;
     4619}
     4620
     4621
     4622/**
     4623 * Tells whether a given BDLE needs an interrupt or not.
     4624 *
     4625 * @return  true if BDLE needs an interrupt, false if not.
     4626 * @param   pBDLE               BDLE to retrieve status for.
     4627 */
     4628static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)
     4629{
     4630    return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);
     4631}
     4632
     4633/**
    48474634 * Writes audio data from an HDA input stream's FIFO to its associated DMA area.
    48484635 *
     
    50144801#endif
    50154802
    5016 #if 0
    5017     uint32_t cbWritten = 0;
    5018     int rc2 = hdaStreamWrite(pThis, pStreamLineIn, &cbWritten);
    5019     if (   RT_SUCCESS(rc2)
    5020         && cbWritten)
    5021     {
    5022         rc2 = hdaStreamTransfer(pThis, pStreamLineIn, cbWritten);
    5023         AssertRC(rc2);
    5024     }
    5025 
    5026 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    5027     rc2 = hdaStreamWrite(pThis, pStreamMicIn, &cbWritten);
    5028     if (   RT_SUCCESS(rc2)
    5029         && cbWritten)
    5030     {
    5031         rc2 = hdaStreamTransfer(pThis, pStreamMicIn, cbWritten);
    5032         AssertRC(rc2);
    5033     }
    5034 #endif
    5035 #endif
    5036 
    5037     int rc2;
    5038 
    5039     /* Is the sink ready to be written to? If so, how much? */
    5040     uint32_t cbToWrite = AudioMixerSinkGetWritable(pThis->SinkFront.pMixSink);
    5041     if (cbToWrite)
    5042     {
    5043         rc2 = hdaStreamTransfer(pThis, pStreamFront, cbToWrite);
    5044         AssertRC(rc2);
    5045 
    5046         if (hdaStreamGetDataSize(pStreamFront))
    5047         {
    5048 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5049             /* Let the asynchronous thread know that there is some new data to process. */
    5050             hdaStreamAsyncIONotify(pThis, pStreamFront);
    5051 #else
    5052             /* Read audio data from the HDA stream and write to the backends. */
    5053             rc2 = hdaStreamRead(pThis, pStreamFront, cbToWrite, NULL /* pcbRead */);
    5054             AssertRC(rc2);
    5055 #endif
    5056         }
    5057     }
    5058 
    5059 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5060     /*
    5061      * Update all mixer sinks here (synchronously).
    5062      * For async I/O this is done in the stream's specific async I/O thread.
    5063      */
    5064     rc2 = AudioMixerSinkUpdate(pThis->SinkFront.pMixSink);
    5065     AssertRC(rc2);
    5066 
    5067 # ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    5068     rc2 = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink);
    5069     AssertRC(rc2);
    5070 
    5071     rc2 = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink);
    5072     AssertRC(rc2);
    5073     /** @todo Check for stream interleaving and only call hdaStreamDoDMA() if required! */
    5074 
    5075     /*
    5076      * Only call hdaTransfer if CenterLFE and/or Rear are on different SDs,
    5077      * otherwise we have to use the interleaved streams support for getting the data
    5078      * out of the Front sink (depending on the mapping layout).
    5079      */
    5080 # endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
    5081 #endif /* !VBOX_WITH_AUDIO_HDA_ASYNC_IO */
     4803    hdaStreamUpdate(pThis, pStreamFront, true /* fSync */);
    50824804}
    50834805
     
    50864808#endif
    50874809
    5088 #if 0
    5089 /**
    5090  * Does a single DMA transfer for a specific HDA stream (SDI/SDO).
    5091  * This either can be a read or write operation, depending on the HDA stream.
    5092  *
    5093  * @returns IPRT status code.
    5094  * @param   pThis               HDA state.
    5095  * @param   pStream             HDA stream to do the DMA transfer for.
    5096  * @param   pvBuf               Pointer to buffer data to write data to / read data from.
    5097  * @param   cbBuf               Size of buffer (in bytes).
    5098  * @param   cbToProcess         Size (in bytes) to transfer (read/write).
    5099  * @param   pcbProcessed        Size (in bytes) transferred (read/written). Optional.
    5100  */
    5101 static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf,
    5102                           uint32_t cbToProcess, uint32_t *pcbProcessed)
    5103 {
    5104     AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
    5105     AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
    5106     AssertPtrReturn(pvBuf,             VERR_INVALID_POINTER);
    5107     AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER);
    5108     /* pcbProcessed is optional. */
    5109 
    5110     if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
    5111     {
    5112         if (pcbProcessed)
    5113             *pcbProcessed = 0;
    5114         return VINF_SUCCESS;
    5115     }
    5116 
    5117     bool fProceed = true;
    5118 
    5119     Log3Func(("[SD%RU8] %R[sdsts] cbToProcess=%RU32\n",
    5120               pStream->u8SD, HDA_STREAM_REG(pThis, STS, pStream->u8SD), cbToProcess));
    5121 
    5122     /* Is the stream not in a running state currently? */
    5123     if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
    5124         fProceed = false;
    5125     /* Is the BCIS (Buffer Completion Interrupt Status) flag set? Then we have to wait and skip. */
    5126     else if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_SDSTS_BCIS))
    5127         fProceed = false;
    5128 
    5129     if (!fProceed)
    5130     {
    5131 #ifdef HDA_DEBUG_DMA
    5132         Log3Func(("[SD%RU8] DMA: Skip\n", pStream->u8SD));
    5133 #endif
    5134         if (pcbProcessed)
    5135             *pcbProcessed = 0;
    5136         return VINF_SUCCESS;
    5137     }
    5138 
    5139     int rc = VINF_SUCCESS;
    5140 
    5141 #ifdef HDA_DEBUG_DMA
    5142     Log3Func(("[SD%RU8] DMA: Start\n", pStream->u8SD));
    5143 #endif
    5144 
    5145     /* Sanity checks. */
    5146     Assert(pStream->u8SD <= HDA_MAX_STREAMS);
    5147     Assert(pStream->u64BDLBase);
    5148     Assert(pStream->u32CBL);
    5149 
    5150     /* State sanity checks. */
    5151     Assert(pStream->State.fInReset == false);
    5152     Assert(HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) <= pStream->u32CBL);
    5153 
    5154     bool fSendInterrupt = false;
    5155 
    5156     /* Only do one FIFO size at a time. */
    5157     uint32_t cbLeft           = RT_MIN(pStream->u16FIFOS, RT_MIN(cbToProcess, cbBuf));
    5158     uint32_t cbTotal          = 0;
    5159     uint32_t cbChunk          = 0;
    5160     uint32_t cbChunkProcessed = 0;
    5161 
    5162 #ifdef HDA_DEBUG_DMA
    5163     LogFunc(("[SD%RU8] DMA: cbToProcess=%RU32, cbLeft=%RU32\n", pStream->u8SD, cbToProcess, cbLeft));
    5164 #endif
    5165 
    5166     /* Get the maximum number of BDL entries. */
    5167     uint16_t cBDLE = pStream->u16LVI + 1;
    5168 
    5169     while (   cbLeft
    5170            && cBDLE--)
    5171     {
    5172         cbChunk          = hdaStreamGetTransferSize(pThis, pStream, cbLeft);
    5173         cbChunkProcessed = 0;
    5174 
    5175         PHDABDLE pBDLE = &pStream->State.BDLE;
    5176 
    5177         if (cbChunk)
    5178         {
    5179             if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    5180             {
    5181                 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    5182                                   pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,
    5183                                   (uint8_t *)pvBuf + cbTotal, cbChunk);
    5184             }
    5185             else /* Input (SDI). */
    5186             {
    5187                 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns),
    5188                                    pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,
    5189                                    (uint8_t *)pvBuf + cbTotal, cbChunk);
    5190             }
    5191 
    5192 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    5193             RTFILE fh;
    5194             RTFileOpen(&fh,
    5195                          hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT
    5196                        ? VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm" : VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",
    5197                        RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    5198             RTFileWrite(fh, (uint8_t *)pvBuf + cbTotal, cbChunk, NULL);
    5199             RTFileClose(fh);
    5200 #endif
    5201         }
    5202 
    5203         cbChunkProcessed = cbChunk;
    5204 
    5205         hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);
    5206 
    5207         LogFunc(("[SD%RU8] DMA: Entry %RU32 Pos %RU32/%RU32 Chunk %RU32\n",
    5208                  pStream->u8SD, pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize, cbChunk));
    5209 
    5210         Assert(cbLeft >= cbChunkProcessed);
    5211         cbLeft  -= cbChunkProcessed;
    5212         cbTotal += cbChunkProcessed;
    5213         Assert(cbTotal <= cbToProcess);
    5214 
    5215         hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);
    5216 
    5217 #ifdef HDA_DEBUG_DMA
    5218         LogFunc(("[SD%RU8] DMA: LPIB %RU32 Pos %RU32 Left %RU32\n",
    5219                  pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbTotal, cbLeft));
    5220 #endif
    5221         bool fNeedsInterrupt = false;
    5222         bool fBDLEIsComplete = hdaBDLEIsComplete(pBDLE, &fNeedsInterrupt);
    5223 
    5224         if (fNeedsInterrupt)
    5225             fSendInterrupt = true;
    5226 
    5227         if (fBDLEIsComplete)
    5228         {
    5229             /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
    5230             if (hdaStreamNeedsNextBDLE(pThis, pStream))
    5231             {
    5232                 bool fWrapAround;
    5233                 rc = hdaStreamGetNextBDLE(pThis, pStream, &fWrapAround);
    5234                 if (   RT_SUCCESS(rc)
    5235                     && fWrapAround)
    5236                 {
    5237                     hdaStreamUpdateLPIB(pThis, pStream, 0);
    5238                 }
    5239             }
    5240         }
    5241 
    5242         if (RT_FAILURE(rc))
    5243             break;
    5244     }
    5245 
    5246     Log3Func(("[SD%RU8]: cbLeft=%RU32, rc=%Rrc\n", pStream->u8SD, cbLeft, rc));
    5247 
    5248     if (fSendInterrupt)
    5249     {
    5250 #ifdef HDA_DEBUG_DMA
    5251         Log3Func(("[SD%RU8] DMA: Interrupt\n", pStream->u8SD));
    5252 #endif
    5253         /**
    5254          * Set the BCIS (Buffer Completion Interrupt Status) flag as the
    5255          * last byte of data for the current descriptor has been fetched
    5256          * from memory and put into the DMA FIFO.
    5257          *
    5258          * Speech synthesis works fine on Mac Guest if this bit isn't set
    5259          * but in general sound quality gets worse.
    5260          *
    5261          * This must be set in *any* case.
    5262          */
    5263         HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;
    5264         Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    5265 
    5266 #ifndef DEBUG
    5267         hdaProcessInterrupt(pThis);
    5268 #else
    5269         hdaProcessInterrupt(pThis, __FUNCTION__);
    5270 #endif
    5271     }
    5272 
    5273     if (RT_SUCCESS(rc))
    5274     {
    5275         if (pcbProcessed)
    5276             *pcbProcessed = cbTotal;
    5277     }
    5278 
    5279 #ifdef HDA_DEBUG_DMA
    5280     Log3Func(("[SD%RU8] DMA: End\n", pStream->u8SD));
    5281 #endif
    5282 
    5283     return rc;
    5284 }
    5285 #endif
    5286 
    52874810/**
    52884811 * Retrieves the available size of (buffered) audio data (in bytes) of a given HDA stream.
     
    52984821        return 0;
    52994822
    5300     return (uint32_t)RTCircBufSize(pStream->State.pCircBuf);
     4823    return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
    53014824}
    53024825
     
    53644887#endif
    53654888
     4889
    53664890/**
    53674891 * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink.
     
    54664990            break;
    54674991
    5468         PHDAMIXERSINK pSink = pStream->pMixSink;
    5469 
    54704992        rc2 = RTCritSectEnter(&pAIO->CritSect);
    54714993        if (RT_SUCCESS(rc2))
     
    54774999            }
    54785000
    5479             uint32_t cbToProcess;
    5480             uint32_t cbProcessed = 0;
    5481 
    5482             if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    5483             {
    5484                 cbToProcess = (uint32_t)RTCircBufUsed(pCircBuf);
    5485                 if (cbToProcess)
    5486                     rc2 = hdaStreamRead(pThis, pStream, cbToProcess, &cbProcessed);
    5487             }
    5488             else /* Input (SDI). */
    5489             {
    5490         #if 0
    5491                 cbToProcess = (uint32_t)RTCircBufFree(pCircBuf);
    5492                 if (cbToProcess)
    5493                     rc2 = hdaStreamWrite(pThis, pStream, cbToProcess, &cbProcessed);
    5494         #endif
    5495             }
    5496 
    5497             if (   pSink
    5498                 && RT_SUCCESS(rc2))
    5499             {
    5500                 rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
    5501             }
     5001            hdaStreamUpdate(pThis, pStream, false /* fSync */);
    55025002
    55035003            int rc3 = RTCritSectLeave(&pAIO->CritSect);
     
    57315231    Assert(pStream->u8SD <= HDA_MAX_STREAMS);
    57325232    Assert(pStream->u64BDLBase);
     5233    Assert(pStream->u32CBL);
    57335234
    57345235    /* State sanity checks. */
     
    57475248
    57485249    const uint32_t cbElapsed         = hdaStreamTransferGetElapsed(pThis, pStream);
     5250    Assert(cbElapsed);         /* Paranoia. */
    57495251
    57505252    /* Limit the data to read, as this routine could be delayed and therefore
    57515253     * report wrong (e.g. too much) cbElapsed bytes. */
    57525254    uint32_t cbLeft                  = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax);
    5753     Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */
    57545255
    57555256    Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n",
    57565257              pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft));
    57575258
    5758     Log2Func(("[SD%RU8]\n", pStream->u8SD));
    5759 
    5760     while (cbLeft >> 1) /** @todo Define frame size? */
     5259    Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */
     5260
     5261    while (cbLeft)
    57615262    {
    57625263        uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft);
     5264        if (!cbChunk)
     5265            break;
     5266
    57635267        uint32_t cbDMA   = 0;
    5764 #if 1
     5268
    57655269        if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    57665270        {
     
    57975301            hdaStreamTransferInc(pThis, pStream, cbDMA);
    57985302
    5799             uint32_t framesDMA = cbDMA / 4; /** @todo Define frame size? */
     5303            uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE;
    58005304
    58015305            /* Add the transferred frames to the period. */
     
    58875391
    58885392    hdaStreamPeriodUnlock(pPeriod);
    5889 #else
    5890         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    5891         {
    5892             STAM_PROFILE_START(&pThis->StatOut, a);
    5893 
    5894             /*
    5895              * Read from DMA.
    5896              */
    5897 
    5898             uint8_t abFIFO[HDA_FIFO_MAX + 1];
    5899             size_t  offFIFO = 0;
    5900 
    5901             /* Do one DMA transfer with FIFOS size at a time. */
    5902             rc2 = hdaStreamDoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), (uint32_t)pStream->u16FIFOS /* cbToProcess */, &cbDMA);
     5393
     5394    Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc));
     5395
     5396    if (RT_FAILURE(rc))
     5397        LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc));
     5398
     5399    hdaStreamUnlock(pStream);
     5400
     5401    return VINF_SUCCESS;
     5402}
     5403
     5404/**
     5405 * Updates a HDA stream by doing its required data transfers.
     5406 * The host sink(s) set the overall pace.
     5407 *
     5408 * This routine is called by both, the synchronous and the asynchronous, implementations.
     5409 *
     5410 * @param   pThis               HDA state.
     5411 * @param   pStream             HDA stream to update.
     5412 * @param   fSync               Whether to use this function in an synchronous
     5413 *                              or asynchronous context.
     5414 */
     5415static void hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fSync)
     5416{
     5417    PAUDMIXSINK pSink = NULL;
     5418    if (   pStream->pMixSink
     5419        && pStream->pMixSink->pMixSink)
     5420    {
     5421        pSink = pStream->pMixSink->pMixSink;
     5422    }
     5423
     5424    if (!pSink) /* No sink available? Bail out. */
     5425        return;
     5426
     5427    int rc2;
     5428
     5429    if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
     5430    {
     5431        /* Is the sink ready to be written (guest output data) to? If so, by how much? */
     5432        const uint32_t cbWritable = AudioMixerSinkGetWritable(pSink);
     5433
     5434        if (   fSync
     5435            && cbWritable)
     5436        {
     5437            /* When running synchronously, do the DMA data transfers here.
     5438             * Otherwise this will be done in the device timer. */
     5439            rc2 = hdaStreamTransfer(pThis, pStream, cbWritable);
    59035440            AssertRC(rc2);
    59045441
    5905             uint32_t cbDMALeft = cbDMA;
    5906 
    5907             while (   cbDMALeft
    5908                    && RTCircBufFree(pCircBuf))
    5909             {
    5910                 void *pvDst;
    5911                 size_t cbDst;
    5912 
    5913                 RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvDst, &cbDst);
    5914 
    5915                 if (cbDst)
    5916                 {
    5917                     memcpy(pvDst, abFIFO + offFIFO, cbDst);
    5918 
    5919                     offFIFO += cbDst;
    5920                     Assert(offFIFO <= sizeof(abFIFO));
    5921                 }
    5922 
    5923                 RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
    5924 
    5925                 Assert(cbDst <= cbDMALeft);
    5926                 cbDMALeft -= (uint32_t)cbDst;
    5927             }
    5928 
    5929             AssertMsg(cbDMALeft == 0, ("%RU32 bytes of DMA data left, CircBuf=%zu/%zu\n",
    5930                                        cbDMALeft, RTCircBufUsed(pCircBuf), RTCircBufSize(pCircBuf)));
    5931 
    5932             /*
    5933              * Process backends.
    5934              */
    5935 
    5936             uint32_t cbUsed = (uint32_t)RTCircBufUsed(pCircBuf);
    5937             if (cbUsed)
    5938             {
    59395442#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5940                 /* Let the asynchronous thread know that there is some new data to process. */
    5941                 hdaStreamAsyncIONotify(pThis, pStream);
    5942 #else
    5943                 /* Read audio data from the HDA stream and write to the backends. */
    5944                 rc2 = hdaStreamRead(pThis, pStream, cbUsed, NULL /* pcbRead */);
    5945                 AssertRC(rc2);
    5946 #endif
    5947             }
    5948 
    5949             /* All DMA transfers done for now? */
    5950             if (   !cbDMA
    5951 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5952             /* All data read *and* processed for now? */
    5953                 && RTCircBufUsed(pCircBuf) == 0
    5954 #endif
    5955                )
    5956             {
    5957                 fDone = true;
    5958             }
    5959 
    5960 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5961             rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
     5443            rc2 = hdaStreamAsyncIONotify(pThis, pStream);
    59625444            AssertRC(rc2);
    59635445#endif
    5964             STAM_PROFILE_STOP(&pThis->StatOut, a);
    5965         }
    5966         else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */
    5967         {
    5968             STAM_PROFILE_START(&pThis->StatIn, a);
    5969 
    5970             /*
    5971              * Process backends.
    5972              */
    5973 
    5974 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    5975             /* Let the asynchronous thread know that there is some new data to process. */
    5976             hdaStreamAsyncIONotify(pThis, pStream);
    5977 #else
    5978             rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
     5446        }
     5447
     5448        /* How much (guest output) data is available at the moment? */
     5449        AssertPtr(pStream->State.pCircBuf);
     5450        uint32_t cbToWrite = hdaStreamGetDataSize(pStream);
     5451
     5452        /* Do not write more than the sink can hold at the moment.
     5453         * The host sets the overall pace. */
     5454        if (cbToWrite > cbWritable)
     5455            cbToWrite = cbWritable;
     5456
     5457        if (cbToWrite)
     5458        {
     5459            /* Read (guest output) data and write it to the stream's sink. */
     5460            rc2 = hdaStreamRead(pThis, pStream, cbToWrite, NULL /* pcbWritten */);
    59795461            AssertRC(rc2);
    5980 
    5981             /* Write read data from the backend to the HDA stream. */
    5982             rc2 = hdaStreamWrite(pThis, pStream, pStream->u16FIFOS, NULL /* pcbWritten */);
     5462        }
     5463
     5464        if (fSync)
     5465        {
     5466            /* When running synchronously, update the associated sink here.
     5467             * Otherwise this will be done in the device timer. */
     5468            rc2 = AudioMixerSinkUpdate(pSink);
    59835469            AssertRC(rc2);
    5984 #endif
    5985             /*
    5986              * Write to DMA.
    5987              */
    5988 
    5989             void *pvSrc;
    5990             size_t cbSrc;
    5991 
    5992             RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc);
    5993 
    5994             if (cbSrc)
    5995             {
    5996                 /* Do one DMA transfer with FIFOS size at a time. */
    5997                 rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbDMA);
    5998                 AssertRC(rc2);
    5999             }
    6000 
    6001             RTCircBufReleaseReadBlock(pCircBuf, cbDMA);
    6002 
    6003             /* All DMA transfers done for now? */
    6004             if (!cbDMA)
    6005                 fDone = true;
    6006 
    6007             STAM_PROFILE_STOP(&pThis->StatIn, a);
    6008         }
    6009         else
    6010             AssertFailed();
    6011 
    6012         if (++cTransfers == UINT8_MAX) /* Failsafe counter. */
    6013             fDone = true;
    6014     } /* while !fDone */
    6015 
    6016 #ifdef VBOX_STRICT
    6017     AssertMsg(cTransfers < UINT8_MAX, ("HDA: Update for SD#%RU8 ran for too long\n", pStream->u8SD));
    6018 #endif
    6019 #endif
    6020 
    6021     Log2Func(("[SD%RU8] End\n", pStream->u8SD));
    6022 
    6023     hdaStreamUnlock(pStream);
    6024 
    6025     return VINF_SUCCESS;
     5470        }
     5471
     5472    }
     5473    else /* Input (SDI). */
     5474    {
     5475#if 0
     5476        cbToProcess = (uint32_t)RTCircBufFree(pCircBuf);
     5477        if (cbToProcess)
     5478            rc2 = hdaStreamWrite(pThis, pStream, cbToProcess, &cbProcessed);
     5479#endif
     5480    }
    60265481}
    60275482#endif /* IN_RING3 */
     
    63245779    Assert(enmType == PCI_ADDRESS_SPACE_MEM);
    63255780    int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    6326                                    IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU,
     5781                                     IOMMMIO_FLAGS_READ_DWORD
     5782                                   | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    63275783                                   hdaMMIOWrite, hdaMMIORead, "HDA");
     5784
    63285785    if (RT_FAILURE(rc))
    63295786        return rc;
     
    63555812{
    63565813    RT_NOREF(pDevIns);
    6357 #ifdef DEBUG
     5814#ifdef VBOX_STRICT
    63585815    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
    63595816#endif
    6360     LogFlowFunc(("[SD%RU8]\n", pStrm->u8SD));
     5817
     5818    Log2Func(("[SD%RU8]\n", pStrm->u8SD));
    63615819
    63625820    /* Save stream ID. */
     
    63685826    AssertRCReturn(rc, rc);
    63695827
    6370 #ifdef DEBUG /* Sanity checks. */
     5828#ifdef VBOX_STRICT /* Sanity checks. */
    63715829    uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8SD),
    63725830                                      HDA_STREAM_REG(pThis, BDPU, pStrm->u8SD));
     
    63745832    uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, pStrm->u8SD);
    63755833
    6376     hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);
    6377 
    63785834    Assert(u64BaseDMA == pStrm->u64BDLBase);
    63795835    Assert(u16LVI     == pStrm->u16LVI);
     
    63895845    AssertRCReturn(rc, rc);
    63905846
    6391 #ifdef DEBUG /* Sanity checks. */
     5847#ifdef VBOX_STRICT /* Sanity checks. */
    63925848    PHDABDLE pBDLE = &pStrm->State.BDLE;
    63935849    if (u64BaseDMA)
     
    80437499        PDMDevHlpDBGFInfoRegister(pDevIns, "hda",         "HDA info. (hda [register case-insensitive])",     hdaDbgInfo);
    80447500        PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle",     "HDA stream BDLE info. (hdabdle [stream number])", hdaDbgInfoBDLE);
    8045         PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm",     "HDA stream info. (hdastrm [stream number])",      hdaDbgInfoStream);
     7501        PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream",   "HDA stream info. (hdastream [stream number])",    hdaDbgInfoStream);
    80467502        PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes",    "HDA codec nodes.",                                hdaDbgInfoCodecNodes);
    80477503        PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].",      hdaDbgInfoCodecSelector);
  • trunk/src/VBox/Devices/Makefile.kmk

    r67400 r67429  
    581581 # Disabled for AC'97 for now.
    582582 #VBoxDD_DEFS  += VBOX_WITH_AUDIO_AC97_ASYNC_IO
    583  VBoxDD_DEFS  += VBOX_WITH_AUDIO_HDA_ASYNC_IO
     583 #VBoxDD_DEFS  += VBOX_WITH_AUDIO_HDA_ASYNC_IO
    584584
    585585 # Not yet enabled: Callbacks for the device emulation to let the backends
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette