VirtualBox

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


Ignore:
Timestamp:
Jun 18, 2021 11:07:06 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145228
Message:

DevIchAc97: Some experiment of PICB sub-buffer reporting. bugref:9890

File:
1 edited

Legend:

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

    r89775 r89776  
    370370     *  Can be 0 if no next transfer is scheduled. */
    371371    uint64_t                tsTransferNext;
    372     /** Transfer chunk size (in bytes) of a transfer period. */
    373     uint32_t                cbTransferChunk;
    374372    /** The stream's timer Hz rate.
    375373     *  This value can can be different from the device's default Hz rate,
     
    386384     *  parameters. */
    387385    uint64_t                nsRetrySetup;
    388     /** (Virtual) clock ticks per transfer. */
    389     uint64_t                cTransferTicks;
    390386    /** Timestamp (in ns) of last stream update. */
    391387    uint64_t                tsLastUpdateNs;
     
    452448    /** Bus master registers of this stream. */
    453449    AC97BMREGS              Regs;
     450
    454451    /** The timer for pumping data thru the attached LUN drivers. */
    455452    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
    456462    STAMCOUNTER             StatWriteLvi;
    457463    STAMCOUNTER             StatWriteSr1;
     
    12591265
    12601266    /* The amount we're supposed to be transfering in this DMA period. */
    1261     uint32_t cbPeriod = pStreamCC->State.cbTransferChunk;
     1267    uint32_t cbPeriod = pStream->cbDmaPeriod;
    12621268
    12631269    /*
     
    15201526
    15211527        if (cbLeftInBdle <= cbMaxPerHz)
    1522             pStreamCC->State.cbTransferChunk = cbLeftInBdle;
     1528            pStream->cbDmaPeriod = cbLeftInBdle;
    15231529        /* Try avoid leaving a very short period at the end of a buffer. */
    15241530        else if (cbLeftInBdle >= cbMaxPerHz + cbMaxPerHz / 2)
    1525             pStreamCC->State.cbTransferChunk = cbMaxPerHz;
     1531            pStream->cbDmaPeriod = cbMaxPerHz;
    15261532        else
    1527             pStreamCC->State.cbTransferChunk = PDMAudioPropsFloorBytesToFrame(&pStreamCC->State.Cfg.Props, cbLeftInBdle / 2);
     1533            pStream->cbDmaPeriod = PDMAudioPropsFloorBytesToFrame(&pStreamCC->State.Cfg.Props, cbLeftInBdle / 2);
    15281534
    15291535        /*
    15301536         * Translate the chunk size to timer ticks.
    15311537         */
    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));
    15391544    }
    15401545}
     
    15521557DECLINLINE(void) ichac97R3TimerSet(PPDMDEVINS pDevIns, PAC97STREAM pStream, uint64_t cTicksToDeadline)
    15531558{
    1554     int rc = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/);
     1559    int rc = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, &pStream->uArmedTs);
    15551560    AssertRC(rc);
    15561561}
     
    15791584        ichac97R3StreamUpdateDma(pDevIns, pThis, pThisCC, pStream, pStreamCC, pSink);
    15801585
     1586        pStream->uDmaPeriod++;
    15811587        ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC);
    1582         ichac97R3TimerSet(pDevIns, pStream, pStreamCC->State.cTransferTicks);
     1588        ichac97R3TimerSet(pDevIns, pStream, pStream->cDmaPeriodTicks);
    15831589    }
    15841590
     
    22842290    if (fEnable)
    22852291    {
    2286         /* Reset the input pre-buffering state. */
     2292        /* Reset the input pre-buffering state and DMA period counter. */
    22872293        pStreamCC->State.fInputPreBuffered = false;
     2294        pStream->uDmaPeriod = 0;
    22882295
    22892296        /* Set up (update) the AC'97 stream as needed. */
     
    25272534                        break;
    25282535                    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
    25302547                        *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
    25322587                        break;
    25332588                    default:
     
    26952750                               This means leaving the device lock to avoid virtual sync lock order issues. */
    26962751                            ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC);
    2697                             uint64_t const cTicksToDeadline = pStreamCC->State.cTransferTicks;
     2752                            uint64_t const cTicksToDeadline = pStream->cDmaPeriodTicks;
    26982753
    26992754                            /** @todo Stop the DMA timer when we get into the AC97_SR_CELV situation to
     
    27052760                                     pStream->u8SD, u32, pRegs->civ, pRegs->piv, pRegs->sr, cTicksToDeadline));
    27062761
    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);
    27092763                            AssertRC(rc2);
    27102764#else
     
    27942848                             */
    27952849                            ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC);
    2796                             uint64_t const cTicksToDeadline = pStreamCC->State.cTransferTicks;
     2850                            uint64_t const cTicksToDeadline = pStream->cDmaPeriodTicks;
    27972851
    27982852                            DEVAC97_UNLOCK(pDevIns, pThis);
     
    28012855                             *        earlier if we push it, just to reduce the lag...  For HDA we do a
    28022856                             *        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);
    28052858                            AssertRC(rc2);
    28062859
     
    37543807            /* Re-arm the timer for this stream. */
    37553808            /** @todo r=aeichner This causes a VM hang upon saved state resume when NetBSD is used as a guest
    3756              * Stopping the timer if cTransferTicks is 0 is a workaround but needs further investigation,
     3809             * Stopping the timer if cDmaPeriodTicks is 0 is a workaround but needs further investigation,
    37573810             * see @bugref{9759} for more information. */
    3758             if (pStreamCC->State.cTransferTicks)
    3759                 ichac97R3TimerSet(pDevIns, pStream, pStreamCC->State.cTransferTicks);
     3811            if (pStream->cDmaPeriodTicks)
     3812                ichac97R3TimerSet(pDevIns, pStream, pStream->cDmaPeriodTicks);
    37603813            else
    37613814                PDMDevHlpTimerStop(pDevIns, pStream->hTimer);
     
    38873940    pHlp->pfnPrintf(pHlp, "  offWrite           %#RX64\n", pStreamR3->State.offWrite);
    38883941    pHlp->pfnPrintf(pHlp, "  uTimerHz           %RU16\n", pStreamR3->State.uTimerHz);
    3889     pHlp->pfnPrintf(pHlp, "  cTransferTicks     %RU64\n", pStreamR3->State.cTransferTicks);
    3890     pHlp->pfnPrintf(pHlp, "  cbTransferChunk    %#RX32\n", pStreamR3->State.cbTransferChunk);
     3942    pHlp->pfnPrintf(pHlp, "  cDmaPeriodTicks    %RU64\n", pStream->cDmaPeriodTicks);
     3943    pHlp->pfnPrintf(pHlp, "  cbDmaPeriod        %#RX32\n", pStream->cbDmaPeriod);
    38913944}
    38923945
     
    45334586    for (unsigned idxStream = 0; idxStream < RT_ELEMENTS(pThis->aStreams); idxStream++)
    45344587    {
    4535         PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aStreams[idxStream].State.cbTransferChunk, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     4588        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].cbDmaPeriod, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    45364589                               "Bytes to transfer in the current DMA period.",  "Stream%u/cbTransferChunk", idxStream);
    45374590        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].Regs.cr, STAMTYPE_X8, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
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