VirtualBox

Changeset 89869 in vbox for trunk/src


Ignore:
Timestamp:
Jun 23, 2021 7:06:11 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145327
Message:

DevHda: Implemented DMA-on-WALCLK access too. Cleanups. bugref:9890

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

Legend:

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

    r89861 r89869  
    5454
    5555#include "DevHda.h"
    56 #include "DevHdaCommon.h"
    57 #include "DevHdaCodec.h"
    58 #include "DevHdaStream.h"
    5956
    6057#include "AudioHlp.h"
     
    245242#endif
    246243} HDADRIVER;
     244/** The HDA host driver backend. */
     245typedef struct HDADRIVER *PHDADRIVER;
    247246
    248247
     
    10541053             * Calculate where the DMA engine should be according to the clock, if we can.
    10551054             */
    1056             uint32_t const idxSched = pStreamShared->State.idxSchedule;
    1057             if (idxSched < RT_MIN(RT_ELEMENTS(pStreamShared->State.aSchedule), pStreamShared->State.cSchedule))
     1055            uint32_t const cbFrame  = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props);
     1056            uint32_t const cbPeriod = pStreamShared->State.cbCurDmaPeriod;
     1057            if (cbPeriod > cbFrame)
    10581058            {
    1059                 uint32_t const cbPeriod = pStreamShared->State.aSchedule[idxSched].cbPeriod;
    1060                 uint32_t const cbFrame  = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props);
    1061                 if (cbPeriod > cbFrame)
     1059                AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod));
     1060                uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext;
     1061                uint64_t const tsNow          = PDMDevHlpTimerGet(pDevIns, pThis->aStreams[0].hTimer); /* only #0 works in r0 */
     1062                uint32_t       cbFuture;
     1063                if (tsNow < tsTransferNext)
    10621064                {
    1063                     AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod));
    1064                     uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext;
    1065                     uint64_t const tsNow          = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
    1066                     uint32_t       cbFuture;
    1067                     if (tsNow < tsTransferNext)
    1068                     {
    1069                         /** @todo ASSUMES nanosecond clock ticks, need to make this
    1070                          *        resolution independent. */
    1071                         cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow);
    1072                         cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame);
    1073                     }
    1074                     else
    1075                     {
    1076                         /* We've hit/overshot the timer deadline.  Return to ring-3 if we're
    1077                            not already there to increase the chance that we'll help expidite
    1078                            the timer.  If we're already in ring-3, do all but the last frame. */
    1079 # ifndef IN_RING3
    1080                         LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n",
    1081                                  tsNow, tsTransferNext));
    1082                         return VINF_IOM_R3_MMIO_READ;
    1083 # else
    1084                         cbFuture = cbPeriod - cbFrame;
    1085                         LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n",
    1086                                  tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame));
    1087 # endif
    1088                     }
    1089                     uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture);
    1090 
    1091                     /*
    1092                      * Should we transfer a little?  Minimum is 64 bytes (semi-random,
    1093                      * suspect real hardware might be doing some cache aligned stuff,
    1094                      * which might soon get complicated if you take unaligned buffers
    1095                      * into consideration and which cache line size (128 bytes is just
    1096                      * as likely as 64 or 32 bytes)).
    1097                      */
    1098                     uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal;
    1099                     if (cbDmaTotal + 64 <= offNow)
    1100                     {
    1101                         VBOXSTRICTRC rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared, offNow - cbDmaTotal);
    1102 
    1103                         /* LPIB is updated by hdaStreamDoOnAccessDmaOutput, so get the new value. */
    1104                         uint32_t const uNewLpib = HDA_STREAM_REG(pThis, LPIB, uSD);
    1105                         *pu32Value = uNewLpib;
    1106 
    1107                         LogFlowFunc(("[SD%RU8] LPIB=%#RX32 (CBL=%#RX32 PrevLPIB=%#x offNow=%#x) rcStrict=%Rrc\n", uSD,
    1108                                      uNewLpib, HDA_STREAM_REG(pThis, CBL, uSD), uLPIB, offNow, VBOXSTRICTRC_VAL(rcStrict) ));
    1109                         return rcStrict;
    1110                     }
    1111 
    1112                     /*
    1113                      * Do nothing, just return LPIB as it is.
    1114                      */
    1115                     LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", uSD, cbDmaTotal, offNow));
     1065                    /** @todo ASSUMES nanosecond clock ticks, need to make this
     1066                     *        resolution independent. */
     1067                    cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow);
     1068                    cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame);
    11161069                }
    11171070                else
    1118                     LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x!!\n", uSD, cbPeriod, cbFrame));
     1071                {
     1072                    /* We've hit/overshot the timer deadline.  Return to ring-3 if we're
     1073                       not already there to increase the chance that we'll help expidite
     1074                       the timer.  If we're already in ring-3, do all but the last frame. */
     1075# ifndef IN_RING3
     1076                    LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n",
     1077                             tsNow, tsTransferNext));
     1078                    return VINF_IOM_R3_MMIO_READ;
     1079# else
     1080                    cbFuture = cbPeriod - cbFrame;
     1081                    LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n",
     1082                             tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame));
     1083# endif
     1084                }
     1085                uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture);
     1086
     1087                /*
     1088                 * Should we transfer a little?  Minimum is 64 bytes (semi-random,
     1089                 * suspect real hardware might be doing some cache aligned stuff,
     1090                 * which might soon get complicated if you take unaligned buffers
     1091                 * into consideration and which cache line size (128 bytes is just
     1092                 * as likely as 64 or 32 bytes)).
     1093                 */
     1094                uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal;
     1095                if (cbDmaTotal + 64 <= offNow)
     1096                {
     1097                    VBOXSTRICTRC rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared,
     1098                                                                         tsNow, offNow - cbDmaTotal);
     1099
     1100                    /* LPIB is updated by hdaStreamDoOnAccessDmaOutput, so get the new value. */
     1101                    uint32_t const uNewLpib = HDA_STREAM_REG(pThis, LPIB, uSD);
     1102                    *pu32Value = uNewLpib;
     1103
     1104                    LogFlowFunc(("[SD%RU8] LPIB=%#RX32 (CBL=%#RX32 PrevLPIB=%#x offNow=%#x) rcStrict=%Rrc\n", uSD,
     1105                                 uNewLpib, HDA_STREAM_REG(pThis, CBL, uSD), uLPIB, offNow, VBOXSTRICTRC_VAL(rcStrict) ));
     1106                    return rcStrict;
     1107                }
     1108
     1109                /*
     1110                 * Do nothing, just return LPIB as it is.
     1111                 */
     1112                LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", uSD, cbDmaTotal, offNow));
    11191113            }
    11201114            else
    1121                 LogFunc(("[SD%RU8] idxSched=%u cSchedule=%u!!\n", uSD, idxSched, pStreamShared->State.cSchedule));
     1115                LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x!!\n", uSD, cbPeriod, cbFrame));
    11221116        }
    11231117        else
     
    11371131 * Used by hdaRegReadWALCLK() and 'info hda'.
    11381132 *
    1139  * @returns The full wall clock value
     1133 * @returns Strict VBox status code if @a fDoDma is @c true, otherwise
     1134 *          VINF_SUCCESS.
    11401135 * @param   pDevIns     The device instance.
    11411136 * @param   pThis       The shared HDA device state.
    1142  */
    1143 static uint64_t hdaGetWallClock(PPDMDEVINS pDevIns, PHDASTATE pThis)
     1137 * @param   fDoDma      Whether to consider doing DMA work or not.
     1138 * @param   puWallNow   Where to return the current wall clock time.
     1139 */
     1140static VBOXSTRICTRC hdaQueryWallClock(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fDoDma, uint64_t *puWallNow)
    11441141{
    11451142    /*
     
    11751172    uint64_t       tsDmaNow = tsNow;
    11761173    for (size_t i = 0; i < RT_ELEMENTS(pThis->aStreams); i++)
    1177         if (   pThis->aStreams[i].State.fRunning
    1178             && pThis->aStreams[i].State.tsTransferLast < tsDmaNow
    1179             && pThis->aStreams[i].State.tsTransferLast > tsStart)
    1180         {
    1181             tsDmaNow = pThis->aStreams[i].State.tsTransferLast;
    1182             iDmaNow  = (int)i;
     1174        if (pThis->aStreams[i].State.fRunning)
     1175        {
     1176#ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA
     1177            /* Linux is reading WALCLK before one of the DMA position reads and
     1178               we've already got the current time from TM, so check if we should
     1179               do a little bit of DMA'ing here to help WALCLK ahead. */
     1180            if (fDoDma)
     1181            {
     1182                if (hdaGetDirFromSD((uint8_t)i) == PDMAUDIODIR_OUT)
     1183                {
     1184                    VBOXSTRICTRC rcStrict = hdaStreamMaybeDoOnAccessDmaOutput(pDevIns, pThis, &pThis->aStreams[i], tsNow);
     1185                    if (rcStrict == VINF_SUCCESS)
     1186                    { /* likely */ }
     1187                    else
     1188                        return rcStrict;
     1189                }
     1190            }
     1191#endif
     1192
     1193            if (   pThis->aStreams[i].State.tsTransferLast < tsDmaNow
     1194                && pThis->aStreams[i].State.tsTransferLast > tsStart)
     1195            {
     1196                tsDmaNow = pThis->aStreams[i].State.tsTransferLast;
     1197                iDmaNow  = (int)i;
     1198            }
    11831199        }
    11841200
     
    11891205    Log3Func(("Returning %#RX64 - tsNow=%#RX64 tsDmaNow=%#RX64 (%d) -> %#RX64\n",
    11901206              uWallClkNow, tsNow, tsDmaNow, iDmaNow, tsNow - tsDmaNow));
    1191     RT_NOREF(iDmaNow);
    1192     return uWallClkNow;
     1207    RT_NOREF(iDmaNow, fDoDma);
     1208    *puWallNow = uWallClkNow;
     1209    return VINF_SUCCESS;
    11931210}
    11941211
    11951212static VBOXSTRICTRC hdaRegReadWALCLK(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    11961213{
    1197     RT_NOREF(pDevIns, iReg);
    1198     *pu32Value = (uint32_t)hdaGetWallClock(pDevIns, pThis);
    1199     return VINF_SUCCESS;
     1214    uint64_t     uWallNow = 0;
     1215    VBOXSTRICTRC rcStrict = hdaQueryWallClock(pDevIns, pThis, true /*fDoDma*/, &uWallNow);
     1216    if (rcStrict == VINF_SUCCESS)
     1217    {
     1218        *pu32Value = (uint32_t)uWallNow;
     1219        return VINF_SUCCESS;
     1220    }
     1221    RT_NOREF(iReg);
     1222    return rcStrict;
    12001223}
    12011224
     
    15271550                        uint64_t tsTransferNext = tsNow + pStreamShared->State.aSchedule[0].cPeriodTicks;
    15281551                        pStreamShared->State.tsTransferNext = tsTransferNext; /* legacy */
    1529                         pStreamShared->State.cbTransferSize = pStreamShared->State.aSchedule[0].cbPeriod;
     1552                        pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[0].cbPeriod;
    15301553                        Log3Func(("[SD%RU8] tsTransferNext=%RU64 (in %RU64)\n",
    15311554                                  pStreamShared->u8SD, tsTransferNext, tsTransferNext - tsNow));
     
    27472770        {
    27482771#  ifdef DEBUG
    2749             PHDASTREAMDEBUG pStreamDbg = &pStream->Dbg;
    2750 
    27512772            const uint64_t tsNowNs     = RTTimeNanoTS();
    2752             const uint32_t tsElapsedMs = (tsNowNs - pStreamDbg->tsWriteSlotBegin) / 1000 / 1000;
    2753 
    2754             uint64_t cWritesHz   = ASMAtomicReadU64(&pStreamDbg->cWritesHz);
    2755             uint64_t cbWrittenHz = ASMAtomicReadU64(&pStreamDbg->cbWrittenHz);
     2773            const uint32_t tsElapsedMs = (tsNowNs - pStream->Dbg.tsWriteSlotBegin) / 1000 / 1000;
     2774
     2775            uint64_t cWritesHz   = ASMAtomicReadU64(&pStream->Dbg.cWritesHz);
     2776            uint64_t cbWrittenHz = ASMAtomicReadU64(&pStream->Dbg.cbWrittenHz);
    27562777
    27572778            if (tsElapsedMs >= (1000 / HDA_TIMER_HZ_DEFAULT))
     
    27612782                         ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ_DEFAULT));
    27622783
    2763                 pStreamDbg->tsWriteSlotBegin = tsNowNs;
     2784                pStream->Dbg.tsWriteSlotBegin = tsNowNs;
    27642785
    27652786                cWritesHz   = 0;
     
    27702791            cbWrittenHz += cbBuf;
    27712792
    2772             ASMAtomicIncU64(&pStreamDbg->cWritesTotal);
    2773             ASMAtomicAddU64(&pStreamDbg->cbWrittenTotal, cbBuf);
    2774 
    2775             ASMAtomicWriteU64(&pStreamDbg->cWritesHz,   cWritesHz);
    2776             ASMAtomicWriteU64(&pStreamDbg->cbWrittenHz, cbWrittenHz);
     2793            ASMAtomicIncU64(&pStream->Dbg.cWritesTotal);
     2794            ASMAtomicAddU64(&pStream->Dbg.cbWrittenTotal, cbBuf);
     2795
     2796            ASMAtomicWriteU64(&pStream->Dbg.cWritesHz,   cWritesHz);
     2797            ASMAtomicWriteU64(&pStream->Dbg.cbWrittenHz, cbWrittenHz);
    27772798
    27782799            LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n",
     
    27802801
    27812802            LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n",
    2782                      pStream->u8SD, pStreamDbg->cWritesTotal, pStreamDbg->cbWrittenTotal,
    2783                      ASMDivU64ByU32RetU32(pStreamDbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));
     2803                     pStream->u8SD, pStream->Dbg.cWritesTotal, pStream->Dbg.cbWrittenTotal,
     2804                     ASMDivU64ByU32RetU32(pStream->Dbg.cbWrittenTotal, pStream->Dbg.cWritesTotal)));
    27842805#  endif
    27852806
     
    41874208        pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
    41884209    else
    4189         pHlp->pfnPrintf(pHlp, "%s: 0x%RX64\n", g_aHdaRegMap[iHdaIndex].abbrev, hdaGetWallClock(pDevIns, pThis));
     4210    {
     4211        uint64_t uWallNow = 0;
     4212        hdaQueryWallClock(pDevIns, pThis, false /*fDoDma*/, &uWallNow);
     4213        pHlp->pfnPrintf(pHlp, "%s: 0x%RX64\n", g_aHdaRegMap[iHdaIndex].abbrev, uWallNow);
     4214    }
    41904215}
    41914216
     
    52045229        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.offWrite, STAMTYPE_U64, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    52055230                               "Virtual internal buffer write position.",   "Stream%u/offWrite", idxStream);
    5206         PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.cbTransferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    5207                                "Bytes transfered per DMA timer callout.",   "Stream%u/cbTransferSize", idxStream);
     5231        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.cbCurDmaPeriod, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     5232                               "Bytes transfered per DMA timer callout.",   "Stream%u/cbCurDmaPeriod", idxStream);
    52085233        PDMDevHlpSTAMRegisterF(pDevIns, (void*)&pThis->aStreams[idxStream].State.fRunning, STAMTYPE_BOOL, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    52095234                               "True if the stream is in RUN mode.",        "Stream%u/fRunning", idxStream);
  • trunk/src/VBox/Devices/Audio/DevHda.h

    r89861 r89869  
    2828#include "AudioMixer.h"
    2929
    30 #include "DevHdaCodec.h"
    31 #include "DevHdaStream.h"
     30/*
     31 * Compile time feature configuration.
     32 */
     33
     34/** @def VBOX_HDA_WITH_ON_REG_ACCESS_DMA
     35 * Enables doing DMA work on certain register accesses (LPIB, WALCLK) in
     36 * addition to the DMA timer.   All but the last frame can be done during
     37 * register accesses (as we don't wish to leave the DMA timer w/o work to
     38 * do in case that upsets it). */
     39#if defined(DOXYGEN_RUNNING) || 0
     40# define VBOX_HDA_WITH_ON_REG_ACCESS_DMA
     41#endif
    3242
    3343#ifdef DEBUG_andy
     
    3646//# define HDA_STRICT
    3747#endif
     48
     49
     50/*
     51 * Common pointer types.
     52 */
     53/** Pointer to an HDA stream (SDI / SDO).  */
     54typedef struct HDASTREAMR3 *PHDASTREAMR3;
     55/** Pointer to a shared HDA device state.  */
     56typedef struct HDASTATE    *PHDASTATE;
     57/** Pointer to a ring-3 HDA device state.  */
     58typedef struct HDASTATER3  *PHDASTATER3;
     59
     60
     61/*
     62 * The rest of the headers.
     63 */
     64#include "DevHdaCommon.h"
     65#include "DevHdaStream.h"
     66#include "DevHdaCodec.h"
     67
    3868
    3969/**
     
    277307    } Dbg;
    278308} HDASTATER3;
    279 /** Pointer to a ring-3 HDA device state.  */
    280 typedef HDASTATER3 *PHDASTATER3;
    281309
    282310
  • trunk/src/VBox/Devices/Audio/DevHdaCodec.cpp

    r89768 r89869  
    4040#include "VBoxDD.h"
    4141#include "AudioMixer.h"
     42#include "DevHda.h"
    4243#include "DevHdaCodec.h"
    4344#include "DevHdaCommon.h"
  • trunk/src/VBox/Devices/Audio/DevHdaCodec.h

    r89810 r89869  
    2222#endif
    2323
     24#ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h
     25# error "Only include DevHda.h!"
     26#endif
     27
    2428#include <iprt/list.h>
    25 
    2629#include "AudioMixer.h"
    2730
    28 /** Pointer to a shared HDA device state.  */
    29 typedef struct HDASTATE *PHDASTATE;
    30 /** Pointer to a ring-3 HDA device state.  */
    31 typedef struct HDASTATER3 *PHDASTATER3;
    3231
    3332/** The ICH HDA (Intel) common codec state. */
     
    3938/** The ICH HDA (Intel) current context codec state. */
    4039typedef CTX_SUFF(PHDACODEC) PHDACODECCC;
    41 
    42 /** The HDA host driver backend. */
    43 typedef struct HDADRIVER *PHDADRIVER;
    4440
    4541/**
  • trunk/src/VBox/Devices/Audio/DevHdaCommon.cpp

    r89406 r89869  
    3434#include "DevHda.h"
    3535#include "DevHdaCommon.h"
    36 #include "DevHdaStream.h"
    3736
    3837
  • trunk/src/VBox/Devices/Audio/DevHdaCommon.h

    r88235 r89869  
    2525#endif
    2626
     27#ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h
     28# error "Only include DevHda.h!"
     29#endif
     30
    2731#include "AudioMixer.h"
    2832#include <VBox/log.h> /* LOG_ENABLED */
    29 
    30 /** Pointer to an HDA stream (SDI / SDO).  */
    31 typedef struct HDASTREAMR3 *PHDASTREAMR3;
    32 
    3333
    3434
  • trunk/src/VBox/Devices/Audio/DevHdaStream.cpp

    r89865 r89869  
    3434
    3535#include "DevHda.h"
    36 #include "DevHdaStream.h"
    3736
    3837#ifdef VBOX_WITH_DTRACE
     
    649648        return rc;
    650649
    651     pStreamShared->State.cbTransferSize = pStreamShared->State.aSchedule[0].cbPeriod;
     650    pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[0].cbPeriod;
    652651
    653652    /*
     
    14631462    PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
    14641463    uint32_t   cbLeft   = cbToConsume;
    1465     Assert(cbLeft == pStreamShared->State.cbTransferSize);
     1464    Assert(cbLeft == pStreamShared->State.cbCurDmaPeriod);
    14661465    Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft));
    14671466
     
    16071606     */
    16081607    Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n",
    1609               uSD, cbToConsume, pStreamShared->State.cbTransferSize, pStreamShared->State.offRead - cbToConsume,
     1608              uSD, cbToConsume, pStreamShared->State.cbCurDmaPeriod, pStreamShared->State.offRead - cbToConsume,
    16101609              pStreamShared->State.cTransferPendingInterrupts));
    16111610}
     
    16841683    uint32_t   cbLeft   = cbToProduce;
    16851684# ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA
    1686     Assert(cbLeft <= pStreamShared->State.cbTransferSize); /* a little pointless with the DMA'ing on LPIB read. */
     1685    Assert(cbLeft <= pStreamShared->State.cbCurDmaPeriod); /* a little pointless with the DMA'ing on LPIB read. */
    16871686# else
    1688     Assert(cbLeft == pStreamShared->State.cbTransferSize);
     1687    Assert(cbLeft == pStreamShared->State.cbCurDmaPeriod);
    16891688# endif
    16901689    Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft));
     
    18681867     */
    18691868    Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n",
    1870               uSD, cbToProduce, pStreamShared->State.cbTransferSize, pStreamShared->State.offWrite - cbToProduce,
     1869              uSD, cbToProduce, pStreamShared->State.cbCurDmaPeriod, pStreamShared->State.offWrite - cbToProduce,
    18711870              pStreamShared->State.cTransferPendingInterrupts));
    18721871}
    18731872
    18741873#endif /* IN_RING3 */
    1875 
    18761874#ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA
    1877 /**
    1878  * Do DMA output transfer on LPIB register access.
     1875
     1876/**
     1877 * Do DMA output transfer on LPIB/WALCLK register access.
    18791878 *
    18801879 * @returns VINF_SUCCESS or VINF_IOM_R3_MMIO_READ.
     
    18821881 * @param   pThis           The shared instance data.
    18831882 * @param   pStreamShared   The shared stream data.
     1883 * @param   tsNow           The current time on the timer clock.
    18841884 * @param   cbToTransfer    How much to transfer.
    18851885 */
    1886 VBOXSTRICTRC hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint32_t cbToTransfer)
     1886VBOXSTRICTRC hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared,
     1887                                          uint64_t tsNow, uint32_t cbToTransfer)
    18871888{
    18881889    AssertReturn(cbToTransfer > 0, VINF_SUCCESS);
     
    19921993
    19931994        /*
    1994          * Advance LPIB.
     1995         * Advance LPIB and update the last transfer time (for WALCLK).
    19951996         */
     1997        pStreamShared->State.tsTransferLast = tsNow;
    19961998        hdaStreamSetPositionAdd(pStreamShared, pDevIns, pThis, cbToTransfer - cbLeft);
    19971999    }
     
    20072009    return rc;
    20082010}
     2011
     2012
     2013/**
     2014 * Consider doing DMA output transfer on LPIB/WALCLK register access.
     2015 *
     2016 * @returns VINF_SUCCESS or VINF_IOM_R3_MMIO_READ.
     2017 * @param   pDevIns         The device instance.
     2018 * @param   pThis           The shared instance data.
     2019 * @param   pStreamShared   The shared stream data.
     2020 * @param   tsNow           The current time on the timer clock.  Used to do the
     2021 *                          calculation.
     2022 */
     2023VBOXSTRICTRC hdaStreamMaybeDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint64_t tsNow)
     2024{
     2025    Assert(pStreamShared->State.fRunning); /* caller should check this */
     2026
     2027    /*
     2028     * Calculate where the DMA engine should be according to the clock, if we can.
     2029     */
     2030    uint32_t const cbFrame  = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props);
     2031    uint32_t const cbPeriod = pStreamShared->State.cbCurDmaPeriod;
     2032    if (cbPeriod > cbFrame)
     2033    {
     2034        AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod));
     2035        uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext;
     2036        uint32_t       cbFuture;
     2037        if (tsNow < tsTransferNext)
     2038        {
     2039            /** @todo ASSUMES nanosecond clock ticks, need to make this
     2040             *        resolution independent. */
     2041            cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow);
     2042            cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame);
     2043        }
     2044        else
     2045        {
     2046            /* We've hit/overshot the timer deadline.  Return to ring-3 if we're
     2047               not already there to increase the chance that we'll help expidite
     2048               the timer.  If we're already in ring-3, do all but the last frame. */
     2049# ifndef IN_RING3
     2050            LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n",
     2051                     tsNow, tsTransferNext));
     2052            return VINF_IOM_R3_MMIO_READ;
     2053# else
     2054            cbFuture = cbPeriod - cbFrame;
     2055            LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n",
     2056                     tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame));
     2057# endif
     2058        }
     2059        uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture);
     2060
     2061        /*
     2062         * Should we transfer a little?  Minimum is 64 bytes (semi-random,
     2063         * suspect real hardware might be doing some cache aligned stuff,
     2064         * which might soon get complicated if you take unaligned buffers
     2065         * into consideration and which cache line size (128 bytes is just
     2066         * as likely as 64 or 32 bytes)).
     2067         */
     2068        uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal;
     2069        if (cbDmaTotal + 64 <= offNow)
     2070        {
     2071# ifdef LOG_ENABLED
     2072            uint32_t const uOldLpib = HDA_STREAM_REG(pThis, CBL, pStreamShared->u8SD);
     2073# endif
     2074            VBOXSTRICTRC   rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared, tsNow, offNow - cbDmaTotal);
     2075            LogFlowFunc(("[SD%RU8] LPIB=%#RX32 -> LPIB=%#RX32 offNow=%#x rcStrict=%Rrc\n", pStreamShared->u8SD,
     2076                         uOldLpib, HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD), offNow, VBOXSTRICTRC_VAL(rcStrict) ));
     2077            return rcStrict;
     2078        }
     2079
     2080        /*
     2081         * Do nothing.
     2082         */
     2083        LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", pStreamShared->u8SD, cbDmaTotal, offNow));
     2084    }
     2085    else
     2086        LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x\n", pStreamShared->u8SD, cbPeriod, cbFrame));
     2087    return VINF_SUCCESS;
     2088}
     2089
    20092090#endif /* VBOX_HDA_WITH_ON_REG_ACCESS_DMA */
    2010 
    2011 
    20122091#ifdef IN_RING3
    20132092
     
    22402319        /* Some legacy stuff: */
    22412320        pStreamShared->State.tsTransferNext = tsTransferNext;
    2242         pStreamShared->State.cbTransferSize = pStreamShared->State.aSchedule[idxSched].cbPeriod;
     2321        pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[idxSched].cbPeriod;
    22432322
    22442323        return tsNow;
  • trunk/src/VBox/Devices/Audio/DevHdaStream.h

    r89861 r89869  
    2222#endif
    2323
    24 #include "DevHdaCommon.h"
     24#ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h
     25# error "Only include DevHda.h!"
     26#endif
    2527
    2628
     
    8385#endif
    8486} HDASTREAMDEBUG;
    85 typedef HDASTREAMDEBUG *PHDASTREAMDEBUG;
    8687
    8788/**
     
    132133     *  Can be 0 if no next transfer is scheduled. */
    133134    uint64_t                tsTransferNext;
    134     /** Total transfer size (in bytes) of a transfer period. */
    135     uint32_t                cbTransferSize;
     135    /** The size of the current DMA transfer period. */
     136    uint32_t                cbCurDmaPeriod;
    136137    /** The size of an average transfer. */
    137138    uint32_t                cbAvgTransfer;
     
    324325 */
    325326VBOXSTRICTRC        hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared,
    326                                                  uint32_t cbToTransfer);
     327                                                 uint64_t tsNow, uint32_t cbToTransfer);
     328VBOXSTRICTRC        hdaStreamMaybeDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis,
     329                                                      PHDASTREAM pStreamShared, uint64_t tsNow);
    327330/** @} */
    328331
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