- Timestamp:
- Mar 17, 2021 4:44:17 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143311
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/HDAStream.cpp
r88160 r88162 1140 1140 1141 1141 /** 1142 * Common do-DMA prologue code. 1143 * 1144 * @retval true if DMA processing can take place 1145 * @retval false if caller should return immediately. 1146 * @param pDevIns The device instance. 1147 * @param pThis The shared HDA device state. 1148 * @param pStreamShared HDA stream to update (shared). 1149 * @param uSD The stream ID (for asserting). 1150 * @param tsNowNs The current RTTimeNano() value. 1151 * @param pszFunction The function name (for logging). 1152 */ 1153 DECLINLINE(bool) hdaR3StreamDoDmaPrologue(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint8_t uSD, 1154 uint64_t tsNowNs, const char *pszFunction) 1155 { 1156 RT_NOREF(uSD, pszFunction); 1157 1158 /* 1159 * Check if we should skip town... 1160 */ 1161 /* Stream not running (anymore)? */ 1162 if (pStreamShared->State.fRunning) 1163 { /* likely */ } 1164 else 1165 { 1166 Log3(("%s: [SD%RU8] Not running, skipping transfer\n", pszFunction, uSD)); 1167 return false; 1168 } 1169 1170 if (!(HDA_STREAM_REG(pThis, STS, uSD) & HDA_SDSTS_BCIS)) 1171 { /* likely */ } 1172 else 1173 { 1174 Log3(("%s: [SD%RU8] BCIS bit set, skipping transfer\n", pszFunction, uSD)); 1175 #ifdef HDA_STRICT 1176 /* Timing emulation bug or guest is misbehaving -- let me know. */ 1177 AssertMsgFailed(("%s: BCIS bit for stream #%RU8 still set when it shouldn't\n", pszFunction, uSD)); 1178 #endif 1179 return false; 1180 } 1181 1182 /* 1183 * Stream sanity checks. 1184 */ 1185 /* Register sanity checks. */ 1186 Assert(uSD < HDA_MAX_STREAMS); 1187 Assert(pStreamShared->u64BDLBase); 1188 Assert(pStreamShared->u32CBL); 1189 Assert(pStreamShared->u8FIFOS); 1190 1191 /* State sanity checks. */ 1192 Assert(ASMAtomicReadBool(&pStreamShared->State.fInReset) == false); 1193 Assert(ASMAtomicReadBool(&pStreamShared->State.fRunning)); 1194 1195 /* 1196 * Some timestamp stuff for logging/debugging. 1197 */ 1198 /*const uint64_t tsNowNs = RTTimeNanoTS();*/ 1199 Log3(("%s: [SD%RU8] tsDeltaNs=%'RU64 ns\n", pszFunction, uSD, tsNowNs - pStreamShared->State.tsLastTransferNs)); 1200 pStreamShared->State.tsLastTransferNs = tsNowNs; 1201 pStreamShared->State.tsTransferLast = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer); 1202 1203 /* 1204 * Set the FIFORDY bit on the stream while doing the transfer. 1205 */ 1206 /** @todo r=bird: I don't get the HDA_SDSTS_FIFORDY logic. Unless we're 1207 * assuming SMP guest and that it can get stream registers while we're 1208 * here. Only it cannot do the later because we're sitting on the big 1209 * HDA device lock, see assertions in hdaR3Timer(). So, this is an 1210 * pointless guesture given that we clear it again after the loop. */ 1211 HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_FIFORDY; 1212 1213 return true; 1214 } 1215 1216 /** 1217 * Common do-DMA epilogue. 1218 * 1219 * @param pThis The shared HDA device state. 1220 * @param pThisCC The ring-3 HDA device state. 1221 * @param pStreamShared HDA stream to update (shared). 1222 * @param cbProcessed The number of bytes processed. 1223 */ 1224 DECLINLINE(void) hdaR3StreamDoDmaEpilogue(PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared, uint32_t cbProcessed) 1225 { 1226 /* 1227 * Clear the (pointless) FIFORDY bit again. 1228 */ 1229 HDA_STREAM_REG(pThis, STS, pStreamShared->u8SD) &= ~HDA_SDSTS_FIFORDY; 1230 1231 /* 1232 * Try updating the wall clock. 1233 * 1234 * Note 1) Only certain guests (like Linux' snd_hda_intel) rely on the WALCLK register 1235 * in order to determine the correct timing of the sound device. Other guests 1236 * like Windows 7 + 10 (or even more exotic ones like Haiku) will completely 1237 * ignore this. 1238 * 1239 * Note 2) When updating the WALCLK register too often / early (or even in a non-monotonic 1240 * fashion) this *will* upset guest device drivers and will completely fuck up the 1241 * sound output. Running VLC on the guest will tell! 1242 */ 1243 uint32_t const cFramesProcessed = PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbProcessed); 1244 /** @todo this needs to go, but we need it for hdaR3WalClkGetMax below. */ 1245 hdaR3StreamPeriodInc(&pStreamShared->State.Period, 1246 RT_MIN(cFramesProcessed, hdaR3StreamPeriodGetRemainingFrames(&pStreamShared->State.Period))); 1247 1248 uint64_t const cWallTicks = hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, cFramesProcessed); 1249 uint64_t const uWallNew = hdaWalClkGetCurrent(pThis) + cWallTicks; 1250 uint64_t const uWallMax = hdaR3WalClkGetMax(pThis, pThisCC); 1251 bool const fWalClkSet = hdaR3WalClkSet(pThis, pThisCC, RT_MIN(uWallNew, uWallMax), false /* fForce */); 1252 RT_NOREF(fWalClkSet); 1253 } 1254 1255 /** 1256 * Completes a BDLE at the end of a DMA loop iteration, if possible. 1257 * 1258 * @param pDevIns The device instance. 1259 * @param pThis The shared HDA device state. 1260 * @param pThisCC The ring-3 HDA device state. 1261 * @param pStreamShared HDA stream to update (shared). 1262 * @param pStreamR3 HDA stream to update (ring-3). 1263 * @param pszFunction The function name (for logging). 1264 */ 1265 DECLINLINE(void) hdaR3StreamDoDmaMaybeCompleteBuffer(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, 1266 PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3, const char *pszFunction) 1267 { 1268 RT_NOREF(pszFunction); 1269 1270 /* 1271 * Is the buffer descriptor complete. 1272 */ 1273 if (hdaR3StreamDmaBufIsComplete(pStreamShared)) 1274 { 1275 Log3(("%s: [SD%RU8] Completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x\n", pszFunction, pStreamShared->u8SD, 1276 pStreamShared->State.idxCurBdle, pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1277 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1278 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags)); 1279 1280 /* Make sure to also update the wall clock when a BDLE is complete. 1281 * Needed for Windows 10 guests. */ 1282 /** @todo there is a rounding error here. */ 1283 hdaR3WalClkSet(pThis, pThisCC, 1284 hdaWalClkGetCurrent(pThis) 1285 + hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, 1286 hdaR3StreamDmaBufGetSize(pStreamShared) 1287 / pStreamR3->State.Mapping.cbGuestFrame), 1288 false /* fForce */); 1289 1290 /* 1291 * Update the stream's current position. 1292 * 1293 * Do this as accurate and close to the actual data transfer as possible. 1294 * All guetsts rely on this, depending on the mechanism they use (LPIB register or DMA counters). 1295 * 1296 * Note for Windows 10: The OS' driver is *very* picky about *when* the (DMA) positions get updated! 1297 * Not doing this at the right time will result in ugly sound crackles! 1298 */ 1299 hdaR3StreamSetPositionAdd(pStreamShared, pDevIns, pThis, hdaR3StreamDmaBufGetSize(pStreamShared)); 1300 1301 /* Does the current BDLE require an interrupt to be sent? */ 1302 if (hdaR3StreamDmaBufNeedsIrq(pStreamShared)) 1303 { 1304 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL 1305 register is set we need to generate an interrupt. */ 1306 if (HDA_STREAM_REG(pThis, CTL, pStreamShared->u8SD) & HDA_SDCTL_IOCE) 1307 { 1308 /* Assert the interrupt before actually fetching the next BDLE below. */ 1309 pStreamShared->State.cTransferPendingInterrupts = 1; 1310 Log3(("%s: [SD%RU8] Scheduling interrupt\n", pszFunction, pStreamShared->u8SD)); 1311 1312 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with 1313 * ending / beginning of a period. */ 1314 /** @todo r=bird: What does the above comment mean? */ 1315 HDA_STREAM_REG(pThis, STS, pStreamShared->u8SD) |= HDA_SDSTS_BCIS; 1316 HDA_PROCESS_INTERRUPT(pDevIns, pThis); 1317 } 1318 } 1319 1320 /* 1321 * Advance to the next BDLE. 1322 */ 1323 hdaR3StreamDmaBufAdvanceToNext(pStreamShared); 1324 } 1325 else 1326 Log3(("%s: [SD%RU8] Not completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x: off=%#RX32\n", pszFunction, pStreamShared->u8SD, 1327 pStreamShared->State.idxCurBdle, pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1328 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1329 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags, pStreamShared->State.offCurBdle)); 1330 } 1331 1332 /** 1142 1333 * Does DMA transfer for an HDA input stream. 1143 1334 * … … 1145 1336 * guest memory. 1146 1337 * 1147 * @returns IPRT status code.1148 1338 * @param pDevIns The device instance. 1149 1339 * @param pThis The shared HDA device state. … … 1164 1354 * @remarks Caller owns the stream lock. 1165 1355 */ 1166 static inthdaR3StreamDoDmaInput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared,1167 PHDASTREAMR3 pStreamR3, uint32_t cbToConsume, bool fWriteSilence, uint64_t tsNowNs)1356 static void hdaR3StreamDoDmaInput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared, 1357 PHDASTREAMR3 pStreamR3, uint32_t cbToConsume, bool fWriteSilence, uint64_t tsNowNs) 1168 1358 { 1169 1359 uint8_t const uSD = pStreamShared->u8SD; 1170 1360 LogFlowFunc(("ENTER - #%u cbToConsume=%#x%s\n", uSD, cbToConsume, fWriteSilence ? " silence" : "")); 1171 1361 1172 1173 /* 1174 * Check if we should skip town... 1175 */ 1176 1177 /* Stream not running (anymore)? */ 1178 if (pStreamShared->State.fRunning) 1362 /* 1363 * Common prologue. 1364 */ 1365 if (hdaR3StreamDoDmaPrologue(pDevIns, pThis, pStreamShared, uSD, tsNowNs, "hdaR3StreamDoDmaInput")) 1179 1366 { /* likely */ } 1180 1367 else 1181 { 1182 Log3Func(("[SD%RU8] Not running, skipping transfer\n", uSD)); 1183 return VINF_SUCCESS; 1184 } 1185 1186 if (!(HDA_STREAM_REG(pThis, STS, uSD) & HDA_SDSTS_BCIS)) 1187 { /* likely */ } 1188 else 1189 { 1190 Log3Func(("[SD%RU8] BCIS bit set, skipping transfer\n", uSD)); 1191 #ifdef HDA_STRICT 1192 /* Timing emulation bug or guest is misbehaving -- let me know. */ 1193 AssertMsgFailed(("BCIS bit for stream #%RU8 still set when it shouldn't\n", uSD)); 1194 #endif 1195 return VINF_SUCCESS; 1196 } 1197 1198 /* 1199 * Stream sanity checks. 1200 */ 1201 /* Register sanity checks. */ 1202 Assert(uSD < HDA_MAX_STREAMS); 1203 Assert(pStreamShared->u64BDLBase); 1204 Assert(pStreamShared->u32CBL); 1205 Assert(pStreamShared->u8FIFOS); 1206 1207 /* State sanity checks. */ 1208 Assert(ASMAtomicReadBool(&pStreamShared->State.fInReset) == false); 1209 Assert(ASMAtomicReadBool(&pStreamShared->State.fRunning)); 1210 1211 /* 1212 * Some timestamp stuff for logging/debugging. 1213 */ 1214 /*const uint64_t tsNowNs = RTTimeNanoTS();*/ 1215 Log3Func(("[SD%RU8] tsDeltaNs=%'RU64 ns\n", uSD, tsNowNs - pStreamShared->State.tsLastTransferNs)); 1216 pStreamShared->State.tsLastTransferNs = tsNowNs; 1217 pStreamShared->State.tsTransferLast = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer); 1218 1219 /* 1220 * Set the FIFORDY bit on the stream while doing the transfer. 1221 */ 1222 /** @todo r=bird: I don't get the HDA_SDSTS_FIFORDY logic. Unless we're 1223 * assuming SMP guest and that it can get stream registers while we're 1224 * here. Only it cannot do the later because we're sitting on the big 1225 * HDA device lock, see assertions in hdaR3Timer(). So, this is an 1226 * pointless guesture given that we clear it again after the loop. */ 1227 HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_FIFORDY; 1368 return; 1228 1369 1229 1370 /* … … 1393 1534 1394 1535 /* 1395 * Is the buffer descriptor complete.1536 * Complete the buffer if necessary (common with the output DMA code). 1396 1537 */ 1397 if (hdaR3StreamDmaBufIsComplete(pStreamShared)) 1398 { 1399 Log3Func(("[SD%RU8] Completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x\n", 1400 uSD, pStreamShared->State.idxCurBdle, pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1401 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1402 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags)); 1403 1404 /* Make sure to also update the wall clock when a BDLE is complete. 1405 * Needed for Windows 10 guests. */ 1406 /** @todo there is a rounding error here. */ 1407 hdaR3WalClkSet(pThis, pThisCC, 1408 hdaWalClkGetCurrent(pThis) 1409 + hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, 1410 hdaR3StreamDmaBufGetSize(pStreamShared) 1411 / pStreamR3->State.Mapping.cbGuestFrame), 1412 false /* fForce */); 1413 1414 /* 1415 * Update the stream's current position. 1416 * 1417 * Do this as accurate and close to the actual data transfer as possible. 1418 * All guetsts rely on this, depending on the mechanism they use (LPIB register or DMA counters). 1419 * 1420 * Note for Windows 10: The OS' driver is *very* picky about *when* the (DMA) positions get updated! 1421 * Not doing this at the right time will result in ugly sound crackles! 1422 */ 1423 hdaR3StreamSetPositionAdd(pStreamShared, pDevIns, pThis, hdaR3StreamDmaBufGetSize(pStreamShared)); 1424 1425 /* Does the current BDLE require an interrupt to be sent? */ 1426 if (hdaR3StreamDmaBufNeedsIrq(pStreamShared)) 1427 { 1428 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL 1429 register is set we need to generate an interrupt. */ 1430 if (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_IOCE) 1431 { 1432 /* Assert the interrupt before actually fetching the next BDLE below. */ 1433 pStreamShared->State.cTransferPendingInterrupts = 1; 1434 Log3Func(("[SD%RU8] Scheduling interrupt\n", uSD)); 1435 1436 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with 1437 * ending / beginning of a period. */ 1438 /** @todo r=bird: What does the above comment mean? */ 1439 HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_BCIS; 1440 HDA_PROCESS_INTERRUPT(pDevIns, pThis); 1441 } 1442 } 1443 1444 /* 1445 * Advance to the next BDLE. 1446 */ 1447 hdaR3StreamDmaBufAdvanceToNext(pStreamShared); 1448 } 1449 else 1450 Log3Func(("[SD%RU8] Not completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x: off=%#RX32\n", 1451 uSD, pStreamShared->State.idxCurBdle, pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1452 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1453 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags, pStreamShared->State.offCurBdle)); 1538 hdaR3StreamDoDmaMaybeCompleteBuffer(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, "hdaR3StreamDoDmaInput"); 1454 1539 } 1455 1540 … … 1458 1543 1459 1544 /* 1460 * Clear the (pointless) FIFORDY bit again. 1461 */ 1462 HDA_STREAM_REG(pThis, STS, uSD) &= ~HDA_SDSTS_FIFORDY; 1463 1464 /* 1465 * Try updating the wall clock. 1466 * 1467 * Note 1) Only certain guests (like Linux' snd_hda_intel) rely on the WALCLK register 1468 * in order to determine the correct timing of the sound device. Other guests 1469 * like Windows 7 + 10 (or even more exotic ones like Haiku) will completely 1470 * ignore this. 1471 * 1472 * Note 2) When updating the WALCLK register too often / early (or even in a non-monotonic 1473 * fashion) this *will* upset guest device drivers and will completely fuck up the 1474 * sound output. Running VLC on the guest will tell! 1475 */ 1476 uint32_t const cFramesProcessed = PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbToConsume); 1477 /** @todo this needs to go, but we need it for hdaR3WalClkGetMax below. */ 1478 hdaR3StreamPeriodInc(&pStreamShared->State.Period, 1479 RT_MIN(cFramesProcessed, hdaR3StreamPeriodGetRemainingFrames(&pStreamShared->State.Period))); 1480 1481 uint64_t const cWallTicks = hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, cFramesProcessed); 1482 uint64_t const uWallNew = hdaWalClkGetCurrent(pThis) + cWallTicks; 1483 uint64_t const uWallMax = hdaR3WalClkGetMax(pThis, pThisCC); 1484 bool const fWalClkSet = hdaR3WalClkSet(pThis, pThisCC, RT_MIN(uWallNew, uWallMax), false /* fForce */); 1485 RT_NOREF(fWalClkSet); 1545 * Common epilogue. 1546 */ 1547 hdaR3StreamDoDmaEpilogue(pThis, pThisCC, pStreamShared, cbToConsume); 1486 1548 1487 1549 /* 1488 1550 * Log and leave. 1489 1551 */ 1490 Log3Func((" [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n",1552 Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n", 1491 1553 uSD, cbToConsume, pStreamShared->State.cbTransferSize, pStreamR3->State.offRead - cbToConsume, 1492 1554 pStreamShared->State.cTransferPendingInterrupts)); 1493 return VINF_SUCCESS;1494 1555 } 1495 1556 … … 1575 1636 * internal DMA buffer. 1576 1637 * 1577 * @returns IPRT status code.1578 1638 * @param pDevIns The device instance. 1579 1639 * @param pThis The shared HDA device state. … … 1589 1649 * @remarks Caller owns the stream lock. 1590 1650 */ 1591 static inthdaR3StreamDoDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared,1592 PHDASTREAMR3 pStreamR3, uint32_t cbToProduce, uint64_t tsNowNs)1651 static void hdaR3StreamDoDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared, 1652 PHDASTREAMR3 pStreamR3, uint32_t cbToProduce, uint64_t tsNowNs) 1593 1653 { 1594 1654 uint8_t const uSD = pStreamShared->u8SD; 1595 1655 LogFlowFunc(("ENTER - #%u cbToProduce=%#x\n", uSD, cbToProduce)); 1596 1656 1597 1598 /* 1599 * Check if we should skip town... 1600 */ 1601 1602 /* Stream not running (anymore)? */ 1603 if (pStreamShared->State.fRunning) 1657 /* 1658 * Common prologue. 1659 */ 1660 if (hdaR3StreamDoDmaPrologue(pDevIns, pThis, pStreamShared, uSD, tsNowNs, "hdaR3StreamDoDmaOutput")) 1604 1661 { /* likely */ } 1605 1662 else 1606 { 1607 Log3Func(("[SD%RU8] Not running, skipping transfer\n", uSD)); 1608 return VINF_SUCCESS; 1609 } 1610 1611 if (!(HDA_STREAM_REG(pThis, STS, uSD) & HDA_SDSTS_BCIS)) 1612 { /* likely */ } 1613 else 1614 { 1615 Log3Func(("[SD%RU8] BCIS bit set, skipping transfer\n", uSD)); 1616 #ifdef HDA_STRICT 1617 /* Timing emulation bug or guest is misbehaving -- let me know. */ 1618 AssertMsgFailed(("BCIS bit for stream #%RU8 still set when it shouldn't\n", uSD)); 1619 #endif 1620 return VINF_SUCCESS; 1621 } 1622 1623 /* 1624 * Stream sanity checks. 1625 */ 1626 /* Register sanity checks. */ 1627 Assert(uSD < HDA_MAX_STREAMS); 1628 Assert(pStreamShared->u64BDLBase); 1629 Assert(pStreamShared->u32CBL); 1630 Assert(pStreamShared->u8FIFOS); 1631 1632 /* State sanity checks. */ 1633 Assert(ASMAtomicReadBool(&pStreamShared->State.fInReset) == false); 1634 Assert(ASMAtomicReadBool(&pStreamShared->State.fRunning)); 1635 1636 /* 1637 * Some timestamp stuff for logging/debugging. 1638 */ 1639 /*const uint64_t tsNowNs = RTTimeNanoTS();*/ 1640 Log3Func(("[SD%RU8] tsDeltaNs=%'RU64 ns\n", uSD, tsNowNs - pStreamShared->State.tsLastTransferNs)); 1641 pStreamShared->State.tsLastTransferNs = tsNowNs; 1642 pStreamShared->State.tsTransferLast = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer); 1643 1644 /* 1645 * Set the FIFORDY bit on the stream while doing the transfer. 1646 */ 1647 /** @todo r=bird: I don't get the HDA_SDSTS_FIFORDY logic. Unless we're 1648 * assuming SMP guest and that it can get stream registers while we're 1649 * here. Only it cannot do the later because we're sitting on the big 1650 * HDA device lock, see assertions in hdaR3Timer(). So, this is an 1651 * pointless guesture given that we clear it again after the loop. */ 1652 HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_FIFORDY; 1663 return; 1653 1664 1654 1665 /* … … 1808 1819 1809 1820 /* 1810 * Is the buffer descriptor complete.1821 * Complete the buffer if necessary (common with the output DMA code). 1811 1822 */ 1812 if (hdaR3StreamDmaBufIsComplete(pStreamShared)) 1813 { 1814 Log3Func(("[SD%RU8] Completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x\n", uSD, pStreamShared->State.idxCurBdle, 1815 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1816 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1817 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags)); 1818 1819 /* Make sure to also update the wall clock when a BDLE is complete. 1820 * Needed for Windows 10 guests. */ 1821 /** @todo there is a rounding error here. */ 1822 hdaR3WalClkSet(pThis, pThisCC, 1823 hdaWalClkGetCurrent(pThis) 1824 + hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, 1825 hdaR3StreamDmaBufGetSize(pStreamShared) 1826 / pStreamR3->State.Mapping.cbGuestFrame), 1827 false /* fForce */); 1828 1829 /* 1830 * Update the stream's current position. 1831 * 1832 * Do this as accurate and close to the actual data transfer as possible. 1833 * All guetsts rely on this, depending on the mechanism they use (LPIB register or DMA counters). 1834 * 1835 * Note for Windows 10: The OS' driver is *very* picky about *when* the (DMA) positions get updated! 1836 * Not doing this at the right time will result in ugly sound crackles! 1837 */ 1838 hdaR3StreamSetPositionAdd(pStreamShared, pDevIns, pThis, hdaR3StreamDmaBufGetSize(pStreamShared)); 1839 1840 /* Does the current BDLE require an interrupt to be sent? */ 1841 if (hdaR3StreamDmaBufNeedsIrq(pStreamShared)) 1842 { 1843 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL 1844 register is set we need to generate an interrupt. */ 1845 if (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_IOCE) 1846 { 1847 /* Assert the interrupt before actually fetching the next BDLE below. */ 1848 pStreamShared->State.cTransferPendingInterrupts = 1; 1849 Log3Func(("[SD%RU8] Scheduling interrupt\n", uSD)); 1850 1851 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with 1852 * ending / beginning of a period. */ 1853 /** @todo r=bird: What does the above comment mean? */ 1854 HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_BCIS; 1855 HDA_PROCESS_INTERRUPT(pDevIns, pThis); 1856 } 1857 } 1858 1859 /* 1860 * Advance to the next BDLE. 1861 */ 1862 hdaR3StreamDmaBufAdvanceToNext(pStreamShared); 1863 } 1864 else 1865 Log3Func(("[SD%RU8] Not completed BDLE%u %#RX64 LB %#RX32 fFlags=%#x: off=%#RX32\n", 1866 uSD, pStreamShared->State.idxCurBdle, pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].GCPhys, 1867 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].cb, 1868 pStreamShared->State.aBdl[pStreamShared->State.idxCurBdle].fFlags, pStreamShared->State.offCurBdle)); 1823 hdaR3StreamDoDmaMaybeCompleteBuffer(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, "hdaR3StreamDoDmaOutput"); 1869 1824 } 1870 1825 … … 1873 1828 1874 1829 /* 1875 * Clear the (pointless) FIFORDY bit again. 1876 */ 1877 HDA_STREAM_REG(pThis, STS, uSD) &= ~HDA_SDSTS_FIFORDY; 1878 1879 /* 1880 * Try updating the wall clock. 1881 * 1882 * Note 1) Only certain guests (like Linux' snd_hda_intel) rely on the WALCLK register 1883 * in order to determine the correct timing of the sound device. Other guests 1884 * like Windows 7 + 10 (or even more exotic ones like Haiku) will completely 1885 * ignore this. 1886 * 1887 * Note 2) When updating the WALCLK register too often / early (or even in a non-monotonic 1888 * fashion) this *will* upset guest device drivers and will completely fuck up the 1889 * sound output. Running VLC on the guest will tell! 1890 */ 1891 uint32_t const cFramesProcessed = PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbToProduce); 1892 /** @todo this needs to go, but we need it for hdaR3WalClkGetMax below. */ 1893 hdaR3StreamPeriodInc(&pStreamShared->State.Period, 1894 RT_MIN(cFramesProcessed, hdaR3StreamPeriodGetRemainingFrames(&pStreamShared->State.Period))); 1895 1896 uint64_t const cWallTicks = hdaR3StreamPeriodFramesToWalClk(&pStreamShared->State.Period, cFramesProcessed); 1897 uint64_t const uWallNew = hdaWalClkGetCurrent(pThis) + cWallTicks; 1898 uint64_t const uWallMax = hdaR3WalClkGetMax(pThis, pThisCC); 1899 bool const fWalClkSet = hdaR3WalClkSet(pThis, pThisCC, RT_MIN(uWallNew, uWallMax), false /* fForce */); 1900 RT_NOREF(fWalClkSet); 1830 * Common epilogue. 1831 */ 1832 hdaR3StreamDoDmaEpilogue(pThis, pThisCC, pStreamShared, cbToProduce); 1901 1833 1902 1834 /* 1903 1835 * Log and leave. 1904 1836 */ 1905 Log3Func((" [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n",1837 Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n", 1906 1838 uSD, cbToProduce, pStreamShared->State.cbTransferSize, pStreamR3->State.offWrite - cbToProduce, 1907 1839 pStreamShared->State.cTransferPendingInterrupts)); 1908 1909 LogFlowFuncLeave(); 1910 return VINF_SUCCESS; 1911 } 1912 1840 } 1913 1841 1914 1842 /** … … 2152 2080 2153 2081 uint64_t const offWriteBefore = pStreamR3->State.offWrite; 2154 rc2 = hdaR3StreamDoDmaOutput(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, RT_MIN(cbStreamFree, cbPeriod), tsNowNs); 2155 AssertRC(rc2); 2082 hdaR3StreamDoDmaOutput(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, RT_MIN(cbStreamFree, cbPeriod), tsNowNs); 2156 2083 2157 2084 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO … … 2351 2278 # endif 2352 2279 2353 rc2 = hdaR3StreamDoDmaInput(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, 2354 RT_MIN(cbStreamUsed, cbPeriod), fWriteSilence, tsNowNs); 2355 AssertRC(rc2); 2280 hdaR3StreamDoDmaInput(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, 2281 RT_MIN(cbStreamUsed, cbPeriod), fWriteSilence, tsNowNs); 2356 2282 2357 2283 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
Note:
See TracChangeset
for help on using the changeset viewer.