VirtualBox

Changeset 67333 in vbox for trunk/src


Ignore:
Timestamp:
Jun 12, 2017 7:42:00 AM (8 years ago)
Author:
vboxsync
Message:

HDA: Updated interrupt logic to observe enable bits.

File:
1 edited

Legend:

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

    r67265 r67333  
    195195#define HDA_INTCTL_CIE              RT_BIT(30)  /* Controller Interrupt Enable */
    196196/* Bits 0-29 correspond to streams 0-29. */
     197#define HDA_STRMINT_MASK            0xFF        /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
    197198
    198199#define HDA_REG_INTSTS              12 /* 0x24 */
     
    935936static void          hdaDoTransfers(PHDASTATE pThis);
    936937#endif /* IN_RING3 */
    937 static int           hdaProcessInterrupt(PHDASTATE pThis);
    938938/** @} */
    939939
     
    13451345    uint32_t intSts = 0;
    13461346
    1347     /** @todo r=michaln This is ignoring HDA_RIRBCTL_ROIC! */
    1348     if (/* Response Overrun Interrupt Status (ROIS aka RIRBOIS) */
    1349            (HDA_REG(pThis, RIRBSTS) & HDA_RIRBSTS_RIRBOIS)
    1350         /* Response Interrupt */
    1351         || (HDA_REG(pThis, RIRBSTS) & HDA_RIRBSTS_RINTFL)
     1347    /* Check controller interrupts (RIRB, STATEST) */
     1348    if (   (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
    13521349        /* SDIN State Change Status Flags (SCSF) */
    13531350        || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
     
    13561353    }
    13571354
    1358     /** @todo r=michaln The logic here ignores enable bits and is generally completely broken. */
     1355    /* For each stream, check if any interrupt status bit is set and enabled. */
    13591356    for (int iStrm = 0; iStrm < 8; ++iStrm)
    13601357    {
    1361         if (   (HDA_REG(pThis, INTCTL) & RT_BIT(iStrm))
    1362             && (HDA_STREAM_REG(pThis, STS, iStrm) & (HDA_SDSTS_DESE | HDA_SDSTS_FIFOE | HDA_SDSTS_BCIS)))
     1358        if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE  | HDA_SDCTL_IOCE))
    13631359        {
    1364             Log3Func(("[SD%d] interrupt set\n", iStrm));
     1360            Log3Func(("[SD%d] interrupt status set\n", iStrm));
    13651361            intSts |= RT_BIT(iStrm);
    13661362        }
     
    13711367
    13721368    HDA_REG(pThis, INTSTS) = intSts;
    1373 
    13741369    Log3Func(("INTSTS=%x\n", intSts));
    13751370}
    13761371
    1377 static int hdaProcessInterrupt(PHDASTATE pThis)
     1372/* Update INTSTS register and the hardware interrupt signal. This function must be called
     1373 * after changing any interrupt status or enable bits.
     1374 */
     1375static int hdaUpdateInterrupt(PHDASTATE pThis)
    13781376{
    13791377    hdaUpdateINTSTS(pThis);
     
    13811379    int iLevel = 0;
    13821380
    1383     /* Global Interrupt Status (GIS) set? */
    1384     /** @todo r=michaln: This is wrong. It is possible to have GIS set when CIS and all stream interrupts are disabled. */
    1385     if (HDA_REG(pThis, INTSTS) & HDA_INTSTS_GIS)
    1386         iLevel = 1;
     1381    /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
     1382     * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
     1383     */
     1384
     1385    /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */
     1386    if (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
     1387        if (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK))
     1388            iLevel = 1;
    13871389
    13881390    Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel));
    13891391
    1390     /* Global Interrupt Enable (GIE) set? */
    1391     if (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
    1392         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel);
     1392    PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel);
    13931393
    13941394    return VINF_SUCCESS;
     
    16111611    Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
    16121612
    1613     if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RINTCTL)
    1614     {
    1615         HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
    1616 
    1617         pThis->u8RespIntCnt = 0;
    1618         rc = hdaProcessInterrupt(pThis);
    1619     }
     1613    HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
     1614
     1615    pThis->u8RespIntCnt = 0;
     1616    rc = hdaUpdateInterrupt(pThis);
    16201617
    16211618    if (RT_FAILURE(rc))
     
    20712068    HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
    20722069
    2073     return hdaProcessInterrupt(pThis);
     2070    return hdaUpdateInterrupt(pThis);
    20742071}
    20752072
     
    20822079    HDA_REG(pThis, INTCTL) = u32Value;
    20832080
    2084     /* Global Interrupt Enable (GIE) set? */
    2085     if (u32Value & HDA_INTCTL_GIE)
    2086     {
    2087         rc = hdaProcessInterrupt(pThis);
    2088     }
    2089     else
    2090     {
    2091         /* Make sure to lower interrupt line, as Global Interrupt Enable (GIE) is disabled. */
    2092         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* iLevel */);
    2093 
    2094         rc = VINF_SUCCESS;
    2095     }
     2081    rc = hdaUpdateInterrupt(pThis);
    20962082
    20972083    return rc;
     
    23192305
    23202306    /* Make sure to handle interrupts here as well. */
    2321     hdaProcessInterrupt(pThis);
     2307    hdaUpdateInterrupt(pThis);
    23222308
    23232309    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     
    23372323    LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg)));
    23382324
    2339     hdaProcessInterrupt(pThis);
     2325    hdaUpdateInterrupt(pThis);
    23402326    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    23412327}
     
    30072993    HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
    30082994
    3009     return hdaProcessInterrupt(pThis);
     2995    return hdaUpdateInterrupt(pThis);
    30102996}
    30112997
     
    41264112        Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    41274113
    4128         hdaProcessInterrupt(pThis);
     4114        hdaUpdateInterrupt(pThis);
    41294115    }
    41304116
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