- Timestamp:
- Jun 12, 2017 7:42:00 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r67265 r67333 195 195 #define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */ 196 196 /* Bits 0-29 correspond to streams 0-29. */ 197 #define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */ 197 198 198 199 #define HDA_REG_INTSTS 12 /* 0x24 */ … … 935 936 static void hdaDoTransfers(PHDASTATE pThis); 936 937 #endif /* IN_RING3 */ 937 static int hdaProcessInterrupt(PHDASTATE pThis);938 938 /** @} */ 939 939 … … 1345 1345 uint32_t intSts = 0; 1346 1346 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)) 1352 1349 /* SDIN State Change Status Flags (SCSF) */ 1353 1350 || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK)) … … 1356 1353 } 1357 1354 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. */ 1359 1356 for (int iStrm = 0; iStrm < 8; ++iStrm) 1360 1357 { 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)) 1363 1359 { 1364 Log3Func(("[SD%d] interrupt s et\n", iStrm));1360 Log3Func(("[SD%d] interrupt status set\n", iStrm)); 1365 1361 intSts |= RT_BIT(iStrm); 1366 1362 } … … 1371 1367 1372 1368 HDA_REG(pThis, INTSTS) = intSts; 1373 1374 1369 Log3Func(("INTSTS=%x\n", intSts)); 1375 1370 } 1376 1371 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 */ 1375 static int hdaUpdateInterrupt(PHDASTATE pThis) 1378 1376 { 1379 1377 hdaUpdateINTSTS(pThis); … … 1381 1379 int iLevel = 0; 1382 1380 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; 1387 1389 1388 1390 Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel)); 1389 1391 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); 1393 1393 1394 1394 return VINF_SUCCESS; … … 1611 1611 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP))); 1612 1612 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); 1620 1617 1621 1618 if (RT_FAILURE(rc)) … … 2071 2068 HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */ 2072 2069 2073 return hda ProcessInterrupt(pThis);2070 return hdaUpdateInterrupt(pThis); 2074 2071 } 2075 2072 … … 2082 2079 HDA_REG(pThis, INTCTL) = u32Value; 2083 2080 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); 2096 2082 2097 2083 return rc; … … 2319 2305 2320 2306 /* Make sure to handle interrupts here as well. */ 2321 hda ProcessInterrupt(pThis);2307 hdaUpdateInterrupt(pThis); 2322 2308 2323 2309 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ … … 2337 2323 LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg))); 2338 2324 2339 hda ProcessInterrupt(pThis);2325 hdaUpdateInterrupt(pThis); 2340 2326 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2341 2327 } … … 3007 2993 HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value); 3008 2994 3009 return hda ProcessInterrupt(pThis);2995 return hdaUpdateInterrupt(pThis); 3010 2996 } 3011 2997 … … 4126 4112 Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD)); 4127 4113 4128 hda ProcessInterrupt(pThis);4114 hdaUpdateInterrupt(pThis); 4129 4115 } 4130 4116
Note:
See TracChangeset
for help on using the changeset viewer.