Changeset 89776 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jun 18, 2021 11:07:06 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 145228
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r89775 r89776 370 370 * Can be 0 if no next transfer is scheduled. */ 371 371 uint64_t tsTransferNext; 372 /** Transfer chunk size (in bytes) of a transfer period. */373 uint32_t cbTransferChunk;374 372 /** The stream's timer Hz rate. 375 373 * This value can can be different from the device's default Hz rate, … … 386 384 * parameters. */ 387 385 uint64_t nsRetrySetup; 388 /** (Virtual) clock ticks per transfer. */389 uint64_t cTransferTicks;390 386 /** Timestamp (in ns) of last stream update. */ 391 387 uint64_t tsLastUpdateNs; … … 452 448 /** Bus master registers of this stream. */ 453 449 AC97BMREGS Regs; 450 454 451 /** The timer for pumping data thru the attached LUN drivers. */ 455 452 TMTIMERHANDLE hTimer; 453 /** When the timer was armed (timer clock). */ 454 uint64_t uArmedTs; 455 /** (Virtual) clock ticks per transfer. */ 456 uint64_t cDmaPeriodTicks; 457 /** Transfer chunk size (in bytes) of a transfer period. */ 458 uint32_t cbDmaPeriod; 459 /** DMA period counter (for logging). */ 460 uint32_t uDmaPeriod; 461 456 462 STAMCOUNTER StatWriteLvi; 457 463 STAMCOUNTER StatWriteSr1; … … 1259 1265 1260 1266 /* The amount we're supposed to be transfering in this DMA period. */ 1261 uint32_t cbPeriod = pStream CC->State.cbTransferChunk;1267 uint32_t cbPeriod = pStream->cbDmaPeriod; 1262 1268 1263 1269 /* … … 1520 1526 1521 1527 if (cbLeftInBdle <= cbMaxPerHz) 1522 pStream CC->State.cbTransferChunk= cbLeftInBdle;1528 pStream->cbDmaPeriod = cbLeftInBdle; 1523 1529 /* Try avoid leaving a very short period at the end of a buffer. */ 1524 1530 else if (cbLeftInBdle >= cbMaxPerHz + cbMaxPerHz / 2) 1525 pStream CC->State.cbTransferChunk= cbMaxPerHz;1531 pStream->cbDmaPeriod = cbMaxPerHz; 1526 1532 else 1527 pStream CC->State.cbTransferChunk= PDMAudioPropsFloorBytesToFrame(&pStreamCC->State.Cfg.Props, cbLeftInBdle / 2);1533 pStream->cbDmaPeriod = PDMAudioPropsFloorBytesToFrame(&pStreamCC->State.Cfg.Props, cbLeftInBdle / 2); 1528 1534 1529 1535 /* 1530 1536 * Translate the chunk size to timer ticks. 1531 1537 */ 1532 uint64_t const cNsXferChunk = PDMAudioPropsBytesToNano(&pStreamCC->State.Cfg.Props, pStreamCC->State.cbTransferChunk); 1533 pStreamCC->State.cTransferTicks = PDMDevHlpTimerFromNano(pDevIns, pStream->hTimer, cNsXferChunk); 1534 Assert(pStreamCC->State.cTransferTicks > 0); 1535 1536 Log3Func(("[SD%RU8] cbLeftInBdle=%#RX32 cbMaxPerHz=%#RX32 (%RU16Hz) -> cbTransferChunk=%#RX32 cTransferTicks=%RX64\n", 1537 pStream->u8SD, cbLeftInBdle, cbMaxPerHz, pStreamCC->State.uTimerHz, 1538 pStreamCC->State.cbTransferChunk, pStreamCC->State.cTransferTicks)); 1538 uint64_t const cNsXferChunk = PDMAudioPropsBytesToNano(&pStreamCC->State.Cfg.Props, pStream->cbDmaPeriod); 1539 pStream->cDmaPeriodTicks = PDMDevHlpTimerFromNano(pDevIns, pStream->hTimer, cNsXferChunk); 1540 Assert(pStream->cDmaPeriodTicks > 0); 1541 1542 Log3Func(("[SD%RU8] cbLeftInBdle=%#RX32 cbMaxPerHz=%#RX32 (%RU16Hz) -> cbDmaPeriod=%#RX32 cDmaPeriodTicks=%RX64\n", 1543 pStream->u8SD, cbLeftInBdle, cbMaxPerHz, pStreamCC->State.uTimerHz, pStream->cbDmaPeriod, pStream->cDmaPeriodTicks)); 1539 1544 } 1540 1545 } … … 1552 1557 DECLINLINE(void) ichac97R3TimerSet(PPDMDEVINS pDevIns, PAC97STREAM pStream, uint64_t cTicksToDeadline) 1553 1558 { 1554 int rc = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/);1559 int rc = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, &pStream->uArmedTs); 1555 1560 AssertRC(rc); 1556 1561 } … … 1579 1584 ichac97R3StreamUpdateDma(pDevIns, pThis, pThisCC, pStream, pStreamCC, pSink); 1580 1585 1586 pStream->uDmaPeriod++; 1581 1587 ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC); 1582 ichac97R3TimerSet(pDevIns, pStream, pStream CC->State.cTransferTicks);1588 ichac97R3TimerSet(pDevIns, pStream, pStream->cDmaPeriodTicks); 1583 1589 } 1584 1590 … … 2284 2290 if (fEnable) 2285 2291 { 2286 /* Reset the input pre-buffering state . */2292 /* Reset the input pre-buffering state and DMA period counter. */ 2287 2293 pStreamCC->State.fInputPreBuffered = false; 2294 pStream->uDmaPeriod = 0; 2288 2295 2289 2296 /* Set up (update) the AC'97 stream as needed. */ … … 2527 2534 break; 2528 2535 case AC97_NABM_OFF_PICB: 2529 /* Position in Current Buffer */ 2536 /* Position in Current Buffer 2537 * --- 2538 * We can do DMA work here if we want to give the guest a better impression of 2539 * the DMA engine of a real device. For ring-0 we'd have to add some buffering 2540 * to AC97STREAM (4K or so), only going to ring-3 if full. Ring-3 would commit 2541 * that buffer and write directly to the internal DMA pCircBuf. 2542 * 2543 * Checking a Linux guest (knoppix 8.6.2), I see some PIC reads each DMA cycle, 2544 * however most of these happen very very early, 1-10% into the buffer. So, I'm 2545 * not sure if it's worth it, as it'll be a big complication... */ 2546 #if 1 2530 2547 *pu32 = pRegs->picb; 2531 Log3Func(("PICB[%d] -> %#x\n", AC97_PORT2IDX(offPort), *pu32)); 2548 # ifdef LOG_ENABLED 2549 if (LogIs3Enabled()) 2550 { 2551 uint64_t offPeriod = PDMDevHlpTimerGet(pDevIns, pStream->hTimer) - pStream->uArmedTs; 2552 Log3Func(("PICB[%d] -> %#x (%RU64 of %RU64 ticks / %RU64%% into DMA period #%RU32)\n", 2553 AC97_PORT2IDX(offPort), *pu32, offPeriod, pStream->cDmaPeriodTicks, 2554 pStream->cDmaPeriodTicks ? offPeriod * 100 / pStream->cDmaPeriodTicks : 0, 2555 pStream->uDmaPeriod)); 2556 } 2557 # endif 2558 #else /* For trying out sub-buffer PICB. Will cause distortions, but can be helpful to see if it help eliminate other issues. */ 2559 if ( (pStream->Regs.cr & AC97_CR_RPBM) 2560 && !(pStream->Regs.sr & AC97_SR_DCH) 2561 && pStream->uArmedTs > 0 2562 && pStream->cDmaPeriodTicks > 0) 2563 { 2564 uint64_t const offPeriod = PDMDevHlpTimerGet(pDevIns, pStream->hTimer) - pStream->uArmedTs; 2565 uint32_t cSamples; 2566 if (offPeriod < pStream->cDmaPeriodTicks) 2567 cSamples = pStream->Regs.picb * offPeriod / pStream->cDmaPeriodTicks; 2568 else 2569 cSamples = pStream->Regs.picb; 2570 if (cSamples + 8 < pStream->Regs.picb) 2571 { /* likely */ } 2572 else if (pStream->Regs.picb > 8) 2573 cSamples = pStream->Regs.picb - 8; 2574 else 2575 cSamples = 0; 2576 *pu32 = pRegs->picb - cSamples; 2577 Log3Func(("PICB[%d] -> %#x (PICB=%#x cSamples=%#x offPeriod=%RU64 of %RU64 / %RU64%%)\n", 2578 AC97_PORT2IDX(offPort), *pu32, pRegs->picb, cSamples, offPeriod, pStream->cDmaPeriodTicks, 2579 offPeriod * 100 / pStream->cDmaPeriodTicks)); 2580 } 2581 else 2582 { 2583 *pu32 = pRegs->picb; 2584 Log3Func(("PICB[%d] -> %#x\n", AC97_PORT2IDX(offPort), *pu32)); 2585 } 2586 #endif 2532 2587 break; 2533 2588 default: … … 2695 2750 This means leaving the device lock to avoid virtual sync lock order issues. */ 2696 2751 ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC); 2697 uint64_t const cTicksToDeadline = pStream CC->State.cTransferTicks;2752 uint64_t const cTicksToDeadline = pStream->cDmaPeriodTicks; 2698 2753 2699 2754 /** @todo Stop the DMA timer when we get into the AC97_SR_CELV situation to … … 2705 2760 pStream->u8SD, u32, pRegs->civ, pRegs->piv, pRegs->sr, cTicksToDeadline)); 2706 2761 2707 /** @todo take down the start time here. */ 2708 int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/); 2762 int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, &pStream->uArmedTs); 2709 2763 AssertRC(rc2); 2710 2764 #else … … 2794 2848 */ 2795 2849 ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC); 2796 uint64_t const cTicksToDeadline = pStream CC->State.cTransferTicks;2850 uint64_t const cTicksToDeadline = pStream->cDmaPeriodTicks; 2797 2851 2798 2852 DEVAC97_UNLOCK(pDevIns, pThis); … … 2801 2855 * earlier if we push it, just to reduce the lag... For HDA we do a 2802 2856 * DMA run immediately after the stream is enabled. */ 2803 /** @todo take down the start time here. */ 2804 int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/); 2857 int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, &pStream->uArmedTs); 2805 2858 AssertRC(rc2); 2806 2859 … … 3754 3807 /* Re-arm the timer for this stream. */ 3755 3808 /** @todo r=aeichner This causes a VM hang upon saved state resume when NetBSD is used as a guest 3756 * Stopping the timer if c TransferTicks is 0 is a workaround but needs further investigation,3809 * Stopping the timer if cDmaPeriodTicks is 0 is a workaround but needs further investigation, 3757 3810 * see @bugref{9759} for more information. */ 3758 if (pStream CC->State.cTransferTicks)3759 ichac97R3TimerSet(pDevIns, pStream, pStream CC->State.cTransferTicks);3811 if (pStream->cDmaPeriodTicks) 3812 ichac97R3TimerSet(pDevIns, pStream, pStream->cDmaPeriodTicks); 3760 3813 else 3761 3814 PDMDevHlpTimerStop(pDevIns, pStream->hTimer); … … 3887 3940 pHlp->pfnPrintf(pHlp, " offWrite %#RX64\n", pStreamR3->State.offWrite); 3888 3941 pHlp->pfnPrintf(pHlp, " uTimerHz %RU16\n", pStreamR3->State.uTimerHz); 3889 pHlp->pfnPrintf(pHlp, " c TransferTicks %RU64\n", pStreamR3->State.cTransferTicks);3890 pHlp->pfnPrintf(pHlp, " cb TransferChunk %#RX32\n", pStreamR3->State.cbTransferChunk);3942 pHlp->pfnPrintf(pHlp, " cDmaPeriodTicks %RU64\n", pStream->cDmaPeriodTicks); 3943 pHlp->pfnPrintf(pHlp, " cbDmaPeriod %#RX32\n", pStream->cbDmaPeriod); 3891 3944 } 3892 3945 … … 4533 4586 for (unsigned idxStream = 0; idxStream < RT_ELEMENTS(pThis->aStreams); idxStream++) 4534 4587 { 4535 PDMDevHlpSTAMRegisterF(pDevIns, &pThis CC->aStreams[idxStream].State.cbTransferChunk, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,4588 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].cbDmaPeriod, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES, 4536 4589 "Bytes to transfer in the current DMA period.", "Stream%u/cbTransferChunk", idxStream); 4537 4590 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].Regs.cr, STAMTYPE_X8, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
Note:
See TracChangeset
for help on using the changeset viewer.