VirtualBox

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


Ignore:
Timestamp:
Jun 14, 2017 2:48:16 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
116135
Message:

Audio/DevHDA: Forward ported / integrated timer code. WIP.

File:
1 edited

Legend:

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

    r67400 r67410  
    104104
    105105/** Default timer frequency (in Hz). */
    106 #define HDA_TIMER_HZ            100
     106#define HDA_TIMER_HZ            200
    107107
    108108/**
     
    789789#endif
    790790} HDADRIVER;
     791
     792#ifdef DEBUG
     793/** @todo Make STAM values out of this? */
     794typedef struct HDASTATEDBGINFO
     795{
     796    /** Timestamp (in ns) of the last timer callback (hdaTimer).
     797     * Used to calculate the time actually elapsed between two timer callbacks. */
     798    uint64_t                           tsTimerLastCalledNs;
     799    /** IRQ debugging information. */
     800    struct
     801    {
     802        /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
     803        uint64_t                       tsProcessedLastNs;
     804        /** Timestamp (in ns) of last asserted IRQ. */
     805        uint64_t                       tsAssertedNs;
     806        /** How many IRQs have been asserted already. */
     807        uint64_t                       cAsserted;
     808        /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
     809        uint64_t                       tsAssertedTotalNs;
     810        /** Timestamp (in ns) of last deasserted IRQ. */
     811        uint64_t                       tsDeassertedNs;
     812        /** How many IRQs have been deasserted already. */
     813        uint64_t                       cDeasserted;
     814        /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
     815        uint64_t                       tsDeassertedTotalNs;
     816    } IRQ;
     817} HDASTATEDBGINFO, *PHDASTATEDBGINFO;
     818#endif
    791819
    792820/**
     
    853881    /** The current timer expire time (in timer ticks). */
    854882    uint64_t                           tsTimerExpire;
    855     /** Timestamp of the last timer callback (hdaTimer).
    856      * Used to calculate the time actually elapsed between two timer callbacks. */
    857     uint64_t                           uTimerTS;
    858     uint64_t                           uTimerMS;
    859883#endif
    860884#ifdef VBOX_WITH_STATISTICS
     
    894918    /** Response Interrupt Count (RINTCNT). */
    895919    uint8_t                            u8RespIntCnt;
     920    /** Current IRQ level. */
     921    uint8_t                            u8IRQL;
    896922    /** Padding for alignment. */
    897     uint8_t                            au8Padding2[7];
     923    uint8_t                            au8Padding2[6];
     924#ifdef DEBUG
     925    HDASTATEDBGINFO                    Dbg;
     926#endif
    898927} HDASTATE;
    899928/** Pointer to the ICH Intel HD Audio Controller state. */
     
    937966static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    938967static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    939 static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    940968static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    941969static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
     
    11491177    { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16   , hdaRegWriteU16     , HDA_REG_IDX(OUTSTRMPAY)   }, /* Output Stream Payload Capability */
    11501178    { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16   , hdaRegWriteUnimpl  , HDA_REG_IDX(INSTRMPAY)    }, /* Input Stream Payload Capability */
    1151     { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, HDA_RD_FLAG_NONE, hdaRegReadU32   , hdaRegWriteINTCTL  , HDA_REG_IDX(INTCTL)       }, /* Interrupt Control */
     1179    { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, HDA_RD_FLAG_NONE, hdaRegReadU32   , hdaRegWriteU32     , HDA_REG_IDX(INTCTL)       }, /* Interrupt Control */
    11521180    { 0x00024, 0x00004, 0xC00000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU32   , hdaRegWriteUnimpl  , HDA_REG_IDX(INTSTS)       }, /* Interrupt Status */
    11531181    { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadWALCLK, hdaRegWriteUnimpl  , HDA_REG_IDX_NOMEM(WALCLK) }, /* Wall Clock Counter */
     
    14551483#endif /* IN_RING3 */
    14561484
    1457 
    1458 static void hdaUpdateINTSTS(PHDASTATE pThis)
     1485static uint32_t hdaGetINTSTS(PHDASTATE pThis)
    14591486{
    14601487    uint32_t intSts = 0;
    14611488
    1462     /* Check controller interrupts (RIRB, STATEST) */
     1489    /* Check controller interrupts (RIRB, STATEST). */
    14631490    if (   (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
    1464         /* SDIN State Change Status Flags (SCSF) */
     1491        /* SDIN State Change Status Flags (SCSF). */
    14651492        || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
    14661493    {
    1467         intSts |= HDA_INTSTS_CIS;   /* Set the Controller Interrupt Status (CIS). */
     1494        intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
     1495    }
     1496
     1497    if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
     1498    {
     1499        intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */
    14681500    }
    14691501
    14701502    /* For each stream, check if any interrupt status bit is set and enabled. */
    1471     for (int iStrm = 0; iStrm < 8; ++iStrm)
     1503    for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)
    14721504    {
    14731505        if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE  | HDA_SDCTL_IOCE))
     
    14791511
    14801512    if (intSts)
    1481         intSts |= HDA_INTSTS_GIS;   /* Set the Global Interrupt Status (GIS). */
    1482 
    1483     HDA_REG(pThis, INTSTS) = intSts;
    1484     Log3Func(("INTSTS=%x\n", intSts));
    1485 }
    1486 
    1487 /* Update INTSTS register and the hardware interrupt signal. This function must be called
    1488  * after changing any interrupt status or enable bits.
    1489  */
    1490 static int hdaUpdateInterrupt(PHDASTATE pThis)
    1491 {
    1492     hdaUpdateINTSTS(pThis);
    1493 
    1494     int iLevel = 0;
     1513        intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
     1514
     1515    Log3Func(("-> 0x%x\n", intSts));
     1516
     1517    return intSts;
     1518}
     1519
     1520#ifndef DEBUG
     1521static int hdaProcessInterrupt(PHDASTATE pThis)
     1522#else
     1523static int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource)
     1524#endif
     1525{
     1526    HDA_REG(pThis, INTSTS) = hdaGetINTSTS(pThis);
     1527
     1528    Log3Func(("IRQL=%RU8\n", pThis->u8IRQL));
    14951529
    14961530    /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
     
    14991533
    15001534    /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */
    1501     if (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
    1502         if (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK))
    1503             iLevel = 1;
    1504 
    1505     Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel));
    1506 
    1507     PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel);
     1535    if (   (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
     1536        && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))
     1537    {
     1538        if (!pThis->u8IRQL)
     1539        {
     1540#ifdef DEBUG
     1541            if (!pThis->Dbg.IRQ.tsProcessedLastNs)
     1542                pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
     1543
     1544            const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
     1545
     1546            if (!pThis->Dbg.IRQ.tsAssertedNs)
     1547                pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
     1548
     1549            const uint64_t tsAssertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsAssertedNs;
     1550
     1551            pThis->Dbg.IRQ.cAsserted++;
     1552            pThis->Dbg.IRQ.tsAssertedTotalNs += tsAssertedElapsedNs;
     1553
     1554            const uint64_t avgAssertedUs = (pThis->Dbg.IRQ.tsAssertedTotalNs / pThis->Dbg.IRQ.cAsserted) / 1000;
     1555
     1556            if (avgAssertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
     1557                Log3Func(("Asserted (%s): %zuus elapsed (%zuus on average) -- %zuus alternation delay\n",
     1558                          pszSource, tsAssertedElapsedNs / 1000,
     1559                          avgAssertedUs,
     1560                          (pThis->Dbg.IRQ.tsDeassertedNs - pThis->Dbg.IRQ.tsAssertedNs) / 1000));
     1561#endif
     1562            Log3Func(("Asserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
     1563                      pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
     1564
     1565            PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1 /* Assert */);
     1566            pThis->u8IRQL = 1;
     1567
     1568#ifdef DEBUG
     1569            pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
     1570            pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
     1571#endif
     1572        }
     1573    }
     1574    else
     1575    {
     1576        if (pThis->u8IRQL)
     1577        {
     1578#ifdef DEBUG
     1579            if (!pThis->Dbg.IRQ.tsProcessedLastNs)
     1580                pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
     1581
     1582            const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
     1583
     1584            if (!pThis->Dbg.IRQ.tsDeassertedNs)
     1585                pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();
     1586
     1587            const uint64_t tsDeassertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsDeassertedNs;
     1588
     1589            pThis->Dbg.IRQ.cDeasserted++;
     1590            pThis->Dbg.IRQ.tsDeassertedTotalNs += tsDeassertedElapsedNs;
     1591
     1592            const uint64_t avgDeassertedUs = (pThis->Dbg.IRQ.tsDeassertedTotalNs / pThis->Dbg.IRQ.cDeasserted) / 1000;
     1593
     1594            if (avgDeassertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
     1595                Log3Func(("Deasserted (%s): %zuus elapsed (%zuus on average)\n",
     1596                          pszSource, tsDeassertedElapsedNs / 1000, avgDeassertedUs));
     1597
     1598            Log3Func(("Deasserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
     1599                      pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
     1600#endif
     1601            PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* Deassert */);
     1602            pThis->u8IRQL = 0;
     1603
     1604#ifdef DEBUG
     1605            pThis->Dbg.IRQ.tsDeassertedNs    = RTTimeNanoTS();
     1606            pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsDeassertedNs;
     1607#endif
     1608        }
     1609    }
    15081610
    15091611    return VINF_SUCCESS;
     
    17241826    rc = hdaCmdSync(pThis, false);
    17251827
    1726     Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
    1727 
    1728     HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
    1729 
    1730     pThis->u8RespIntCnt = 0;
    1731     rc = hdaUpdateInterrupt(pThis);
     1828    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n",
     1829              HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
     1830
     1831    if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_ROIC) /* Response Interrupt Control (ROIC) enabled? */
     1832    {
     1833        if (pThis->u8RespIntCnt)
     1834        {
     1835            pThis->u8RespIntCnt = 0;
     1836
     1837            HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
     1838
     1839#ifndef DEBUG
     1840            rc = hdaProcessInterrupt(pThis);
     1841#else
     1842            rc = hdaProcessInterrupt(pThis, __FUNCTION__);
     1843#endif
     1844        }
     1845    }
    17321846
    17331847    if (RT_FAILURE(rc))
     
    19212035    }
    19222036
     2037    if (fEnable)
     2038    {
     2039        /* Begin a new period for this stream. */
     2040        int rc2 = hdaStreamPeriodBegin(&pStream->State.Period, hdaWalClkGetCurrent(pThis)/* Use current wall clock time */);
     2041        AssertRC(rc2);
     2042    }
     2043    else
     2044    {
     2045        /* Reset the period. */
     2046        hdaStreamPeriodReset(&pStream->State.Period);
     2047    }
     2048
    19232049#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
    19242050    hdaStreamAsyncIOUnlock(pStream);
     
    21912317    HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
    21922318
    2193     return hdaUpdateInterrupt(pThis);
    2194 }
    2195 
    2196 static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    2197 {
    2198     RT_NOREF(iReg);
    2199 
    2200     int rc;
    2201 
    2202     HDA_REG(pThis, INTCTL) = u32Value;
    2203 
    2204     rc = hdaUpdateInterrupt(pThis);
    2205 
    2206     return rc;
     2319    return VINF_SUCCESS;
    22072320}
    22082321
     
    24552568}
    24562569
     2570#ifdef IN_RING3
     2571/**
     2572 * Reschedules pending interrupts for all audio streams which have complete
     2573 * audio periods but did not have the chance to issue their (pending) interrupts yet.
     2574 *
     2575 * @param   pThis               The HDA device state.
     2576 */
     2577static void hdaReschedulePendingInterrupts(PHDASTATE pThis)
     2578{
     2579    bool fInterrupt = false;
     2580
     2581    for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
     2582    {
     2583        PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
     2584
     2585        if (   hdaStreamPeriodIsComplete    (&pStream->State.Period)
     2586            && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period)
     2587            && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
     2588        {
     2589            fInterrupt = true;
     2590            break;
     2591        }
     2592    }
     2593
     2594    LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
     2595
     2596    if (fInterrupt)
     2597    {
     2598#ifndef DEBUG
     2599        hdaProcessInterrupt(pThis);
     2600#else
     2601        hdaProcessInterrupt(pThis, __FUNCTION__);
     2602#endif
     2603    }
     2604}
     2605#endif
     2606
    24572607static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    24582608{
     
    25532703
    25542704            hdaStreamEnable(pThis, pStream, fRun /* fEnable */);
     2705
     2706            if (!fRun)
     2707            {
     2708                /* Make sure to (re-)schedule outstanding (delayed) interrupts. */
     2709                hdaReschedulePendingInterrupts(pThis);
     2710            }
    25552711        }
    25562712    }
     
    25582714    int rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
    25592715    AssertRC(rc2);
    2560 
    2561     /* Make sure to handle interrupts here as well. */
    2562     hdaUpdateInterrupt(pThis);
    25632716
    25642717    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     
    25712724static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    25722725{
     2726#ifdef IN_RING3
    25732727    uint32_t v = HDA_REG_IND(pThis, iReg);
     2728
     2729    PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, STS, iReg));
     2730    if (!pStream)
     2731    {
     2732        AssertMsgFailed(("[SD%RU8]: Warning: Writing SDSTS on non-attached stream (0x%x)\n",
     2733                         HDA_SD_NUM_FROM_REG(pThis, STS, iReg), u32Value));
     2734        return hdaRegWriteU16(pThis, iReg, u32Value);
     2735    }
    25742736
    25752737    /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */
    25762738    HDA_REG_IND(pThis, iReg) &= ~(u32Value & v);
    25772739
    2578     LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg)));
    2579 
    2580     hdaUpdateInterrupt(pThis);
    2581     return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     2740    /* Some guests tend to write SDnSTS even if the stream is not running.
     2741     * So make sure to check if the RUN bit is set first. */
     2742    const bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_RUN);
     2743
     2744    Log3Func(("[SD%RU8] fRun=%RTbool %R[sdsts]\n", pStream->u8SD, fInRun, v));
     2745
     2746    PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
     2747
     2748    if (hdaStreamPeriodLock(pPeriod))
     2749    {
     2750        const bool fNeedsInterrupt = hdaStreamPeriodNeedsInterrupt(pPeriod);
     2751        if (fNeedsInterrupt)
     2752            hdaStreamPeriodReleaseInterrupt(pPeriod);
     2753
     2754        if (hdaStreamPeriodIsComplete(pPeriod))
     2755        {
     2756            hdaStreamPeriodEnd(pPeriod);
     2757
     2758            if (fInRun)
     2759                hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
     2760        }
     2761
     2762        hdaStreamPeriodUnlock(pPeriod); /* Unlock before processing interrupt. */
     2763
     2764        if (fNeedsInterrupt)
     2765        {
     2766#ifndef DEBUG
     2767            hdaProcessInterrupt(pThis);
     2768#else
     2769            hdaProcessInterrupt(pThis, __FUNCTION__);
     2770#endif
     2771        }
     2772    }
     2773
     2774    return VINF_SUCCESS;
     2775#else /* IN_RING3 */
     2776    RT_NOREF(pThis, iReg, u32Value);
     2777    return VINF_IOM_R3_MMIO_WRITE;
     2778#endif /* !IN_RING3 */
    25822779}
    25832780
     
    32683465    HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
    32693466
    3270     return hdaUpdateInterrupt(pThis);
     3467#ifndef DEBUG
     3468    return hdaProcessInterrupt(pThis);
     3469#else
     3470    return hdaProcessInterrupt(pThis, __FUNCTION__);
     3471#endif
    32713472}
    32723473
     
    41744375
    41754376        /* Update current time timestamp. */
    4176         pThis->uTimerTS = TMTimerGet(pThis->pTimer);
     4377        pThis->tsTimerExpire = TMTimerGet(pThis->pTimer) + pThis->cTimerTicks;
    41774378
    41784379        /* Start transfers. */
     
    41924393    /* Set timer flag. */
    41934394    ASMAtomicXchgBool(&pThis->fTimerActive, false);
     4395
     4396    /*
     4397     * Stop the timer, if any.
     4398     */
     4399    if (   pThis->pTimer
     4400        && TMTimerIsActive(pThis->pTimer))
     4401    {
     4402        int rc2 = TMTimerStop(pThis->pTimer);
     4403        AssertRC(rc2);
     4404    }
    41944405}
    41954406
     
    42284439
    42294440    STAM_PROFILE_START(&pThis->StatTimer, a);
    4230 
    4231     uint64_t cTicksNow = TMTimerGet(pThis->pTimer);
    4232 
    4233     /* Update current time timestamp. */
    4234     pThis->uTimerTS = cTicksNow;
    42354441
    42364442    /* Flag indicating whether to kick the timer again for a
     
    42554461    }
    42564462
    4257     pThis->uTimerMS = RTTimeMilliTS();
    4258 
    42594463    if (   ASMAtomicReadBool(&pThis->fTimerActive)
    42604464        || fKickTimer)
    42614465    {
    42624466        /* Kick the timer again. */
    4263         uint64_t cTicks = pThis->cTimerTicks;
    4264         /** @todo adjust cTicks down by now much cbOutMin represents. */
    4265         TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     4467        pThis->tsTimerExpire += pThis->cTimerTicks;
     4468        TMTimerSet(pThis->pTimer, pThis->tsTimerExpire);
    42664469    }
    42674470    else
     
    46924895        Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    46934896
    4694         hdaUpdateInterrupt(pThis);
     4897#ifndef DEBUG
     4898        hdaProcessInterrupt(pThis);
     4899#else
     4900        hdaProcessInterrupt(pThis, __FUNCTION__);
     4901#endif
    46954902    }
    46964903
     
    72537460    if (RT_SUCCESS(rc))
    72547461    {
    7255         /* Create the emulation timer. */
    7256         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis,
     7462        /* Create the emulation timer.
     7463         *
     7464         * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
     7465         *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
     7466         *        instead of the LPIB registers.
     7467         */
     7468        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, pThis,
    72577469                                    TMTIMER_FLAGS_NO_CRIT_SECT, "DevHDA", &pThis->pTimer);
    72587470        AssertRCReturn(rc, rc);
     
    72617473        {
    72627474            pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
    7263             pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
    72647475            LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
    72657476        }
Note: See TracChangeset for help on using the changeset viewer.

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