VirtualBox

Changeset 82450 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Dec 6, 2019 12:39:15 PM (5 years ago)
Author:
vboxsync
Message:

DevHDA: Split structures. bugref:9218

Location:
trunk/src/VBox/Devices/Audio
Files:
8 edited

Legend:

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

    r82425 r82450  
    2424*   Header Files                                                                                                                 *
    2525*********************************************************************************************************************************/
    26 #ifdef DEBUG_bird
    27 # define RT_NO_STRICT /* I'm tried of this crap asserting on save and restore of Maverics guests.  */
    28 #endif
    2926#define LOG_GROUP LOG_GROUP_DEV_HDA
    3027#include <VBox/log.h>
     
    219216    /** Node for storing this driver in our device driver list of HDASTATE. */
    220217    RTLISTNODER3                       Node;
    221     /** Pointer to HDA controller (state). */
    222     R3PTRTYPE(PHDASTATE)               pHDAState;
     218    /** Pointer to shared HDA device state. */
     219    R3PTRTYPE(PHDASTATE)               pHDAStateShared;
     220    /** Pointer to the ring-3 HDA device state. */
     221    R3PTRTYPE(PHDASTATER3)             pHDAStateR3;
    223222    /** Driver flags. */
    224223    PDMAUDIODRVFLAGS                   fFlags;
     
    254253#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    255254#ifdef IN_RING3
    256 static void hdaR3GCTLReset(PHDASTATE pThis);
     255static void hdaR3GCTLReset(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC);
    257256#endif
    258257
     
    317316 */
    318317#ifdef IN_RING3
    319 static int                        hdaR3AddStream(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg);
    320 static int                        hdaR3RemoveStream(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg);
     318static int                        hdaR3AddStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg);
     319static int                        hdaR3RemoveStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg);
    321320# ifdef HDA_USE_DMA_ACCESS_HANDLER
    322321static DECLCALLBACK(VBOXSTRICTRC) hdaR3DmaAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
     
    331330 */
    332331#ifdef IN_RING3
    333 static int hdaR3MixerAddDrvStream(PHDASTATE pThis, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv);
     332static int hdaR3MixerAddDrvStream(PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv);
    334333#endif
    335334/** @} */
     
    564563 * audio periods but did not have the chance to issue their (pending) interrupts yet.
    565564 *
    566  * @param   pThis               The HDA device state.
    567  */
    568 static void hdaR3ReschedulePendingInterrupts(PHDASTATE pThis)
     565 * @param   pDevIns             The device instance.
     566 * @param   pThis               The shared HDA device state.
     567 * @param   pThisCC             The ring-3 HDA device state.
     568 */
     569static void hdaR3ReschedulePendingInterrupts(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
    569570{
    570571    bool fInterrupt = false;
     
    572573    for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
    573574    {
    574         PHDASTREAM pStream = hdaGetStreamFromSD(pThis, i);
    575         if (!pStream)
    576             continue;
    577 
    578         if (   hdaR3StreamPeriodIsComplete    (&pStream->State.Period)
     575        PHDASTREAM pStream = &pThis->aStreams[i];
     576        if (   hdaR3StreamPeriodIsComplete(    &pStream->State.Period)
    579577            && hdaR3StreamPeriodNeedsInterrupt(&pStream->State.Period)
    580             && hdaR3WalClkSet(pThis, hdaR3StreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
     578            && hdaR3WalClkSet(pThis, pThisCC, hdaR3StreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
    581579        {
    582580            fInterrupt = true;
     
    587585    LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
    588586
    589     HDA_PROCESS_INTERRUPT(pThis->pDevInsR3, pThis);
     587    HDA_PROCESS_INTERRUPT(pDevIns, pThis);
    590588}
    591589#endif /* IN_RING3 */
     
    703701 *
    704702 * @returns IPRT status code.
    705  * @param   pThis               HDA state.
     703 *
     704 * @param   pDevIns             The device instance.
     705 * @param   pThis               The shared HDA device state.
    706706 * @param   fLocal              Specify true to synchronize HDA state's CORB buffer with the device state,
    707707 *                              or false to synchronize the device state's RIRB buffer with the HDA state.
     
    709709 * @todo r=andy Break this up into two functions?
    710710 */
    711 static int hdaR3CmdSync(PHDASTATE pThis, bool fLocal)
     711static int hdaR3CmdSync(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fLocal)
    712712{
    713713    int rc = VINF_SUCCESS;
     
    716716        if (pThis->u64CORBBase)
    717717        {
    718             AssertPtr(pThis->pu32CorbBuf);
    719718            Assert(pThis->cbCorbBuf);
    720719
     
    722721 *        the CORB and PDMDevHlpPCIPhysWrite with RIRB below.  There are
    723722 *        similar unexplained inconsistencies in DevHDACommon.cpp. */
    724             rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
     723            rc = PDMDevHlpPhysRead(pDevIns, pThis->u64CORBBase, pThis->au32CorbBuf,
     724                                   RT_MIN(pThis->cbCorbBuf, sizeof(pThis->au32CorbBuf)));
    725725            Log(("hdaR3CmdSync/CORB: read %RGp LB %#x (%Rrc)\n", pThis->u64CORBBase, pThis->cbCorbBuf, rc));
    726726            AssertRCReturn(rc, rc);
     
    731731        if (pThis->u64RIRBBase)
    732732        {
    733             AssertPtr(pThis->pu64RirbBuf);
    734733            Assert(pThis->cbRirbBuf);
    735734
    736             rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
    737             Log(("hdaR3CmdSync/RIRB: phys read %RGp LB %#x (%Rrc)\n", pThis->u64RIRBBase, pThis->pu64RirbBuf, rc));
     735            rc = PDMDevHlpPCIPhysWrite(pDevIns, pThis->u64RIRBBase, pThis->au64RirbBuf,
     736                                       RT_MIN(pThis->cbRirbBuf, sizeof(pThis->au64RirbBuf)));
     737            Log(("hdaR3CmdSync/RIRB: phys read %RGp LB %#x (%Rrc)\n", pThis->u64RIRBBase, pThis->cbRirbBuf, rc));
    738738            AssertRCReturn(rc, rc);
    739739        }
     
    789789 * This will invoke the HDA codec verb dispatcher.
    790790 *
    791  * @returns IPRT status code.
    792  * @param   pThis               HDA state.
    793  */
    794 static int hdaR3CORBCmdProcess(PHDASTATE pThis)
    795 {
    796     uint8_t corbRp = HDA_REG(pThis, CORBRP);
    797     uint8_t corbWp = HDA_REG(pThis, CORBWP);
    798     uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
    799 
    800     Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", corbRp, corbWp, rirbWp));
     791 * @returns VBox status code suitable for MMIO write return.
     792 * @param   pDevIns             The device instance.
     793 * @param   pThis               The shared HDA device state.
     794 * @param   pThisCC             The ring-3 HDA device state.
     795 */
     796static int hdaR3CORBCmdProcess(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
     797{
     798    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
    801799
    802800    if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
     
    808806    Assert(pThis->cbCorbBuf);
    809807
    810     int rc = hdaR3CmdSync(pThis, true /* Sync from guest */);
     808    int rc = hdaR3CmdSync(pDevIns, pThis, true /* Sync from guest */);
    811809    AssertRCReturn(rc, rc);
    812810
     811    /*
     812     * Prepare local copies of relevant registers.
     813     */
    813814    uint16_t cIntCnt = HDA_REG(pThis, RINTCNT) & 0xff;
    814 
    815815    if (!cIntCnt) /* 0 means 256 interrupts. */
    816816        cIntCnt = HDA_MAX_RINTCNT;
    817817
    818     Log3Func(("START CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n",
    819               corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
    820 
     818    uint32_t const cCorbEntries = RT_MIN(RT_MAX(pThis->cbCorbBuf, 1), sizeof(pThis->au32CorbBuf)) / HDA_CORB_ELEMENT_SIZE;
     819    uint8_t const  corbWp       = HDA_REG(pThis, CORBWP) % cCorbEntries;
     820    uint8_t        corbRp       = HDA_REG(pThis, CORBRP);
     821    uint8_t        rirbWp       = HDA_REG(pThis, RIRBWP);
     822
     823    /*
     824     * The loop.
     825     */
     826    Log3Func(("START CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
    821827    while (corbRp != corbWp)
    822828    {
    823         corbRp = (corbRp + 1) % (pThis->cbCorbBuf / HDA_CORB_ELEMENT_SIZE); /* Advance +1 as the first command(s) are at CORBWP + 1. */
    824 
    825         uint32_t uCmd  = pThis->pu32CorbBuf[corbRp];
     829        /* Fetch the command from the CORB. */
     830        corbRp = (corbRp + 1) /* Advance +1 as the first command(s) are at CORBWP + 1. */ % cCorbEntries;
     831        uint32_t const uCmd = pThis->au32CorbBuf[corbRp];
     832
     833        /*
     834         * Execute the command.
     835         */
    826836        uint64_t uResp = 0;
    827 
    828         rc = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
     837        rc = pThisCC->pCodec->pfnLookup(pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
    829838        if (RT_FAILURE(rc))
    830839            LogFunc(("Codec lookup failed with rc=%Rrc\n", rc));
    831 
    832         Log3Func(("Codec verb %08x -> response %016lx\n", uCmd, uResp));
     840        Log3Func(("Codec verb %08x -> response %016RX64\n", uCmd, uResp));
    833841
    834842        if (   (uResp & CODEC_RESPONSE_UNSOLICITED)
     
    837845            LogFunc(("Unexpected unsolicited response.\n"));
    838846            HDA_REG(pThis, CORBRP) = corbRp;
    839 
    840             /** @todo r=andy No CORB/RIRB syncing to guest required in that case? */
    841             return rc;
    842         }
    843 
     847            /** @todo r=andy No RIRB syncing to guest required in that case? */
     848            /** @todo r=bird: Why isn't RIRBWP updated here.  The response might come
     849             *        after already processing several commands, can't it?  (When you think
     850             *        about it, it is bascially the same question as Andy is asking.) */
     851            return VINF_SUCCESS;
     852        }
     853
     854        /*
     855         * Store the response in the RIRB.
     856         */
     857        AssertCompile(HDA_RIRB_SIZE == RT_ELEMENTS(pThis->au64RirbBuf));
    844858        rirbWp = (rirbWp + 1) % HDA_RIRB_SIZE;
    845 
    846         pThis->pu64RirbBuf[rirbWp] = uResp;
    847 
     859        pThis->au64RirbBuf[rirbWp] = uResp;
     860
     861        /*
     862         * Send interrupt if needed.
     863         */
     864        bool fSendInterrupt = false;
    848865        pThis->u16RespIntCnt++;
    849 
    850         bool fSendInterrupt = false;
    851 
    852         if (pThis->u16RespIntCnt == cIntCnt) /* Response interrupt count reached? */
     866        if (pThis->u16RespIntCnt >= cIntCnt) /* Response interrupt count reached? */
    853867        {
    854868            pThis->u16RespIntCnt = 0; /* Reset internal interrupt response counter. */
     
    856870            Log3Func(("Response interrupt count reached (%RU16)\n", pThis->u16RespIntCnt));
    857871            fSendInterrupt = true;
    858 
    859872        }
    860873        else if (corbRp == corbWp) /* Did we reach the end of the current command buffer? */
     
    863876            fSendInterrupt = true;
    864877        }
    865 
    866878        if (fSendInterrupt)
    867879        {
     
    869881            {
    870882                HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
    871 
    872                 rc = HDA_PROCESS_INTERRUPT(pThis->pDevInsR3, pThis);
     883                HDA_PROCESS_INTERRUPT(pDevIns, pThis);
    873884            }
    874885        }
    875886    }
    876887
    877     Log3Func(("END CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n",
    878               corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
    879 
     888    /*
     889     * Put register locals back.
     890     */
     891    Log3Func(("END CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
    880892    HDA_REG(pThis, CORBRP) = corbRp;
    881893    HDA_REG(pThis, RIRBWP) = rirbWp;
    882894
    883     rc = hdaR3CmdSync(pThis, false /* Sync to guest */);
    884     AssertRCReturn(rc, rc);
    885 
    886     if (RT_FAILURE(rc))
    887         AssertRCReturn(rc, rc);
     895    /*
     896     * Write out the response.
     897     */
     898    rc = hdaR3CmdSync(pDevIns, pThis, false /* Sync to guest */);
     899    AssertRC(rc);
    888900
    889901    return rc;
     
    9891001        HDA_REG(pThis, GCTL) &= ~HDA_GCTL_CRST;
    9901002
    991         hdaR3GCTLReset(pThis);
     1003        hdaR3GCTLReset(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns,  PHDASTATER3));
    9921004#else
    9931005        return VINF_IOM_R3_MMIO_WRITE;
     
    10321044/**
    10331045 * Returns the current maximum value the wall clock counter can be set to.
     1046 *
    10341047 * This maximum value depends on all currently handled HDA streams and their own current timing.
    10351048 *
    10361049 * @return  Current maximum value the wall clock counter can be set to.
    1037  * @param   pThis               HDA state.
     1050 * @param   pThis               The shared HDA device state.
     1051 * @param   pThisCC             The ring-3 HDA device state.
    10381052 *
    10391053 * @remark  Does not actually set the wall clock counter.
    1040  */
    1041 static uint64_t hdaR3WalClkGetMax(PHDASTATE pThis)
     1054 *
     1055 * @todo r=bird: This function is in the wrong file.
     1056 */
     1057static uint64_t hdaR3WalClkGetMax(PHDASTATE pThis, PHDASTATER3 pThisCC)
    10421058{
    10431059    const uint64_t u64WalClkCur       = ASMAtomicReadU64(&pThis->u64WalClk);
    1044     const uint64_t u64FrontAbsWalClk  = pThis->SinkFront.pStream
    1045                                       ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThis->SinkFront.pStream->State.Period) : 0;
     1060    const uint64_t u64FrontAbsWalClk  = pThisCC->SinkFront.pStreamShared
     1061                                      ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkFront.pStreamShared->State.Period) : 0;
    10461062# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    10471063#  error "Implement me!"
    10481064# endif
    1049     const uint64_t u64LineInAbsWalClk = pThis->SinkLineIn.pStream
    1050                                       ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThis->SinkLineIn.pStream->State.Period) : 0;
     1065    const uint64_t u64LineInAbsWalClk = pThisCC->SinkLineIn.pStreamShared
     1066                                      ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkLineIn.pStreamShared->State.Period) : 0;
    10511067# ifdef VBOX_WITH_HDA_MIC_IN
    1052     const uint64_t u64MicInAbsWalClk  = pThis->SinkMicIn.pStream
    1053                                       ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThis->SinkMicIn.pStream->State.Period) : 0;
     1068    const uint64_t u64MicInAbsWalClk  = pThisCC->SinkMicIn.pStreamShared
     1069                                      ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkMicIn.pStreamShared->State.Period) : 0;
    10541070# endif
    10551071
     
    10781094    *pu32Value = RT_LO_U32(u64WalClkCur);
    10791095
    1080     Log3Func(("%RU32 (max @ %RU64)\n", *pu32Value, hdaR3WalClkGetMax(pThis)));
     1096    Log3Func(("%RU32 (max @ %RU64)\n", *pu32Value, hdaR3WalClkGetMax(pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3))));
    10811097    return VINF_SUCCESS;
    10821098#else
     
    10941110        if (pThis->cbCorbBuf)
    10951111        {
    1096 #ifdef IN_RING3
    1097             AssertPtr(pThis->pu32CorbBuf);
    1098             RT_BZERO(pThis->pu32CorbBuf, pThis->cbCorbBuf);
    1099 #else
     1112            RT_ZERO(pThis->au32CorbBuf);
    11001113            return VINF_IOM_R3_MMIO_WRITE;
    1101 #endif
    11021114        }
    11031115
     
    11191131
    11201132    if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* Start DMA engine. */
    1121         rc = hdaR3CORBCmdProcess(pThis);
     1133        rc = hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
    11221134    else
    11231135        LogFunc(("CORB DMA not running, skipping\n"));
     
    11321144static VBOXSTRICTRC hdaRegWriteCORBSIZE(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    11331145{
    1134 #ifdef IN_RING3
    11351146    RT_NOREF(pDevIns, iReg);
    11361147
     
    11591170
    11601171        uint32_t cbCorbBuf = cEntries * HDA_CORB_ELEMENT_SIZE;
    1161         Assert(cbCorbBuf <= HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE); /* Paranoia. */
     1172        Assert(cbCorbBuf <= sizeof(pThis->au32CorbBuf)); /* paranoia */
    11621173
    11631174        if (cbCorbBuf != pThis->cbCorbBuf)
    11641175        {
    1165             RT_BZERO(pThis->pu32CorbBuf, HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE); /* Clear CORB when setting a new size. */
     1176            RT_ZERO(pThis->au32CorbBuf); /* Clear CORB when setting a new size. */
    11661177            pThis->cbCorbBuf = cbCorbBuf;
    11671178        }
     
    11741185        LogFunc(("CORB DMA is (still) running, skipping\n"));
    11751186    return VINF_SUCCESS;
     1187}
     1188
     1189static VBOXSTRICTRC hdaRegWriteCORBSTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     1190{
     1191    RT_NOREF(pDevIns, iReg);
     1192
     1193    uint32_t v = HDA_REG(pThis, CORBSTS);
     1194    HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
     1195
     1196    return VINF_SUCCESS;
     1197}
     1198
     1199static VBOXSTRICTRC hdaRegWriteCORBWP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     1200{
     1201#ifdef IN_RING3
     1202    VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
     1203    AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
     1204
     1205    return hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
    11761206#else
    11771207    RT_NOREF(pDevIns, pThis, iReg, u32Value);
     
    11801210}
    11811211
    1182 static VBOXSTRICTRC hdaRegWriteCORBSTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    1183 {
    1184     RT_NOREF(pDevIns, iReg);
    1185 
    1186     uint32_t v = HDA_REG(pThis, CORBSTS);
    1187     HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
    1188 
    1189     return VINF_SUCCESS;
    1190 }
    1191 
    1192 static VBOXSTRICTRC hdaRegWriteCORBWP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     1212static VBOXSTRICTRC hdaRegWriteSDCBL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     1213{
     1214    return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
     1215}
     1216
     1217static VBOXSTRICTRC hdaRegWriteSDCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    11931218{
    11941219#ifdef IN_RING3
    1195     VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
    1196     AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
    1197 
    1198     return hdaR3CORBCmdProcess(pThis);
    1199 #else
    1200     RT_NOREF(pDevIns, pThis, iReg, u32Value);
    1201     return VINF_IOM_R3_MMIO_WRITE;
    1202 #endif
    1203 }
    1204 
    1205 static VBOXSTRICTRC hdaRegWriteSDCBL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    1206 {
    1207     return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
    1208 }
    1209 
    1210 static VBOXSTRICTRC hdaRegWriteSDCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    1211 {
    1212 #ifdef IN_RING3
    1213     /* Get the stream descriptor. */
     1220    /* Get the stream descriptor number. */
    12141221    const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
     1222    AssertReturn(uSD < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
    12151223
    12161224    /*
     
    12211229     * So depending on the guest OS, SD3 can use stream tag 4, for example.
    12221230     */
    1223     uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
    1224     ASSERT_GUEST_MSG_RETURN(uTag < RT_ELEMENTS(pThis->aTags),
     1231    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     1232    uint8_t     uTag    = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
     1233    ASSERT_GUEST_MSG_RETURN(uTag < RT_ELEMENTS(pThisCC->aTags),
    12251234                            ("SD%RU8: Invalid stream tag %RU8 (u32Value=%#x)!\n", uSD, uTag, u32Value),
    12261235                            VINF_SUCCESS /* Always return success to the MMIO handler. */);
    12271236
    1228     PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
    1229     ASSERT_GUEST_LOGREL_MSG_RETURN(pStream, ("Guest tried writing SDCTL (0x%x) to unhandled stream #%RU8\n", u32Value, uSD),
    1230                                    VINF_SUCCESS /* Always return success to the MMIO handler. */);
     1237    PHDASTREAM   const pStreamShared = &pThis->aStreams[uSD];
     1238    PHDASTREAMR3 const pStreamR3     = &pThisCC->aStreams[uSD];
    12311239
    12321240    const bool fRun      = RT_BOOL(u32Value & HDA_SDCTL_RUN);
     
    12421250    {
    12431251        DEVHDA_UNLOCK(pDevIns, pThis);
    1244         DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStream, VINF_IOM_R3_MMIO_WRITE);
     1252        DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStreamShared, VINF_IOM_R3_MMIO_WRITE);
    12451253    }
    12461254
     
    12561264
    12571265        /* Exit reset state. */
    1258         ASMAtomicXchgBool(&pStream->State.fInReset, false);
     1266        ASMAtomicXchgBool(&pStreamShared->State.fInReset, false);
    12591267
    12601268        /* Report that we're done resetting this stream by clearing SRST. */
     
    12701278        LogFunc(("[SD%RU8] Reset enter\n", uSD));
    12711279
    1272         hdaR3StreamLock(pStream);
     1280        hdaR3StreamLock(pStreamR3);
    12731281
    12741282# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1275         hdaR3StreamAsyncIOLock(pStream);
     1283        hdaR3StreamAsyncIOLock(pStreamR3);
    12761284# endif
    12771285        /* Make sure to remove the run bit before doing the actual stream reset. */
    12781286        HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
    12791287
    1280         hdaR3StreamReset(pThis, pStream, pStream->u8SD);
     1288        hdaR3StreamReset(pThis, pThisCC, pStreamShared, pStreamR3, uSD);
    12811289
    12821290# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1283         hdaR3StreamAsyncIOUnlock(pStream);
     1291        hdaR3StreamAsyncIOUnlock(pStreamR3);
    12841292# endif
    1285         hdaR3StreamUnlock(pStream);
     1293        hdaR3StreamUnlock(pStreamR3);
    12861294    }
    12871295    else
     
    12951303            LogFunc(("[SD%RU8] State changed (fRun=%RTbool)\n", uSD, fRun));
    12961304
    1297             hdaR3StreamLock(pStream);
     1305            hdaR3StreamLock(pStreamR3);
    12981306
    12991307            int rc2 = VINF_SUCCESS;
     
    13011309# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    13021310            if (fRun)
    1303                 rc2 = hdaR3StreamAsyncIOCreate(pStream);
    1304 
    1305             hdaR3StreamAsyncIOLock(pStream);
     1311                rc2 = hdaR3StreamAsyncIOCreate(pStreamR3);
     1312
     1313            hdaR3StreamAsyncIOLock(pStreamR3);
    13061314# endif
    13071315            if (fRun)
     
    13161324                }
    13171325
    1318                 PHDATAG pTag = &pThis->aTags[uTag];
    1319                 AssertPtr(pTag);
    1320 
     1326                /* Assign new values. */
    13211327                LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
    1322 
    1323                 /* Assign new values. */
    1324                 pTag->uTag    = uTag;
    1325                 pTag->pStream = hdaGetStreamFromSD(pThis, uSD);
     1328                PHDATAG pTag = &pThisCC->aTags[uTag];
     1329                pTag->uTag      = uTag;
     1330                pTag->pStreamR3 = &pThisCC->aStreams[uSD];
    13261331
    13271332# ifdef LOG_ENABLED
    13281333                PDMAUDIOPCMPROPS Props;
    1329                 rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, pStream->u8SD), &Props);
     1334                rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &Props);
    13301335                AssertRC(rc2);
    13311336                LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
    1332                          pStream->u8SD, Props.uHz, Props.cbSample * 8 /* Bit */, Props.cChannels));
     1337                         uSD, Props.uHz, Props.cbSample * 8 /* Bit */, Props.cChannels));
    13331338# endif
    13341339                /* (Re-)initialize the stream with current values. */
    1335                 rc2 = hdaR3StreamInit(pDevIns, pStream, pStream->u8SD);
     1340                rc2 = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, uSD);
    13361341                if (   RT_SUCCESS(rc2)
    13371342                    /* Any vital stream change occurred so that we need to (re-)add the stream to our setup?
     
    13401345                {
    13411346                    /* Remove the old stream from the device setup. */
    1342                     rc2 = hdaR3RemoveStream(pThis, &pStream->State.Cfg);
     1347                    rc2 = hdaR3RemoveStream(pThisCC, &pStreamShared->State.Cfg);
    13431348                    AssertRC(rc2);
    13441349
    13451350                    /* Add the stream to the device setup. */
    1346                     rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
     1351                    rc2 = hdaR3AddStream(pThisCC, &pStreamShared->State.Cfg);
    13471352                    AssertRC(rc2);
    13481353                }
     
    13521357            {
    13531358                /* Enable/disable the stream. */
    1354                 rc2 = hdaR3StreamEnable(pStream, fRun /* fEnable */);
     1359                rc2 = hdaR3StreamEnable(pStreamShared, pStreamR3, fRun /* fEnable */);
    13551360                AssertRC(rc2);
    13561361
     
    13581363                {
    13591364                    /* Keep track of running streams. */
    1360                     pThis->cStreamsActive++;
     1365                    pThisCC->cStreamsActive++;
    13611366
    13621367                    /* (Re-)init the stream's period. */
    1363                     hdaR3StreamPeriodInit(&pStream->State.Period,
    1364                                           pStream->u8SD, pStream->u16LVI, pStream->u32CBL, &pStream->State.Cfg);
     1368                    hdaR3StreamPeriodInit(&pStreamShared->State.Period, uSD, pStreamShared->u16LVI,
     1369                                          pStreamShared->u32CBL, &pStreamShared->State.Cfg);
    13651370
    13661371                    /* Begin a new period for this stream. */
    1367                     rc2 = hdaR3StreamPeriodBegin(&pStream->State.Period, hdaWalClkGetCurrent(pThis)/* Use current wall clock time */);
     1372                    rc2 = hdaR3StreamPeriodBegin(&pStreamShared->State.Period,
     1373                                                 hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
    13681374                    AssertRC(rc2);
    13691375
    1370                     uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, pStream->hTimer);
    1371                     rc2 = hdaR3TimerSet(pDevIns, pStream, tsNow + pStream->State.cTransferTicks, false /* fForce */, tsNow);
     1376                    uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
     1377                    rc2 = hdaR3TimerSet(pDevIns, pStreamShared, tsNow + pStreamShared->State.cTransferTicks, false /* fForce */, tsNow);
    13721378                    AssertRC(rc2);
    13731379                }
     
    13751381                {
    13761382                    /* Keep track of running streams. */
    1377                     Assert(pThis->cStreamsActive);
    1378                     if (pThis->cStreamsActive)
    1379                         pThis->cStreamsActive--;
     1383                    Assert(pThisCC->cStreamsActive);
     1384                    if (pThisCC->cStreamsActive)
     1385                        pThisCC->cStreamsActive--;
    13801386
    13811387                    /* Make sure to (re-)schedule outstanding (delayed) interrupts. */
    1382                     hdaR3ReschedulePendingInterrupts(pThis);
     1388                    hdaR3ReschedulePendingInterrupts(pDevIns, pThis, pThisCC);
    13831389
    13841390                    /* Reset the period. */
    1385                     hdaR3StreamPeriodReset(&pStream->State.Period);
     1391                    hdaR3StreamPeriodReset(&pStreamShared->State.Period);
    13861392                }
    13871393            }
    13881394
    13891395# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1390             hdaR3StreamAsyncIOUnlock(pStream);
     1396            hdaR3StreamAsyncIOUnlock(pStreamR3);
    13911397# endif
    13921398            /* Make sure to leave the lock before (eventually) starting the timer. */
    1393             hdaR3StreamUnlock(pStream);
     1399            hdaR3StreamUnlock(pStreamR3);
    13941400        }
    13951401    }
    13961402
    13971403    if (fNeedVirtualSyncClockLock)
    1398         PDMDevHlpTimerUnlockClock(pDevIns, pStream->hTimer); /* Caller will unlock pThis->CritSect. */
     1404        PDMDevHlpTimerUnlockClock(pDevIns, pStreamShared->hTimer); /* Caller will unlock pThis->CritSect. */
    13991405
    14001406    return hdaRegWriteU24(pDevIns, pThis, iReg, u32Value);
     
    14091415#ifdef IN_RING3
    14101416    const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, STS, iReg);
    1411     PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
    1412     ASSERT_GUEST_LOGREL_MSG_RETURN(pStream, ("Guest tried writing SDSTS (0x%x) to unhandled stream #%RU8\n", u32Value, uSD),
    1413                                    VINF_SUCCESS);
     1417    AssertReturn(uSD < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
     1418    PHDASTATER3 const  pThisCC       = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     1419    PHDASTREAMR3 const pStreamR3     = &pThisCC->aStreams[uSD];
     1420    PHDASTREAM const   pStreamShared = &pThis->aStreams[uSD];
    14141421
    14151422    /* We only need to take the virtual-sync lock if we want to call
    14161423       PDMDevHlpTimerGet or hdaR3TimerSet later.  Only precondition for that
    14171424       is that we've got a non-zero ticks-per-transfer value. */
    1418     uint64_t const cTransferTicks = pStream->State.cTransferTicks;
     1425    uint64_t const cTransferTicks = pStreamShared->State.cTransferTicks;
    14191426    if (cTransferTicks)
    14201427    {
    14211428        DEVHDA_UNLOCK(pDevIns, pThis);
    1422         DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStream, VINF_IOM_R3_MMIO_WRITE);
    1423     }
    1424 
    1425     hdaR3StreamLock(pStream);
     1429        DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStreamShared, VINF_IOM_R3_MMIO_WRITE);
     1430    }
     1431
     1432    hdaR3StreamLock(pStreamR3);
    14261433
    14271434    uint32_t v = HDA_REG_IND(pThis, iReg);
     
    14381445    /* Some guests tend to write SDnSTS even if the stream is not running.
    14391446     * So make sure to check if the RUN bit is set first. */
    1440     const bool fRunning = pStream->State.fRunning;
    1441 
    1442     Log3Func(("[SD%RU8] fRunning=%RTbool %R[sdsts]\n", pStream->u8SD, fRunning, v));
    1443 
    1444     PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
     1447    const bool fRunning = pStreamShared->State.fRunning;
     1448
     1449    Log3Func(("[SD%RU8] fRunning=%RTbool %R[sdsts]\n", uSD, fRunning, v));
     1450
     1451    PHDASTREAMPERIOD pPeriod = &pStreamShared->State.Period;
    14451452    hdaR3StreamPeriodLock(pPeriod);
    14461453    if (hdaR3StreamPeriodNeedsInterrupt(pPeriod))
     
    14501457        /* Make sure to try to update the WALCLK register if a period is complete.
    14511458         * Use the maximum WALCLK value all (active) streams agree to. */
    1452         const uint64_t uWalClkMax = hdaR3WalClkGetMax(pThis);
     1459        const uint64_t uWalClkMax = hdaR3WalClkGetMax(pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
    14531460        if (uWalClkMax > hdaWalClkGetCurrent(pThis))
    1454             hdaR3WalClkSet(pThis, uWalClkMax, false /* fForce */);
     1461            hdaR3WalClkSet(pThis, pThisCC, uWalClkMax, false /* fForce */);
    14551462
    14561463        hdaR3StreamPeriodEnd(pPeriod);
     
    14661473     * ...
    14671474     */
    1468     uint64_t cTicksToNext = pStream->State.cTransferTicks;
     1475    uint64_t cTicksToNext = pStreamShared->State.cTransferTicks;
    14691476    Assert(cTicksToNext == cTicksToNext);
    14701477    if (cTicksToNext) /* Only do any calculations if the stream currently is set up for transfers. */
    14711478    {
    1472         const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pStream->hTimer);
    1473         Assert(tsNow >= pStream->State.tsTransferLast);
    1474 
    1475         const uint64_t cTicksElapsed     = tsNow - pStream->State.tsTransferLast;
     1479        const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
     1480        Assert(tsNow >= pStreamShared->State.tsTransferLast);
     1481
     1482        const uint64_t cTicksElapsed     = tsNow - pStreamShared->State.tsTransferLast;
    14761483# ifdef LOG_ENABLED
    1477         const uint64_t cTicksTransferred = pStream->State.cbTransferProcessed * pStream->State.cTicksPerByte;
     1484        const uint64_t cTicksTransferred = pStreamShared->State.cbTransferProcessed * pStreamShared->State.cTicksPerByte;
    14781485# endif
    14791486
    14801487        Log3Func(("[SD%RU8] cTicksElapsed=%RU64, cTicksTransferred=%RU64, cTicksToNext=%RU64\n",
    1481                   pStream->u8SD, cTicksElapsed, cTicksTransferred, cTicksToNext));
    1482 
    1483         Log3Func(("[SD%RU8] cbTransferProcessed=%RU32, cbTransferChunk=%RU32, cbTransferSize=%RU32\n",
    1484                   pStream->u8SD, pStream->State.cbTransferProcessed, pStream->State.cbTransferChunk, pStream->State.cbTransferSize));
     1488                  uSD, cTicksElapsed, cTicksTransferred, cTicksToNext));
     1489
     1490        Log3Func(("[SD%RU8] cbTransferProcessed=%RU32, cbTransferChunk=%RU32, cbTransferSize=%RU32\n", uSD,
     1491                  pStreamShared->State.cbTransferProcessed, pStreamShared->State.cbTransferChunk, pStreamShared->State.cbTransferSize));
    14851492
    14861493        if (cTicksElapsed <= cTicksToNext)
     
    14891496        {
    14901497            Log3Func(("[SD%RU8] Warning: Lagging behind (%RU64 ticks elapsed, maximum allowed is %RU64)\n",
    1491                      pStream->u8SD, cTicksElapsed, cTicksToNext));
    1492 
    1493             LogRelMax2(64, ("HDA: Stream #%RU8 interrupt lagging behind (expected %uus, got %uus), trying to catch up ...\n",
    1494                             pStream->u8SD,
    1495                             (PDMDevHlpTimerGetFreq(pDevIns, pStream->hTimer) / pThis->uTimerHz) / 1000,
    1496                             (tsNow - pStream->State.tsTransferLast) / 1000));
     1498                     uSD, cTicksElapsed, cTicksToNext));
     1499
     1500            LogRelMax2(64, ("HDA: Stream #%RU8 interrupt lagging behind (expected %uus, got %uus), trying to catch up ...\n", uSD,
     1501                            (PDMDevHlpTimerGetFreq(pDevIns, pStreamShared->hTimer) / pThis->uTimerHz) / 1000,
     1502                            (tsNow - pStreamShared->State.tsTransferLast) / 1000));
    14971503
    14981504            cTicksToNext = 0;
    14991505        }
    15001506
    1501         Log3Func(("[SD%RU8] -> cTicksToNext=%RU64\n", pStream->u8SD, cTicksToNext));
     1507        Log3Func(("[SD%RU8] -> cTicksToNext=%RU64\n", uSD, cTicksToNext));
    15021508
    15031509        /* Reset processed data counter. */
    1504         pStream->State.cbTransferProcessed = 0;
    1505         pStream->State.tsTransferNext      = tsNow + cTicksToNext;
     1510        pStreamShared->State.cbTransferProcessed = 0;
     1511        pStreamShared->State.tsTransferNext      = tsNow + cTicksToNext;
    15061512
    15071513        /* Only re-arm the timer if there were pending transfer interrupts left
    15081514         *  -- it could happen that we land in here if a guest writes to SDnSTS
    15091515         * unconditionally. */
    1510         if (pStream->State.cTransferPendingInterrupts)
    1511         {
    1512             pStream->State.cTransferPendingInterrupts--;
     1516        if (pStreamShared->State.cTransferPendingInterrupts)
     1517        {
     1518            pStreamShared->State.cTransferPendingInterrupts--;
    15131519
    15141520            /* Re-arm the timer. */
    1515             LogFunc(("Timer set SD%RU8\n", pStream->u8SD));
    1516             hdaR3TimerSet(pDevIns, pStream, tsNow + cTicksToNext, true /* fForce - we just set tsTransferNext*/, 0 /*tsNow*/);
     1521            LogFunc(("Timer set SD%RU8\n", uSD));
     1522            hdaR3TimerSet(pDevIns, pStreamShared, tsNow + cTicksToNext,
     1523                          true /* fForce - we just set tsTransferNext*/, 0 /*tsNow*/);
    15171524        }
    15181525    }
    15191526
    15201527    if (cTransferTicks)
    1521         PDMDevHlpTimerUnlockClock(pDevIns, pStream->hTimer); /* Caller will unlock pThis->CritSect. */
    1522     hdaR3StreamUnlock(pStream);
     1528        PDMDevHlpTimerUnlockClock(pDevIns, pStreamShared->hTimer); /* Caller will unlock pThis->CritSect. */
     1529    hdaR3StreamUnlock(pStreamR3);
    15231530    return VINF_SUCCESS;
    15241531#else  /* !IN_RING3 */
     
    15301537static VBOXSTRICTRC hdaRegWriteSDLVI(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    15311538{
    1532     const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
     1539    const size_t idxStream = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
     1540    AssertReturn(idxStream < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
    15331541
    15341542#ifdef HDA_USE_DMA_ACCESS_HANDLER
     
    15371545        /* Try registering the DMA handlers.
    15381546         * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
    1539         PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
     1547        PHDASTREAM pStream = hdaGetStreamFromSD(pThis, idxStream);
    15401548        if (   pStream
    15411549            && hdaR3StreamRegisterDMAHandlers(pThis, pStream))
     
    15451553
    15461554    ASSERT_GUEST_LOGREL_MSG(u32Value <= UINT8_MAX, /* Should be covered by the register write mask, but just to make sure. */
    1547                             ("LVI for stream #%RU8 must not be bigger than %RU8\n", uSD, UINT8_MAX - 1));
     1555                            ("LVI for stream #%zu must not be bigger than %RU8\n", idxStream, UINT8_MAX - 1));
    15481556    return hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
    15491557}
     
    15511559static VBOXSTRICTRC hdaRegWriteSDFIFOW(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    15521560{
    1553     uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
    1554 
    1555     if (RT_LIKELY(hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)) /* FIFOW for input streams only. */
     1561    size_t const idxStream = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
     1562    AssertReturn(idxStream < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
     1563
     1564    if (RT_LIKELY(hdaGetDirFromSD((uint8_t)idxStream) == PDMAUDIODIR_IN)) /* FIFOW for input streams only. */
    15561565    { /* likely */ }
    15571566    else
    15581567    {
    15591568#ifndef IN_RING0
    1560         LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", uSD));
     1569        LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", idxStream));
    15611570        return VINF_SUCCESS;
    15621571#else
     
    15651574    }
    15661575
    1567     PHDASTREAM pStream = hdaGetStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg));
    1568     if (pStream)
    1569     {
    1570         uint32_t u32FIFOW = 0;
    1571         switch (u32Value)
    1572         {
    1573             case HDA_SDFIFOW_8B:
    1574             case HDA_SDFIFOW_16B:
    1575             case HDA_SDFIFOW_32B:
    1576                 u32FIFOW = u32Value;
    1577                 break;
    1578             default:
    1579                 ASSERT_GUEST_LOGREL_MSG_FAILED(("Guest tried writing unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
    1580                                                 u32Value, uSD));
    1581                 u32FIFOW = HDA_SDFIFOW_32B;
    1582                 break;
    1583         }
    1584 
    1585         if (u32FIFOW) /** @todo r=bird: Logic error. it will never be zero, so why this check? */
    1586         {
    1587             pStream->u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW);
    1588             LogFunc(("[SD%RU8] Updating FIFOW to %RU32 bytes\n", uSD, pStream->u16FIFOW));
    1589             return hdaRegWriteU16(pDevIns, pThis, iReg, u32FIFOW);
    1590         }
     1576    uint32_t u32FIFOW = 0;
     1577    switch (u32Value)
     1578    {
     1579        case HDA_SDFIFOW_8B:
     1580        case HDA_SDFIFOW_16B:
     1581        case HDA_SDFIFOW_32B:
     1582            u32FIFOW = u32Value;
     1583            break;
     1584        default:
     1585            ASSERT_GUEST_LOGREL_MSG_FAILED(("Guest tried writing unsupported FIFOW (0x%zx) to stream #%RU8, defaulting to 32 bytes\n",
     1586                                            u32Value, idxStream));
     1587            u32FIFOW = HDA_SDFIFOW_32B;
     1588            break;
     1589    }
     1590
     1591    if (u32FIFOW) /** @todo r=bird: Logic error. it will never be zero, so why this check? */
     1592    {
     1593        pThis->aStreams[idxStream].u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW);
     1594        LogFunc(("[SD%zu] Updating FIFOW to %u bytes\n", idxStream, pThis->aStreams[idxStream].u16FIFOW));
     1595        return hdaRegWriteU16(pDevIns, pThis, iReg, u32FIFOW);
    15911596    }
    15921597    return VINF_SUCCESS;
     
    16321637 *
    16331638 * @returns IPRT status code.
    1634  * @param   pThis               Device state.
     1639 * @param   pThisCC             The ring-3 HDA device state.
    16351640 * @param   pCfg                Stream configuration to use for adding a stream.
    16361641 */
    1637 static int hdaR3AddStreamOut(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
    1638 {
    1639     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1642static int hdaR3AddStreamOut(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
     1643{
    16401644    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    16411645
     
    17181722            pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
    17191723
    1720             rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
     1724            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
    17211725        }
    17221726
     
    17331737            pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
    17341738
    1735             rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
     1739            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
    17361740        }
    17371741
     
    17471751            pCfg->Props.cShift      = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
    17481752
    1749             rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
     1753            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
    17501754        }
    17511755# endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
     
    17611765 *
    17621766 * @returns IPRT status code.
    1763  * @param   pThis               Device state.
     1767 * @param   pThisCC             The ring-3 HDA device state.
    17641768 * @param   pCfg                Stream configuration to use for adding a stream.
    17651769 */
    1766 static int hdaR3AddStreamIn(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
    1767 {
    1768     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1770static int hdaR3AddStreamIn(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
     1771{
    17691772    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    17701773
     
    17741777
    17751778    int rc;
    1776 
    17771779    switch (pCfg->u.enmSrc)
    17781780    {
    17791781        case PDMAUDIORECSRC_LINE:
    1780         {
    1781             rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
     1782            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
    17821783            break;
    1783         }
    17841784# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    17851785        case PDMAUDIORECSRC_MIC:
    1786         {
    1787             rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
     1786            rc = hdaCodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
    17881787            break;
    1789         }
    17901788# endif
    17911789        default:
     
    18021800 *
    18031801 * @returns IPRT status code.
    1804  * @param   pThis               Device state.
     1802 * @param   pThisCC             The ring-3 HDA device state.
    18051803 * @param   pCfg                Stream configuration to use for adding a stream.
    18061804 */
    1807 static int hdaR3AddStream(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
    1808 {
    1809     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1805static int hdaR3AddStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
     1806{
    18101807    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    18111808
     1809    LogFlowFuncEnter();
     1810
    18121811    int rc;
    1813 
    1814     LogFlowFuncEnter();
    1815 
    18161812    switch (pCfg->enmDir)
    18171813    {
    18181814        case PDMAUDIODIR_OUT:
    1819             rc = hdaR3AddStreamOut(pThis, pCfg);
     1815            rc = hdaR3AddStreamOut(pThisCC, pCfg);
    18201816            break;
    18211817
    18221818        case PDMAUDIODIR_IN:
    1823             rc = hdaR3AddStreamIn(pThis, pCfg);
     1819            rc = hdaR3AddStreamIn(pThisCC, pCfg);
    18241820            break;
    18251821
     
    18391835 *
    18401836 * @returns IPRT status code.
    1841  * @param   pThis               Device state.
     1837 * @param   pThisCC             The ring-3 HDA device state.
    18421838 * @param   pCfg                Stream configuration to use for removing a stream.
    18431839 */
    1844 static int hdaR3RemoveStream(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
    1845 {
    1846     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1840static int hdaR3RemoveStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
     1841{
    18471842    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    18481843
     
    18981893        && enmMixerCtl != PDMAUDIOMIXERCTL_UNKNOWN)
    18991894    {
    1900         rc = hdaCodecRemoveStream(pThis->pCodec, enmMixerCtl);
     1895        rc = hdaCodecRemoveStream(pThisCC->pCodec, enmMixerCtl);
    19011896    }
    19021897
     
    19931988        HDA_REG(pThis, IRS) = HDA_IRS_ICB;  /* busy */
    19941989
    1995         uint64_t uResp = 0;
    1996         int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
     1990        PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     1991        uint64_t    uResp   = 0;
     1992        int rc2 = pThisCC->pCodec->pfnLookup(pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
    19971993        if (RT_FAILURE(rc2))
    19981994            LogFunc(("Codec lookup failed with rc2=%Rrc\n", rc2));
     
    20282024            /* Do a RIRB reset. */
    20292025            if (pThis->cbRirbBuf)
    2030             {
    2031 #ifdef IN_RING3
    2032                 Assert(pThis->pu64RirbBuf);
    2033                 RT_BZERO(pThis->pu64RirbBuf, pThis->cbRirbBuf);
    2034 #else
    2035                 return VINF_IOM_R3_MMIO_WRITE;
    2036 #endif
    2037             }
     2026                RT_ZERO(pThis->au64RirbBuf);
    20382027
    20392028            LogRel2(("HDA: RIRB reset\n"));
     
    20572046    VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
    20582047    AssertRC(VBOXSTRICTRC_VAL(rc));
     2048
     2049    /** @todo r=bird: Shouldn't we make sure the HDASTATE::u16RespIntCnt is below
     2050     *        the new RINTCNT value?  Or alterantively, make the DMA look take
     2051     *        this into account instead...  I'll do the later for now. */
    20592052
    20602053    LogFunc(("Response interrupt count is now %RU8\n", HDA_REG(pThis, RINTCNT) & 0xFF));
     
    21162109    HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
    21172110
    2118     return HDA_PROCESS_INTERRUPT(pDevIns, pThis);
     2111    HDA_PROCESS_INTERRUPT(pDevIns, pThis);
     2112    return VINF_SUCCESS;
    21192113}
    21202114
     
    21232117/**
    21242118 * Retrieves a corresponding sink for a given mixer control.
    2125  * Returns NULL if no sink is found.
    21262119 *
    2127  * @return  PHDAMIXERSINK
    2128  * @param   pThis               HDA state.
     2120 * @return  Pointer to the sink, NULL if no sink is found.
     2121 * @param   pThisCC             The ring-3 HDA device state.
    21292122 * @param   enmMixerCtl         Mixer control to get the corresponding sink for.
    21302123 */
    2131 static PHDAMIXERSINK hdaR3MixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
     2124static PHDAMIXERSINK hdaR3MixerControlToSink(PHDASTATER3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl)
    21322125{
    21332126    PHDAMIXERSINK pSink;
     
    21382131            /* Fall through is intentional. */
    21392132        case PDMAUDIOMIXERCTL_FRONT:
    2140             pSink = &pThis->SinkFront;
     2133            pSink = &pThisCC->SinkFront;
    21412134            break;
    21422135# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    21432136        case PDMAUDIOMIXERCTL_CENTER_LFE:
    2144             pSink = &pThis->SinkCenterLFE;
     2137            pSink = &pThisCC->SinkCenterLFE;
    21452138            break;
    21462139        case PDMAUDIOMIXERCTL_REAR:
    2147             pSink = &pThis->SinkRear;
     2140            pSink = &pThisCC->SinkRear;
    21482141            break;
    21492142# endif
    21502143        case PDMAUDIOMIXERCTL_LINE_IN:
    2151             pSink = &pThis->SinkLineIn;
     2144            pSink = &pThisCC->SinkLineIn;
    21522145            break;
    21532146# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    21542147        case PDMAUDIOMIXERCTL_MIC_IN:
    2155             pSink = &pThis->SinkMicIn;
     2148            pSink = &pThisCC->SinkMicIn;
    21562149            break;
    21572150# endif
    21582151        default:
     2152            AssertMsgFailed(("Unhandled mixer control\n"));
    21592153            pSink = NULL;
    2160             AssertMsgFailed(("Unhandled mixer control\n"));
    21612154            break;
    21622155    }
     
    21692162 *
    21702163 * @return IPRT status code.
    2171  * @param  pThis                HDA state.
     2164 * @param   pThisCC             The ring-3 HDA device state.
    21722165 * @param  pDrv                 HDA driver to add.
    21732166 */
    2174 static int hdaR3MixerAddDrv(PHDASTATE pThis, PHDADRIVER pDrv)
     2167static int hdaR3MixerAddDrv(PHDASTATER3 pThisCC, PHDADRIVER pDrv)
    21752168{
    21762169    int rc = VINF_SUCCESS;
    21772170
    2178     PHDASTREAM pStream = hdaR3GetStreamFromSink(pThis, &pThis->SinkLineIn);
     2171    PHDASTREAM pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkLineIn);
    21792172    if (   pStream
    21802173        && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
    21812174    {
    2182         int rc2 = hdaR3MixerAddDrvStream(pThis, pThis->SinkLineIn.pMixSink, &pStream->State.Cfg, pDrv);
     2175        int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkLineIn.pMixSink, &pStream->State.Cfg, pDrv);
    21832176        if (RT_SUCCESS(rc))
    21842177            rc = rc2;
     
    21862179
    21872180# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2188     pStream = hdaR3GetStreamFromSink(pThis, &pThis->SinkMicIn);
     2181    pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkMicIn);
    21892182    if (   pStream
    21902183        && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
    21912184    {
    2192         int rc2 = hdaR3MixerAddDrvStream(pThis, pThis->SinkMicIn.pMixSink, &pStream->State.Cfg, pDrv);
     2185        int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkMicIn.pMixSink, &pStream->State.Cfg, pDrv);
    21932186        if (RT_SUCCESS(rc))
    21942187            rc = rc2;
     
    21962189# endif
    21972190
    2198     pStream = hdaR3GetStreamFromSink(pThis, &pThis->SinkFront);
     2191    pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkFront);
    21992192    if (   pStream
    22002193        && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
    22012194    {
    2202         int rc2 = hdaR3MixerAddDrvStream(pThis, pThis->SinkFront.pMixSink, &pStream->State.Cfg, pDrv);
     2195        int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkFront.pMixSink, &pStream->State.Cfg, pDrv);
    22032196        if (RT_SUCCESS(rc))
    22042197            rc = rc2;
     
    22062199
    22072200# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2208     pStream = hdaR3GetStreamFromSink(pThis, &pThis->SinkCenterLFE);
     2201    pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkCenterLFE);
    22092202    if (   pStream
    22102203        && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
    22112204    {
    2212         int rc2 = hdaR3MixerAddDrvStream(pThis, pThis->SinkCenterLFE.pMixSink, &pStream->State.Cfg, pDrv);
     2205        int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkCenterLFE.pMixSink, &pStream->State.Cfg, pDrv);
    22132206        if (RT_SUCCESS(rc))
    22142207            rc = rc2;
    22152208    }
    22162209
    2217     pStream = hdaR3GetStreamFromSink(pThis, &pThis->SinkRear);
     2210    pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkRear);
    22182211    if (   pStream
    22192212        && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
    22202213    {
    2221         int rc2 = hdaR3MixerAddDrvStream(pThis, pThis->SinkRear.pMixSink, &pStream->State.Cfg, pDrv);
     2214        int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkRear.pMixSink, &pStream->State.Cfg, pDrv);
    22222215        if (RT_SUCCESS(rc))
    22232216            rc = rc2;
     
    22322225 * associated streams.
    22332226 *
    2234  * @param pThis                 HDA state.
    2235  * @param pDrv                  HDA driver to remove.
    2236  */
    2237 static void hdaR3MixerRemoveDrv(PHDASTATE pThis, PHDADRIVER pDrv)
    2238 {
    2239     AssertPtrReturnVoid(pThis);
     2227 * @param   pThisCC             The ring-3 HDA device state.
     2228 * @param   pDrv                HDA driver to remove.
     2229 */
     2230static void hdaR3MixerRemoveDrv(PHDASTATER3 pThisCC, PHDADRIVER pDrv)
     2231{
    22402232    AssertPtrReturnVoid(pDrv);
    22412233
    22422234    if (pDrv->LineIn.pMixStrm)
    22432235    {
    2244         if (AudioMixerSinkGetRecordingSource(pThis->SinkLineIn.pMixSink) == pDrv->LineIn.pMixStrm)
    2245             AudioMixerSinkSetRecordingSource(pThis->SinkLineIn.pMixSink, NULL);
    2246 
    2247         AudioMixerSinkRemoveStream(pThis->SinkLineIn.pMixSink, pDrv->LineIn.pMixStrm);
     2236        if (AudioMixerSinkGetRecordingSource(pThisCC->SinkLineIn.pMixSink) == pDrv->LineIn.pMixStrm)
     2237            AudioMixerSinkSetRecordingSource(pThisCC->SinkLineIn.pMixSink, NULL);
     2238
     2239        AudioMixerSinkRemoveStream(pThisCC->SinkLineIn.pMixSink, pDrv->LineIn.pMixStrm);
    22482240        AudioMixerStreamDestroy(pDrv->LineIn.pMixStrm);
    22492241        pDrv->LineIn.pMixStrm = NULL;
     
    22532245    if (pDrv->MicIn.pMixStrm)
    22542246    {
    2255         if (AudioMixerSinkGetRecordingSource(pThis->SinkMicIn.pMixSink) == pDrv->MicIn.pMixStrm)
    2256             AudioMixerSinkSetRecordingSource(&pThis->SinkMicIn.pMixSink, NULL);
    2257 
    2258         AudioMixerSinkRemoveStream(pThis->SinkMicIn.pMixSink, pDrv->MicIn.pMixStrm);
     2247        if (AudioMixerSinkGetRecordingSource(pThisCC->SinkMicIn.pMixSink) == pDrv->MicIn.pMixStrm)
     2248            AudioMixerSinkSetRecordingSource(&pThisCC->SinkMicIn.pMixSink, NULL);
     2249
     2250        AudioMixerSinkRemoveStream(pThisCC->SinkMicIn.pMixSink, pDrv->MicIn.pMixStrm);
    22592251        AudioMixerStreamDestroy(pDrv->MicIn.pMixStrm);
    22602252        pDrv->MicIn.pMixStrm = NULL;
     
    22642256    if (pDrv->Front.pMixStrm)
    22652257    {
    2266         AudioMixerSinkRemoveStream(pThis->SinkFront.pMixSink, pDrv->Front.pMixStrm);
     2258        AudioMixerSinkRemoveStream(pThisCC->SinkFront.pMixSink, pDrv->Front.pMixStrm);
    22672259        AudioMixerStreamDestroy(pDrv->Front.pMixStrm);
    22682260        pDrv->Front.pMixStrm = NULL;
     
    22722264    if (pDrv->CenterLFE.pMixStrm)
    22732265    {
    2274         AudioMixerSinkRemoveStream(pThis->SinkCenterLFE.pMixSink, pDrv->CenterLFE.pMixStrm);
     2266        AudioMixerSinkRemoveStream(pThisCC->SinkCenterLFE.pMixSink, pDrv->CenterLFE.pMixStrm);
    22752267        AudioMixerStreamDestroy(pDrv->CenterLFE.pMixStrm);
    22762268        pDrv->CenterLFE.pMixStrm = NULL;
     
    22792271    if (pDrv->Rear.pMixStrm)
    22802272    {
    2281         AudioMixerSinkRemoveStream(pThis->SinkRear.pMixSink, pDrv->Rear.pMixStrm);
     2273        AudioMixerSinkRemoveStream(pThisCC->SinkRear.pMixSink, pDrv->Rear.pMixStrm);
    22822274        AudioMixerStreamDestroy(pDrv->Rear.pMixStrm);
    22832275        pDrv->Rear.pMixStrm = NULL;
     
    22922284 *
    22932285 * @returns IPRT status code (ignored by caller).
    2294  * @param   pThis               HDA state.
    22952286 * @param   pMixSink            Audio mixer sink to add audio streams to.
    22962287 * @param   pCfg                Audio stream configuration to use for the audio streams to add.
    22972288 * @param   pDrv                Driver stream to add.
    22982289 */
    2299 static int hdaR3MixerAddDrvStream(PHDASTATE pThis, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv)
    2300 {
    2301     AssertPtrReturn(pThis,    VERR_INVALID_POINTER);
     2290static int hdaR3MixerAddDrvStream(PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv)
     2291{
    23022292    AssertPtrReturn(pMixSink, VERR_INVALID_POINTER);
    23032293    AssertPtrReturn(pCfg,     VERR_INVALID_POINTER);
     
    24172407 *
    24182408 * @returns IPRT status code.
    2419  * @param   pThis               HDA state.
     2409 * @param   pThisCC             The ring-3 HDA device state.
    24202410 * @param   pMixSink            Audio mixer sink to add stream to.
    24212411 * @param   pCfg                Audio stream configuration to use for the audio streams to add.
    24222412 */
    2423 static int hdaR3MixerAddDrvStreams(PHDASTATE pThis, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg)
    2424 {
    2425     AssertPtrReturn(pThis,    VERR_INVALID_POINTER);
     2413static int hdaR3MixerAddDrvStreams(PHDASTATER3 pThisCC, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg)
     2414{
    24262415    AssertPtrReturn(pMixSink, VERR_INVALID_POINTER);
    24272416    AssertPtrReturn(pCfg,     VERR_INVALID_POINTER);
     
    24372426
    24382427    PHDADRIVER pDrv;
    2439     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
    2440     {
    2441         int rc2 = hdaR3MixerAddDrvStream(pThis, pMixSink, pCfg, pDrv);
     2428    RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
     2429    {
     2430        int rc2 = hdaR3MixerAddDrvStream(pMixSink, pCfg, pDrv);
    24422431        if (RT_FAILURE(rc2))
    24432432            LogFunc(("Attaching stream failed with %Rrc\n", rc2));
     
    24522441/**
    24532442 * @interface_method_impl{HDACODEC,pfnCbMixerAddStream}
    2454  *
    2455  * Adds a new audio stream to a specific mixer control.
    2456  *
    2457  * Depending on the mixer control the stream then gets assigned to one of the internal
    2458  * mixer sinks, which in turn then handle the mixing of all connected streams to that sink.
    2459  *
    2460  * @return  IPRT status code.
    2461  * @param   pThis               HDA state.
    2462  * @param   enmMixerCtl         Mixer control to assign new stream to.
    2463  * @param   pCfg                Stream configuration for the new stream.
    2464  */
    2465 static DECLCALLBACK(int) hdaR3MixerAddStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
    2466 {
    2467     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2443 */
     2444static DECLCALLBACK(int) hdaR3MixerAddStream(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
     2445{
     2446    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    24682447    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    2469 
    24702448    int rc;
    24712449
    2472     PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThis, enmMixerCtl);
     2450    PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
    24732451    if (pSink)
    24742452    {
    2475         rc = hdaR3MixerAddDrvStreams(pThis, pSink->pMixSink, pCfg);
     2453        rc = hdaR3MixerAddDrvStreams(pThisCC, pSink->pMixSink, pCfg);
    24762454
    24772455        AssertPtr(pSink->pMixSink);
     
    24872465/**
    24882466 * @interface_method_impl{HDACODEC,pfnCbMixerRemoveStream}
    2489  *
    2490  * Removes a specified mixer control from the HDA's mixer.
    2491  *
    2492  * @return  IPRT status code.
    2493  * @param   pThis               HDA state.
    2494  * @param   enmMixerCtl         Mixer control to remove.
    2495  *
    2496  * @remarks Can be called as a callback by the HDA codec.
    2497  */
    2498 static DECLCALLBACK(int) hdaR3MixerRemoveStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
    2499 {
    2500     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    2501 
    2502     int rc;
    2503 
    2504     PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThis, enmMixerCtl);
     2467 */
     2468static DECLCALLBACK(int) hdaR3MixerRemoveStream(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl)
     2469{
     2470    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     2471    int         rc;
     2472
     2473    PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
    25052474    if (pSink)
    25062475    {
    25072476        PHDADRIVER pDrv;
    2508         RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     2477        RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
    25092478        {
    25102479            PAUDMIXSTREAM pMixStream = NULL;
     
    25682537 * @interface_method_impl{HDACODEC,pfnCbMixerControl}
    25692538 *
    2570  * Controls an input / output converter widget, that is, which converter is connected
    2571  * to which stream (and channel).
    2572  *
    2573  * @returns IPRT status code.
    2574  * @param   pThis               HDA State.
    2575  * @param   enmMixerCtl         Mixer control to set SD stream number and channel for.
    2576  * @param   uSD                 SD stream number (number + 1) to set. Set to 0 for unassign.
    2577  * @param   uChannel            Channel to set. Only valid if a valid SD stream number is specified.
    2578  *
    2579  * @remarks Can be called as a callback by the HDA codec.
    2580  */
    2581 static DECLCALLBACK(int) hdaR3MixerControl(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
    2582 {
     2539 * @note Is also called directly by the DevHDA code.
     2540 */
     2541static DECLCALLBACK(int) hdaR3MixerControl(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
     2542{
     2543    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     2544    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    25832545    LogFunc(("enmMixerCtl=%s, uSD=%RU8, uChannel=%RU8\n", DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), uSD, uChannel));
    25842546
     
    26062568    int rc = VINF_SUCCESS;
    26072569
    2608     PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThis, enmMixerCtl);
     2570    PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
    26092571    if (pSink)
    26102572    {
     
    26122574
    26132575        /* If this an output stream, determine the correct SD#. */
    2614         if (   (uSD < HDA_MAX_SDI)
     2576        if (   uSD < HDA_MAX_SDI
    26152577            && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT)
    2616         {
    26172578            uSD += HDA_MAX_SDI;
    2618         }
     2579
     2580        /* Make 100% sure we got a good stream number before continuing. */
     2581        AssertLogRelReturn(uSD < RT_ELEMENTS(pThisCC->aStreams), VERR_NOT_IMPLEMENTED);
    26192582
    26202583        /* Detach the existing stream from the sink. */
    2621         if (   pSink->pStream
    2622             && (   pSink->pStream->u8SD      != uSD
    2623                 || pSink->pStream->u8Channel != uChannel)
     2584        if (   pSink->pStreamShared
     2585            && pSink->pStreamR3
     2586            && (   pSink->pStreamShared->u8SD      != uSD
     2587                || pSink->pStreamShared->u8Channel != uChannel)
    26242588           )
    26252589        {
    26262590            LogFunc(("Sink '%s' was assigned to stream #%RU8 (channel %RU8) before\n",
    2627                      pSink->pMixSink->pszName, pSink->pStream->u8SD, pSink->pStream->u8Channel));
    2628 
    2629             hdaR3StreamLock(pSink->pStream);
     2591                     pSink->pMixSink->pszName, pSink->pStreamShared->u8SD, pSink->pStreamShared->u8Channel));
     2592
     2593            hdaR3StreamLock(pSink->pStreamR3);
    26302594
    26312595            /* Only disable the stream if the stream descriptor # has changed. */
    2632             if (pSink->pStream->u8SD != uSD)
    2633                 hdaR3StreamEnable(pSink->pStream, false);
    2634 
    2635             pSink->pStream->pMixSink = NULL;
    2636 
    2637             hdaR3StreamUnlock(pSink->pStream);
    2638 
    2639             pSink->pStream = NULL;
    2640         }
    2641 
    2642         Assert(uSD < HDA_MAX_STREAMS);
     2596            if (pSink->pStreamShared->u8SD != uSD)
     2597                hdaR3StreamEnable(pSink->pStreamShared, pSink->pStreamR3, false /*fEnable*/);
     2598
     2599            pSink->pStreamR3->pMixSink = NULL;
     2600
     2601            hdaR3StreamUnlock(pSink->pStreamR3);
     2602
     2603            pSink->pStreamShared = NULL;
     2604            pSink->pStreamR3     = NULL;
     2605        }
    26432606
    26442607        /* Attach the new stream to the sink.
    26452608         * Enabling the stream will be done by the gust via a separate SDnCTL call then. */
    2646         if (pSink->pStream == NULL)
     2609        if (pSink->pStreamShared == NULL)
    26472610        {
    26482611            LogRel2(("HDA: Setting sink '%s' to stream #%RU8 (channel %RU8), mixer control=%s\n",
    26492612                     pSink->pMixSink->pszName, uSD, uChannel, DrvAudioHlpAudMixerCtlToStr(enmMixerCtl)));
    26502613
    2651             PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
    2652             if (pStream)
    2653             {
    2654                 hdaR3StreamLock(pStream);
    2655 
    2656                 pSink->pStream = pStream;
    2657 
    2658                 pStream->u8Channel = uChannel;
    2659                 pStream->pMixSink  = pSink;
    2660 
    2661                 hdaR3StreamUnlock(pStream);
    2662 
    2663                 rc = VINF_SUCCESS;
    2664             }
    2665             else
    2666                 rc = VERR_NOT_IMPLEMENTED;
     2614            PHDASTREAMR3 pStreamR3     = &pThisCC->aStreams[uSD];
     2615            PHDASTREAM   pStreamShared = &pThis->aStreams[uSD];
     2616            hdaR3StreamLock(pStreamR3);
     2617
     2618            pSink->pStreamR3     = pStreamR3;
     2619            pSink->pStreamShared = pStreamShared;
     2620
     2621            pStreamShared->u8Channel = uChannel;
     2622            pStreamR3->pMixSink      = pSink;
     2623
     2624            hdaR3StreamUnlock(pStreamR3);
     2625            rc = VINF_SUCCESS;
    26672626        }
    26682627    }
     
    26802639/**
    26812640 * @interface_method_impl{HDACODEC,pfnCbMixerSetVolume}
    2682  *
    2683  * Sets the volume of a specified mixer control.
    2684  *
    2685  * @return  IPRT status code.
    2686  * @param   pThis               HDA State.
    2687  * @param   enmMixerCtl         Mixer control to set volume for.
    2688  * @param   pVol                Pointer to volume data to set.
    2689  *
    2690  * @remarks Can be called as a callback by the HDA codec.
    2691  */
    2692 static DECLCALLBACK(int) hdaR3MixerSetVolume(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)
    2693 {
    2694     int rc;
    2695 
    2696     PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThis, enmMixerCtl);
     2641 */
     2642static DECLCALLBACK(int) hdaR3MixerSetVolume(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)
     2643{
     2644    PHDASTATER3   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     2645    int           rc;
     2646
     2647    PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
    26972648    if (   pSink
    26982649        && pSink->pMixSink)
     
    27172668static DECLCALLBACK(void) hdaR3Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    27182669{
    2719     PHDASTATE       pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    2720     PHDASTREAM      pStream = (PHDASTREAM)pvUser;
    2721     TMTIMERHANDLE   hTimer  = pStream->hTimer;
     2670    PHDASTATE       pThis         = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     2671    PHDASTATER3     pThisCC       = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     2672    uintptr_t       idxStream     = (uintptr_t)pvUser;
     2673    AssertReturnVoid(idxStream < RT_ELEMENTS(pThis->aStreams));
     2674    PHDASTREAM      pStreamShared = &pThis->aStreams[idxStream];
     2675    PHDASTREAMR3    pStreamR3     = &pThisCC->aStreams[idxStream];
     2676    TMTIMERHANDLE   hTimer        = pStreamShared->hTimer;
    27222677    RT_NOREF(pTimer);
    27232678
    2724     AssertPtr(pStream);
    27252679    Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect));
    27262680    Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
    27272681
    2728     hdaR3StreamUpdate(pDevIns, pStream, true /* fInTimer */);
     2682    hdaR3StreamUpdate(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, true /* fInTimer */);
    27292683
    27302684    /* Flag indicating whether to kick the timer again for a new data processing round. */
    27312685    bool fSinkActive = false;
    2732     if (pStream->pMixSink)
    2733         fSinkActive = AudioMixerSinkIsActive(pStream->pMixSink->pMixSink);
     2686    if (pStreamR3->pMixSink)
     2687        fSinkActive = AudioMixerSinkIsActive(pStreamR3->pMixSink->pMixSink);
    27342688
    27352689    if (fSinkActive)
    27362690    {
    27372691        uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, hTimer); /* (For virtual sync this remains the same for the whole callout IIRC) */
    2738         const bool fTimerScheduled = hdaR3StreamTransferIsScheduled(pStream, tsNow);
     2692        const bool fTimerScheduled = hdaR3StreamTransferIsScheduled(pStreamShared, tsNow);
    27392693        Log3Func(("fSinksActive=%RTbool, fTimerScheduled=%RTbool\n", fSinkActive, fTimerScheduled));
    27402694        if (!fTimerScheduled)
    2741             hdaR3TimerSet(pDevIns, pStream, tsNow + PDMDevHlpTimerGetFreq(pDevIns, hTimer) / pThis->uTimerHz,
     2695            hdaR3TimerSet(pDevIns, pStreamShared, tsNow + PDMDevHlpTimerGetFreq(pDevIns, hTimer) / pThis->uTimerHz,
    27422696                          true /*fForce*/, tsNow /*fixed*/ );
    27432697    }
     
    28822836 * Soft reset of the device triggered via GCTL.
    28832837 *
    2884  * @param   pThis   HDA state.
    2885  *
    2886  */
    2887 static void hdaR3GCTLReset(PHDASTATE pThis)
     2838 * @param   pDevIns             The device instance.
     2839 * @param   pThis               The shared HDA device state.
     2840 * @param   pThisCC             The ring-3 HDA device state.
     2841 */
     2842static void hdaR3GCTLReset(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
    28882843{
    28892844    LogFlowFuncEnter();
    28902845
    2891     pThis->cStreamsActive = 0;
     2846    pThisCC->cStreamsActive = 0;
    28922847
    28932848    HDA_REG(pThis, GCAP)     = HDA_MAKE_GCAP(HDA_MAX_SDO, HDA_MAX_SDI, 0, 0, 1); /* see 6.2.1 */
     
    29082863     * Stop any audio currently playing and/or recording.
    29092864     */
    2910     pThis->SinkFront.pStream = NULL;
    2911     if (pThis->SinkFront.pMixSink)
    2912         AudioMixerSinkReset(pThis->SinkFront.pMixSink);
     2865    pThisCC->SinkFront.pStreamShared = NULL;
     2866    pThisCC->SinkFront.pStreamR3     = NULL;
     2867    if (pThisCC->SinkFront.pMixSink)
     2868        AudioMixerSinkReset(pThisCC->SinkFront.pMixSink);
    29132869# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2914     pThis->SinkMicIn.pStream = NULL;
    2915     if (pThis->SinkMicIn.pMixSink)
    2916         AudioMixerSinkReset(pThis->SinkMicIn.pMixSink);
     2870    pThisCC->SinkMicIn.pStreamShared = NULL;
     2871    pThisCC->SinkMicIn.pStreamR3     = NULL;
     2872    if (pThisCC->SinkMicIn.pMixSink)
     2873        AudioMixerSinkReset(pThisCC->SinkMicIn.pMixSink);
    29172874# endif
    2918     pThis->SinkLineIn.pStream = NULL;
    2919     if (pThis->SinkLineIn.pMixSink)
    2920         AudioMixerSinkReset(pThis->SinkLineIn.pMixSink);
     2875    pThisCC->SinkLineIn.pStreamShared = NULL;
     2876    pThisCC->SinkLineIn.pStreamR3     = NULL;
     2877    if (pThisCC->SinkLineIn.pMixSink)
     2878        AudioMixerSinkReset(pThisCC->SinkLineIn.pMixSink);
    29212879# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2922     pThis->SinkCenterLFE = NULL;
    2923     if (pThis->SinkCenterLFE.pMixSink)
    2924         AudioMixerSinkReset(pThis->SinkCenterLFE.pMixSink);
    2925     pThis->SinkRear.pStream = NULL;
    2926     if (pThis->SinkRear.pMixSink)
    2927         AudioMixerSinkReset(pThis->SinkRear.pMixSink);
     2880    pThisCC->SinkCenterLFE = NULL;
     2881    if (pThisCC->SinkCenterLFE.pMixSink)
     2882        AudioMixerSinkReset(pThisCC->SinkCenterLFE.pMixSink);
     2883    pThisCC->SinkRear.pStreamShared = NULL;
     2884    pThisCC->SinkRear.pStreamR3     = NULL;
     2885    if (pThisCC->SinkRear.pMixSink)
     2886        AudioMixerSinkReset(pThisCC->SinkRear.pMixSink);
    29282887# endif
    29292888
     
    29312890     * Reset the codec.
    29322891     */
    2933     if (   pThis->pCodec
    2934         && pThis->pCodec->pfnReset)
    2935     {
    2936         pThis->pCodec->pfnReset(pThis->pCodec);
     2892    if (   pThisCC->pCodec
     2893        && pThisCC->pCodec->pfnReset)
     2894    {
     2895        pThisCC->pCodec->pfnReset(pThisCC->pCodec);
    29372896    }
    29382897
     
    29442903     * These stream numbers can be changed by the guest dynamically lateron.
    29452904     */
     2905    ASMCompilerBarrier(); /* paranoia */
    29462906# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2947     hdaR3MixerControl(pThis, PDMAUDIOMIXERCTL_MIC_IN    , 1 /* SD0 */, 0 /* Channel */);
     2907    hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_MIC_IN    , 1 /* SD0 */, 0 /* Channel */);
    29482908# endif
    2949     hdaR3MixerControl(pThis, PDMAUDIOMIXERCTL_LINE_IN   , 1 /* SD0 */, 0 /* Channel */);
    2950 
    2951     hdaR3MixerControl(pThis, PDMAUDIOMIXERCTL_FRONT     , 5 /* SD4 */, 0 /* Channel */);
     2909    hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_LINE_IN   , 1 /* SD0 */, 0 /* Channel */);
     2910
     2911    hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_FRONT     , 5 /* SD4 */, 0 /* Channel */);
    29522912# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2953     hdaR3MixerControl(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
    2954     hdaR3MixerControl(pThis, PDMAUDIOMIXERCTL_REAR      , 5 /* SD4 */, 0 /* Channel */);
     2913    hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
     2914    hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_REAR      , 5 /* SD4 */, 0 /* Channel */);
    29552915# endif
     2916    ASMCompilerBarrier(); /* paranoia */
    29562917
    29572918    /* Reset CORB. */
    29582919    pThis->cbCorbBuf = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE;
    2959     RT_BZERO(pThis->pu32CorbBuf, pThis->cbCorbBuf);
     2920    RT_ZERO(pThis->au32CorbBuf);
    29602921
    29612922    /* Reset RIRB. */
    29622923    pThis->cbRirbBuf = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE;
    2963     RT_BZERO(pThis->pu64RirbBuf, pThis->cbRirbBuf);
     2924    RT_ZERO(pThis->au64RirbBuf);
    29642925
    29652926    /* Clear our internal response interrupt counter. */
    29662927    pThis->u16RespIntCnt = 0;
    29672928
    2968     for (uint8_t uSD = 0; uSD < HDA_MAX_STREAMS; ++uSD)
    2969     {
    2970         int rc2 = hdaR3StreamEnable(&pThis->aStreams[uSD], false /* fEnable */);
     2929    for (size_t idxStream = 0; idxStream < RT_ELEMENTS(pThis->aStreams); idxStream++)
     2930    {
     2931        int rc2 = hdaR3StreamEnable(&pThis->aStreams[idxStream], &pThisCC->aStreams[idxStream], false /* fEnable */);
    29712932        if (RT_SUCCESS(rc2))
    29722933        {
    29732934            /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
    2974             HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
    2975             hdaR3StreamReset(pThis, &pThis->aStreams[uSD], uSD);
     2935            HDA_STREAM_REG(pThis, CTL, idxStream) &= ~HDA_SDCTL_RUN;
     2936            hdaR3StreamReset(pThis, pThisCC, &pThis->aStreams[idxStream], &pThisCC->aStreams[idxStream], (uint8_t)idxStream);
    29762937        }
    29772938    }
    29782939
    29792940    /* Clear stream tags <-> objects mapping table. */
    2980     RT_ZERO(pThis->aTags);
     2941    RT_ZERO(pThisCC->aTags);
    29812942
    29822943    /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
     
    34263387
    34273388
    3428 static int hdaR3SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStream)
     3389static int hdaR3SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3)
    34293390{
    34303391    PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
     
    34333394# endif
    34343395
    3435     Log2Func(("[SD%RU8]\n", pStream->u8SD));
     3396    Log2Func(("[SD%RU8]\n", pStreamShared->u8SD));
    34363397
    34373398    /* Save stream ID. */
    3438     int rc = pHlp->pfnSSMPutU8(pSSM, pStream->u8SD);
     3399    Assert(pStreamShared->u8SD < HDA_MAX_STREAMS);
     3400    int rc = pHlp->pfnSSMPutU8(pSSM, pStreamShared->u8SD);
    34393401    AssertRCReturn(rc, rc);
    3440     Assert(pStream->u8SD < HDA_MAX_STREAMS);
    3441 
    3442     rc = pHlp->pfnSSMPutStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
     3402
     3403    rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State, sizeof(pStreamShared->State),
     3404                                0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
    34433405    AssertRCReturn(rc, rc);
    34443406
    3445     rc = pHlp->pfnSSMPutStructEx(pSSM, &pStream->State.BDLE.Desc, sizeof(HDABDLEDESC), 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
     3407    rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(pStreamShared->State.BDLE.Desc),
     3408                                 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
    34463409    AssertRCReturn(rc, rc);
    34473410
    3448     rc = pHlp->pfnSSMPutStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE), 0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
     3411    rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(pStreamShared->State.BDLE.State),
     3412                                 0 /*fFlags*/,  g_aSSMBDLEStateFields7, NULL);
    34493413    AssertRCReturn(rc, rc);
    34503414
    3451     rc = pHlp->pfnSSMPutStructEx(pSSM, &pStream->State.Period, sizeof(HDASTREAMPERIOD), 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
     3415    rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.Period, sizeof(pStreamShared->State.Period),
     3416                                 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
    34523417    AssertRCReturn(rc, rc);
    34533418
     
    34553420    uint32_t cbCircBufUsed = 0;
    34563421
    3457     if (pStream->State.pCircBuf)
    3458     {
    3459         cbCircBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf);
    3460         cbCircBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
     3422    if (pStreamR3->State.pCircBuf)
     3423    {
     3424        cbCircBufSize = (uint32_t)RTCircBufSize(pStreamR3->State.pCircBuf);
     3425        cbCircBufUsed = (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf);
    34613426    }
    34623427
     
    34763441         * So get the current read offset and serialize the buffer data manually based on that.
    34773442         */
    3478         size_t const offBuf = RTCircBufOffsetRead(pStream->State.pCircBuf);
     3443        size_t const offBuf = RTCircBufOffsetRead(pStreamR3->State.pCircBuf);
    34793444        void  *pvBuf;
    34803445        size_t cbBuf;
    3481         RTCircBufAcquireReadBlock(pStream->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
     3446        RTCircBufAcquireReadBlock(pStreamR3->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
    34823447        Assert(cbBuf);
    34833448        if (cbBuf)
     
    34913456            }
    34923457        }
    3493         RTCircBufReleaseReadBlock(pStream->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
    3494     }
    3495 
    3496     Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
    3497               pStream->u8SD,
    3498               HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), HDA_STREAM_REG(pThis, CBL, pStream->u8SD), HDA_STREAM_REG(pThis, LVI, pStream->u8SD)));
     3458        RTCircBufReleaseReadBlock(pStreamR3->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
     3459    }
     3460
     3461    Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n", pStreamR3->u8SD, HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD),
     3462              HDA_STREAM_REG(pThis, CBL, pStreamShared->u8SD), HDA_STREAM_REG(pThis, LVI, pStreamShared->u8SD)));
    34993463
    35003464#ifdef LOG_ENABLED
    3501     hdaR3BDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
     3465    hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
    35023466#endif
    35033467
     
    35103474static DECLCALLBACK(int) hdaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    35113475{
    3512     PHDASTATE     pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    3513     PCPDMDEVHLPR3 pHlp  = pDevIns->pHlpR3;
     3476    PHDASTATE     pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     3477    PHDASTATER3   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     3478    PCPDMDEVHLPR3 pHlp    = pDevIns->pHlpR3;
    35143479
    35153480    /* Save Codec nodes states. */
    3516     hdaCodecSaveState(pDevIns, pThis->pCodec, pSSM);
     3481    hdaCodecSaveState(pDevIns, pThisCC->pCodec, pSSM);
    35173482
    35183483    /* Save MMIO registers. */
     
    35303495    for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
    35313496    {
    3532         int rc = hdaR3SaveStream(pDevIns, pSSM, &pThis->aStreams[i]);
     3497        int rc = hdaR3SaveStream(pDevIns, pSSM, &pThis->aStreams[i], &pThisCC->aStreams[i]);
    35333498        AssertRCReturn(rc, rc);
    35343499    }
     
    35413506 *
    35423507 * @param   pDevIns             The device instance.
    3543  * @param   pThis               Pointer to HDA state.
    3544  */
    3545 static int hdaR3LoadExecPost(PPDMDEVINS pDevIns, PHDASTATE pThis)
    3546 {
    3547     int rc = VINF_SUCCESS;
     3508 * @param   pThis               Pointer to the shared HDA state.
     3509 * @param   pThisCC             Pointer to the ring-3 HDA state.
     3510 */
     3511static int hdaR3LoadExecPost(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
     3512{
     3513    int rc = VINF_SUCCESS; /** @todo r=bird: Really, what's the point of this? */
    35483514
    35493515    /*
    35503516     * Enable all previously active streams.
    35513517     */
    3552     for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
    3553     {
    3554         PHDASTREAM pStream = hdaGetStreamFromSD(pThis, i);
    3555         if (pStream)
    3556         {
     3518    for (size_t i = 0; i < HDA_MAX_STREAMS; i++)
     3519    {
     3520        PHDASTREAM pStreamShared = &pThis->aStreams[i];
     3521
     3522        bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
     3523        if (fActive)
     3524        {
     3525            PHDASTREAMR3 pStreamR3 = &pThisCC->aStreams[i];
     3526
    35573527            int rc2;
    3558 
    3559             bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
    3560             if (fActive)
    3561             {
    35623528#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    3563                 /* Make sure to also create the async I/O thread before actually enabling the stream. */
    3564                 rc2 = hdaR3StreamAsyncIOCreate(pStream);
    3565                 AssertRC(rc2);
    3566 
    3567                 /* ... and enabling it. */
    3568                 hdaR3StreamAsyncIOEnable(pStream, true /* fEnable */);
     3529            /* Make sure to also create the async I/O thread before actually enabling the stream. */
     3530            rc2 = hdaR3StreamAsyncIOCreate(pStreamR3);
     3531            AssertRC(rc2);
     3532
     3533            /* ... and enabling it. */
     3534            hdaR3StreamAsyncIOEnable(pStreamR3, true /* fEnable */);
    35693535#endif
    3570                 /* Resume the stream's period. */
    3571                 hdaR3StreamPeriodResume(&pStream->State.Period);
    3572 
    3573                 /* (Re-)enable the stream. */
    3574                 rc2 = hdaR3StreamEnable(pStream, true /* fEnable */);
    3575                 AssertRC(rc2);
    3576 
    3577                 /* Add the stream to the device setup. */
    3578                 rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
    3579                 AssertRC(rc2);
     3536            /* Resume the stream's period. */
     3537            hdaR3StreamPeriodResume(&pStreamShared->State.Period);
     3538
     3539            /* (Re-)enable the stream. */
     3540            rc2 = hdaR3StreamEnable(pStreamShared, pStreamR3, true /* fEnable */);
     3541            AssertRC(rc2);
     3542
     3543            /* Add the stream to the device setup. */
     3544            rc2 = hdaR3AddStream(pThisCC, &pStreamShared->State.Cfg);
     3545            AssertRC(rc2);
    35803546
    35813547#ifdef HDA_USE_DMA_ACCESS_HANDLER
    3582                 /* (Re-)install the DMA handler. */
    3583                 hdaR3StreamRegisterDMAHandlers(pThis, pStream);
     3548            /* (Re-)install the DMA handler. */
     3549            hdaR3StreamRegisterDMAHandlers(pThis, pStreamShared);
    35843550#endif
    3585                 if (hdaR3StreamTransferIsScheduled(pStream, PDMDevHlpTimerGet(pDevIns, pStream->hTimer)))
    3586                     hdaR3TimerSet(pDevIns, pStream, hdaR3StreamTransferGetNext(pStream), true /*fForce*/, 0 /*tsNow*/);
    3587 
    3588                 /* Also keep track of the currently active streams. */
    3589                 pThis->cStreamsActive++;
    3590             }
     3551            if (hdaR3StreamTransferIsScheduled(pStreamShared, PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer)))
     3552                hdaR3TimerSet(pDevIns, pStreamShared, hdaR3StreamTransferGetNext(pStreamShared), true /*fForce*/, 0 /*tsNow*/);
     3553
     3554            /* Also keep track of the currently active streams. */
     3555            pThisCC->cStreamsActive++;
    35913556        }
    35923557    }
     
    36013566 *
    36023567 * @param   pDevIns     The device instance.
    3603  * @param   pThis       Pointer to HDA state.
     3568 * @param   pThis       Pointer to the shared HDA state.
     3569 * @param   pThisCC     Pointer to the ring-3 HDA state.
    36043570 * @param   pSSM        Pointer to SSM handle.
    36053571 * @param   uVersion    Saved state version to load.
    36063572 */
    3607 static int hdaR3LoadExecLegacy(PPDMDEVINS pDevIns, PHDASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion)
     3573static int hdaR3LoadExecLegacy(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PSSMHANDLE pSSM, uint32_t uVersion)
    36083574{
    36093575    PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
     
    36943660
    36953661            /* Output */
    3696             PHDASTREAM pStream = &pThis->aStreams[4];
    3697             rc = hdaR3StreamInit(pDevIns, pStream, 4 /* Stream descriptor, hardcoded */);
     3662            PHDASTREAM pStreamShared = &pThis->aStreams[4];
     3663            rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[4], 4 /* Stream descriptor, hardcoded */);
    36983664            AssertRCReturn(rc, rc);
    3699             rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE, sizeof(pStream->State.BDLE),
     3665            rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
    37003666                                         0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
    37013667            AssertRCReturn(rc, rc);
    3702             pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
     3668            pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
    37033669
    37043670            /* Microphone-In */
    3705             pStream = &pThis->aStreams[2];
    3706             rc = hdaR3StreamInit(pDevIns, pStream, 2 /* Stream descriptor, hardcoded */);
     3671            pStreamShared = &pThis->aStreams[2];
     3672            rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[2], 2 /* Stream descriptor, hardcoded */);
    37073673            AssertRCReturn(rc, rc);
    3708             rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE, sizeof(pStream->State.BDLE),
     3674            rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
    37093675                                         0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
    37103676            AssertRCReturn(rc, rc);
    3711             pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
     3677            pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
    37123678
    37133679            /* Line-In */
    3714             pStream = &pThis->aStreams[0];
    3715             rc = hdaR3StreamInit(pDevIns, pStream, 0 /* Stream descriptor, hardcoded */);
     3680            pStreamShared = &pThis->aStreams[0];
     3681            rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[0], 0 /* Stream descriptor, hardcoded */);
    37163682            AssertRCReturn(rc, rc);
    3717             rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE, sizeof(pStream->State.BDLE),
     3683            rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
    37183684                                         0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
    37193685            AssertRCReturn(rc, rc);
    3720             pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
     3686            pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
    37213687            break;
    37223688        }
     
    37433709                AssertRCReturn(rc, rc);
    37443710
    3745                 HDASTREAM  StreamDummy;
    3746                 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, idStream);
    3747                 if (!pStream)
    3748                 {
    3749                     pStream = &StreamDummy;
    3750                     LogRel2(("HDA: Warning: Stream ID=%RU32 not supported, skipping loading it ...\n", idStream));
    3751                 }
    3752 
    3753                 rc = hdaR3StreamInit(pDevIns, pStream, idStream);
     3711                HDASTREAM    StreamDummyShared;
     3712                HDASTREAMR3  StreamDummyR3;
     3713                PHDASTREAM   pStreamShared = idStream < RT_ELEMENTS(pThis->aStreams) ? &pThis->aStreams[idStream] : &StreamDummyShared;
     3714                PHDASTREAMR3 pStreamR3     = idStream < RT_ELEMENTS(pThisCC->aStreams) ? &pThisCC->aStreams[idStream] : &StreamDummyR3;
     3715                AssertLogRelMsgStmt(idStream < RT_ELEMENTS(pThisCC->aStreams),
     3716                                    ("HDA stream ID=%RU8 not supported, skipping loadingit ...\n", idStream),
     3717                                    RT_ZERO(StreamDummyShared); RT_ZERO(StreamDummyR3));
     3718
     3719                rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, idStream);
    37543720                if (RT_FAILURE(rc))
    37553721                {
    3756                     LogRel(("HDA: Stream #%RU32: Initialization of stream %RU8 failed, rc=%Rrc\n", i, idStream, rc));
     3722                    LogRel(("HDA: Stream #%RU32: Setting up of stream %RU8 failed, rc=%Rrc\n", i, idStream, rc));
    37573723                    break;
    37583724                }
     
    37793745                    rc = pHlp->pfnSSMGetStructEx(pSSM, &Tmp, sizeof(Tmp), 0 /* fFlags */, g_aV5State1Fields, NULL);
    37803746                    AssertRCReturn(rc, rc);
    3781                     pStream->State.uCurBDLE = Tmp.uCurBDLE;
     3747                    pStreamShared->State.uCurBDLE = Tmp.uCurBDLE;
    37823748
    37833749                    for (uint16_t a = 0; a < Tmp.cBLDEs; a++)
     
    37923758                        rc = pHlp->pfnSSMGetStructEx(pSSM, &Tmp, sizeof(Tmp), 0 /* fFlags */, g_aV5State2Fields, NULL);
    37933759                        AssertRCReturn(rc, rc);
    3794                         if (Tmp.u32BDLEIndex == pStream->State.uCurBDLE)
     3760                        if (Tmp.u32BDLEIndex == pStreamShared->State.uCurBDLE)
    37953761                        {
    3796                             pStream->State.BDLE.State.cbBelowFIFOW = Tmp.cbBelowFIFOW;
    3797                             pStream->State.BDLE.State.u32BufOff    = Tmp.u32BufOff;
     3762                            pStreamShared->State.BDLE.State.cbBelowFIFOW = Tmp.cbBelowFIFOW;
     3763                            pStreamShared->State.BDLE.State.u32BufOff    = Tmp.u32BufOff;
    37983764                        }
    37993765                    }
     
    38013767                else
    38023768                {
    3803                     rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE),
     3769                    rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State, sizeof(HDASTREAMSTATE),
    38043770                                                 0 /* fFlags */, g_aSSMStreamStateFields6, NULL);
    38053771                    AssertRCReturn(rc, rc);
    38063772
    3807                     rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE.Desc, sizeof(pStream->State.BDLE.Desc),
     3773                    rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(pStreamShared->State.BDLE.Desc),
    38083774                                                 0 /* fFlags */, g_aSSMBDLEDescFields6, pDevIns);
    38093775                    AssertRCReturn(rc, rc);
    38103776
    3811                     rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE),
     3777                    rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(HDABDLESTATE),
    38123778                                                 0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
    38133779                    AssertRCReturn(rc, rc);
     
    38163782                              HDA_STREAM_REG(pThis, CBL, idStream), HDA_STREAM_REG(pThis, LVI, idStream)));
    38173783#ifdef LOG_ENABLED
    3818                     hdaR3BDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
     3784                    hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
    38193785#endif
    38203786                }
     
    38333799static DECLCALLBACK(int) hdaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    38343800{
    3835     PHDASTATE     pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    3836     PCPDMDEVHLPR3 pHlp  = pDevIns->pHlpR3;
     3801    PHDASTATE     pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     3802    PHDASTATER3   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     3803    PCPDMDEVHLPR3 pHlp    = pDevIns->pHlpR3;
    38373804
    38383805    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
     
    38433810     * Load Codec nodes states.
    38443811     */
    3845     int rc = hdaCodecLoadState(pDevIns, pThis->pCodec, pSSM, uVersion);
     3812    int rc = hdaCodecLoadState(pDevIns, pThisCC->pCodec, pSSM, uVersion);
    38463813    if (RT_FAILURE(rc))
    38473814    {
     
    38523819    if (uVersion <= HDA_SAVED_STATE_VERSION_6) /* Handle older saved states? */
    38533820    {
    3854         rc = hdaR3LoadExecLegacy(pDevIns, pThis, pSSM, uVersion);
     3821        rc = hdaR3LoadExecLegacy(pDevIns, pThis, pThisCC, pSSM, uVersion);
    38553822        if (RT_SUCCESS(rc))
    3856             rc = hdaR3LoadExecPost(pDevIns, pThis);
     3823            rc = hdaR3LoadExecPost(pDevIns, pThis, pThisCC);
    38573824        return rc;
    38583825    }
     
    39183885        AssertRCReturn(rc, rc);
    39193886
    3920         PHDASTREAM pStream = hdaGetStreamFromSD(pThis, idStream);
    3921         HDASTREAM  StreamDummy;
    3922 
    3923         if (!pStream)
    3924         {
    3925             RT_ZERO(StreamDummy);
    3926             pStream = &StreamDummy;
    3927             LogRel2(("HDA: Warning: Loading of stream #%RU8 not supported, skipping to load ...\n", idStream));
    3928         }
    3929 
    3930         rc = hdaR3StreamInit(pDevIns, pStream, idStream);
     3887        HDASTREAM    StreamDummyShared;
     3888        HDASTREAMR3  StreamDummyR3;
     3889        PHDASTREAM   pStreamShared = idStream < RT_ELEMENTS(pThis->aStreams) ? &pThis->aStreams[idStream] : &StreamDummyShared;
     3890        PHDASTREAMR3 pStreamR3     = idStream < RT_ELEMENTS(pThisCC->aStreams) ? &pThisCC->aStreams[idStream] : &StreamDummyR3;
     3891        AssertLogRelMsgStmt(idStream < RT_ELEMENTS(pThisCC->aStreams),
     3892                            ("HDA stream ID=%RU8 not supported, skipping loadingit ...\n", idStream),
     3893                            RT_ZERO(StreamDummyShared); RT_ZERO(StreamDummyR3));
     3894
     3895        rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, idStream);
    39313896        if (RT_FAILURE(rc))
    39323897        {
    3933             LogRel(("HDA: Stream #%RU8: Loading initialization failed, rc=%Rrc\n", idStream, rc));
     3898            LogRel(("HDA: Stream #%RU8: Setting up failed, rc=%Rrc\n", idStream, rc));
    39343899            /* Continue. */
    39353900        }
    39363901
    3937         rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE),
     3902        rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State, sizeof(HDASTREAMSTATE),
    39383903                                     0 /* fFlags */, g_aSSMStreamStateFields7, NULL);
    39393904        AssertRCReturn(rc, rc);
     
    39423907         * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
    39433908         */
    3944         rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE.Desc, sizeof(HDABDLEDESC),
     3909        rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(HDABDLEDESC),
    39453910                                     0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
    39463911        AssertRCReturn(rc, rc);
    39473912
    3948         rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE),
     3913        rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(HDABDLESTATE),
    39493914                                     0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
    39503915        AssertRCReturn(rc, rc);
    39513916
    3952         Log2Func(("[SD%RU8] %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));
     3917        Log2Func(("[SD%RU8] %R[bdle]\n", pStreamShared->u8SD, &pStreamShared->State.BDLE));
    39533918
    39543919        /*
    39553920         * Load period state.
    39563921         */
    3957         hdaR3StreamPeriodInit(&pStream->State.Period, pStream->u8SD, pStream->u16LVI, pStream->u32CBL, &pStream->State.Cfg);
    3958 
    3959         rc = pHlp->pfnSSMGetStructEx(pSSM, &pStream->State.Period, sizeof(HDASTREAMPERIOD),
     3922        hdaR3StreamPeriodInit(&pStreamShared->State.Period, pStreamShared->u8SD, pStreamShared->u16LVI,
     3923                              pStreamShared->u32CBL, &pStreamShared->State.Cfg);
     3924
     3925        rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.Period, sizeof(pStreamShared->State.Period),
    39603926                                     0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
    39613927        AssertRCReturn(rc, rc);
     
    39833949
    39843950            /* Do we need to cre-create the circular buffer do fit the data size? */
    3985             if (   pStream->State.pCircBuf
    3986                 && cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
     3951            if (   pStreamR3->State.pCircBuf
     3952                && cbCircBufSize != (uint32_t)RTCircBufSize(pStreamR3->State.pCircBuf))
    39873953            {
    3988                 RTCircBufDestroy(pStream->State.pCircBuf);
    3989                 pStream->State.pCircBuf = NULL;
     3954                RTCircBufDestroy(pStreamR3->State.pCircBuf);
     3955                pStreamR3->State.pCircBuf = NULL;
    39903956            }
    39913957
    3992             rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
     3958            rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBufSize);
    39933959            AssertRCReturn(rc, rc);
    39943960
     
    39973963                void  *pvBuf;
    39983964                size_t cbBuf;
    3999                 RTCircBufAcquireWriteBlock(pStream->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
     3965                RTCircBufAcquireWriteBlock(pStreamR3->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
    40003966
    40013967                AssertLogRelMsgReturn(cbBuf == cbCircBufUsed, ("cbBuf=%zu cbCircBufUsed=%zu\n", cbBuf, cbCircBufUsed),
     
    40043970                AssertRCReturn(rc, rc);
    40053971
    4006                 RTCircBufReleaseWriteBlock(pStream->State.pCircBuf, cbBuf);
     3972                RTCircBufReleaseWriteBlock(pStreamR3->State.pCircBuf, cbBuf);
    40073973
    40083974                Assert(cbBuf == cbCircBufUsed);
     
    40133979                  HDA_STREAM_REG(pThis, CBL, idStream), HDA_STREAM_REG(pThis, LVI, idStream)));
    40143980#ifdef LOG_ENABLED
    4015         hdaR3BDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
     3981        hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
    40163982#endif
    40173983        /** @todo (Re-)initialize active periods? */
     
    40193985    } /* for cStreams */
    40203986
    4021     rc = hdaR3LoadExecPost(pDevIns, pThis);
     3987    rc = hdaR3LoadExecPost(pDevIns, pThis, pThisCC);
    40223988    AssertRC(rc);
    40233989
     
    41704136}
    41714137
    4172 static void hdaR3DbgPrintBDLE(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
     4138static void hdaR3DbgPrintBDLE(PPDMDEVINS pDevIns, PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
    41734139{
    41744140    Assert(   pThis
     
    41974163    {
    41984164        HDABDLEDESC bd;
    4199         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
     4165        PDMDevHlpPhysRead(pDevIns, u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
    42004166
    42014167        pHlp->pfnPrintf(pHlp, "\t\t%s #%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
     
    42204186    {
    42214187        uint32_t uDMACnt;
    4222         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
     4188        PDMDevHlpPhysRead(pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
    42234189                          &uDMACnt, sizeof(uDMACnt));
    42244190
     
    42564222    int         iHdaStreamdex = hdaR3DbgLookupStrmIdx(pThis, pszArgs);
    42574223    if (iHdaStreamdex != -1)
    4258         hdaR3DbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
     4224        hdaR3DbgPrintBDLE(pDevIns, pThis, pHlp, iHdaStreamdex);
    42594225    else
    42604226        for (iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
    4261             hdaR3DbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
     4227            hdaR3DbgPrintBDLE(pDevIns, pThis, pHlp, iHdaStreamdex);
    42624228}
    42634229
     
    42674233static DECLCALLBACK(void) hdaR3DbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    42684234{
    4269     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    4270 
    4271     if (pThis->pCodec->pfnDbgListNodes)
    4272         pThis->pCodec->pfnDbgListNodes(pThis->pCodec, pHlp, pszArgs);
     4235    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     4236
     4237    if (pThisCC->pCodec->pfnDbgListNodes)
     4238        pThisCC->pCodec->pfnDbgListNodes(pThisCC->pCodec, pHlp, pszArgs);
    42734239    else
    42744240        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
     
    42804246static DECLCALLBACK(void) hdaR3DbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    42814247{
    4282     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    4283 
    4284     if (pThis->pCodec->pfnDbgSelector)
    4285         pThis->pCodec->pfnDbgSelector(pThis->pCodec, pHlp, pszArgs);
     4248    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     4249
     4250    if (pThisCC->pCodec->pfnDbgSelector)
     4251        pThisCC->pCodec->pfnDbgSelector(pThisCC->pCodec, pHlp, pszArgs);
    42864252    else
    42874253        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
     
    42934259static DECLCALLBACK(void) hdaR3DbgInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    42944260{
    4295     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
    4296 
    4297     if (pThis->pMixer)
    4298         AudioMixerDebug(pThis->pMixer, pHlp, pszArgs);
     4261    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
     4262
     4263    if (pThisCC->pMixer)
     4264        AudioMixerDebug(pThisCC->pMixer, pHlp, pszArgs);
    42994265    else
    43004266        pHlp->pfnPrintf(pHlp, "Mixer not available\n");
     
    43114277static DECLCALLBACK(void *) hdaR3QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
    43124278{
    4313     PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
    4314     Assert(&pThis->IBase == pInterface);
    4315 
    4316     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
     4279    PHDASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, HDASTATER3, IBase);
     4280
     4281    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
    43174282    return NULL;
    43184283}
     
    43314296 *
    43324297 * @returns VBox status code.
    4333  * @param   pThis       HDA state.
     4298 * @param   pDevIns     The device instance.
     4299 * @param   pThis       The shared HDA device state.
     4300 * @param   pThisR3     The ring-3 HDA device state.
    43344301 * @param   uLUN        The logical unit which is being detached.
    43354302 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    43364303 * @param   ppDrv       Attached driver instance on success. Optional.
    43374304 */
    4338 static int hdaR3AttachInternal(PHDASTATE pThis, unsigned uLUN, uint32_t fFlags, PHDADRIVER *ppDrv)
     4305static int hdaR3AttachInternal(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, unsigned uLUN, uint32_t fFlags, PHDADRIVER *ppDrv)
    43394306{
    43404307    RT_NOREF(fFlags);
     
    43484315
    43494316    PPDMIBASE pDrvBase;
    4350     int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, uLUN,
    4351                                    &pThis->IBase, &pDrvBase, pszDesc);
     4317    int rc = PDMDevHlpDriverAttach(pDevIns, uLUN, &pThisCC->IBase, &pDrvBase, pszDesc);
    43524318    if (RT_SUCCESS(rc))
    43534319    {
     
    43554321        if (pDrv)
    43564322        {
    4357             pDrv->pDrvBase   = pDrvBase;
    4358             pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
     4323            pDrv->pDrvBase          = pDrvBase;
     4324            pDrv->pHDAStateShared   = pThis;
     4325            pDrv->pHDAStateR3       = pThisCC;
     4326            pDrv->uLUN              = uLUN;
     4327            pDrv->pConnector        = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
    43594328            AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
    4360             pDrv->pHDAState  = pThis;
    4361             pDrv->uLUN       = uLUN;
    43624329
    43634330            /*
     
    43734340            if (!pDrv->fAttached)
    43744341            {
    4375                 RTListAppend(&pThis->lstDrv, &pDrv->Node);
     4342                RTListAppend(&pThisCC->lstDrv, &pDrv->Node);
    43764343                pDrv->fAttached = true;
    43774344            }
     
    44044371 *
    44054372 * @returns VBox status code.
    4406  * @param   pThis       HDA state.
     4373 * @param   pThisR3     The ring-3 HDA device state.
    44074374 * @param   pDrv        Driver to detach from device.
    44084375 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    44094376 */
    4410 static int hdaR3DetachInternal(PHDASTATE pThis, PHDADRIVER pDrv, uint32_t fFlags)
     4377static int hdaR3DetachInternal(PHDASTATER3 pThisCC, PHDADRIVER pDrv, uint32_t fFlags)
    44114378{
    44124379    RT_NOREF(fFlags);
     
    44144381    /* First, remove the driver from our list and destory it's associated streams.
    44154382     * This also will un-set the driver as a recording source (if associated). */
    4416     hdaR3MixerRemoveDrv(pThis, pDrv);
     4383    hdaR3MixerRemoveDrv(pThisCC, pDrv);
    44174384
    44184385    /* Next, search backwards for a capable (attached) driver which now will be the
    44194386     * new recording source. */
    44204387    PHDADRIVER pDrvCur;
    4421     RTListForEachReverse(&pThis->lstDrv, pDrvCur, HDADRIVER, Node)
     4388    RTListForEachReverse(&pThisCC->lstDrv, pDrvCur, HDADRIVER, Node)
    44224389    {
    44234390        if (!pDrvCur->pConnector)
     
    44354402            && pDrvStrm->pMixStrm)
    44364403        {
    4437             rc2 = AudioMixerSinkSetRecordingSource(pThis->SinkMicIn.pMixSink, pDrvStrm->pMixStrm);
     4404            rc2 = AudioMixerSinkSetRecordingSource(pThisCC->SinkMicIn.pMixSink, pDrvStrm->pMixStrm);
    44384405            if (RT_SUCCESS(rc2))
    44394406                LogRel2(("HDA: Set new recording source for 'Mic In' to '%s'\n", Cfg.szName));
     
    44444411            && pDrvStrm->pMixStrm)
    44454412        {
    4446             rc2 = AudioMixerSinkSetRecordingSource(pThis->SinkLineIn.pMixSink, pDrvStrm->pMixStrm);
     4413            rc2 = AudioMixerSinkSetRecordingSource(pThisCC->SinkLineIn.pMixSink, pDrvStrm->pMixStrm);
    44474414            if (RT_SUCCESS(rc2))
    44484415                LogRel2(("HDA: Set new recording source for 'Line In' to '%s'\n", Cfg.szName));
     
    44594426static DECLCALLBACK(int) hdaR3Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
    44604427{
    4461     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4428    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4429    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    44624430
    44634431    DEVHDA_LOCK_RETURN(pDevIns, pThis, VERR_IGNORED);
     
    44664434
    44674435    PHDADRIVER pDrv;
    4468     int rc2 = hdaR3AttachInternal(pThis, uLUN, fFlags, &pDrv);
     4436    int rc2 = hdaR3AttachInternal(pDevIns, pThis, pThisCC, uLUN, fFlags, &pDrv);
    44694437    if (RT_SUCCESS(rc2))
    4470         rc2 = hdaR3MixerAddDrv(pThis, pDrv);
     4438        rc2 = hdaR3MixerAddDrv(pThisCC, pDrv);
    44714439
    44724440    if (RT_FAILURE(rc2))
     
    44834451static DECLCALLBACK(void) hdaR3Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
    44844452{
    4485     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4453    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4454    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    44864455
    44874456    DEVHDA_LOCK(pDevIns, pThis);
     
    44904459
    44914460    PHDADRIVER pDrv, pDrvNext;
    4492     RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, HDADRIVER, Node)
     4461    RTListForEachSafe(&pThisCC->lstDrv, pDrv, pDrvNext, HDADRIVER, Node)
    44934462    {
    44944463        if (pDrv->uLUN == uLUN)
    44954464        {
    4496             int rc2 = hdaR3DetachInternal(pThis, pDrv, fFlags);
     4465            int rc2 = hdaR3DetachInternal(pThisCC, pDrv, fFlags);
    44974466            if (RT_SUCCESS(rc2))
    44984467            {
     
    45154484static DECLCALLBACK(void) hdaR3PowerOff(PPDMDEVINS pDevIns)
    45164485{
    4517     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4486    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4487    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    45184488
    45194489    DEVHDA_LOCK_RETURN_VOID(pDevIns, pThis);
     
    45224492
    45234493    /* Ditto goes for the codec, which in turn uses the mixer. */
    4524     hdaCodecPowerOff(pThis->pCodec);
     4494    hdaCodecPowerOff(pThisCC->pCodec);
    45254495
    45264496    /*
     
    45294499     *       PDM audio streams it maintains.
    45304500     */
    4531     if (pThis->pMixer)
    4532     {
    4533         AudioMixerDestroy(pThis->pMixer);
    4534         pThis->pMixer = NULL;
     4501    if (pThisCC->pMixer)
     4502    {
     4503        AudioMixerDestroy(pThisCC->pMixer);
     4504        pThisCC->pMixer = NULL;
    45354505    }
    45364506
     
    45424512 *
    45434513 * @returns VBox status code.
     4514 * @param   pDevIns     The device instance.
     4515 * @param   pThis       The shared HDA device state.
     4516 * @param   pThisCC     The ring-3 HDA device state.
    45444517 * @param   pThis       Device instance.
    45454518 * @param   iLun        The logical unit which is being replaced.
    45464519 */
    4547 static int hdaR3ReconfigLunWithNullAudio(PHDASTATE pThis, unsigned iLun)
    4548 {
    4549     int rc = PDMDevHlpDriverReconfigure2(pThis->pDevInsR3, iLun, "AUDIO", "NullAudio");
     4520static int hdaR3ReconfigLunWithNullAudio(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, unsigned iLun)
     4521{
     4522    int rc = PDMDevHlpDriverReconfigure2(pDevIns, iLun, "AUDIO", "NullAudio");
    45504523    if (RT_SUCCESS(rc))
    4551         rc = hdaR3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4524        rc = hdaR3AttachInternal(pDevIns, pThis, pThisCC, iLun, 0 /* fFlags */, NULL /* ppDrv */);
    45524525    LogFunc(("pThis=%p, iLun=%u, rc=%Rrc\n", pThis, iLun, rc));
    45534526    return rc;
     
    45604533static DECLCALLBACK(void) hdaR3Reset(PPDMDEVINS pDevIns)
    45614534{
    4562     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4535    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4536    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    45634537
    45644538    LogFlowFuncEnter();
     
    45724546    HDA_REG(pThis, WAKEEN)  = 0x0;
    45734547
    4574     hdaR3GCTLReset(pThis);
     4548    hdaR3GCTLReset(pDevIns, pThis, pThisCC);
    45754549
    45764550    /* Indicate that HDA is not in reset. The firmware is supposed to (un)reset HDA,
     
    45894563{
    45904564    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); /* this shall come first */
    4591     PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4565    PHDASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4566    PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    45924567    DEVHDA_LOCK(pDevIns, pThis); /** @todo r=bird: this will fail on early constructor failure. */
    45934568
    45944569    PHDADRIVER pDrv;
    4595     while (!RTListIsEmpty(&pThis->lstDrv))
    4596     {
    4597         pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node);
     4570    while (!RTListIsEmpty(&pThisCC->lstDrv))
     4571    {
     4572        pDrv = RTListGetFirst(&pThisCC->lstDrv, HDADRIVER, Node);
    45984573
    45994574        RTListNodeRemove(&pDrv->Node);
     
    46014576    }
    46024577
    4603     if (pThis->pCodec)
    4604     {
    4605         hdaCodecDestruct(pThis->pCodec);
    4606 
    4607         RTMemFree(pThis->pCodec);
    4608         pThis->pCodec = NULL;
    4609     }
    4610 
    4611     RTMemFree(pThis->pu32CorbBuf);
    4612     pThis->pu32CorbBuf = NULL;
    4613 
    4614     RTMemFree(pThis->pu64RirbBuf);
    4615     pThis->pu64RirbBuf = NULL;
     4578    if (pThisCC->pCodec)
     4579    {
     4580        hdaCodecDestruct(pThisCC->pCodec);
     4581
     4582        RTMemFree(pThisCC->pCodec);
     4583        pThisCC->pCodec = NULL;
     4584    }
    46164585
    46174586    for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
    4618         hdaR3StreamDestroy(&pThis->aStreams[i]);
     4587        hdaR3StreamDestroy(&pThis->aStreams[i], &pThisCC->aStreams[i]);
    46194588
    46204589    DEVHDA_UNLOCK(pDevIns, pThis);
     
    46304599    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* this shall come first */
    46314600    PHDASTATE       pThis   = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
     4601    PHDASTATER3     pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
    46324602    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    46334603    Assert(iInstance == 0); RT_NOREF(iInstance);
     
    46374607     */
    46384608    pThis->uAlignmentCheckMagic = HDASTATE_ALIGNMENT_CHECK_MAGIC;
    4639     RTListInit(&pThis->lstDrv);
     4609    RTListInit(&pThisCC->lstDrv);
     4610    pThis->cbCorbBuf            = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE;
     4611    pThis->cbRirbBuf            = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE;
     4612
    46404613    /** @todo r=bird: There are probably other things which should be
    46414614     *        initialized here before we start failing. */
     
    46704643        LogRel(("HDA: Using custom position adjustment (%RU16 audio frames)\n", pThis->cPosAdjustFrames));
    46714644
    4672     rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "DebugEnabled", &pThis->Dbg.fEnabled, false);
     4645    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "DebugEnabled", &pThisCC->Dbg.fEnabled, false);
    46734646    if (RT_FAILURE(rc))
    46744647        return PDMDEV_SET_ERROR(pDevIns, rc,
    46754648                                N_("HDA configuration error: failed to read debugging enabled flag as boolean"));
    46764649
    4677     rc = pHlp->pfnCFGMQueryStringDef(pCfg, "DebugPathOut", pThis->Dbg.szOutPath, sizeof(pThis->Dbg.szOutPath),
     4650    rc = pHlp->pfnCFGMQueryStringDef(pCfg, "DebugPathOut", pThisCC->Dbg.szOutPath, sizeof(pThisCC->Dbg.szOutPath),
    46784651                                     VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
    46794652    if (RT_FAILURE(rc))
     
    46814654                                N_("HDA configuration error: failed to read debugging output path flag as string"));
    46824655
    4683     if (pThis->Dbg.fEnabled)
    4684         LogRel2(("HDA: Debug output will be saved to '%s'\n", pThis->Dbg.szOutPath));
     4656    if (pThisCC->Dbg.fEnabled)
     4657        LogRel2(("HDA: Debug output will be saved to '%s'\n", pThisCC->Dbg.szOutPath));
    46854658
    46864659    /*
     
    46984671     * Initialize data (most of it anyway).
    46994672     */
    4700     pThis->pDevInsR3                = pDevIns;
     4673    pThisCC->pDevIns                  = pDevIns;
    47014674    /* IBase */
    4702     pThis->IBase.pfnQueryInterface  = hdaR3QueryInterface;
     4675    pThisCC->IBase.pfnQueryInterface  = hdaR3QueryInterface;
    47034676
    47044677    /* PCI Device */
     
    48274800        AssertBreak(iLun < UINT8_MAX);
    48284801        LogFunc(("Trying to attach driver for LUN#%u ...\n", iLun));
    4829         rc = hdaR3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4802        rc = hdaR3AttachInternal(pDevIns, pThis, pThisCC, iLun, 0 /* fFlags */, NULL /* ppDrv */);
    48304803        if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    48314804        {
     
    48354808        if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
    48364809        {
    4837             hdaR3ReconfigLunWithNullAudio(pThis, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
     4810            hdaR3ReconfigLunWithNullAudio(pDevIns, pThis, pThisCC, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
    48384811            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    48394812                                       N_("Host audio backend initialization has failed. Selecting the NULL audio backend with the consequence that no sound is audible"));
     
    48464819     * Create the mixer.
    48474820     */
    4848     rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer);
     4821    rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThisCC->pMixer);
    48494822    AssertRCReturn(rc, rc);
    48504823
     
    48534826     */
    48544827#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    4855     rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front", AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
     4828    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Front", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
    48564829    AssertRCReturn(rc, rc);
    4857     rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer", AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink);
     4830    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Center / Subwoofer", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkCenterLFE.pMixSink);
    48584831    AssertRCReturn(rc, rc);
    4859     rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear", AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink);
     4832    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Rear", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkRear.pMixSink);
    48604833    AssertRCReturn(rc, rc);
    48614834#else
    4862     rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
     4835    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
    48634836    AssertRCReturn(rc, rc);
    48644837#endif
     
    48674840     * Add mixer input sinks.
    48684841     */
    4869     rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink);
     4842    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkLineIn.pMixSink);
    48704843    AssertRCReturn(rc, rc);
    48714844#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    4872     rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink);
     4845    rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkMicIn.pMixSink);
    48734846    AssertRCReturn(rc, rc);
    48744847#endif
     
    48764849    /* There is no master volume control. Set the master to max. */
    48774850    PDMAUDIOVOLUME vol = { false, 255, 255 };
    4878     rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
     4851    rc = AudioMixerSetMasterVolume(pThisCC->pMixer, &vol);
    48794852    AssertRCReturn(rc, rc);
    48804853
    4881     /* Allocate CORB buffer. */
    4882     pThis->cbCorbBuf   = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE;
    4883     pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
    4884     AssertReturn(pThis->pu32CorbBuf, VERR_NO_MEMORY);
    4885 
    4886     /* Allocate RIRB buffer. */
    4887     pThis->cbRirbBuf   = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE;
    4888     pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
    4889     AssertReturn(pThis->pu64RirbBuf, VERR_NO_MEMORY);
    4890 
    48914854    /* Allocate codec. */
    4892     pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
    4893     AssertReturn(pThis->pCodec, VERR_NO_MEMORY);
     4855    PHDACODEC pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
     4856    pThisCC->pCodec = pCodec;
     4857    AssertReturn(pCodec, VERR_NO_MEMORY);
    48944858
    48954859    /* Set codec callbacks to this controller. */
    4896     pThis->pCodec->pfnCbMixerAddStream    = hdaR3MixerAddStream;
    4897     pThis->pCodec->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream;
    4898     pThis->pCodec->pfnCbMixerControl      = hdaR3MixerControl;
    4899     pThis->pCodec->pfnCbMixerSetVolume    = hdaR3MixerSetVolume;
    4900 
    4901     pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */
     4860    pCodec->pDevIns                = pDevIns;
     4861    pCodec->pfnCbMixerAddStream    = hdaR3MixerAddStream;
     4862    pCodec->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream;
     4863    pCodec->pfnCbMixerControl      = hdaR3MixerControl;
     4864    pCodec->pfnCbMixerSetVolume    = hdaR3MixerSetVolume;
    49024865
    49034866    /* Construct the codec. */
    4904     rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg);
     4867    rc = hdaCodecConstruct(pDevIns, pCodec, 0 /* Codec index */, pCfg);
    49054868    AssertRCReturn(rc, rc);
    49064869
    49074870    /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
    49084871       verb F20 should provide device/codec recognition. */
    4909     Assert(pThis->pCodec->u16VendorId);
    4910     Assert(pThis->pCodec->u16DeviceId);
    4911     PDMPciDevSetSubSystemVendorId(pPciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
    4912     PDMPciDevSetSubSystemId(      pPciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
     4872    Assert(pCodec->u16VendorId);
     4873    Assert(pCodec->u16DeviceId);
     4874    PDMPciDevSetSubSystemVendorId(pPciDev, pCodec->u16VendorId); /* 2c ro - intel.) */
     4875    PDMPciDevSetSubSystemId(      pPciDev, pCodec->u16DeviceId); /* 2e ro. */
    49134876
    49144877    /*
     
    49304893    for (size_t i = 0; i < HDA_MAX_STREAMS; i++)
    49314894    {
    4932         rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaR3Timer, &pThis->aStreams[i],
     4895        rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaR3Timer, (void *)(uintptr_t)i,
    49334896                                  TMTIMER_FLAGS_NO_CRIT_SECT, s_apszNames[i], &pThis->aStreams[i].hTimer);
    49344897        AssertRCReturn(rc, rc);
     
    49434906    for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
    49444907    {
    4945         rc = hdaR3StreamCreate(&pThis->aStreams[i], pThis, i /* u8SD */);
     4908        rc = hdaR3StreamConstruct(&pThis->aStreams[i], &pThisCC->aStreams[i], pThis, pThisCC, i /* u8SD */);
    49464909        AssertRCReturn(rc, rc);
    49474910    }
     
    49524915     */
    49534916    PHDADRIVER pDrv;
    4954     RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     4917    RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
    49554918    {
    49564919        /*
     
    51325095     * Register statistics.
    51335096     */
    5134     PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer,            STAMTYPE_PROFILE, "Timer",             STAMUNIT_TICKS_PER_CALL, "Profiling hdaR3Timer.");
    51355097    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn,               STAMTYPE_PROFILE, "Input",             STAMUNIT_TICKS_PER_CALL, "Profiling input.");
    51365098    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut,              STAMTYPE_PROFILE, "Output",            STAMUNIT_TICKS_PER_CALL, "Profiling output.");
     
    52035165    /* .uSharedVersion = */         42,
    52045166    /* .cbInstanceShared = */       sizeof(HDASTATE),
    5205     /* .cbInstanceCC = */           0,
     5167    /* .cbInstanceCC = */           CTX_EXPR(sizeof(HDASTATER3), 0, 0),
    52065168    /* .cbInstanceRC = */           0,
    52075169    /* .cMaxPciDevices = */         1,
  • trunk/src/VBox/Devices/Audio/DevHDA.h

    r82421 r82450  
    3636
    3737/**
    38  * Structure defining an HDA mixer sink.
    39  * Its purpose is to know which audio mixer sink is bound to
    40  * which SDn (SDI/SDO) device stream.
    41  *
    42  * This is needed in order to handle interleaved streams
    43  * (that is, multiple channels in one stream) or non-interleaved
    44  * streams (each channel has a dedicated stream).
     38 * HDA mixer sink definition (ring-3).
     39 *
     40 * Its purpose is to know which audio mixer sink is bound to which SDn
     41 * (SDI/SDO) device stream.
     42 *
     43 * This is needed in order to handle interleaved streams (that is, multiple
     44 * channels in one stream) or non-interleaved streams (each channel has a
     45 * dedicated stream).
    4546 *
    4647 * This is only known to the actual device emulation level.
     
    4849typedef struct HDAMIXERSINK
    4950{
    50     R3PTRTYPE(PHDASTREAM)   pStream;
     51    R3PTRTYPE(PHDASTREAM)   pStreamShared;
     52    R3PTRTYPE(PHDASTREAMR3) pStreamR3;
    5153    /** Pointer to the actual audio mixer sink. */
    5254    R3PTRTYPE(PAUDMIXSINK)  pMixSink;
    53 } HDAMIXERSINK, *PHDAMIXERSINK;
    54 
    55 /**
    56  * Mapping a stream tag to an HDA stream.
     55} HDAMIXERSINK;
     56/** Pointer to an HDA mixer sink definition (ring-3). */
     57typedef HDAMIXERSINK *PHDAMIXERSINK;
     58
     59/**
     60 * Mapping a stream tag to an HDA stream (ring-3).
    5761 */
    5862typedef struct HDATAG
     
    6266    uint8_t                 Padding[7];
    6367    /** Pointer to associated stream. */
    64     R3PTRTYPE(PHDASTREAM) pStream;
     68    R3PTRTYPE(PHDASTREAMR3) pStreamR3;
    6569} HDATAG;
    6670/** Pointer to a HDA stream tag mapping. */
    6771typedef HDATAG *PHDATAG;
    6872
    69 /** @todo Make STAM values out of this? */
    70 typedef struct HDASTATEDEBUG
    71 {
    72 #ifdef DEBUG
    73     /** Timestamp (in ns) of the last timer callback (hdaTimer).
    74      * Used to calculate the time actually elapsed between two timer callbacks. */
    75     uint64_t                tsTimerLastCalledNs;
    76     /** IRQ debugging information. */
    77     struct
    78     {
    79         /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
    80         uint64_t            tsProcessedLastNs;
    81         /** Timestamp (in ns) of last asserted IRQ. */
    82         uint64_t            tsAssertedNs;
    83         /** How many IRQs have been asserted already. */
    84         uint64_t            cAsserted;
    85         /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
    86         uint64_t            tsAssertedTotalNs;
    87         /** Timestamp (in ns) of last deasserted IRQ. */
    88         uint64_t            tsDeassertedNs;
    89         /** How many IRQs have been deasserted already. */
    90         uint64_t            cDeasserted;
    91         /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
    92         uint64_t            tsDeassertedTotalNs;
    93     } IRQ;
    94 #endif
    95     /** Whether debugging is enabled or not. */
    96     bool                    fEnabled;
    97     /** Path where to dump the debug output to.
    98      *  Defaults to VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH. */
    99     char                    szOutPath[RTPATH_MAX + 1];
    100 } HDASTATEDEBUG;
    101 
    10273/**
    10374 * Shared ICH Intel HD audio controller state.
     
    10778    /** Critical section protecting the HDA state. */
    10879    PDMCRITSECT             CritSect;
    109     /** R3 Pointer to the device instance. */
    110     PPDMDEVINSR3            pDevInsR3;
    111     /** The base interface for LUN\#0. */
    112     PDMIBASE                IBase;
    11380    /** The HDA's register set. */
    11481    uint32_t                au32Regs[HDA_NUM_REGS];
    11582    /** Internal stream states. */
    11683    HDASTREAM               aStreams[HDA_MAX_STREAMS];
    117     /** Mapping table between stream tags and stream states. */
    118     HDATAG                  aTags[HDA_MAX_TAGS];
    11984    /** CORB buffer base address. */
    12085    uint64_t                u64CORBBase;
     
    12489     *  Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */
    12590    uint64_t                u64DPBase;
    126     /** Pointer to CORB buffer. */
    127     R3PTRTYPE(uint32_t *)   pu32CorbBuf;
    128     /** Size in bytes of CORB buffer. */
     91    /** Size in bytes of CORB buffer (#au32CorbBuf). */
    12992    uint32_t                cbCorbBuf;
    130     /** Padding for alignment. */
    131     uint32_t                u32Padding1;
    132     /** Pointer to RIRB buffer. */
    133     R3PTRTYPE(uint64_t *)   pu64RirbBuf;
    134     /** Size in bytes of RIRB buffer. */
     93    /** Size in bytes of RIRB buffer (#au64RirbBuf). */
    13594    uint32_t                cbRirbBuf;
    136     /** DMA position buffer enable bit. */
    137     bool                    fDMAPosition;
    138     /** Reserved. */
    139     bool                    afPadding1b[2];
    140     /** Number of active (running) SDn streams. */
    141     uint8_t                 cStreamsActive;
    142     /** Pointer to HDA codec to use. */
    143     R3PTRTYPE(PHDACODEC)    pCodec;
    144     /** List of associated LUN drivers (HDADRIVER). */
    145     RTLISTANCHORR3          lstDrv;
    146     /** The device' software mixer. */
    147     R3PTRTYPE(PAUDIOMIXER)  pMixer;
    148     /** HDA sink for (front) output. */
    149     HDAMIXERSINK            SinkFront;
    150 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    151     /** HDA sink for center / LFE output. */
    152     HDAMIXERSINK            SinkCenterLFE;
    153     /** HDA sink for rear output. */
    154     HDAMIXERSINK            SinkRear;
    155 #endif
    156     /** HDA mixer sink for line input. */
    157     HDAMIXERSINK            SinkLineIn;
    158 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    159     /** Audio mixer sink for microphone input. */
    160     HDAMIXERSINK            SinkMicIn;
    161 #endif
    162     /** Last updated wall clock (WALCLK) counter. */
    163     uint64_t                u64WalClk;
    16495    /** Response Interrupt Count (RINTCNT). */
    16596    uint16_t                u16RespIntCnt;
     
    177108    /** Whether the position adjustment is enabled or not. */
    178109    bool                    fPosAdjustEnabled;
     110    /** DMA position buffer enable bit. */
     111    bool                    fDMAPosition;
     112    /** Current IRQ level. */
     113    uint8_t                 u8IRQL;
    179114#ifdef VBOX_STRICT
    180115    /** Wall clock (WALCLK) stale count.
     
    182117     *  move the counter forward (stale). */
    183118    uint8_t                 u8WalClkStaleCnt;
    184     uint8_t                 Padding1[2];
    185119#else
    186     uint8_t                 Padding1[3];
    187 #endif
    188     /** Current IRQ level. */
    189     uint8_t                 u8IRQL;
     120    uint8_t                 bPadding1;
     121#endif
    190122    /** The device timer Hz rate. Defaults to HDA_TIMER_HZ_DEFAULT. */
    191123    uint16_t                uTimerHz;
    192124    /** Padding for alignment. */
    193     uint8_t                 au8Padding3[3];
    194     /** Debug stuff. */
    195     HDASTATEDEBUG           Dbg;
     125    uint16_t                au16Padding3[3];
     126    /** Last updated wall clock (WALCLK) counter. */
     127    uint64_t                u64WalClk;
     128    /** The CORB buffer. */
     129    uint32_t                au32CorbBuf[HDA_CORB_SIZE];
     130    /** Pointer to RIRB buffer. */
     131    uint64_t                au64RirbBuf[HDA_RIRB_SIZE];
    196132
    197133    /** PCI Region \#0: 16KB of MMIO stuff. */
     
    199135
    200136#ifdef VBOX_WITH_STATISTICS
    201     STAMPROFILE             StatTimer;
    202137    STAMPROFILE             StatIn;
    203138    STAMPROFILE             StatOut;
     
    224159    /** @} */
    225160#endif
     161
     162#ifdef DEBUG
     163    /** Debug stuff.
     164     * @todo Make STAM values out some of this? */
     165    struct
     166    {
     167# if 0 /* unused */
     168        /** Timestamp (in ns) of the last timer callback (hdaTimer).
     169         * Used to calculate the time actually elapsed between two timer callbacks. */
     170        uint64_t                tsTimerLastCalledNs;
     171# endif
     172        /** IRQ debugging information. */
     173        struct
     174        {
     175            /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
     176            uint64_t            tsProcessedLastNs;
     177            /** Timestamp (in ns) of last asserted IRQ. */
     178            uint64_t            tsAssertedNs;
     179# if 0 /* unused */
     180            /** How many IRQs have been asserted already. */
     181            uint64_t            cAsserted;
     182            /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
     183            uint64_t            tsAssertedTotalNs;
     184            /** Timestamp (in ns) of last deasserted IRQ. */
     185            uint64_t            tsDeassertedNs;
     186            /** How many IRQs have been deasserted already. */
     187            uint64_t            cDeasserted;
     188            /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
     189            uint64_t            tsDeassertedTotalNs;
     190# endif
     191        } IRQ;
     192    } Dbg;
     193#endif
    226194    /** This is for checking that the build was correctly configured in all contexts.
    227195     *  This is set to HDASTATE_ALIGNMENT_CHECK_MAGIC. */
     
    234202#define HDASTATE_ALIGNMENT_CHECK_MAGIC  UINT64_C(0x1298afb75893e059)
    235203
     204
     205/**
     206 * Ring-3 ICH Intel HD audio controller state.
     207 */
     208typedef struct HDASTATER3
     209{
     210    /** Internal stream states. */
     211    HDASTREAMR3             aStreams[HDA_MAX_STREAMS];
     212    /** Mapping table between stream tags and stream states. */
     213    HDATAG                  aTags[HDA_MAX_TAGS];
     214    /** Number of active (running) SDn streams. */
     215    uint8_t                 cStreamsActive;
     216    uint8_t                 abPadding0[7];
     217    /** R3 Pointer to the device instance. */
     218    PPDMDEVINSR3            pDevIns;
     219    /** The base interface for LUN\#0. */
     220    PDMIBASE                IBase;
     221    /** Pointer to HDA codec to use. */
     222    R3PTRTYPE(PHDACODEC)    pCodec;
     223    /** List of associated LUN drivers (HDADRIVER). */
     224    RTLISTANCHORR3          lstDrv;
     225    /** The device' software mixer. */
     226    R3PTRTYPE(PAUDIOMIXER)  pMixer;
     227    /** HDA sink for (front) output. */
     228    HDAMIXERSINK            SinkFront;
     229#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     230    /** HDA sink for center / LFE output. */
     231    HDAMIXERSINK            SinkCenterLFE;
     232    /** HDA sink for rear output. */
     233    HDAMIXERSINK            SinkRear;
     234#endif
     235    /** HDA mixer sink for line input. */
     236    HDAMIXERSINK            SinkLineIn;
     237#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
     238    /** Audio mixer sink for microphone input. */
     239    HDAMIXERSINK            SinkMicIn;
     240#endif
     241    /** Debug stuff. */
     242    struct
     243    {
     244        /** Whether debugging is enabled or not. */
     245        bool                    fEnabled;
     246        /** Path where to dump the debug output to.
     247         *  Defaults to VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH. */
     248        char                    szOutPath[RTPATH_MAX];
     249    } Dbg;
     250} HDASTATER3;
     251/** Pointer to a ring-3 HDA device state.  */
     252typedef HDASTATER3 *PHDASTATER3;
     253
     254
    236255#endif /* !VBOX_INCLUDED_SRC_Audio_DevHDA_h */
    237256
  • trunk/src/VBox/Devices/Audio/DevHDACommon.cpp

    r82406 r82450  
    4141 * Processes (de/asserts) the interrupt according to the HDA's current state.
    4242 *
    43  * @returns IPRT status code.
    4443 * @param   pDevIns             The device instance.
    45  * @param   pThis               HDA state.
     44 * @param   pThis               The shared HDA device state.
    4645 * @param   pszSource           Caller information.
    4746 */
    4847#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
    49 int hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource)
     48void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource)
    5049#else
    51 int hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis)
     50void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis)
    5251#endif
    5352{
     
    8079        pThis->u8IRQL = 0;
    8180    }
    82 
    83     return VINF_SUCCESS;
    8481}
    8582
     
    8986 * @return  IPRT status code.
    9087 * @return  Currently set wall clock value.
    91  * @param   pThis               HDA state.
     88 * @param   pThis               The shared HDA device state.
    9289 *
    9390 * @remark  Operation is atomic.
     
    9996
    10097#ifdef IN_RING3
     98
     99/**
     100 * Helper for hdaR3WalClkSet.
     101 */
     102DECLINLINE(PHDASTREAMPERIOD) hdaR3SinkToStreamPeriod(PHDAMIXERSINK pSink)
     103{
     104    PHDASTREAM pStream = hdaR3GetSharedStreamFromSink(pSink);
     105    if (pStream)
     106        return &pStream->State.Period;
     107    return NULL;
     108}
    101109
    102110/**
     
    107115 *
    108116 * @return  true if the WALCLK register has been updated, false if not.
    109  * @param   pThis               HDA state.
     117 * @param   pThis               The shared HDA device state.
     118 * @param   pThisCC             The ring-3 HDA device state.
    110119 * @param   u64WalClk           Wall clock value to set WALCLK register to.
    111120 * @param   fForce              Whether to force setting the wall clock value or not.
    112121 */
    113 bool hdaR3WalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)
    114 {
    115     const bool     fFrontPassed       = hdaR3StreamPeriodHasPassedAbsWalClk (&hdaR3GetStreamFromSink(pThis, &pThis->SinkFront)->State.Period,
    116                                                                            u64WalClk);
    117     const uint64_t u64FrontAbsWalClk  = hdaR3StreamPeriodGetAbsElapsedWalClk(&hdaR3GetStreamFromSink(pThis, &pThis->SinkFront)->State.Period);
     122bool hdaR3WalClkSet(PHDASTATE pThis, PHDASTATER3 pThisCC, uint64_t u64WalClk, bool fForce)
     123{
     124    const bool     fFrontPassed       = hdaR3StreamPeriodHasPassedAbsWalClk( hdaR3SinkToStreamPeriod(&pThisCC->SinkFront), u64WalClk);
     125    const uint64_t u64FrontAbsWalClk  = hdaR3StreamPeriodGetAbsElapsedWalClk(hdaR3SinkToStreamPeriod(&pThisCC->SinkFront));
    118126# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    119127#  error "Implement me!"
    120128# endif
    121129
    122     const bool     fLineInPassed      = hdaR3StreamPeriodHasPassedAbsWalClk (&hdaR3GetStreamFromSink(pThis, &pThis->SinkLineIn)->State.Period, u64WalClk);
    123     const uint64_t u64LineInAbsWalClk = hdaR3StreamPeriodGetAbsElapsedWalClk(&hdaR3GetStreamFromSink(pThis, &pThis->SinkLineIn)->State.Period);
     130    const bool     fLineInPassed      = hdaR3StreamPeriodHasPassedAbsWalClk (hdaR3SinkToStreamPeriod(&pThisCC->SinkLineIn), u64WalClk);
     131    const uint64_t u64LineInAbsWalClk = hdaR3StreamPeriodGetAbsElapsedWalClk(hdaR3SinkToStreamPeriod(&pThisCC->SinkLineIn));
    124132# ifdef VBOX_WITH_HDA_MIC_IN
    125     const bool     fMicInPassed       = hdaR3StreamPeriodHasPassedAbsWalClk (&hdaR3GetStreamFromSink(pThis, &pThis->SinkMicIn)->State.Period,  u64WalClk);
    126     const uint64_t u64MicInAbsWalClk  = hdaR3StreamPeriodGetAbsElapsedWalClk(&hdaR3GetStreamFromSink(pThis, &pThis->SinkMicIn)->State.Period);
     133    const bool     fMicInPassed       = hdaR3StreamPeriodHasPassedAbsWalClk (hdaR3SinkToStreamPeriod(&pThisCC->SinkMicIn),  u64WalClk);
     134    const uint64_t u64MicInAbsWalClk  = hdaR3StreamPeriodGetAbsElapsedWalClk(hdaR3SinkToStreamPeriod(&pThisCC->SinkMicIn));
    127135# endif
    128136
     
    190198 *
    191199 * @return  PHDAMIXERSINK
    192  * @param   pThis               HDA state.
     200 * @param   pThisCC             The ring-3 HDA device state.
    193201 * @param   uSD                 SD# to return mixer sink for.
    194202 *                              NULL if not found / handled.
    195203 */
    196 PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATE pThis, uint8_t uSD)
     204PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATER3 pThisCC, uint8_t uSD)
    197205{
    198206    if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
     
    201209
    202210        if (uSD == uFirstSDI) /* First SDI. */
    203             return &pThis->SinkLineIn;
     211            return &pThisCC->SinkLineIn;
    204212# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    205213        if (uSD == uFirstSDI + 1)
    206             return &pThis->SinkMicIn;
     214            return &pThisCC->SinkMicIn;
    207215# else
    208216        /* If we don't have a dedicated Mic-In sink, use the always present Line-In sink. */
    209         return &pThis->SinkLineIn;
     217        return &pThisCC->SinkLineIn;
    210218# endif
    211219    }
     
    215223
    216224        if (uSD == uFirstSDO)
    217             return &pThis->SinkFront;
     225            return &pThisCC->SinkFront;
    218226# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    219227        if (uSD == uFirstSDO + 1)
    220             return &pThis->SinkCenterLFE;
     228            return &pThisCC->SinkCenterLFE;
    221229        if (uSD == uFirstSDO + 2)
    222             return &pThis->SinkRear;
     230            return &pThisCC->SinkRear;
    223231# endif
    224232    }
     
    270278 * @return  Pointer to HDA stream, or NULL if none found.
    271279 */
    272 PHDASTREAM hdaR3GetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink)
    273 {
    274     AssertPtrReturn(pThis, NULL);
     280PHDASTREAMR3 hdaR3GetR3StreamFromSink(PHDAMIXERSINK pSink)
     281{
    275282    AssertPtrReturn(pSink, NULL);
    276283
    277284    /** @todo Do something with the channel mapping here? */
    278     return pSink->pStream;
    279 }
    280 
    281 /**
     285    return pSink->pStreamR3;
     286}
     287
     288
     289/**
     290 * Returns the HDA stream of specified HDA sink.
     291 *
     292 * @return  Pointer to HDA stream, or NULL if none found.
     293 */
     294PHDASTREAM hdaR3GetSharedStreamFromSink(PHDAMIXERSINK pSink)
     295{
     296    AssertPtrReturn(pSink, NULL);
     297
     298    /** @todo Do something with the channel mapping here? */
     299    return pSink->pStreamShared;
     300}
     301
     302/*
    282303 * Reads DMA data from a given HDA output stream.
    283304 *
    284305 * @return  IPRT status code.
    285  * @param   pThis               HDA state.
    286  * @param   pStream             HDA output stream to read DMA data from.
     306 * @param   pDevIns             The device instance.
     307 * @param   pThis               The shared HDA device state (for stats).
     308 * @param   pStreamShared       HDA output stream to read DMA data from - shared bits.
     309 * @param   pStreamR3           HDA output stream to read DMA data from - shared ring-3.
    287310 * @param   pvBuf               Where to store the read data.
    288311 * @param   cbBuf               How much to read in bytes.
    289312 * @param   pcbRead             Returns read bytes from DMA. Optional.
    290313 */
    291 int hdaR3DMARead(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    292 {
    293     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    294     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    295     /* pcbRead is optional. */
    296 
    297     PHDABDLE pBDLE       = &pStream->State.BDLE;
     314int hdaR3DMARead(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3,
     315                 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     316{
     317    RT_NOREF(pThis);
     318    PHDABDLE pBDLE = &pStreamShared->State.BDLE;
    298319
    299320    int rc = VINF_SUCCESS;
     
    305326    uint64_t   csSilence = 0;
    306327
    307     pStream->Dbg.cSilenceThreshold = 100;
    308     pStream->Dbg.cbSilenceReadMin  = _1M;
    309 # endif
    310 
    311     RTGCPHYS addrChunk = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
     328    pStreamCC->Dbg.cSilenceThreshold = 100;
     329    pStreamCC->Dbg.cbSilenceReadMin  = _1M;
     330# endif
     331
     332    RTGCPHYS GCPhysChunk = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
    312333
    313334    while (cbLeft)
    314335    {
    315         uint32_t cbChunk = RT_MIN(cbLeft, pStream->u16FIFOS);
    316 
    317         rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), addrChunk, (uint8_t *)pvBuf + cbReadTotal, cbChunk);
    318         if (RT_FAILURE(rc))
    319             break;
     336        uint32_t cbChunk = RT_MIN(cbLeft, pStreamShared->u16FIFOS);
     337
     338        rc = PDMDevHlpPhysRead(pDevIns, GCPhysChunk, (uint8_t *)pvBuf + cbReadTotal, cbChunk);
     339        AssertRCBreak(rc);
    320340
    321341# ifdef HDA_DEBUG_SILENCE
     
    330350        }
    331351# endif
    332         if (pStream->Dbg.Runtime.fEnabled)
    333             DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbReadTotal, cbChunk, 0 /* fFlags */);
     352        if (RT_LIKELY(!pStreamR3->Dbg.Runtime.fEnabled))
     353        { /* likely */ }
     354        else
     355            DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbReadTotal, cbChunk, 0 /* fFlags */);
    334356
    335357        STAM_COUNTER_ADD(&pThis->StatBytesRead, cbChunk);
    336         addrChunk         = (addrChunk + cbChunk) % pBDLE->Desc.u32BufSize;
    337 
     358
     359        /* advance */
    338360        Assert(cbLeft    >= cbChunk);
     361        GCPhysChunk       = (GCPhysChunk + cbChunk) % pBDLE->Desc.u32BufSize;
     362        cbReadTotal      += cbChunk;
    339363        cbLeft           -= cbChunk;
    340 
    341         cbReadTotal      += cbChunk;
    342364    }
    343365
    344366# ifdef HDA_DEBUG_SILENCE
    345367    if (csSilence)
    346         pStream->Dbg.csSilence += csSilence;
     368        pStreamR3->Dbg.csSilence += csSilence;
    347369
    348370    if (   csSilence == 0
    349         && pStream->Dbg.csSilence   >  pStream->Dbg.cSilenceThreshold
    350         && pStream->Dbg.cbReadTotal >= pStream->Dbg.cbSilenceReadMin)
    351     {
    352         LogFunc(("Silent block detected: %RU64 audio samples\n", pStream->Dbg.csSilence));
    353         pStream->Dbg.csSilence = 0;
     371        && pStreamR3->Dbg.csSilence   >  pStreamR3->Dbg.cSilenceThreshold
     372        && pStreamR3->Dbg.cbReadTotal >= pStreamR3->Dbg.cbSilenceReadMin)
     373    {
     374        LogFunc(("Silent block detected: %RU64 audio samples\n", pStreamR3->Dbg.csSilence));
     375        pStreamR3->Dbg.csSilence = 0;
    354376    }
    355377# endif
     
    368390 *
    369391 * @return  IPRT status code.
    370  * @param   pThis               HDA state.
    371  * @param   pStream             HDA input stream to write audio data to.
     392 * @param   pDevIns             The device instance.
     393 * @param   pThis               The shared HDA device state (for stats).
     394 * @param   pStreamShared       HDA input stream to write audio data to - shared.
     395 * @param   pStreamR3           HDA input stream to write audio data to - ring-3.
    372396 * @param   pvBuf               Data to write.
    373397 * @param   cbBuf               How much (in bytes) to write.
    374398 * @param   pcbWritten          Returns written bytes on success. Optional.
    375399 */
    376 int hdaR3DMAWrite(PHDASTATE pThis, PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    377 {
    378     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    379     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    380     /* pcbWritten is optional. */
    381 
    382     PHDABDLE pBDLE  = &pStream->State.BDLE;
    383 
    384     int rc = VINF_SUCCESS;
    385 
    386     uint32_t cbWrittenTotal = 0;
    387     uint32_t cbLeft = RT_MIN(cbBuf, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    388 
    389     RTGCPHYS addrChunk = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
    390 
     400int hdaR3DMAWrite(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3,
     401                  const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     402{
     403    RT_NOREF(pThis);
     404    PHDABDLE    pBDLE          = &pStreamShared->State.BDLE;
     405    int         rc             = VINF_SUCCESS;
     406    uint32_t    cbWrittenTotal = 0;
     407    uint32_t    cbLeft         = RT_MIN(cbBuf, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
     408    RTGCPHYS    GCPhysChunk    = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
    391409    while (cbLeft)
    392410    {
    393         uint32_t cbChunk = RT_MIN(cbLeft, pStream->u16FIFOS);
     411        uint32_t cbChunk = RT_MIN(cbLeft, pStreamShared->u16FIFOS);
    394412
    395413        /* Sanity checks. */
    396414        Assert(cbChunk <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    397415
    398         if (pStream->Dbg.Runtime.fEnabled)
    399             DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, 0 /* fFlags */);
    400 
    401         rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    402                                    addrChunk, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk);
    403         if (RT_FAILURE(rc))
    404             break;
     416        if (RT_LIKELY(!pStreamR3->Dbg.Runtime.fEnabled))
     417        { /* likely */ }
     418        else
     419            DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMARaw, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk, 0 /* fFlags */);
     420
     421        rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysChunk, (uint8_t *)pvBuf + cbWrittenTotal, cbChunk);
     422        AssertRCReturn(rc, rc);
    405423
    406424        STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbChunk);
    407         addrChunk       = (addrChunk + cbChunk) % pBDLE->Desc.u32BufSize;
    408 
     425
     426        /* advance */
    409427        Assert(cbLeft  >= cbChunk);
    410         cbLeft -= (uint32_t)cbChunk;
    411 
    412428        cbWrittenTotal += (uint32_t)cbChunk;
     429        GCPhysChunk     = (GCPhysChunk + cbChunk) % pBDLE->Desc.u32BufSize;
     430        cbLeft         -= (uint32_t)cbChunk;
    413431    }
    414432
     
    430448 *
    431449 * @returns Determined INTSTS register value.
    432  * @param   pThis               HDA state.
     450 * @param   pThis               The shared HDA device state.
    433451 *
    434452 * @remark  This function does *not* set INTSTS!
     
    554572
    555573# ifdef LOG_ENABLED
    556 void hdaR3BDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
     574void hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
    557575{
    558576    LogFlowFunc(("BDLEs @ 0x%x (%RU16):\n", u64BDLBase, cBDLE));
     
    564582    {
    565583        HDABDLEDESC bd;
    566         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
     584        PDMDevHlpPhysRead(pDevIns, u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
    567585
    568586        LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
     
    582600    {
    583601        uint32_t uDMACnt;
    584         PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
     602        PDMDevHlpPhysRead(pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
    585603                          &uDMACnt, sizeof(uDMACnt));
    586604
     
    593611 * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.
    594612 *
    595  * @param   pThis                   Pointer to HDA state.
    596  * @param   pBDLE                   Where to store the fetched result.
    597  * @param   u64BaseDMA              Address base of DMA engine to use.
    598  * @param   u16Entry                BDLE entry to fetch.
    599  */
    600 int hdaR3BDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)
    601 {
    602     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     613 * @param   pDevIns             The device instance.
     614 * @param   pBDLE               Where to store the fetched result.
     615 * @param   u64BaseDMA          Address base of DMA engine to use.
     616 * @param   u16Entry            BDLE entry to fetch.
     617 */
     618int hdaR3BDLEFetch(PPDMDEVINS pDevIns, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)
     619{
    603620    AssertPtrReturn(pBDLE,   VERR_INVALID_POINTER);
    604621    AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
     
    611628    /** @todo Compare u16Entry with LVI. */
    612629
    613     int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
     630    int rc = PDMDevHlpPhysRead(pDevIns, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
    614631                               &pBDLE->Desc, sizeof(pBDLE->Desc));
    615632
     
    664681 *
    665682 * @returns Whether the new expiration time was set or not.
    666  * @param   pDevIns     The device instance.
    667  * @param   pStream     HDA stream to set timer for.
    668  * @param   tsExpire    New (virtual) expiration time to set.
    669  * @param   fForce      Whether to force setting the expiration time or not.
    670  * @param   tsNow       The current clock timestamp if available, 0 if not.
     683 * @param   pDevIns         The device instance.
     684 * @param   pStreamShared   HDA stream to set timer for (shared).
     685 * @param   tsExpire        New (virtual) expiration time to set.
     686 * @param   fForce          Whether to force setting the expiration time or not.
     687 * @param   tsNow           The current clock timestamp if available, 0 if not.
    671688 *
    672689 * @remark  This function takes all active HDA streams and their
     
    679696 *          Forcing a new expiration time will override the above mechanism.
    680697 */
    681 bool hdaR3TimerSet(PPDMDEVINS pDevIns, PHDASTREAM pStream, uint64_t tsExpire, bool fForce, uint64_t tsNow)
    682 {
    683     AssertPtr(pStream);
     698bool hdaR3TimerSet(PPDMDEVINS pDevIns, PHDASTREAM pStreamShared, uint64_t tsExpire, bool fForce, uint64_t tsNow)
     699{
     700    AssertPtr(pStreamShared);
    684701
    685702    if (!tsNow)
    686         tsNow = PDMDevHlpTimerGet(pDevIns, pStream->hTimer);
     703        tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
    687704
    688705    if (!fForce)
     
    691708         * PDMDevHlpTimerGet(), so, some callers does one, this does, and then we do
    692709         * right afterwards == very inefficient! */
    693         if (hdaR3StreamTransferIsScheduled(pStream, tsNow))
     710        if (hdaR3StreamTransferIsScheduled(pStreamShared, tsNow))
    694711        {
    695             uint64_t const tsNext = hdaR3StreamTransferGetNext(pStream);
     712            uint64_t const tsNext = hdaR3StreamTransferGetNext(pStreamShared);
    696713            if (tsExpire > tsNext)
    697714                tsExpire = tsNext;
     
    706723        tsExpire = tsNow;
    707724
    708     int rc = PDMDevHlpTimerSet(pDevIns, pStream->hTimer, tsExpire);
     725    int rc = PDMDevHlpTimerSet(pDevIns, pStreamShared->hTimer, tsExpire);
    709726    AssertRCReturn(rc, false);
    710727
  • trunk/src/VBox/Devices/Audio/DevHDACommon.h

    r82417 r82450  
    2525#include <VBox/log.h> /* LOG_ENABLED */
    2626
    27     /** Read callback. */
     27/** Pointer to an HDA stream (SDI / SDO).  */
     28typedef struct HDASTREAMR3 *PHDASTREAMR3;
     29
     30
     31
     32/** Read callback. */
    2833typedef VBOXSTRICTRC FNHDAREGREAD(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    29     /** Write callback. */
     34/** Write callback. */
    3035typedef VBOXSTRICTRC FNHDAREGWRITE(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    3136
     
    598603 */
    599604#ifdef IN_RING3
    600 PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATE pThis, uint8_t uSD);
     605PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATER3 pThisCC, uint8_t uSD);
    601606#endif
    602607PDMAUDIODIR   hdaGetDirFromSD(uint8_t uSD);
    603 PHDASTREAM    hdaGetStreamFromSD(PHDASTATE pThis, uint8_t uSD);
     608//PHDASTREAM    hdaGetStreamFromSD(PHDASTATER3 pThisCC, uint8_t uSD);
    604609#ifdef IN_RING3
    605 PHDASTREAM    hdaR3GetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink);
     610PHDASTREAMR3  hdaR3GetR3StreamFromSink(PHDAMIXERSINK pSink);
     611PHDASTREAM    hdaR3GetSharedStreamFromSink(PHDAMIXERSINK pSink);
    606612#endif
    607613/** @} */
     
    610616 * @{
    611617 */
    612 #ifdef LOG_ENABLED
    613 int           hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource);
     618#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
     619void          hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource);
    614620# define HDA_PROCESS_INTERRUPT(a_pDevIns, a_pThis)  hdaProcessInterrupt((a_pDevIns), (a_pThis), __FUNCTION__)
    615621#else
    616 int           hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis);
     622void          hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis);
    617623# define HDA_PROCESS_INTERRUPT(a_pDevIns, a_pThis)  hdaProcessInterrupt((a_pDevIns), (a_pThis))
    618624#endif
     
    624630uint64_t      hdaWalClkGetCurrent(PHDASTATE pThis);
    625631#ifdef IN_RING3
    626 bool          hdaR3WalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
     632bool          hdaR3WalClkSet(PHDASTATE pThis, PHDASTATER3 pThisCC, uint64_t u64WalClk, bool fForce);
    627633#endif
    628634/** @} */
     
    632638 */
    633639#ifdef IN_RING3
    634 int           hdaR3DMARead(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    635 int           hdaR3DMAWrite(PHDASTATE pThis, PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
     640int           hdaR3DMARead(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3,
     641                           void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
     642int           hdaR3DMAWrite(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3,
     643                            const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    636644#endif
    637645/** @} */
     
    651659#ifdef IN_RING3
    652660# ifdef LOG_ENABLED
    653 void          hdaR3BDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE);
     661void          hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE);
    654662# endif
    655 int           hdaR3BDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
     663int           hdaR3BDLEFetch(PPDMDEVINS pDevIns, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
    656664bool          hdaR3BDLEIsComplete(PHDABDLE pBDLE);
    657665bool          hdaR3BDLENeedsInterrupt(PHDABDLE pBDLE);
     
    663671 */
    664672#ifdef IN_RING3
    665 bool          hdaR3TimerSet(PPDMDEVINS pDevIns, PHDASTREAM pStream, uint64_t u64Expire, bool fForce, uint64_t tsNow);
     673bool          hdaR3TimerSet(PPDMDEVINS pDevIns, PHDASTREAM pStreamShared, uint64_t u64Expire, bool fForce, uint64_t tsNow);
    666674#endif
    667675/** @} */
  • trunk/src/VBox/Devices/Audio/HDACodec.cpp

    r82421 r82450  
    16311631             DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), lVol, rVol, RT_BOOL(iMute) ? "Muted" : "Unmuted"));
    16321632
    1633     return pThis->pfnCbMixerSetVolume(pThis->pHDAState, enmMixerCtl, &Vol);
     1633    return pThis->pfnCbMixerSetVolume(pThis->pDevIns, enmMixerCtl, &Vol);
    16341634}
    16351635
     
    24122412
    24132413            /* Propagate to the controller. */
    2414             pThis->pfnCbMixerControl(pThis->pHDAState, PDMAUDIOMIXERCTL_FRONT,      uSD, uChannel);
     2414            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_FRONT,      uSD, uChannel);
    24152415#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    2416             pThis->pfnCbMixerControl(pThis->pHDAState, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel);
    2417             pThis->pfnCbMixerControl(pThis->pHDAState, PDMAUDIOMIXERCTL_REAR,       uSD, uChannel);
     2416            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_CENTER_LFE, uSD, uChannel);
     2417            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_REAR,       uSD, uChannel);
    24182418#endif
    24192419        }
    24202420        else if (enmDir == PDMAUDIODIR_IN)
    24212421        {
    2422             pThis->pfnCbMixerControl(pThis->pHDAState, PDMAUDIOMIXERCTL_LINE_IN,    uSD, uChannel);
     2422            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_LINE_IN,    uSD, uChannel);
    24232423#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    2424             pThis->pfnCbMixerControl(pThis->pHDAState, PDMAUDIOMIXERCTL_MIC_IN,     uSD, uChannel);
     2424            pThis->pfnCbMixerControl(pThis->pDevIns, PDMAUDIOMIXERCTL_MIC_IN,     uSD, uChannel);
    24252425#endif
    24262426        }
     
    30653065        case PDMAUDIOMIXERCTL_REAR:
    30663066#endif
    3067         {
    30683067            break;
    3069         }
     3068
    30703069        case PDMAUDIOMIXERCTL_LINE_IN:
    30713070#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    30723071        case PDMAUDIOMIXERCTL_MIC_IN:
    30733072#endif
    3074         {
    30753073            break;
    3076         }
     3074
    30773075        default:
    30783076            AssertMsgFailed(("Mixer control %d not implemented\n", enmMixerCtl));
     
    30823080
    30833081    if (RT_SUCCESS(rc))
    3084         rc = pThis->pfnCbMixerAddStream(pThis->pHDAState, enmMixerCtl, pCfg);
     3082        rc = pThis->pfnCbMixerAddStream(pThis->pDevIns, enmMixerCtl, pCfg);
    30853083
    30863084    LogFlowFuncLeaveRC(rc);
     
    30923090    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    30933091
    3094     int rc = pThis->pfnCbMixerRemoveStream(pThis->pHDAState, enmMixerCtl);
     3092    int rc = pThis->pfnCbMixerRemoveStream(pThis->pDevIns, enmMixerCtl);
    30953093
    30963094    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Devices/Audio/HDACodec.h

    r82406 r82450  
    2626#include "AudioMixer.h"
    2727
    28 /** The ICH HDA (Intel) controller. */
     28/** Pointer to a shared HDA device state. */
    2929typedef struct HDASTATE *PHDASTATE;
     30/** Pointer to a ring-3 HDA device state.  */
     31typedef struct HDASTATER3 *PHDASTATER3;
    3032/** The ICH HDA (Intel) codec state. */
    3133typedef struct HDACODEC *PHDACODEC;
    3234/** The HDA host driver backend. */
    3335typedef struct HDADRIVER *PHDADRIVER;
    34 typedef struct PDMIAUDIOCONNECTOR *PPDMIAUDIOCONNECTOR;
    35 typedef struct PDMAUDIOGSTSTRMOUT *PPDMAUDIOGSTSTRMOUT;
    36 typedef struct PDMAUDIOGSTSTRMIN  *PPDMAUDIOGSTSTRMIN;
    3736
    3837/**
     
    4140typedef DECLCALLBACK(int) FNHDACODECVERBPROCESSOR(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp);
    4241typedef FNHDACODECVERBPROCESSOR *PFNHDACODECVERBPROCESSOR;
    43 typedef FNHDACODECVERBPROCESSOR **PPFNHDACODECVERBPROCESSOR;
    4442
    4543/* PRM 5.3.1 */
     
    7169    uint8_t                 u8BSKU;
    7270    uint8_t                 u8AssemblyId;
     71
    7372    /** List of assigned HDA drivers to this codec.
    7473     * A driver only can be assigned to one codec at a time. */
     
    7978
    8079    PCODECNODE              paNodes;
    81     /** Pointer to HDA state (controller) this
    82      *  codec is assigned to. */
    83     PHDASTATE               pHDAState;
     80
    8481    bool                    fInReset;
     82    uint8_t                 abPadding1[3];
    8583
    8684    const uint8_t           cTotalNodes;
     85    const uint8_t           u8AdcVolsLineIn;
     86    const uint8_t           u8DacLineOut;
     87    uint8_t                 bPadding2;
    8788    const uint8_t          *au8Ports;
    8889    const uint8_t          *au8Dacs;
     
    9899    const uint8_t          *au8VolKnobs;
    99100    const uint8_t          *au8Reserveds;
    100     const uint8_t           u8AdcVolsLineIn;
    101     const uint8_t           u8DacLineOut;
    102101
    103102    /** @name Public codec functions.
     
    106105    DECLR3CALLBACKMEMBER(void, pfnReset, (PHDACODEC pThis));
    107106    DECLR3CALLBACKMEMBER(int,  pfnNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE));
     107    DECLR3CALLBACKMEMBER(void, pfnDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
     108    DECLR3CALLBACKMEMBER(void, pfnDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
    108109    /** @} */
     110
     111    /** The parent device instance. */
     112    PPDMDEVINS              pDevIns;
    109113
    110114    /** @name Callbacks to the HDA controller, mostly used for multiplexing to the
    111115     *        various host backends.
    112116     * @{ */
    113     DECLR3CALLBACKMEMBER(int,  pfnCbMixerAddStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg));
    114     DECLR3CALLBACKMEMBER(int,  pfnCbMixerRemoveStream, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl));
    115     DECLR3CALLBACKMEMBER(int,  pfnCbMixerControl, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel));
    116     DECLR3CALLBACKMEMBER(int,  pfnCbMixerSetVolume, (PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol));
    117     /** @} */
    118 
    119     /** @name These callbacks are set by codec implementation to answer debugger requests.
    120      * @{ */
    121     DECLR3CALLBACKMEMBER(void, pfnDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
    122     DECLR3CALLBACKMEMBER(void, pfnDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
     117    /**
     118     *
     119     * Adds a new audio stream to a specific mixer control.
     120     *
     121     * Depending on the mixer control the stream then gets assigned to one of the
     122     * internal mixer sinks, which in turn then handle the mixing of all connected
     123     * streams to that sink.
     124     *
     125     * @return  VBox status code.
     126     * @param   pThisCC             The ring-3 HDA device state.
     127     * @param   enmMixerCtl         Mixer control to assign new stream to.
     128     * @param   pCfg                Stream configuration for the new stream.
     129     */
     130    DECLR3CALLBACKMEMBER(int,  pfnCbMixerAddStream, (PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg));
     131    /**
     132     * Removes a specified mixer control from the HDA's mixer.
     133     *
     134     * @return  VBox status code.
     135     * @param   pThisCC             The ring-3 HDA device state.
     136     * @param   enmMixerCtl         Mixer control to remove.
     137     */
     138    DECLR3CALLBACKMEMBER(int,  pfnCbMixerRemoveStream, (PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl));
     139    /**
     140     * Controls an input / output converter widget, that is, which converter is
     141     * connected to which stream (and channel).
     142     *
     143     * @return  VBox status code.
     144     * @param   pThisCC             The ring-3 HDA device state.
     145     * @param   enmMixerCtl         Mixer control to set SD stream number and channel for.
     146     * @param   uSD                 SD stream number (number + 1) to set. Set to 0 for unassign.
     147     * @param   uChannel            Channel to set. Only valid if a valid SD stream number is specified.
     148     */
     149    DECLR3CALLBACKMEMBER(int,  pfnCbMixerControl, (PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel));
     150    /**
     151     * Sets the volume of a specified mixer control.
     152     *
     153     * @return  IPRT status code.
     154     * @param   pThisCC             The ring-3 HDA device state.
     155     * @param   enmMixerCtl         Mixer control to set volume for.
     156     * @param   pVol                Pointer to volume data to set.
     157     */
     158    DECLR3CALLBACKMEMBER(int,  pfnCbMixerSetVolume, (PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol));
    123159    /** @} */
    124160
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r82420 r82450  
    3636
    3737
    38 #ifdef IN_RING3
     38#ifdef IN_RING3 /* whole file */
     39
     40/*********************************************************************************************************************************
     41*   Internal Functions                                                                                                           *
     42*********************************************************************************************************************************/
     43static void hdaR3StreamSetPosition(PHDASTREAM pStreamShared, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t u32LPIB);
     44
     45static int  hdaR3StreamAsyncIODestroy(PHDASTREAMR3 pStreamR3);
     46static int  hdaR3StreamAsyncIONotify(PHDASTREAMR3 pStreamR3);
     47
     48
    3949
    4050/**
     
    4252 *
    4353 * @returns IPRT status code.
    44  * @param   pStream             HDA stream to create.
    45  * @param   pThis               HDA state to assign the HDA stream to.
    46  * @param   u8SD                Stream descriptor number to assign.
    47  */
    48 int hdaR3StreamCreate(PHDASTREAM pStream, PHDASTATE pThis, uint8_t u8SD)
     54 * @param   pStreamShared       The HDA stream to construct - shared bits.
     55 * @param   pStreamR3           The HDA stream to construct - ring-3 bits.
     56 * @param   pThis               The shared HDA device instance.
     57 * @param   pThisCC             The ring-3 HDA device instance.
     58 * @param   uSD                 Stream descriptor number to assign.
     59 */
     60int hdaR3StreamConstruct(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, PHDASTATE pThis, PHDASTATER3 pThisCC, uint8_t uSD)
    4961{
    5062    int rc;
    51     RT_NOREF(pThis);
    52     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    53 
    54     pStream->u8SD           = u8SD;
    55     pStream->pMixSink       = NULL;
    56     pStream->pHDAState      = pThis;
    57     Assert(pStream->hTimer != NIL_TMTIMERHANDLE); /* hdaR3Construct initalized this one already. */
    58 
    59     pStream->State.fInReset = false;
    60     pStream->State.fRunning = false;
     63
     64    pStreamR3->u8SD             = uSD;
     65    pStreamShared->u8SD         = uSD;
     66    pStreamR3->pMixSink         = NULL;
     67    pStreamR3->pHDAStateShared  = pThis;
     68    pStreamR3->pHDAStateR3      = pThisCC;
     69    Assert(pStreamShared->hTimer != NIL_TMTIMERHANDLE); /* hdaR3Construct initalized this one already. */
     70
     71    pStreamShared->State.fInReset = false;
     72    pStreamShared->State.fRunning = false;
    6173#ifdef HDA_USE_DMA_ACCESS_HANDLER
    62     RTListInit(&pStream->State.lstDMAHandlers);
     74    RTListInit(&pStreamR3->State.lstDMAHandlers);
    6375#endif
    6476
    6577# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    66     rc = RTCritSectInit(&pStream->CritSect);
     78    rc = RTCritSectInit(&pStreamR3->CritSect);
    6779    AssertRCReturn(rc, rc);
    6880# endif
    6981
    70     rc = hdaR3StreamPeriodCreate(&pStream->State.Period);
     82    rc = hdaR3StreamPeriodCreate(&pStreamShared->State.Period);
    7183    AssertRCReturn(rc, rc);
    7284
    73     pStream->State.tsLastUpdateNs = 0;
     85    pStreamShared->State.tsLastUpdateNs = 0;
    7486
    7587#ifdef DEBUG
    76     rc = RTCritSectInit(&pStream->Dbg.CritSect);
     88    rc = RTCritSectInit(&pStreamR3->Dbg.CritSect);
    7789    AssertRCReturn(rc, rc);
    7890#endif
    7991
    80     pStream->Dbg.Runtime.fEnabled = pThis->Dbg.fEnabled;
    81 
    82     if (pStream->Dbg.Runtime.fEnabled)
     92    pStreamR3->Dbg.Runtime.fEnabled = pThisCC->Dbg.fEnabled;
     93
     94    if (pStreamR3->Dbg.Runtime.fEnabled)
    8395    {
    8496        char szFile[64];
    85 
    86         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
    87             RTStrPrintf(szFile, sizeof(szFile), "hdaStreamWriteSD%RU8", pStream->u8SD);
     97        char szPath[RTPATH_MAX];
     98
     99        /* pFileStream */
     100        if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
     101            RTStrPrintf(szFile, sizeof(szFile), "hdaStreamWriteSD%RU8", uSD);
    88102        else
    89             RTStrPrintf(szFile, sizeof(szFile), "hdaStreamReadSD%RU8", pStream->u8SD);
    90 
    91         char szPath[RTPATH_MAX + 1];
    92         int rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
     103            RTStrPrintf(szFile, sizeof(szFile), "hdaStreamReadSD%RU8", uSD);
     104
     105        int rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThisCC->Dbg.szOutPath, szFile,
    93106                                         0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAGS_NONE);
    94107        AssertRC(rc2);
    95         rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStream->Dbg.Runtime.pFileStream);
     108
     109        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStreamR3->Dbg.Runtime.pFileStream);
    96110        AssertRC(rc2);
    97111
    98         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
    99             RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawWriteSD%RU8", pStream->u8SD);
     112        /* pFileDMARaw */
     113        if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
     114            RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawWriteSD%RU8", uSD);
    100115        else
    101             RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawReadSD%RU8", pStream->u8SD);
    102 
    103         rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
     116            RTStrPrintf(szFile, sizeof(szFile), "hdaDMARawReadSD%RU8", uSD);
     117
     118        rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThisCC->Dbg.szOutPath, szFile,
    104119                                     0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAGS_NONE);
    105120        AssertRC(rc2);
    106121
    107         rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStream->Dbg.Runtime.pFileDMARaw);
     122        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStreamR3->Dbg.Runtime.pFileDMARaw);
    108123        AssertRC(rc2);
    109124
    110         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
    111             RTStrPrintf(szFile, sizeof(szFile), "hdaDMAWriteMappedSD%RU8", pStream->u8SD);
     125        /* pFileDMAMapped */
     126        if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
     127            RTStrPrintf(szFile, sizeof(szFile), "hdaDMAWriteMappedSD%RU8", uSD);
    112128        else
    113             RTStrPrintf(szFile, sizeof(szFile), "hdaDMAReadMappedSD%RU8", pStream->u8SD);
    114 
    115         rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.szOutPath, szFile,
     129            RTStrPrintf(szFile, sizeof(szFile), "hdaDMAReadMappedSD%RU8", uSD);
     130
     131        rc2 = DrvAudioHlpFileNameGet(szPath, sizeof(szPath), pThisCC->Dbg.szOutPath, szFile,
    116132                                     0 /* uInst */, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAGS_NONE);
    117133        AssertRC(rc2);
    118134
    119         rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStream->Dbg.Runtime.pFileDMAMapped);
     135        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szPath, PDMAUDIOFILE_FLAGS_NONE, &pStreamR3->Dbg.Runtime.pFileDMAMapped);
    120136        AssertRC(rc2);
    121137
    122138        /* Delete stale debugging files from a former run. */
    123         DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileStream);
    124         DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMARaw);
    125         DrvAudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMAMapped);
     139        DrvAudioHlpFileDelete(pStreamR3->Dbg.Runtime.pFileStream);
     140        DrvAudioHlpFileDelete(pStreamR3->Dbg.Runtime.pFileDMARaw);
     141        DrvAudioHlpFileDelete(pStreamR3->Dbg.Runtime.pFileDMAMapped);
    126142    }
    127143
     
    132148 * Destroys an HDA stream.
    133149 *
    134  * @param   pStream             HDA stream to destroy.
    135  */
    136 void hdaR3StreamDestroy(PHDASTREAM pStream)
    137 {
    138     AssertPtrReturnVoid(pStream);
    139 
    140     LogFlowFunc(("[SD%RU8] Destroying ...\n", pStream->u8SD));
    141 
    142     hdaR3StreamMapDestroy(&pStream->State.Mapping);
     150 * @param   pStreamShared       The HDA stream to destroy - shared bits.
     151 * @param   pStreamR3           The HDA stream to destroy - ring-3 bits.
     152 */
     153void hdaR3StreamDestroy(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3)
     154{
     155    LogFlowFunc(("[SD%RU8] Destroying ...\n", pStreamShared->u8SD));
     156
     157    hdaR3StreamMapDestroy(&pStreamR3->State.Mapping);
    143158
    144159    int rc2;
    145160
    146161#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    147     rc2 = hdaR3StreamAsyncIODestroy(pStream);
     162    rc2 = hdaR3StreamAsyncIODestroy(pStreamR3);
    148163    AssertRC(rc2);
    149164#endif
    150165
    151166# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    152     if (RTCritSectIsInitialized(&pStream->CritSect))
    153     {
    154         rc2 = RTCritSectDelete(&pStream->CritSect);
     167    if (RTCritSectIsInitialized(&pStreamR3->CritSect))
     168    {
     169        rc2 = RTCritSectDelete(&pStreamR3->CritSect);
    155170        AssertRC(rc2);
    156171    }
    157172# endif
    158173
    159     if (pStream->State.pCircBuf)
    160     {
    161         RTCircBufDestroy(pStream->State.pCircBuf);
    162         pStream->State.pCircBuf = NULL;
    163     }
    164 
    165     hdaR3StreamPeriodDestroy(&pStream->State.Period);
     174    if (pStreamR3->State.pCircBuf)
     175    {
     176        RTCircBufDestroy(pStreamR3->State.pCircBuf);
     177        pStreamR3->State.pCircBuf = NULL;
     178    }
     179
     180    hdaR3StreamPeriodDestroy(&pStreamShared->State.Period);
    166181
    167182#ifdef DEBUG
    168     if (RTCritSectIsInitialized(&pStream->Dbg.CritSect))
    169     {
    170         rc2 = RTCritSectDelete(&pStream->Dbg.CritSect);
     183    if (RTCritSectIsInitialized(&pStreamR3->Dbg.CritSect))
     184    {
     185        rc2 = RTCritSectDelete(&pStreamR3->Dbg.CritSect);
    171186        AssertRC(rc2);
    172187    }
    173188#endif
    174189
    175     if (pStream->Dbg.Runtime.fEnabled)
    176     {
    177         DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileStream);
    178         pStream->Dbg.Runtime.pFileStream = NULL;
    179 
    180         DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMARaw);
    181         pStream->Dbg.Runtime.pFileDMARaw = NULL;
    182 
    183         DrvAudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMAMapped);
    184         pStream->Dbg.Runtime.pFileDMAMapped = NULL;
     190    if (pStreamR3->Dbg.Runtime.fEnabled)
     191    {
     192        DrvAudioHlpFileDestroy(pStreamR3->Dbg.Runtime.pFileStream);
     193        pStreamR3->Dbg.Runtime.pFileStream = NULL;
     194
     195        DrvAudioHlpFileDestroy(pStreamR3->Dbg.Runtime.pFileDMARaw);
     196        pStreamR3->Dbg.Runtime.pFileDMARaw = NULL;
     197
     198        DrvAudioHlpFileDestroy(pStreamR3->Dbg.Runtime.pFileDMAMapped);
     199        pStreamR3->Dbg.Runtime.pFileDMAMapped = NULL;
    185200    }
    186201
     
    189204
    190205/**
    191  * Initializes an HDA stream.
    192  *
    193  * @returns IPRT status code. VINF_NO_CHANGE if the stream does not need (re-)initialization because the stream's (hardware)
    194  *          parameters did not change.
    195  * @param   pDevIns The device instance.
    196  * @param   pStream HDA stream to initialize.
    197  * @param   uSD     SD (stream descriptor) number to assign the HDA stream to.
    198  */
    199 int hdaR3StreamInit(PPDMDEVINS pDevIns, PHDASTREAM pStream, uint8_t uSD)
    200 {
    201     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    202 
    203     PHDASTATE pThis = pStream->pHDAState;
    204     AssertPtr(pThis);
     206 * Sets up ((re-)iniitalizes) an HDA stream.
     207 *
     208 * @returns IPRT status code. VINF_NO_CHANGE if the stream does not need
     209 *          be set-up again because the stream's (hardware) parameters did
     210 *          not change.
     211 * @param   pDevIns         The device instance.
     212 * @param   pThis           The shared HDA device state (for HW register
     213 *                          parameters).
     214 * @param   pStreamShared   HDA stream to set up, shared portion.
     215 * @param   pStreamR3       HDA stream to set up, ring-3 portion.
     216 * @param   uSD             Stream descriptor number to assign it.
     217 */
     218int hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, uint8_t uSD)
     219{
     220    /* These member can only change on data corruption, despite what the code does further down (bird).  */
     221    Assert(pStreamShared->u8SD == uSD);
     222    Assert(pStreamR3->u8SD     == uSD);
    205223
    206224    const uint64_t u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
     
    232250
    233251    /* Reset (any former) stream map. */
    234     hdaR3StreamMapReset(&pStream->State.Mapping);
     252    hdaR3StreamMapReset(&pStreamR3->State.Mapping);
    235253
    236254    /*
     
    242260     * number of channels in a single audio stream.
    243261     */
    244     rc = hdaR3StreamMapInit(&pStream->State.Mapping, &Props);
     262    rc = hdaR3StreamMapInit(&pStreamR3->State.Mapping, &Props);
    245263    AssertRCReturn(rc, rc);
    246264
    247     ASSERT_GUEST_LOGREL_MSG_RETURN(u32CBL % pStream->State.Mapping.cbFrameSize == 0,
    248                                    ("CBL for stream #%RU8 does not align to frame size\n", pStream->u8SD),
     265    ASSERT_GUEST_LOGREL_MSG_RETURN(   pStreamR3->State.Mapping.cbFrameSize > 0
     266                                   && u32CBL % pStreamR3->State.Mapping.cbFrameSize == 0,
     267                                   ("CBL for stream #%RU8 does not align to frame size (u32CBL=%u cbFrameSize=%u)\n",
     268                                    uSD, u32CBL, pStreamR3->State.Mapping.cbFrameSize),
    249269                                   VERR_INVALID_PARAMETER);
    250270
     
    258278    {
    259279        if (Props.cChannels >= 5)
    260             pStream->State.uTimerHz = 300;
     280            pStreamShared->State.uTimerHz = 300;
    261281        else if (Props.cChannels == 4)
    262             pStream->State.uTimerHz = 150;
     282            pStreamShared->State.uTimerHz = 150;
    263283        else
    264             pStream->State.uTimerHz = 100;
     284            pStreamShared->State.uTimerHz = 100;
    265285    }
    266286    else
    267         pStream->State.uTimerHz = pThis->uTimerHz;
     287        pStreamShared->State.uTimerHz = pThis->uTimerHz;
    268288
    269289#ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
     
    286306     * If not, we can skip a lot of the (re-)initialization and just (re-)use the existing stuff.
    287307     * Also, tell the caller so that further actions can be taken. */
    288     if (   uSD        == pStream->u8SD
    289         && u64BDLBase == pStream->u64BDLBase
    290         && u16LVI     == pStream->u16LVI
    291         && u32CBL     == pStream->u32CBL
    292         && u16FIFOS   == pStream->u16FIFOS
    293         && u16FMT     == pStream->u16FMT)
     308    if (   uSD        == pStreamShared->u8SD   /* paranoia OFC */
     309        && u64BDLBase == pStreamShared->u64BDLBase
     310        && u16LVI     == pStreamShared->u16LVI
     311        && u32CBL     == pStreamShared->u32CBL
     312        && u16FIFOS   == pStreamShared->u16FIFOS
     313        && u16FMT     == pStreamShared->u16FMT)
    294314    {
    295315        LogFunc(("[SD%RU8] No format change, skipping (re-)initialization\n", uSD));
     
    297317    }
    298318
    299     pStream->u8SD       = uSD;
     319    pStreamShared->u8SD       = uSD;
    300320
    301321    /* Update all register copies so that we later know that something has changed. */
    302     pStream->u64BDLBase = u64BDLBase;
    303     pStream->u16LVI     = u16LVI;
    304     pStream->u32CBL     = u32CBL;
    305     pStream->u16FIFOS   = u16FIFOS;
    306     pStream->u16FMT     = u16FMT;
    307 
    308     PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
     322    pStreamShared->u64BDLBase = u64BDLBase;
     323    pStreamShared->u16LVI     = u16LVI;
     324    pStreamShared->u32CBL     = u32CBL;
     325    pStreamShared->u16FIFOS   = u16FIFOS;
     326    pStreamShared->u16FMT     = u16FMT;
     327
     328    PPDMAUDIOSTREAMCFG pCfg = &pStreamShared->State.Cfg;
    309329    pCfg->Props = Props;
    310330
    311331    /* (Re-)Allocate the stream's internal DMA buffer, based on the PCM  properties we just got above. */
    312     if (pStream->State.pCircBuf)
    313     {
    314         RTCircBufDestroy(pStream->State.pCircBuf);
    315         pStream->State.pCircBuf = NULL;
     332    if (pStreamR3->State.pCircBuf)
     333    {
     334        RTCircBufDestroy(pStreamR3->State.pCircBuf);
     335        pStreamR3->State.pCircBuf = NULL;
    316336    }
    317337
    318338    /* By default we allocate an internal buffer of 100ms. */
    319     rc = RTCircBufCreate(&pStream->State.pCircBuf,
     339    rc = RTCircBufCreate(&pStreamR3->State.pCircBuf,
    320340                         DrvAudioHlpMilliToBytes(100 /* ms */, &pCfg->Props)); /** @todo Make this configurable. */
    321341    AssertRCReturn(rc, rc);
    322342
    323343    /* Set the stream's direction. */
    324     pCfg->enmDir = hdaGetDirFromSD(pStream->u8SD);
     344    pCfg->enmDir = hdaGetDirFromSD(uSD);
    325345
    326346    /* The the stream's name, based on the direction. */
     
    348368
    349369    /* Set scheduling hint (if available). */
    350     if (pStream->State.uTimerHz)
    351         pCfg->Device.cMsSchedulingHint = 1000 /* ms */ / pStream->State.uTimerHz;
     370    if (pStreamShared->State.uTimerHz)
     371        pCfg->Device.cMsSchedulingHint = 1000 /* ms */ / pStreamShared->State.uTimerHz;
    352372
    353373    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
    354              pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS));
     374             uSD, pStreamShared->u64BDLBase, pStreamShared->u32CBL, pStreamShared->u16LVI, pStreamShared->u16FIFOS));
    355375
    356376    if (RT_SUCCESS(rc))
    357377    {
    358378        /* Make sure that the chosen Hz rate dividable by the stream's rate. */
    359         if (pStream->State.Cfg.Props.uHz % pStream->State.uTimerHz != 0)
     379        if (pStreamShared->State.Cfg.Props.uHz % pStreamShared->State.uTimerHz != 0)
    360380            LogRel(("HDA: Stream timer Hz rate (%RU32) does not fit to stream #%RU8 timing (%RU32)\n",
    361                     pStream->State.uTimerHz, pStream->u8SD, pStream->State.Cfg.Props.uHz));
     381                    pStreamShared->State.uTimerHz, uSD, pStreamShared->State.Cfg.Props.uHz));
    362382
    363383        /* Figure out how many transfer fragments we're going to use for this stream. */
    364384        /** @todo Use a more dynamic fragment size? */
    365         uint8_t cFragments = pStream->u16LVI + 1;
     385        uint8_t cFragments = pStreamShared->u16LVI + 1;
    366386        if (cFragments <= 1)
    367387            cFragments = 2; /* At least two fragments (BDLEs) must be present. */
     
    373393
    374394        LogFunc(("[SD%RU8] fPosAdjustEnabled=%RTbool, cPosAdjustFrames=%RU16\n",
    375                  pStream->u8SD, pThis->fPosAdjustEnabled, pThis->cPosAdjustFrames));
     395                 uSD, pThis->fPosAdjustEnabled, pThis->cPosAdjustFrames));
    376396
    377397        if (pThis->fPosAdjustEnabled) /* Is the position adjustment enabled at all? */
     
    380400            RT_ZERO(BDLE);
    381401
    382             int rc2 = hdaR3BDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */);
     402            int rc2 = hdaR3BDLEFetch(pDevIns, &BDLE, pStreamShared->u64BDLBase, 0 /* Entry */);
    383403            AssertRC(rc2);
    384404
     
    400420#ifdef VBOX_WITH_INTEL_HDA
    401421                /* Intel ICH / PCH: 1 frame. */
    402                 if (BDLE.Desc.u32BufSize == (uint32_t)(1 * pStream->State.Mapping.cbFrameSize))
     422                if (BDLE.Desc.u32BufSize == (uint32_t)(1 * pStreamR3->State.Mapping.cbFrameSize))
    403423                {
    404424                    cfPosAdjust = 1;
    405425                }
    406426                /* Intel Baytrail / Braswell: 32 frames. */
    407                 else if (BDLE.Desc.u32BufSize == (uint32_t)(32 * pStream->State.Mapping.cbFrameSize))
     427                else if (BDLE.Desc.u32BufSize == (uint32_t)(32 * pStreamR3->State.Mapping.cbFrameSize))
    408428                {
    409429                    cfPosAdjust = 32;
     
    426446                 * position adjustment.
    427447                 */
    428                 if (   (cfPosAdjust * pStream->State.Mapping.cbFrameSize) == BDLE.Desc.u32BufSize
     448                if (   (cfPosAdjust * pStreamR3->State.Mapping.cbFrameSize) == BDLE.Desc.u32BufSize
    429449                    && cFragments)
    430450                {
     
    433453
    434454                /* Initialize position adjustment counter. */
    435                 pStream->State.cfPosAdjustDefault = cfPosAdjust;
    436                 pStream->State.cfPosAdjustLeft    = pStream->State.cfPosAdjustDefault;
     455                pStreamShared->State.cfPosAdjustDefault = cfPosAdjust;
     456                pStreamShared->State.cfPosAdjustLeft    = pStreamShared->State.cfPosAdjustDefault;
    437457
    438458                LogRel2(("HDA: Position adjustment for stream #%RU8 active (%RU32 frames)\n",
    439                          pStream->u8SD, pStream->State.cfPosAdjustDefault));
     459                         uSD, pStreamShared->State.cfPosAdjustDefault));
    440460            }
    441461        }
    442462
    443         LogFunc(("[SD%RU8] cfPosAdjust=%RU32, cFragments=%RU8\n", pStream->u8SD, cfPosAdjust, cFragments));
     463        LogFunc(("[SD%RU8] cfPosAdjust=%RU32, cFragments=%RU8\n", uSD, cfPosAdjust, cFragments));
    444464
    445465        /*
     
    448468
    449469        /* Calculate the fragment size the guest OS expects interrupt delivery at. */
    450         pStream->State.cbTransferSize = pStream->u32CBL / cFragments;
    451         Assert(pStream->State.cbTransferSize);
    452         Assert(pStream->State.cbTransferSize % pStream->State.Mapping.cbFrameSize == 0);
    453         ASSERT_GUEST_LOGREL_MSG_STMT(pStream->State.cbTransferSize,
    454                                      ("Transfer size for stream #%RU8 is invalid\n", pStream->u8SD), rc = VERR_INVALID_PARAMETER);
     470        pStreamShared->State.cbTransferSize = pStreamShared->u32CBL / cFragments;
     471        Assert(pStreamShared->State.cbTransferSize);
     472        Assert(pStreamShared->State.cbTransferSize % pStreamR3->State.Mapping.cbFrameSize == 0);
     473        ASSERT_GUEST_LOGREL_MSG_STMT(pStreamShared->State.cbTransferSize,
     474                                     ("Transfer size for stream #%RU8 is invalid\n", uSD), rc = VERR_INVALID_PARAMETER);
    455475        if (RT_SUCCESS(rc))
    456476        {
    457477            /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration.
    458478             * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */
    459             pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pStream->State.uTimerHz) * pStream->State.Mapping.cbFrameSize;
    460             Assert(pStream->State.cbTransferChunk);
    461             Assert(pStream->State.cbTransferChunk % pStream->State.Mapping.cbFrameSize == 0);
    462             ASSERT_GUEST_LOGREL_MSG_STMT(pStream->State.cbTransferChunk,
    463                                          ("Transfer chunk for stream #%RU8 is invalid\n", pStream->u8SD),
     479            pStreamShared->State.cbTransferChunk = (pStreamShared->State.Cfg.Props.uHz / pStreamShared->State.uTimerHz) * pStreamR3->State.Mapping.cbFrameSize;
     480            Assert(pStreamShared->State.cbTransferChunk);
     481            Assert(pStreamShared->State.cbTransferChunk % pStreamR3->State.Mapping.cbFrameSize == 0);
     482            ASSERT_GUEST_LOGREL_MSG_STMT(pStreamShared->State.cbTransferChunk,
     483                                         ("Transfer chunk for stream #%RU8 is invalid\n", uSD),
    464484                                         rc = VERR_INVALID_PARAMETER);
    465485            if (RT_SUCCESS(rc))
    466486            {
    467487                /* Make sure that the transfer chunk does not exceed the overall transfer size. */
    468                 if (pStream->State.cbTransferChunk > pStream->State.cbTransferSize)
    469                     pStream->State.cbTransferChunk = pStream->State.cbTransferSize;
    470 
    471                 const uint64_t cTicksPerHz = PDMDevHlpTimerGetFreq(pDevIns, pStream->hTimer) / pStream->State.uTimerHz;
     488                if (pStreamShared->State.cbTransferChunk > pStreamShared->State.cbTransferSize)
     489                    pStreamShared->State.cbTransferChunk = pStreamShared->State.cbTransferSize;
     490
     491                const uint64_t cTicksPerHz = PDMDevHlpTimerGetFreq(pDevIns, pStreamShared->hTimer) / pStreamShared->State.uTimerHz;
    472492
    473493                /* Calculate the timer ticks per byte for this stream. */
    474                 pStream->State.cTicksPerByte = cTicksPerHz / pStream->State.cbTransferChunk;
    475                 Assert(pStream->State.cTicksPerByte);
     494                pStreamShared->State.cTicksPerByte = cTicksPerHz / pStreamShared->State.cbTransferChunk;
     495                Assert(pStreamShared->State.cTicksPerByte);
    476496
    477497                /* Calculate timer ticks per transfer. */
    478                 pStream->State.cTransferTicks = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
    479                 Assert(pStream->State.cTransferTicks);
     498                pStreamShared->State.cTransferTicks = pStreamShared->State.cbTransferChunk * pStreamShared->State.cTicksPerByte;
     499                Assert(pStreamShared->State.cTransferTicks);
    480500
    481501                LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, " \
    482502                         "cTransferTicks=%RU64, cbTransferSize=%RU32\n",
    483                          pStream->u8SD, pStream->State.uTimerHz, cTicksPerHz, pStream->State.cTicksPerByte,
    484                          pStream->State.cbTransferChunk, pStream->State.cTransferTicks, pStream->State.cbTransferSize));
     503                         uSD, pStreamShared->State.uTimerHz, cTicksPerHz, pStreamShared->State.cTicksPerByte,
     504                         pStreamShared->State.cbTransferChunk, pStreamShared->State.cTransferTicks, pStreamShared->State.cbTransferSize));
    485505
    486506                /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
    487                 hdaR3StreamSetPosition(pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
     507                hdaR3StreamSetPosition(pStreamShared, pDevIns, pThis, HDA_STREAM_REG(pThis, LPIB, uSD));
    488508
    489509#ifdef LOG_ENABLED
    490                 hdaR3BDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
     510                hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
    491511#endif
    492512            }
     
    495515
    496516    if (RT_FAILURE(rc))
    497         LogRel(("HDA: Initializing stream #%RU8 failed with %Rrc\n", pStream->u8SD, rc));
     517        LogRel(("HDA: Initializing stream #%RU8 failed with %Rrc\n", uSD, rc));
    498518
    499519    return rc;
     
    503523 * Resets an HDA stream.
    504524 *
    505  * @param   pThis               HDA state.
    506  * @param   pStream             HDA stream to reset.
     525 * @param   pThis               The shared HDA device state.
     526 * @param   pThisCC             The ring-3 HDA device state.
     527 * @param   pStreamShared       HDA stream to reset (shared).
     528 * @param   pStreamR3           HDA stream to reset (ring-3).
    507529 * @param   uSD                 Stream descriptor (SD) number to use for this stream.
    508530 */
    509 void hdaR3StreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
    510 {
    511     AssertPtrReturnVoid(pThis);
    512     AssertPtrReturnVoid(pStream);
    513     AssertReturnVoid(uSD < HDA_MAX_STREAMS);
    514 
    515 # ifdef VBOX_STRICT
    516     AssertReleaseMsg(!pStream->State.fRunning, ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
    517 # endif
     531void hdaR3StreamReset(PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, uint8_t uSD)
     532{
     533    AssertPtr(pThis);
     534    AssertPtr(pStreamShared);
     535    AssertPtr(pStreamR3);
     536    Assert(uSD < HDA_MAX_STREAMS);
     537    AssertMsg(!pStreamShared->State.fRunning, ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
    518538
    519539    LogFunc(("[SD%RU8] Reset\n", uSD));
     
    522542     * Set reset state.
    523543     */
    524     Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
    525     ASMAtomicXchgBool(&pStream->State.fInReset, true);
     544    Assert(ASMAtomicReadBool(&pStreamShared->State.fInReset) == false); /* No nested calls. */
     545    ASMAtomicXchgBool(&pStreamShared->State.fInReset, true);
    526546
    527547    /*
     
    548568
    549569    /* Assign the default mixer sink to the stream. */
    550     pStream->pMixSink = hdaR3GetDefaultSink(pThis, uSD);
     570    pStreamR3->pMixSink = hdaR3GetDefaultSink(pThisCC, uSD);
    551571
    552572    /* Reset position adjustment counter. */
    553     pStream->State.cfPosAdjustLeft = pStream->State.cfPosAdjustDefault;
     573    pStreamShared->State.cfPosAdjustLeft = pStreamShared->State.cfPosAdjustDefault;
    554574
    555575    /* Reset transfer stuff. */
    556     pStream->State.cbTransferProcessed        = 0;
    557     pStream->State.cTransferPendingInterrupts = 0;
    558     pStream->State.tsTransferLast = 0;
    559     pStream->State.tsTransferNext = 0;
     576    pStreamShared->State.cbTransferProcessed        = 0;
     577    pStreamShared->State.cTransferPendingInterrupts = 0;
     578    pStreamShared->State.tsTransferLast = 0;
     579    pStreamShared->State.tsTransferNext = 0;
    560580
    561581    /* Initialize other timestamps. */
    562     pStream->State.tsLastUpdateNs = 0;
    563 
    564     RT_ZERO(pStream->State.BDLE);
    565     pStream->State.uCurBDLE = 0;
    566 
    567     if (pStream->State.pCircBuf)
    568         RTCircBufReset(pStream->State.pCircBuf);
     582    pStreamShared->State.tsLastUpdateNs = 0;
     583
     584    RT_ZERO(pStreamShared->State.BDLE);
     585    pStreamShared->State.uCurBDLE = 0;
     586
     587    if (pStreamR3->State.pCircBuf)
     588        RTCircBufReset(pStreamR3->State.pCircBuf);
    569589
    570590    /* Reset the stream's period. */
    571     hdaR3StreamPeriodReset(&pStream->State.Period);
     591    hdaR3StreamPeriodReset(&pStreamShared->State.Period);
    572592
    573593#ifdef DEBUG
    574     pStream->Dbg.cReadsTotal      = 0;
    575     pStream->Dbg.cbReadTotal      = 0;
    576     pStream->Dbg.tsLastReadNs     = 0;
    577     pStream->Dbg.cWritesTotal     = 0;
    578     pStream->Dbg.cbWrittenTotal   = 0;
    579     pStream->Dbg.cWritesHz        = 0;
    580     pStream->Dbg.cbWrittenHz      = 0;
    581     pStream->Dbg.tsWriteSlotBegin = 0;
     594    pStreamR3->Dbg.cReadsTotal      = 0;
     595    pStreamR3->Dbg.cbReadTotal      = 0;
     596    pStreamR3->Dbg.tsLastReadNs     = 0;
     597    pStreamR3->Dbg.cWritesTotal     = 0;
     598    pStreamR3->Dbg.cbWrittenTotal   = 0;
     599    pStreamR3->Dbg.cWritesHz        = 0;
     600    pStreamR3->Dbg.cbWrittenHz      = 0;
     601    pStreamR3->Dbg.tsWriteSlotBegin = 0;
    582602#endif
    583603
     
    588608
    589609    /* Exit reset mode. */
    590     ASMAtomicXchgBool(&pStream->State.fInReset, false);
     610    ASMAtomicXchgBool(&pStreamShared->State.fInReset, false);
    591611}
    592612
     
    595615 *
    596616 * @returns IPRT status code.
    597  * @param   pStream             HDA stream to enable or disable.
     617 * @param   pStreamShared       HDA stream to enable or disable - shared bits.
     618 * @param   pStreamR3           HDA stream to enable or disable - ring-3 bits.
    598619 * @param   fEnable             Whether to enable or disble the stream.
    599620 */
    600 int hdaR3StreamEnable(PHDASTREAM pStream, bool fEnable)
    601 {
    602     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    603 
    604     LogFunc(("[SD%RU8] fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
     621int hdaR3StreamEnable(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fEnable)
     622{
     623    AssertPtr(pStreamR3);
     624    AssertPtr(pStreamShared);
     625
     626    LogFunc(("[SD%RU8] fEnable=%RTbool, pMixSink=%p\n", pStreamShared->u8SD, fEnable, pStreamR3->pMixSink));
    605627
    606628    int rc = VINF_SUCCESS;
     
    610632
    611633    /* First, enable or disable the stream and the stream's sink, if any. */
    612     if (   pStream->pMixSink
    613         && pStream->pMixSink->pMixSink)
    614         rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
     634    if (   pStreamR3->pMixSink
     635        && pStreamR3->pMixSink->pMixSink)
     636        rc = AudioMixerSinkCtl(pStreamR3->pMixSink->pMixSink, enmCmd);
    615637
    616638    if (   RT_SUCCESS(rc)
    617639        && fEnable
    618         && pStream->Dbg.Runtime.fEnabled)
    619     {
    620         Assert(DrvAudioHlpPCMPropsAreValid(&pStream->State.Cfg.Props));
     640        && pStreamR3->Dbg.Runtime.fEnabled)
     641    {
     642        Assert(DrvAudioHlpPCMPropsAreValid(&pStreamShared->State.Cfg.Props));
    621643
    622644        if (fEnable)
    623645        {
    624             if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileStream))
    625             {
    626                 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileStream, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    627                                               &pStream->State.Cfg.Props);
     646            if (!DrvAudioHlpFileIsOpen(pStreamR3->Dbg.Runtime.pFileStream))
     647            {
     648                int rc2 = DrvAudioHlpFileOpen(pStreamR3->Dbg.Runtime.pFileStream, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     649                                              &pStreamShared->State.Cfg.Props);
    628650                AssertRC(rc2);
    629651            }
    630652
    631             if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMARaw))
    632             {
    633                 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMARaw, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    634                                               &pStream->State.Cfg.Props);
     653            if (!DrvAudioHlpFileIsOpen(pStreamR3->Dbg.Runtime.pFileDMARaw))
     654            {
     655                int rc2 = DrvAudioHlpFileOpen(pStreamR3->Dbg.Runtime.pFileDMARaw, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     656                                              &pStreamShared->State.Cfg.Props);
    635657                AssertRC(rc2);
    636658            }
    637659
    638             if (!DrvAudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMAMapped))
    639             {
    640                 int rc2 = DrvAudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMAMapped, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    641                                               &pStream->State.Cfg.Props);
     660            if (!DrvAudioHlpFileIsOpen(pStreamR3->Dbg.Runtime.pFileDMAMapped))
     661            {
     662                int rc2 = DrvAudioHlpFileOpen(pStreamR3->Dbg.Runtime.pFileDMAMapped, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     663                                              &pStreamShared->State.Cfg.Props);
    642664                AssertRC(rc2);
    643665            }
     
    647669    if (RT_SUCCESS(rc))
    648670    {
    649         pStream->State.fRunning = fEnable;
    650     }
    651 
    652     LogFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8SD, rc));
     671        pStreamShared->State.fRunning = fEnable;
     672    }
     673
     674    LogFunc(("[SD%RU8] rc=%Rrc\n", pStreamShared->u8SD, rc));
    653675    return rc;
    654676}
    655677
    656 uint32_t hdaR3StreamGetPosition(PHDASTATE pThis, PHDASTREAM pStream)
    657 {
    658     return HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    659 }
    660 
    661 /**
     678static uint32_t hdaR3StreamGetPosition(PHDASTATE pThis, PHDASTREAM pStreamShared)
     679{
     680    return HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD);
     681}
     682
     683/*
    662684 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
    663685 * updating its associated LPIB register and DMA position buffer (if enabled).
    664686 *
    665  * @param   pStream             HDA stream to update read / write position for.
     687 * @param   pStreamShared       HDA stream to update read / write position for (shared).
     688 * @param   pDevIns             The device instance.
     689 * @param   pThis               The shared HDA device state.
    666690 * @param   u32LPIB             Absolute position (in bytes) to set current read / write position to.
    667691 */
    668 void hdaR3StreamSetPosition(PHDASTREAM pStream, uint32_t u32LPIB)
    669 {
    670     AssertPtrReturnVoid(pStream);
    671 
    672     Log3Func(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    673               pStream->u8SD, u32LPIB, pStream->pHDAState->fDMAPosition));
     692static void hdaR3StreamSetPosition(PHDASTREAM pStreamShared, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t u32LPIB)
     693{
     694    AssertPtrReturnVoid(pStreamShared);
     695
     696    Log3Func(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",  pStreamShared->u8SD, u32LPIB, pThis->fDMAPosition));
    674697
    675698    /* Update LPIB in any case. */
    676     HDA_STREAM_REG(pStream->pHDAState, LPIB, pStream->u8SD) = u32LPIB;
     699    HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD) = u32LPIB;
    677700
    678701    /* Do we need to tell the current DMA position? */
    679     if (pStream->pHDAState->fDMAPosition)
    680     {
    681         int rc2 = PDMDevHlpPCIPhysWrite(pStream->pHDAState->CTX_SUFF(pDevIns),
    682                                         pStream->pHDAState->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
     702    if (pThis->fDMAPosition)
     703    {
     704        int rc2 = PDMDevHlpPCIPhysWrite(pDevIns,
     705                                        pThis->u64DPBase + (pStreamShared->u8SD * 2 * sizeof(uint32_t)),
    683706                                        (void *)&u32LPIB, sizeof(uint32_t));
    684707        AssertRC(rc2);
     
    690713 *
    691714 * @returns Available data (in bytes).
    692  * @param   pStream             HDA stream to retrieve size for.
    693  */
    694 uint32_t hdaR3StreamGetUsed(PHDASTREAM pStream)
    695 {
    696     AssertPtrReturn(pStream, 0);
    697 
    698     if (!pStream->State.pCircBuf)
    699         return 0;
    700 
    701     return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
     715 * @param   pStreamR3           HDA stream to retrieve size for (ring-3).
     716 */
     717static uint32_t hdaR3StreamGetUsed(PHDASTREAMR3 pStreamR3)
     718{
     719    AssertPtrReturn(pStreamR3, 0);
     720
     721    if (pStreamR3->State.pCircBuf)
     722        return (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf);
     723    return 0;
    702724}
    703725
     
    706728 *
    707729 * @returns Free data (in bytes).
    708  * @param   pStream             HDA stream to retrieve size for.
    709  */
    710 uint32_t hdaR3StreamGetFree(PHDASTREAM pStream)
    711 {
    712     AssertPtrReturn(pStream, 0);
    713 
    714     if (!pStream->State.pCircBuf)
    715         return 0;
    716 
    717     return (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
     730 * @param   pStreamR3           HDA stream to retrieve size for (ring-3).
     731 */
     732static uint32_t hdaR3StreamGetFree(PHDASTREAMR3 pStreamR3)
     733{
     734    AssertPtrReturn(pStreamR3, 0);
     735
     736    if (pStreamR3->State.pCircBuf)
     737        return (uint32_t)RTCircBufFree(pStreamR3->State.pCircBuf);
     738    return 0;
    718739}
    719740
     
    725746 *
    726747 * @returns True if a next transfer is scheduled, false if not.
    727  * @param   pStream             HDA stream to retrieve schedule status for.
     748 * @param   pStreamShared       HDA stream to retrieve schedule status for (shared).
    728749 * @param   tsNow               The current time.
    729750 */
    730 bool hdaR3StreamTransferIsScheduled(PHDASTREAM pStream, uint64_t tsNow)
    731 {
    732     if (pStream)
    733     {
    734         AssertPtrReturn(pStream->pHDAState, false);
    735 
    736         if (pStream->State.fRunning)
    737         {
    738             if (pStream->State.cTransferPendingInterrupts)
    739             {
    740                 Log3Func(("[SD%RU8] Scheduled (%RU8 IRQs pending)\n", pStream->u8SD, pStream->State.cTransferPendingInterrupts));
     751bool hdaR3StreamTransferIsScheduled(PHDASTREAM pStreamShared, uint64_t tsNow)
     752{
     753    if (pStreamShared)
     754    {
     755        if (pStreamShared->State.fRunning)
     756        {
     757            if (pStreamShared->State.cTransferPendingInterrupts)
     758            {
     759                Log3Func(("[SD%RU8] Scheduled (%RU8 IRQs pending)\n", pStreamShared->u8SD, pStreamShared->State.cTransferPendingInterrupts));
    741760                return true;
    742761            }
    743762
    744             if (pStream->State.tsTransferNext > tsNow)
    745             {
    746                 Log3Func(("[SD%RU8] Scheduled in %RU64\n", pStream->u8SD, pStream->State.tsTransferNext - tsNow));
     763            if (pStreamShared->State.tsTransferNext > tsNow)
     764            {
     765                Log3Func(("[SD%RU8] Scheduled in %RU64\n", pStreamShared->u8SD, pStreamShared->State.tsTransferNext - tsNow));
    747766                return true;
    748767            }
     
    757776 *
    758777 * @returns The (virtual) clock timestamp of the next transfer.
    759  * @param   pStream             HDA stream to retrieve timestamp for.
    760  */
    761 uint64_t hdaR3StreamTransferGetNext(PHDASTREAM pStream)
    762 {
    763     return pStream->State.tsTransferNext;
     778 * @param   pStreamShared       HDA stream to retrieve timestamp for (shared).
     779 */
     780uint64_t hdaR3StreamTransferGetNext(PHDASTREAM pStreamShared)
     781{
     782    return pStreamShared->State.tsTransferNext;
    764783}
    765784
     
    768787 *
    769788 * @returns IPRT status code.
    770  * @param   pStream             HDA stream to write to.
     789 * @param   pStreamR3           HDA stream to write to (ring-3).
    771790 * @param   pvBuf               Data buffer to write.
    772791 *                              If NULL, silence will be written.
     
    774793 * @param   pcbWritten          Number of bytes written. Optional.
    775794 */
    776 int hdaR3StreamWrite(PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    777 {
    778     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    779     /* pvBuf is optional. */
    780     AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
    781     /* pcbWritten is optional. */
    782 
    783     PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
     795static int hdaR3StreamWrite(PHDASTREAMR3 pStreamR3, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     796{
     797    Assert(cbBuf);
     798
     799    PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
    784800    AssertPtr(pCircBuf);
    785 
    786     int rc = VINF_SUCCESS;
    787801
    788802    uint32_t cbWrittenTotal = 0;
     
    793807        void *pvDst;
    794808        size_t cbDst;
    795 
    796809        RTCircBufAcquireWriteBlock(pCircBuf, cbLeft, &pvDst, &cbDst);
    797810
     
    799812        {
    800813            if (pvBuf)
    801             {
    802814                memcpy(pvDst, (uint8_t *)pvBuf + cbWrittenTotal, cbDst);
    803             }
    804815            else /* Send silence. */
    805816            {
     
    809820            }
    810821
    811             if (pStream->Dbg.Runtime.fEnabled)
    812                 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileStream, pvDst, cbDst, 0 /* fFlags */);
     822            if (RT_LIKELY(!pStreamR3->Dbg.Runtime.fEnabled))
     823            { /* likely */ }
     824            else
     825                DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileStream, pvDst, cbDst, 0 /* fFlags */);
    813826        }
    814827
    815828        RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
    816 
    817         if (RT_FAILURE(rc))
    818             break;
    819829
    820830        Assert(cbLeft  >= (uint32_t)cbDst);
    821831        cbLeft         -= (uint32_t)cbDst;
    822 
    823832        cbWrittenTotal += (uint32_t)cbDst;
    824833    }
     
    829838        *pcbWritten = cbWrittenTotal;
    830839
    831     return rc;
     840    return VINF_SUCCESS;
    832841}
    833842
     
    837846 *
    838847 * @returns IPRT status code.
    839  * @param   pStream             HDA stream to read audio data from.
     848 * @param   pStreamR3           HDA stream to read audio data from (ring-3).
    840849 * @param   cbToRead            Number of bytes to read.
    841850 * @param   pcbRead             Number of bytes read. Optional.
    842851 */
    843 int hdaR3StreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
    844 {
    845     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    846     AssertReturn(cbToRead,   VERR_INVALID_PARAMETER);
    847     /* pcbWritten is optional. */
    848 
    849     PHDAMIXERSINK pSink = pStream->pMixSink;
    850     if (!pSink)
    851     {
    852         AssertMsgFailed(("[SD%RU8] Can't read from a stream with no sink attached\n", pStream->u8SD));
    853 
    854         if (pcbRead)
    855             *pcbRead = 0;
    856         return VINF_SUCCESS;
    857     }
    858 
    859     PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
     852static int hdaR3StreamRead(PHDASTREAMR3 pStreamR3, uint32_t cbToRead, uint32_t *pcbRead)
     853{
     854    Assert(cbToRead);
     855
     856    PHDAMIXERSINK pSink = pStreamR3->pMixSink;
     857    AssertMsgReturnStmt(pSink, ("[SD%RU8] Can't read from a stream with no sink attached\n", pStreamR3->u8SD),
     858                        if (pcbRead) *pcbRead = 0,
     859                        VINF_SUCCESS);
     860
     861    PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
    860862    AssertPtr(pCircBuf);
    861863
     
    876878        if (cbSrc)
    877879        {
    878             if (pStream->Dbg.Runtime.fEnabled)
    879                 DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileStream, pvSrc, cbSrc, 0 /* fFlags */);
     880            if (pStreamR3->Dbg.Runtime.fEnabled)
     881                DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileStream, pvSrc, cbSrc, 0 /* fFlags */);
    880882
    881883            rc = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);
     
    883885
    884886            Assert(cbSrc >= cbWritten);
    885             Log2Func(("[SD%RU8] %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
     887            Log2Func(("[SD%RU8] %RU32/%zu bytes read\n", pStreamR3->u8SD, cbWritten, cbSrc));
    886888        }
    887889
     
    915917 * @returns IPRT status code.
    916918 * @param   pDevIns             The device instance.
    917  * @param   pStream             HDA stream to update.
     919 * @param   pThis               The shared HDA device state.
     920 * @param   pThisCC             The ring-3 HDA device state.
     921 * @param   pStreamShared       HDA stream to update (shared).
     922 * @param   pStreamR3           HDA stream to update (ring-3).
    918923 * @param   cbToProcessMax      How much data (in bytes) to process as maximum.
    919924 * @param   fInTimer            Set if we're in the timer callout.
    920925 */
    921 static int hdaR3StreamTransfer(PPDMDEVINS pDevIns, PHDASTREAM pStream, uint32_t cbToProcessMax, bool fInTimer)
    922 {
    923     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    924 
    925     hdaR3StreamLock(pStream);
    926 
    927     PHDASTATE pThis = pStream->pHDAState;
    928     AssertPtr(pThis);
    929 
    930     PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
     926static int hdaR3StreamTransfer(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared,
     927                               PHDASTREAMR3 pStreamR3, uint32_t cbToProcessMax, bool fInTimer)
     928{
     929    uint8_t const uSD = pStreamShared->u8SD;
     930    hdaR3StreamLock(pStreamR3);
     931
     932    PHDASTREAMPERIOD pPeriod = &pStreamShared->State.Period;
    931933    hdaR3StreamPeriodLock(pPeriod);
    932934
     
    934936
    935937    /* Stream not running? */
    936     if (!pStream->State.fRunning)
    937     {
    938         Log3Func(("[SD%RU8] Not running\n", pStream->u8SD));
     938    if (!pStreamShared->State.fRunning)
     939    {
     940        Log3Func(("[SD%RU8] Not running\n", uSD));
    939941        fProceed = false;
    940942    }
    941     else if (HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_SDSTS_BCIS)
    942     {
    943         Log3Func(("[SD%RU8] BCIS bit set\n", pStream->u8SD));
     943    else if (HDA_STREAM_REG(pThis, STS, uSD) & HDA_SDSTS_BCIS)
     944    {
     945        Log3Func(("[SD%RU8] BCIS bit set\n", uSD));
    944946        fProceed = false;
    945947    }
     
    948950    {
    949951        hdaR3StreamPeriodUnlock(pPeriod);
    950         hdaR3StreamUnlock(pStream);
     952        hdaR3StreamUnlock(pStreamR3);
    951953        return VINF_SUCCESS;
    952954    }
    953955
    954     const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pStream->hTimer);
    955 
    956     if (!pStream->State.tsTransferLast)
    957         pStream->State.tsTransferLast = tsNow;
     956    const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
     957
     958    if (!pStreamShared->State.tsTransferLast)
     959        pStreamShared->State.tsTransferLast = tsNow;
    958960
    959961#ifdef DEBUG
    960     const int64_t iTimerDelta = tsNow - pStream->State.tsTransferLast;
     962    const int64_t iTimerDelta = tsNow - pStreamShared->State.tsTransferLast;
    961963    Log3Func(("[SD%RU8] Time now=%RU64, last=%RU64 -> %RI64 ticks delta\n",
    962               pStream->u8SD, tsNow, pStream->State.tsTransferLast, iTimerDelta));
     964              uSD, tsNow, pStreamShared->State.tsTransferLast, iTimerDelta));
    963965#endif
    964966
    965     pStream->State.tsTransferLast = tsNow;
     967    pStreamShared->State.tsTransferLast = tsNow;
    966968
    967969    /* Sanity checks. */
    968     Assert(pStream->u8SD < HDA_MAX_STREAMS);
    969     Assert(pStream->u64BDLBase);
    970     Assert(pStream->u32CBL);
    971     Assert(pStream->u16FIFOS);
     970    Assert(uSD < HDA_MAX_STREAMS);
     971    Assert(pStreamShared->u64BDLBase);
     972    Assert(pStreamShared->u32CBL);
     973    Assert(pStreamShared->u16FIFOS);
    972974
    973975    /* State sanity checks. */
    974     Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false);
     976    Assert(ASMAtomicReadBool(&pStreamShared->State.fInReset) == false);
    975977
    976978    int rc = VINF_SUCCESS;
    977979
    978980    /* Fetch first / next BDL entry. */
    979     PHDABDLE pBDLE = &pStream->State.BDLE;
     981    PHDABDLE pBDLE = &pStreamShared->State.BDLE;
    980982    if (hdaR3BDLEIsComplete(pBDLE))
    981983    {
    982         rc = hdaR3BDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
     984        rc = hdaR3BDLEFetch(pDevIns, pBDLE, pStreamShared->u64BDLBase, pStreamShared->State.uCurBDLE);
    983985        AssertRC(rc);
    984986    }
    985987
    986     uint32_t cbToProcess = RT_MIN(pStream->State.cbTransferSize - pStream->State.cbTransferProcessed,
    987                                   pStream->State.cbTransferChunk);
    988 
    989     Log3Func(("[SD%RU8] cbToProcess=%RU32, cbToProcessMax=%RU32\n", pStream->u8SD, cbToProcess, cbToProcessMax));
     988    uint32_t cbToProcess = RT_MIN(pStreamShared->State.cbTransferSize - pStreamShared->State.cbTransferProcessed,
     989                                  pStreamShared->State.cbTransferChunk);
     990
     991    Log3Func(("[SD%RU8] cbToProcess=%RU32, cbToProcessMax=%RU32\n", uSD, cbToProcess, cbToProcessMax));
    990992
    991993    if (cbToProcess > cbToProcessMax)
    992994    {
    993         LogFunc(("[SD%RU8] Limiting transfer (cbToProcess=%RU32, cbToProcessMax=%RU32)\n",
    994                  pStream->u8SD, cbToProcess, cbToProcessMax));
     995        LogFunc(("[SD%RU8] Limiting transfer (cbToProcess=%RU32, cbToProcessMax=%RU32)\n", uSD, cbToProcess, cbToProcessMax));
    995996
    996997        /* Never process more than a stream currently can handle. */
     
    10051006    {
    10061007        /* Limit the chunk to the stream's FIFO size and what's left to process. */
    1007         uint32_t cbChunk = RT_MIN(cbLeft, pStream->u16FIFOS);
     1008        uint32_t cbChunk = RT_MIN(cbLeft, pStreamShared->u16FIFOS);
    10081009
    10091010        /* Limit the chunk to the remaining data of the current BDLE. */
     
    10121013        /* If there are position adjustment frames left to be processed,
    10131014         * make sure that we process them first as a whole. */
    1014         if (pStream->State.cfPosAdjustLeft)
    1015             cbChunk = RT_MIN(cbChunk, uint32_t(pStream->State.cfPosAdjustLeft * pStream->State.Mapping.cbFrameSize));
     1015        if (pStreamShared->State.cfPosAdjustLeft)
     1016            cbChunk = RT_MIN(cbChunk, uint32_t(pStreamShared->State.cfPosAdjustLeft * pStreamR3->State.Mapping.cbFrameSize));
    10161017
    10171018        Log3Func(("[SD%RU8] cbChunk=%RU32, cPosAdjustFramesLeft=%RU16\n",
    1018                   pStream->u8SD, cbChunk, pStream->State.cfPosAdjustLeft));
     1019                  uSD, cbChunk, pStreamShared->State.cfPosAdjustLeft));
    10191020
    10201021        if (!cbChunk)
     
    10221023
    10231024        uint32_t   cbDMA    = 0;
    1024         PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
    1025 
    1026         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */
     1025        PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
     1026
     1027        if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN) /* Input (SDI). */
    10271028        {
    10281029            STAM_PROFILE_START(&pThis->StatIn, a);
     
    10541055            if (cbDMAToWrite)
    10551056            {
    1056                 LogRel2(("HDA: FIFO underflow for stream #%RU8 (%RU32 bytes outstanding)\n", pStream->u8SD, cbDMAToWrite));
     1057                LogRel2(("HDA: FIFO underflow for stream #%RU8 (%RU32 bytes outstanding)\n", uSD, cbDMAToWrite));
    10571058
    10581059                Assert(cbChunk == cbDMAWritten + cbDMAToWrite);
     
    10611062            }
    10621063
    1063             rc = hdaR3DMAWrite(pThis, pStream, abChunk, cbDMAWritten, &cbDMA /* pcbWritten */);
     1064            rc = hdaR3DMAWrite(pDevIns, pThis, pStreamShared, pStreamR3, abChunk, cbDMAWritten, &cbDMA /* pcbWritten */);
    10641065            if (RT_FAILURE(rc))
    1065                 LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
     1066                LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", uSD, rc));
    10661067
    10671068            STAM_PROFILE_STOP(&pThis->StatIn, a);
    10681069        }
    1069         else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
     1070        else if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    10701071        {
    10711072            STAM_PROFILE_START(&pThis->StatOut, a);
    10721073
    1073             rc = hdaR3DMARead(pThis, pStream, abChunk, cbChunk, &cbDMA /* pcbRead */);
     1074            rc = hdaR3DMARead(pDevIns, pThis, pStreamShared, pStreamR3, abChunk, cbChunk, &cbDMA /* pcbRead */);
    10741075            if (RT_SUCCESS(rc))
    10751076            {
     
    10831084                 * Only macOS guests need the frame extraction branch below at the moment AFAIK.
    10841085                 */
    1085                 if (pStream->State.Mapping.cbFrameSize == HDA_FRAME_SIZE_DEFAULT)
     1086                if (pStreamR3->State.Mapping.cbFrameSize == HDA_FRAME_SIZE_DEFAULT)
    10861087                {
    10871088                    uint32_t cbDMARead = 0;
     
    11191120                     */
    11201121                    /** @todo Optimize channel data extraction! Use some SSE(3) / intrinsics? */
    1121                     for (unsigned m = 0; m < pStream->State.Mapping.cMappings; m++)
     1122                    for (unsigned m = 0; m < pStreamR3->State.Mapping.cMappings; m++)
    11221123                    {
    1123                         const uint32_t cbFrame  = pStream->State.Mapping.cbFrameSize;
     1124                        const uint32_t cbFrame  = pStreamR3->State.Mapping.cbFrameSize;
    11241125
    11251126                        Assert(cbFree >= cbDMA);
    11261127
    1127                         PPDMAUDIOSTREAMMAP pMap = &pStream->State.Mapping.paMappings[m];
     1128                        PPDMAUDIOSTREAMMAP pMap = &pStreamR3->State.Mapping.paMappings[m];
    11281129                        AssertPtr(pMap);
    11291130
     
    11501151
    11511152#if 0 /* Too slow, even for release builds, so disabled it. */
    1152                                 if (pStream->Dbg.Runtime.fEnabled)
    1153                                     DrvAudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMAMapped, pvDstBuf, cbDstBuf,
     1153                                if (pStreamR3->Dbg.Runtime.fEnabled)
     1154                                    DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMAMapped, pvDstBuf, cbDstBuf,
    11541155                                                         0 /* fFlags */);
    11551156#endif
     
    12001201            }
    12011202            else
    1202                 LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
     1203                LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", uSD, rc));
    12031204
    12041205            STAM_PROFILE_STOP(&pThis->StatOut, a);
     
    12171218            /* Are we done doing the position adjustment?
    12181219             * Only then do the transfer accounting .*/
    1219             if (pStream->State.cfPosAdjustLeft == 0)
     1220            if (pStreamShared->State.cfPosAdjustLeft == 0)
    12201221            {
    12211222                Assert(cbLeft >= cbDMA);
     
    12301231             * All guetsts rely on this, depending on the mechanism they use (LPIB register or DMA counters).
    12311232             */
    1232             uint32_t cbStreamPos = hdaR3StreamGetPosition(pThis, pStream);
    1233             if (cbStreamPos == pStream->u32CBL)
     1233            uint32_t cbStreamPos = hdaR3StreamGetPosition(pThis, pStreamShared);
     1234            if (cbStreamPos == pStreamShared->u32CBL)
    12341235                cbStreamPos = 0;
    12351236
    1236             hdaR3StreamSetPosition(pStream, cbStreamPos + cbDMA);
     1237            hdaR3StreamSetPosition(pStreamShared, pDevIns, pThis, cbStreamPos + cbDMA);
    12371238        }
    12381239
    12391240        if (hdaR3BDLEIsComplete(pBDLE))
    12401241        {
    1241             Log3Func(("[SD%RU8] Complete: %R[bdle]\n", pStream->u8SD, pBDLE));
     1242            Log3Func(("[SD%RU8] Complete: %R[bdle]\n", uSD, pBDLE));
    12421243
    12431244                /* Does the current BDLE require an interrupt to be sent? */
     
    12481249                 *
    12491250                 * In such a case we need to skip such an interrupt and just move on. */
    1250                 && pStream->State.cfPosAdjustLeft == 0)
     1251                && pStreamShared->State.cfPosAdjustLeft == 0)
    12511252            {
    12521253                /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set
    12531254                 * we need to generate an interrupt.
    12541255                 */
    1255                 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_IOCE)
     1256                if (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_IOCE)
    12561257                {
    1257                     pStream->State.cTransferPendingInterrupts++;
    1258 
    1259                     AssertMsg(pStream->State.cTransferPendingInterrupts <= 32,
     1258                    pStreamShared->State.cTransferPendingInterrupts++;
     1259
     1260                    AssertMsg(pStreamShared->State.cTransferPendingInterrupts <= 32,
    12601261                              ("Too many pending interrupts (%RU8) for stream #%RU8\n",
    1261                                pStream->State.cTransferPendingInterrupts, pStream->u8SD));
     1262                               pStreamShared->State.cTransferPendingInterrupts, uSD));
    12621263                }
    12631264            }
    12641265
    1265             if (pStream->State.uCurBDLE == pStream->u16LVI)
    1266             {
    1267                 pStream->State.uCurBDLE = 0;
     1266            if (pStreamShared->State.uCurBDLE == pStreamShared->u16LVI)
     1267            {
     1268                pStreamShared->State.uCurBDLE = 0;
    12681269            }
    12691270            else
    1270                 pStream->State.uCurBDLE++;
     1271                pStreamShared->State.uCurBDLE++;
    12711272
    12721273            /* Fetch the next BDLE entry. */
    1273             hdaR3BDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
     1274            hdaR3BDLEFetch(pDevIns, pBDLE, pStreamShared->u64BDLBase, pStreamShared->State.uCurBDLE);
    12741275        }
    12751276
    12761277        /* Do the position adjustment accounting. */
    1277         pStream->State.cfPosAdjustLeft -=
    1278             RT_MIN(pStream->State.cfPosAdjustLeft, cbDMA / pStream->State.Mapping.cbFrameSize);
     1278        pStreamShared->State.cfPosAdjustLeft -=
     1279            RT_MIN(pStreamShared->State.cfPosAdjustLeft, cbDMA / pStreamR3->State.Mapping.cbFrameSize);
    12791280
    12801281        if (RT_FAILURE(rc))
     
    12831284
    12841285    Log3Func(("[SD%RU8] cbToProcess=%RU32, cbProcessed=%RU32, cbLeft=%RU32, %R[bdle], rc=%Rrc\n",
    1285               pStream->u8SD, cbToProcess, cbProcessed, cbLeft, pBDLE, rc));
     1286              uSD, cbToProcess, cbProcessed, cbLeft, pBDLE, rc));
    12861287
    12871288    /* Sanity. */
     
    12911292    /* Only do the data accounting if we don't have to do any position
    12921293     * adjustment anymore. */
    1293     if (pStream->State.cfPosAdjustLeft == 0)
    1294     {
    1295         hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStream->State.Mapping.cbFrameSize,
     1294    if (pStreamShared->State.cfPosAdjustLeft == 0)
     1295    {
     1296        hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStreamR3->State.Mapping.cbFrameSize,
    12961297                                             hdaR3StreamPeriodGetRemainingFrames(pPeriod)));
    12971298
    1298         pStream->State.cbTransferProcessed += cbProcessed;
     1299        pStreamShared->State.cbTransferProcessed += cbProcessed;
    12991300    }
    13001301
    13011302    /* Make sure that we never report more stuff processed than initially announced. */
    1302     if (pStream->State.cbTransferProcessed > pStream->State.cbTransferSize)
    1303         pStream->State.cbTransferProcessed = pStream->State.cbTransferSize;
    1304 
    1305     uint32_t cbTransferLeft     = pStream->State.cbTransferSize - pStream->State.cbTransferProcessed;
     1303    if (pStreamShared->State.cbTransferProcessed > pStreamShared->State.cbTransferSize)
     1304        pStreamShared->State.cbTransferProcessed = pStreamShared->State.cbTransferSize;
     1305
     1306    uint32_t cbTransferLeft     = pStreamShared->State.cbTransferSize - pStreamShared->State.cbTransferProcessed;
    13061307    bool     fTransferComplete  = !cbTransferLeft;
    13071308    uint64_t tsTransferNext     = 0;
     
    13211322         *         sound output. Running VLC on the guest will tell!
    13221323         */
    1323         const bool fWalClkSet = hdaR3WalClkSet(pThis,
     1324        const bool fWalClkSet = hdaR3WalClkSet(pThis, pThisCC,
    13241325                                                 hdaWalClkGetCurrent(pThis)
    13251326                                               + hdaR3StreamPeriodFramesToWalClk(pPeriod,
    1326                                                                                    pStream->State.cbTransferProcessed
    1327                                                                                  / pStream->State.Mapping.cbFrameSize),
     1327                                                                                   pStreamShared->State.cbTransferProcessed
     1328                                                                                 / pStreamR3->State.Mapping.cbFrameSize),
    13281329                                               false /* fForce */);
    13291330        RT_NOREF(fWalClkSet);
     
    13311332
    13321333    /* Does the period have any interrupts outstanding? */
    1333     if (pStream->State.cTransferPendingInterrupts)
    1334     {
    1335         Log3Func(("[SD%RU8] Scheduling interrupt\n", pStream->u8SD));
     1334    if (pStreamShared->State.cTransferPendingInterrupts)
     1335    {
     1336        Log3Func(("[SD%RU8] Scheduling interrupt\n", uSD));
    13361337
    13371338        /*
     
    13461347         * snd_hda_intel on Linux will tell.
    13471348         */
    1348         HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;
     1349        HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_BCIS;
    13491350
    13501351        /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
    13511352         * ending / beginning a period. */
    1352         HDA_PROCESS_INTERRUPT(pThis->pDevInsR3, pThis);
     1353        HDA_PROCESS_INTERRUPT(pDevIns, pThis);
    13531354    }
    13541355    else /* Transfer still in-flight -- schedule the next timing slot. */
     
    13591360         * than we can transfer per timing slot? Clamp. */
    13601361        if (   !cbTransferNext
    1361             || cbTransferNext > pStream->State.cbTransferChunk)
    1362         {
    1363             cbTransferNext = pStream->State.cbTransferChunk;
     1362            || cbTransferNext > pStreamShared->State.cbTransferChunk)
     1363        {
     1364            cbTransferNext = pStreamShared->State.cbTransferChunk;
    13641365        }
    13651366
    1366         tsTransferNext = tsNow + (cbTransferNext * pStream->State.cTicksPerByte);
     1367        tsTransferNext = tsNow + (cbTransferNext * pStreamShared->State.cTicksPerByte);
    13671368
    13681369        /*
     
    13741375         */
    13751376        if (fTransferComplete)
    1376             pStream->State.cbTransferProcessed = 0;
     1377            pStreamShared->State.cbTransferProcessed = 0;
    13771378    }
    13781379
     
    13801381    if (tsTransferNext) /* Can be 0 if no next transfer is needed. */
    13811382    {
    1382         Log3Func(("[SD%RU8] Scheduling timer\n", pStream->u8SD));
    1383 
    1384         LogFunc(("Timer set SD%RU8\n", pStream->u8SD));
    1385         Assert(!fInTimer || tsNow == PDMDevHlpTimerGet(pDevIns, pStream->hTimer));
    1386         hdaR3TimerSet(pDevIns, pStream, tsTransferNext, true /* fForce - skip tsTransferNext check */, fInTimer ? tsNow : 0);
    1387 
    1388         pStream->State.tsTransferNext = tsTransferNext;
    1389     }
    1390 
    1391     pStream->State.tsTransferLast = tsNow;
     1383        Log3Func(("[SD%RU8] Scheduling timer\n", uSD));
     1384
     1385        LogFunc(("Timer set SD%RU8\n", uSD));
     1386        Assert(!fInTimer || tsNow == PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer));
     1387        hdaR3TimerSet(pDevIns, pStreamShared, tsTransferNext,
     1388                      true /* fForce - skip tsTransferNext check */, fInTimer ? tsNow : 0);
     1389
     1390        pStreamShared->State.tsTransferNext = tsTransferNext;
     1391    }
     1392
     1393    pStreamShared->State.tsTransferLast = tsNow;
    13921394
    13931395    Log3Func(("[SD%RU8] cbTransferLeft=%RU32 -- %RU32/%RU32\n",
    1394               pStream->u8SD, cbTransferLeft, pStream->State.cbTransferProcessed, pStream->State.cbTransferSize));
     1396              uSD, cbTransferLeft, pStreamShared->State.cbTransferProcessed, pStreamShared->State.cbTransferSize));
    13951397    Log3Func(("[SD%RU8] fTransferComplete=%RTbool, cTransferPendingInterrupts=%RU8\n",
    1396               pStream->u8SD, fTransferComplete, pStream->State.cTransferPendingInterrupts));
     1398              uSD, fTransferComplete, pStreamShared->State.cTransferPendingInterrupts));
    13971399    Log3Func(("[SD%RU8] tsNow=%RU64, tsTransferNext=%RU64 (in %RU64 ticks)\n",
    1398               pStream->u8SD, tsNow, tsTransferNext, tsTransferNext - tsNow));
     1400              uSD, tsNow, tsTransferNext, tsTransferNext - tsNow));
    13991401
    14001402    hdaR3StreamPeriodUnlock(pPeriod);
    1401     hdaR3StreamUnlock(pStream);
     1403    hdaR3StreamUnlock(pStreamR3);
    14021404
    14031405    return VINF_SUCCESS;
     
    14211423 * (with fInTimer set to @c false).
    14221424 *
    1423  * @param   pDevIns     The device instance.
    1424  * @param   pStream     HDA stream to update.
    1425  * @param   fInTimer    Whether to this function was called from the timer
    1426  *                      context or an asynchronous I/O stream thread (if supported).
    1427  */
    1428 void hdaR3StreamUpdate(PPDMDEVINS pDevIns, PHDASTREAM pStream, bool fInTimer)
    1429 {
    1430     if (!pStream)
     1425 * @param   pDevIns         The device instance.
     1426 * @param   pThis           The shared HDA device state.
     1427 * @param   pThisCC         The ring-3 HDA device state.
     1428 * @param   pStreamShared   HDA stream to update (shared bits).
     1429 * @param   pStreamR3       HDA stream to update (ring-3 bits).
     1430 * @param   fInTimer        Whether to this function was called from the timer
     1431 *                          context or an asynchronous I/O stream thread (if supported).
     1432 */
     1433void hdaR3StreamUpdate(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC,
     1434                       PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fInTimer)
     1435{
     1436    if (!pStreamShared)
    14311437        return;
    14321438
    14331439    PAUDMIXSINK pSink = NULL;
    1434     if (   pStream->pMixSink
    1435         && pStream->pMixSink->pMixSink)
    1436     {
    1437         pSink = pStream->pMixSink->pMixSink;
    1438     }
     1440    if (pStreamR3->pMixSink)
     1441        pSink = pStreamR3->pMixSink->pMixSink;
    14391442
    14401443    if (!AudioMixerSinkIsActive(pSink)) /* No sink available? Bail out. */
     
    14431446    int rc2;
    14441447
    1445     if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
     1448    if (hdaGetDirFromSD(pStreamShared->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
    14461449    {
    14471450        bool fDoRead = false; /* Whether to read from the HDA stream or not. */
     
    14511454# endif
    14521455        {
    1453             const uint32_t cbStreamFree = hdaR3StreamGetFree(pStream);
     1456            const uint32_t cbStreamFree = hdaR3StreamGetFree(pStreamR3);
    14541457            if (cbStreamFree)
    14551458            {
    14561459                /* Do the DMA transfer. */
    1457                 rc2 = hdaR3StreamTransfer(pDevIns, pStream, cbStreamFree, fInTimer);
     1460                rc2 = hdaR3StreamTransfer(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, cbStreamFree, fInTimer);
    14581461                AssertRC(rc2);
    14591462            }
     
    14611464            /* Only read from the HDA stream at the given scheduling rate. */
    14621465            const uint64_t tsNowNs = RTTimeNanoTS();
    1463             if (tsNowNs - pStream->State.tsLastUpdateNs >= pStream->State.Cfg.Device.cMsSchedulingHint * RT_NS_1MS)
     1466            if (tsNowNs - pStreamShared->State.tsLastUpdateNs >= pStreamShared->State.Cfg.Device.cMsSchedulingHint * RT_NS_1MS)
    14641467            {
    14651468                fDoRead = true;
    1466                 pStream->State.tsLastUpdateNs = tsNowNs;
     1469                pStreamShared->State.tsLastUpdateNs = tsNowNs;
    14671470            }
    14681471        }
    14691472
    1470         Log3Func(("[SD%RU8] fInTimer=%RTbool, fDoRead=%RTbool\n", pStream->u8SD, fInTimer, fDoRead));
     1473        Log3Func(("[SD%RU8] fInTimer=%RTbool, fDoRead=%RTbool\n", pStreamShared->u8SD, fInTimer, fDoRead));
    14711474
    14721475# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    14731476        if (fDoRead)
    14741477        {
    1475             rc2 = hdaR3StreamAsyncIONotify(pStream);
     1478            rc2 = hdaR3StreamAsyncIONotify(pStreamR3);
    14761479            AssertRC(rc2);
    14771480        }
     
    14861489# endif
    14871490            const uint32_t cbSinkWritable     = AudioMixerSinkGetWritable(pSink);
    1488             const uint32_t cbStreamReadable   = hdaR3StreamGetUsed(pStream);
     1491            const uint32_t cbStreamReadable   = hdaR3StreamGetUsed(pStreamR3);
    14891492            const uint32_t cbToReadFromStream = RT_MIN(cbStreamReadable, cbSinkWritable);
    14901493
    1491             Log3Func(("[SD%RU8] cbSinkWritable=%RU32, cbStreamReadable=%RU32\n", pStream->u8SD, cbSinkWritable, cbStreamReadable));
     1494            Log3Func(("[SD%RU8] cbSinkWritable=%RU32, cbStreamReadable=%RU32\n", pStreamShared->u8SD, cbSinkWritable, cbStreamReadable));
    14921495
    14931496            if (cbToReadFromStream)
    14941497            {
    14951498                /* Read (guest output) data and write it to the stream's sink. */
    1496                 rc2 = hdaR3StreamRead(pStream, cbToReadFromStream, NULL /* pcbRead */);
     1499                rc2 = hdaR3StreamRead(pStreamR3, cbToReadFromStream, NULL /* pcbRead */);
    14971500                AssertRC(rc2);
    14981501            }
     
    15171520
    15181521            /* How much (guest input) data is available for writing at the moment for the HDA stream? */
    1519             const uint32_t cbStreamFree = hdaR3StreamGetFree(pStream);
    1520 
    1521             Log3Func(("[SD%RU8] cbSinkReadable=%RU32, cbStreamFree=%RU32\n", pStream->u8SD, cbSinkReadable, cbStreamFree));
     1522            const uint32_t cbStreamFree = hdaR3StreamGetFree(pStreamR3);
     1523
     1524            Log3Func(("[SD%RU8] cbSinkReadable=%RU32, cbStreamFree=%RU32\n", pStreamShared->u8SD, cbSinkReadable, cbStreamFree));
    15221525
    15231526            /* Do not read more than the HDA stream can hold at the moment.
     
    15441547                    /* Write (guest input) data to the stream which was read from stream's sink before. */
    15451548                    uint32_t cbWritten;
    1546                     rc2 = hdaR3StreamWrite(pStream, abFIFO, cbRead, &cbWritten);
     1549                    rc2 = hdaR3StreamWrite(pStreamR3, abFIFO, cbRead, &cbWritten);
    15471550                    AssertRCBreak(rc2);
    1548 
    1549                     if (!cbWritten)
    1550                     {
    1551                         AssertFailed(); /* Should never happen, as we know how much we can write. */
    1552                         break;
    1553                     }
     1551                    AssertBreak(cbWritten > 0); /* Should never happen, as we know how much we can write. */
    15541552
    15551553                    Assert(cbSinkReadable >= cbRead);
     
    15651563# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    15661564            const uint64_t tsNowNs = RTTimeNanoTS();
    1567             if (tsNowNs - pStream->State.tsLastUpdateNs >= pStream->State.Cfg.Device.cMsSchedulingHint * RT_NS_1MS)
    1568             {
    1569                 rc2 = hdaR3StreamAsyncIONotify(pStream);
     1565            if (tsNowNs - pStreamShared->State.tsLastUpdateNs >= pStreamShared->State.Cfg.Device.cMsSchedulingHint * RT_NS_1MS)
     1566            {
     1567                rc2 = hdaR3StreamAsyncIONotify(pStreamR3);
    15701568                AssertRC(rc2);
    15711569
    1572                 pStream->State.tsLastUpdateNs = tsNowNs;
     1570                pStreamShared->State.tsLastUpdateNs = tsNowNs;
    15731571            }
    15741572# endif
    1575             const uint32_t cbStreamUsed = hdaR3StreamGetUsed(pStream);
     1573            const uint32_t cbStreamUsed = hdaR3StreamGetUsed(pStreamR3);
    15761574            if (cbStreamUsed)
    15771575            {
    1578                 rc2 = hdaR3StreamTransfer(pDevIns, pStream, cbStreamUsed, fInTimer);
     1576                rc2 = hdaR3StreamTransfer(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, cbStreamUsed, fInTimer);
    15791577                AssertRC(rc2);
    15801578            }
     
    15891587 *
    15901588 * @returns IPRT status code.
    1591  * @param   pStream             HDA stream to lock.
    1592  */
    1593 void hdaR3StreamLock(PHDASTREAM pStream)
    1594 {
    1595     AssertPtrReturnVoid(pStream);
     1589 * @param   pStreamR3           HDA stream to lock (ring-3 bits).
     1590 */
     1591void hdaR3StreamLock(PHDASTREAMR3 pStreamR3)
     1592{
     1593    AssertPtrReturnVoid(pStreamR3);
    15961594# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1597     int rc2 = RTCritSectEnter(&pStream->CritSect);
     1595    int rc2 = RTCritSectEnter(&pStreamR3->CritSect);
    15981596    AssertRC(rc2);
    15991597# else
     
    16061604 *
    16071605 * @returns IPRT status code.
    1608  * @param   pStream             HDA stream to unlock.
    1609  */
    1610 void hdaR3StreamUnlock(PHDASTREAM pStream)
    1611 {
    1612     AssertPtrReturnVoid(pStream);
     1606 * @param   pStreamR3           HDA stream to unlock (ring-3 bits).
     1607 */
     1608void hdaR3StreamUnlock(PHDASTREAMR3 pStreamR3)
     1609{
     1610    AssertPtrReturnVoid(pStreamR3);
    16131611# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    1614     int rc2 = RTCritSectLeave(&pStream->CritSect);
     1612    int rc2 = RTCritSectLeave(&pStreamR3->CritSect);
    16151613    AssertRC(rc2);
    16161614# endif
    16171615}
    16181616
     1617#if 0 /* unused - no prototype even */
    16191618/**
    16201619 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
     
    16221621 *
    16231622 * @returns Set LPIB value.
     1623 * @param   pDevIns             The device instance.
    16241624 * @param   pStream             HDA stream to update read / write position for.
    16251625 * @param   u32LPIB             New LPIB (position) value to set.
    16261626 */
    1627 uint32_t hdaR3StreamUpdateLPIB(PHDASTREAM pStream, uint32_t u32LPIB)
    1628 {
    1629     AssertPtrReturn(pStream, 0);
    1630 
    1631     AssertMsg(u32LPIB <= pStream->u32CBL,
    1632               ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));
    1633 
    1634     const PHDASTATE pThis = pStream->pHDAState;
    1635 
    1636     u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
     1627uint32_t hdaR3StreamUpdateLPIB(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint32_t u32LPIB)
     1628{
     1629    AssertMsg(u32LPIB <= pStreamShared->u32CBL,
     1630              ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStreamShared->u8SD, u32LPIB, pStreamShared->u32CBL));
     1631
     1632    u32LPIB = RT_MIN(u32LPIB, pStreamShared->u32CBL);
    16371633
    16381634    LogFlowFunc(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    1639                  pStream->u8SD, u32LPIB, pThis->fDMAPosition));
     1635                 pStreamShared->u8SD, u32LPIB, pThis->fDMAPosition));
    16401636
    16411637    /* Update LPIB in any case. */
    1642     HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
     1638    HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD) = u32LPIB;
    16431639
    16441640    /* Do we need to tell the current DMA position? */
    16451641    if (pThis->fDMAPosition)
    16461642    {
    1647         int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    1648                                         pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
     1643        int rc2 = PDMDevHlpPCIPhysWrite(pDevIns,
     1644                                        pThis->u64DPBase + (pStreamShared->u8SD * 2 * sizeof(uint32_t)),
    16491645                                        (void *)&u32LPIB, sizeof(uint32_t));
    16501646        AssertRC(rc2);
     
    16531649    return u32LPIB;
    16541650}
     1651#endif
    16551652
    16561653# ifdef HDA_USE_DMA_ACCESS_HANDLER
     
    16641661{
    16651662    /* At least LVI and the BDL base must be set. */
    1666     if (   !pStream->u16LVI
    1667         || !pStream->u64BDLBase)
     1663    if (   !pStreamShared->u16LVI
     1664        || !pStreamShared->u64BDLBase)
    16681665    {
    16691666        return false;
     
    16881685    size_t cRanges = 0;
    16891686
    1690     for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)
     1687    for (uint16_t i = 0; i < pStreamShared->u16LVI + 1; i++)
    16911688    {
    16921689        HDABDLE BDLE;
    1693         rc = hdaR3BDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);
     1690        rc = hdaR3BDLEFetch(pDevIns, &BDLE, pStreamShared->u64BDLBase, i /* Index */);
    16941691        if (RT_FAILURE(rc))
    16951692            break;
     
    18271824# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    18281825/**
     1826 * @callback_method_impl{FNRTTHREAD,
    18291827 * Asynchronous I/O thread for a HDA stream.
    1830  * This will do the heavy lifting work for us as soon as it's getting notified by another thread.
    1831  *
    1832  * @returns IPRT status code.
    1833  * @param   hThreadSelf         Thread handle.
    1834  * @param   pvUser              User argument. Must be of type PHDASTREAMTHREADCTX.
    1835  */
    1836 DECLCALLBACK(int) hdaR3StreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
    1837 {
    1838     PHDASTREAMTHREADCTX pCtx = (PHDASTREAMTHREADCTX)pvUser;
    1839     AssertPtr(pCtx);
    1840     PHDASTREAM pStream = pCtx->pStream;
    1841 
    1842     AssertPtr(pStream);
    1843     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
    1844 
    1845     PPDMDEVINS pDevIns = pCtx->pThis->pDevInsR3;
    1846 
     1828 *
     1829 * This will do the heavy lifting work for us as soon as it's getting notified
     1830 * by another thread.}
     1831 */
     1832static DECLCALLBACK(int) hdaR3StreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
     1833{
     1834    PHDASTREAMR3 const       pStreamR3     = (PHDASTREAMR3)pvUser;
     1835    PHDASTREAMSTATEAIO const pAIO          = &pStreamR3->State.AIO;
     1836    PHDASTATE const          pThis         = pStreamR3->pHDAStateShared;
     1837    PHDASTATER3 const        pThisCC       = pStreamR3->pHDAStateR3;
     1838    PPDMDEVINS const         pDevIns       = pThisCC->pDevIns;
     1839    PHDASTREAM const         pStreamShared = &pThis->aStreams[pStreamR3 - &pThisCC->aStreams[0]];
     1840    Assert(pStreamR3 - &pThisCC->aStreams[0] == pStreamR3->u8SD);
     1841    Assert(pStreamShared->u8SD == pStreamR3->u8SD);
     1842
     1843    /* Signal parent thread that we've started  */
    18471844    ASMAtomicXchgBool(&pAIO->fStarted, true);
    1848 
    18491845    RTThreadUserSignal(hThreadSelf);
    18501846
    1851     LogFunc(("[SD%RU8] Started\n", pStream->u8SD));
     1847    LogFunc(("[SD%RU8] Started\n", pStreamShared->u8SD));
    18521848
    18531849    for (;;)
    18541850    {
    1855         int rc2 = RTSemEventWait(pAIO->Event, RT_INDEFINITE_WAIT);
     1851        int rc2 = RTSemEventWait(pAIO->hEvent, RT_INDEFINITE_WAIT);
    18561852        if (RT_FAILURE(rc2))
    18571853            break;
     
    18611857
    18621858        rc2 = RTCritSectEnter(&pAIO->CritSect);
     1859        AssertRC(rc2);
    18631860        if (RT_SUCCESS(rc2))
    18641861        {
     
    18691866            }
    18701867
    1871             hdaR3StreamUpdate(pDevIns, pStream, false /* fInTimer */);
     1868            hdaR3StreamUpdate(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, false /* fInTimer */);
    18721869
    18731870            int rc3 = RTCritSectLeave(&pAIO->CritSect);
    18741871            AssertRC(rc3);
    18751872        }
    1876 
    1877         AssertRC(rc2);
    1878     }
    1879 
    1880     LogFunc(("[SD%RU8] Ended\n", pStream->u8SD));
    1881 
     1873    }
     1874
     1875    LogFunc(("[SD%RU8] Ended\n", pStreamShared->u8SD));
    18821876    ASMAtomicXchgBool(&pAIO->fStarted, false);
    18831877
     
    18891883 *
    18901884 * @returns IPRT status code.
    1891  * @param   pStream             HDA audio stream to create the async I/O thread for.
    1892  */
    1893 int hdaR3StreamAsyncIOCreate(PHDASTREAM pStream)
    1894 {
    1895     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
     1885 * @param   pStreamR3           HDA audio stream to create the async I/O thread for.
     1886 */
     1887int hdaR3StreamAsyncIOCreate(PHDASTREAMR3 pStreamR3)
     1888{
     1889    PHDASTREAMSTATEAIO pAIO = &pStreamR3->State.AIO;
    18961890
    18971891    int rc;
     
    19021896        pAIO->fEnabled  = true; /* Enabled by default. */
    19031897
    1904         rc = RTSemEventCreate(&pAIO->Event);
     1898        rc = RTSemEventCreate(&pAIO->hEvent);
    19051899        if (RT_SUCCESS(rc))
    19061900        {
     
    19081902            if (RT_SUCCESS(rc))
    19091903            {
    1910                 HDASTREAMTHREADCTX Ctx = { pStream->pHDAState, pStream };
    1911 
    1912                 char szThreadName[64];
    1913                 RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
    1914 
    1915                 rc = RTThreadCreate(&pAIO->Thread, hdaR3StreamAsyncIOThread, &Ctx,
    1916                                     0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
     1904                rc = RTThreadCreateF(&pAIO->hThread, hdaR3StreamAsyncIOThread, pStreamR3, 0 /*cbStack*/,
     1905                                     RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "hdaAIO%RU8", pStreamR3->u8SD);
    19171906                if (RT_SUCCESS(rc))
    1918                     rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
     1907                    rc = RTThreadUserWait(pAIO->hThread, 10 * 1000 /* 10s timeout */);
    19191908            }
    19201909        }
     
    19231912        rc = VINF_SUCCESS;
    19241913
    1925     LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
     1914    LogFunc(("[SD%RU8] Returning %Rrc\n", pStreamR3->u8SD, rc));
    19261915    return rc;
    19271916}
     
    19311920 *
    19321921 * @returns IPRT status code.
    1933  * @param   pStream             HDA audio stream to destroy the async I/O thread for.
    1934  */
    1935 int hdaR3StreamAsyncIODestroy(PHDASTREAM pStream)
    1936 {
    1937     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
     1922 * @param   pStreamR3           HDA audio stream to destroy the async I/O thread for.
     1923 */
     1924static int hdaR3StreamAsyncIODestroy(PHDASTREAMR3 pStreamR3)
     1925{
     1926    PHDASTREAMSTATEAIO pAIO = &pStreamR3->State.AIO;
    19381927
    19391928    if (!ASMAtomicReadBool(&pAIO->fStarted))
     
    19421931    ASMAtomicWriteBool(&pAIO->fShutdown, true);
    19431932
    1944     int rc = hdaR3StreamAsyncIONotify(pStream);
     1933    int rc = hdaR3StreamAsyncIONotify(pStreamR3);
    19451934    AssertRC(rc);
    19461935
    19471936    int rcThread;
    1948     rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
     1937    rc = RTThreadWait(pAIO->hThread, 30 * 1000 /* 30s timeout */, &rcThread);
    19491938    LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
    19501939
    19511940    if (RT_SUCCESS(rc))
    19521941    {
     1942        pAIO->hThread = NIL_RTTHREAD;
     1943
    19531944        rc = RTCritSectDelete(&pAIO->CritSect);
    19541945        AssertRC(rc);
    19551946
    1956         rc = RTSemEventDestroy(pAIO->Event);
     1947        rc = RTSemEventDestroy(pAIO->hEvent);
    19571948        AssertRC(rc);
     1949        pAIO->hEvent = NIL_RTSEMEVENT;
    19581950
    19591951        pAIO->fStarted  = false;
     
    19621954    }
    19631955
    1964     LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
     1956    LogFunc(("[SD%RU8] Returning %Rrc\n", pStreamR3->u8SD, rc));
    19651957    return rc;
    19661958}
     
    19701962 *
    19711963 * @returns IPRT status code.
    1972  * @param   pStream             HDA stream to notify async I/O thread for.
    1973  */
    1974 int hdaR3StreamAsyncIONotify(PHDASTREAM pStream)
    1975 {
    1976     return RTSemEventSignal(pStream->State.AIO.Event);
     1964 * @param   pStreamR3           HDA stream to notify async I/O thread for.
     1965 */
     1966static int hdaR3StreamAsyncIONotify(PHDASTREAMR3 pStreamR3)
     1967{
     1968    return RTSemEventSignal(pStreamR3->State.AIO.hEvent);
    19771969}
    19781970
     
    19801972 * Locks the async I/O thread of a specific HDA audio stream.
    19811973 *
    1982  * @param   pStream             HDA stream to lock async I/O thread for.
    1983  */
    1984 void hdaR3StreamAsyncIOLock(PHDASTREAM pStream)
    1985 {
    1986     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
     1974 * @param   pStreamR3           HDA stream to lock async I/O thread for.
     1975 */
     1976void hdaR3StreamAsyncIOLock(PHDASTREAMR3 pStreamR3)
     1977{
     1978    PHDASTREAMSTATEAIO pAIO = &pStreamR3->State.AIO;
    19871979
    19881980    if (!ASMAtomicReadBool(&pAIO->fStarted))
     
    19961988 * Unlocks the async I/O thread of a specific HDA audio stream.
    19971989 *
    1998  * @param   pStream             HDA stream to unlock async I/O thread for.
    1999  */
    2000 void hdaR3StreamAsyncIOUnlock(PHDASTREAM pStream)
    2001 {
    2002     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
     1990 * @param   pStreamR3           HDA stream to unlock async I/O thread for.
     1991 */
     1992void hdaR3StreamAsyncIOUnlock(PHDASTREAMR3 pStreamR3)
     1993{
     1994    PHDASTREAMSTATEAIO pAIO = &pStreamR3->State.AIO;
    20031995
    20041996    if (!ASMAtomicReadBool(&pAIO->fStarted))
     
    20122004 * Enables (resumes) or disables (pauses) the async I/O thread.
    20132005 *
    2014  * @param   pStream             HDA stream to enable/disable async I/O thread for.
     2006 * @param   pStreamR3           HDA stream to enable/disable async I/O thread for.
    20152007 * @param   fEnable             Whether to enable or disable the I/O thread.
    20162008 *
    20172009 * @remarks Does not do locking.
    20182010 */
    2019 void hdaR3StreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable)
    2020 {
    2021     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
     2011void hdaR3StreamAsyncIOEnable(PHDASTREAMR3 pStreamR3, bool fEnable)
     2012{
     2013    PHDASTREAMSTATEAIO pAIO = &pStreamR3->State.AIO;
    20222014    ASMAtomicXchgBool(&pAIO->fEnabled, fEnable);
    20232015}
  • trunk/src/VBox/Devices/Audio/HDAStream.h

    r82420 r82450  
    3434{
    3535    /** Thread handle for the actual I/O thread. */
    36     RTTHREAD                Thread;
     36    RTTHREAD                hThread;
    3737    /** Event for letting the thread know there is some data to process. */
    38     RTSEMEVENT              Event;
     38    RTSEMEVENT              hEvent;
    3939    /** Critical section for synchronizing access. */
    4040    RTCRITSECT              CritSect;
     
    123123    volatile bool           fRunning;
    124124    /** Unused, padding. */
    125     uint8_t                 Padding0[4];
    126 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    127     /** Asynchronous I/O state members. */
    128     HDASTREAMSTATEAIO       AIO;
    129 #endif
    130     /** This stream's data mapping. */
    131     HDASTREAMMAP            Mapping;
     125    uint8_t                 abPadding0[4];
    132126    /** Current BDLE (Buffer Descriptor List Entry). */
    133127    HDABDLE                 BDLE;
    134     /** Circular buffer (FIFO) for holding DMA'ed data. */
    135     R3PTRTYPE(PRTCIRCBUF)   pCircBuf;
    136 #if HC_ARCH_BITS == 32
    137     RTR3PTR                 Padding1;
    138 #endif
    139128    /** Timestamp of the last DMA data transfer. */
    140129    uint64_t                tsTransferLast;
     
    153142     *  BDLE interrupt-on-completion (IOC) bits set. */
    154143    uint8_t                 cTransferPendingInterrupts;
    155     uint8_t                 Padding2[2];
     144    uint8_t                 abPadding2[3];
    156145    /** The stream's timer Hz rate.
    157146     *  This value can can be different from the device's default Hz rate,
     
    167156     *  0 if position adjustment handling is done or inactive. */
    168157    uint16_t                cfPosAdjustLeft;
     158    uint16_t                u16Padding3;
    169159    /** (Virtual) clock ticks per byte. */
    170160    uint64_t                cTicksPerByte;
     
    177167    PDMAUDIOSTREAMCFG       Cfg;
    178168    uint32_t                Padding4;
    179 #ifdef HDA_USE_DMA_ACCESS_HANDLER
    180     /** List of DMA handlers. */
    181     RTLISTANCHORR3          lstDMAHandlers;
    182 #endif
    183    /** Timestamp (in ns) of last stream update. */
     169    /** Timestamp (in ns) of last stream update. */
    184170    uint64_t                tsLastUpdateNs;
    185171} HDASTREAMSTATE;
    186172AssertCompileSizeAlignment(HDASTREAMSTATE, 8);
    187 /** Pointer to the internal state of an HDA stream. */
    188 typedef HDASTREAMSTATE *PHDASTREAMSTATE;
    189 
    190 /**
    191  * An HDA stream (SDI / SDO).
     173
     174/**
     175 * An HDA stream (SDI / SDO) - shared.
    192176 *
    193177 * @note This HDA stream has nothing to do with a regular audio stream handled
     
    232216    uint16_t                    u16LVI;
    233217    uint16_t                    au16Padding1[2];
    234     /** Pointer to the HDA state this stream is attached to. */
    235     R3PTRTYPE(PHDASTATE)        pHDAState;
     218    /** The timer for pumping data thru the attached LUN drivers. */
     219    TMTIMERHANDLE               hTimer;
     220    /** Internal state of this stream. */
     221    HDASTREAMSTATE              State;
     222} HDASTREAM;
     223/** Pointer to an HDA stream (SDI / SDO).  */
     224typedef HDASTREAM *PHDASTREAM;
     225
     226
     227/**
     228 * An HDA stream (SDI / SDO) - ring-3 bits.
     229 */
     230typedef struct HDASTREAMR3
     231{
     232    /** Stream descriptor number (SDn). */
     233    uint8_t                     u8SD;
     234    uint8_t                     abPadding[7];
     235    /** The shared state for the parent HDA device. */
     236    R3PTRTYPE(PHDASTATE)        pHDAStateShared;
     237    /** The ring-3 state for the parent HDA device. */
     238    R3PTRTYPE(PHDASTATER3)      pHDAStateR3;
    236239    /** Pointer to HDA sink this stream is attached to. */
    237240    R3PTRTYPE(PHDAMIXERSINK)    pMixSink;
    238     /** The timer for pumping data thru the attached LUN drivers. */
    239     TMTIMERHANDLE               hTimer;
    240241#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    241242    /** The stream's critical section to serialize access between the async I/O
     
    244245#endif
    245246    /** Internal state of this stream. */
    246     HDASTREAMSTATE              State;
    247     /** Debug information. */
     247    struct
     248    {
     249        /** This stream's data mapping. */
     250        HDASTREAMMAP            Mapping;
     251        /** Circular buffer (FIFO) for holding DMA'ed data. */
     252        R3PTRTYPE(PRTCIRCBUF)   pCircBuf;
     253#ifdef HDA_USE_DMA_ACCESS_HANDLER
     254        /** List of DMA handlers. */
     255        RTLISTANCHORR3          lstDMAHandlers;
     256#endif
     257#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
     258        /** Asynchronous I/O state members. */
     259        HDASTREAMSTATEAIO       AIO;
     260#endif
     261    } State;
     262    /** Debug bits. */
    248263    HDASTREAMDEBUG              Dbg;
    249 } HDASTREAM;
     264} HDASTREAMR3;
    250265/** Pointer to an HDA stream (SDI / SDO).  */
    251 typedef HDASTREAM *PHDASTREAM;
    252 
    253 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    254 /**
    255  * HDA stream thread context (arguments).
    256  */
    257 typedef struct HDASTREAMTHREADCTX
    258 {
    259     PHDASTATE  pThis;
    260     PHDASTREAM pStream;
    261 } HDASTREAMTHREADCTX, *PHDASTREAMTHREADCTX;
    262 #endif
     266typedef HDASTREAMR3 *PHDASTREAMR3;
    263267
    264268#ifdef IN_RING3
     
    267271 * @{
    268272 */
    269 int               hdaR3StreamCreate(PHDASTREAM pStream, PHDASTATE pThis, uint8_t u8SD);
    270 void              hdaR3StreamDestroy(PHDASTREAM pStream);
    271 int               hdaR3StreamInit(PPDMDEVINS pDevIns, PHDASTREAM pStream, uint8_t uSD);
    272 void              hdaR3StreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD);
    273 int               hdaR3StreamEnable(PHDASTREAM pStream, bool fEnable);
    274 uint32_t          hdaR3StreamGetPosition(PHDASTATE pThis, PHDASTREAM pStream);
    275 void              hdaR3StreamSetPosition(PHDASTREAM pStream, uint32_t u32LPIB);
    276 uint32_t          hdaR3StreamGetFree(PHDASTREAM pStream);
    277 uint32_t          hdaR3StreamGetUsed(PHDASTREAM pStream);
    278 bool              hdaR3StreamTransferIsScheduled(PHDASTREAM pStream, uint64_t tsNow);
    279 uint64_t          hdaR3StreamTransferGetNext(PHDASTREAM pStream);
    280 void              hdaR3StreamLock(PHDASTREAM pStream);
    281 void              hdaR3StreamUnlock(PHDASTREAM pStream);
    282 int               hdaR3StreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);
    283 int               hdaR3StreamWrite(PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    284 void              hdaR3StreamUpdate(PPDMDEVINS pDevIns, PHDASTREAM pStream, bool fAsync);
     273int                 hdaR3StreamConstruct(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, PHDASTATE pThis,
     274                                         PHDASTATER3 pThisCC, uint8_t uSD);
     275void                hdaR3StreamDestroy(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3);
     276int                 hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared,
     277                                     PHDASTREAMR3 pStreamR3, uint8_t uSD);
     278void                hdaR3StreamReset(PHDASTATE pThis, PHDASTATER3 pThisCC,
     279                                     PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, uint8_t uSD);
     280int                 hdaR3StreamEnable(PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fEnable);
     281/* uint32_t            hdaR3StreamGetPosition(PHDASTATE pThis, PHDASTREAMR3 pStreamShared); - only used in HDAStream.cpp */
     282/*void                hdaR3StreamSetPosition(PHDASTREAM pStream, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t u32LPIB); - only used in HDAStream.cpp */
     283/*uint32_t            hdaR3StreamGetFree(PHDASTREAM pStream); - only used in HDAStream.cpp */
     284/*uint32_t            hdaR3StreamGetUsed(PHDASTREAM pStream); - only used in HDAStream.cpp */
     285bool                hdaR3StreamTransferIsScheduled(PHDASTREAM pStreamShared, uint64_t tsNow);
     286uint64_t            hdaR3StreamTransferGetNext(PHDASTREAM pStreamShared);
     287void                hdaR3StreamLock(PHDASTREAMR3 pStreamR3);
     288void                hdaR3StreamUnlock(PHDASTREAMR3 pStreamR3);
     289/* int                 hdaR3StreamRead(PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead); - only used in HDAStream.cpp */
     290/*int                 hdaR3StreamWrite(PHDASTREAM pStream, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten); - only used in HDAStream.cpp */
     291void                hdaR3StreamUpdate(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC,
     292                                      PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, bool fInTimer);
     293PHDASTREAM          hdaR3StreamR3ToShared(PHDASTREAMR3 pStreamCC);
    285294# ifdef HDA_USE_DMA_ACCESS_HANDLER
    286 bool              hdaR3StreamRegisterDMAHandlers(PHDASTREAM pStream);
    287 void              hdaR3StreamUnregisterDMAHandlers(PHDASTREAM pStream);
     295bool                hdaR3StreamRegisterDMAHandlers(PHDASTREAM pStream);
     296void                hdaR3StreamUnregisterDMAHandlers(PHDASTREAM pStream);
    288297# endif
    289298/** @} */
     
    293302 */
    294303# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    295 DECLCALLBACK(int) hdaR3StreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
    296 int               hdaR3StreamAsyncIOCreate(PHDASTREAM pStream);
    297 int               hdaR3StreamAsyncIODestroy(PHDASTREAM pStream);
    298 int               hdaR3StreamAsyncIONotify(PHDASTREAM pStream);
    299 void              hdaR3StreamAsyncIOLock(PHDASTREAM pStream);
    300 void              hdaR3StreamAsyncIOUnlock(PHDASTREAM pStream);
    301 void              hdaR3StreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable);
     304int                 hdaR3StreamAsyncIOCreate(PHDASTREAMR3 pStreamR3);
     305void                hdaR3StreamAsyncIOLock(PHDASTREAMR3 pStreamR3);
     306void                hdaR3StreamAsyncIOUnlock(PHDASTREAMR3 pStreamR3);
     307void                hdaR3StreamAsyncIOEnable(PHDASTREAMR3 pStreamR3, bool fEnable);
    302308# endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */
    303309/** @} */
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