VirtualBox

Changeset 70435 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jan 2, 2018 4:21:53 PM (7 years ago)
Author:
vboxsync
Message:

Audio/HDA: Do not count transfer fragment in hdaStreamInit() if a fragment is part of the position adjustment the guest set up (like newer Ubuntu guests).

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

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

    r70433 r70435  
    15601560        pStream->State.tsTransferNext      = tsNow + cTicksToNext;
    15611561
    1562         Assert(pStream->State.cTransferPendingInterrupts);
    15631562        if (pStream->State.cTransferPendingInterrupts)
    15641563            pStream->State.cTransferPendingInterrupts--;
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r70321 r70435  
    243243                    pThis->u16TimerHz, pStream->State.Cfg.Props.uHz));
    244244
     245        /* Figure out how many transfer fragments we're going to use for this stream. */
    245246        /** @todo Use a more dynamic fragment size? */
    246247        Assert(pStream->u16LVI <= UINT8_MAX - 1);
     
    249250            cFragments = 2; /* At least two fragments (BDLEs) must be present. */
    250251
    251         /* Calculate the fragment size the guest OS expects interrupt delivery at. */
    252         pStream->State.cbTransferSize = pStream->u32CBL / cFragments;
    253         Assert(pStream->State.cbTransferSize);
    254         Assert(pStream->State.cbTransferSize % pStream->State.cbFrameSize == 0);
    255 
    256         /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration.
    257          * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */
    258         pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * pStream->State.cbFrameSize;
    259         Assert(pStream->State.cbTransferChunk);
    260         Assert(pStream->State.cbTransferChunk % pStream->State.cbFrameSize == 0);
    261 
    262         /* Make sure that the transfer chunk does not exceed the overall transfer size. */
    263         if (pStream->State.cbTransferChunk > pStream->State.cbTransferSize)
    264             pStream->State.cbTransferChunk = pStream->State.cbTransferSize;
    265 
    266         pStream->State.cbTransferProcessed        = 0;
    267         pStream->State.cTransferPendingInterrupts = 0;
    268 
    269         const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz;
    270 
    271         /* Calculate the timer ticks per byte for this stream. */
    272         pStream->State.cTicksPerByte = cTicksPerHz / pStream->State.cbTransferChunk;
    273         Assert(pStream->State.cTicksPerByte);
    274 
    275         /* Calculate timer ticks per transfer. */
    276         pStream->State.cTransferTicks     = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
    277 
    278         /* Initialize the transfer timestamps. */
    279         pStream->State.tsTransferLast     = 0;
    280         pStream->State.tsTransferNext     = 0;
    281 
    282         LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \
    283                  "cbTransferSize=%RU32\n",
    284                  pStream->u8SD, pThis->u16TimerHz, cTicksPerHz, pStream->State.cTicksPerByte,
    285                  pStream->State.cbTransferChunk, pStream->State.cTransferTicks, pStream->State.cbTransferSize));
    286252        /*
    287253         * Handle the stream's position adjustment.
     
    289255        uint32_t cfPosAdjust = 0;
    290256
     257        LogFunc(("[SD%RU8] fPosAdjustEnabled=%RTbool, cPosAdjustFrames=%RU16\n",
     258                 pStream->u8SD, pThis->fPosAdjustEnabled, pThis->cPosAdjustFrames));
     259
    291260        if (pThis->fPosAdjustEnabled) /* Is the position adjustment enabled at all? */
    292261        {
     262            HDABDLE BDLE;
     263            RT_ZERO(BDLE);
     264
     265            Assert(pStream->u64BDLBase);
     266
     267            int rc2 = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */);
     268            AssertRC(rc2);
     269
     270            Assert(BDLE.Desc.u32BufSize % pStream->State.cbFrameSize == 0);
     271
    293272            /* If no custom set position adjustment is set, apply some
    294273             * simple heuristics to detect the appropriate position adjustment. */
    295             if (   pStream->u64BDLBase
    296                 && !pThis->cPosAdjustFrames)
     274            if (   !pThis->cPosAdjustFrames
     275            /* Position adjustmenet buffer *must* have the IOC bit set! */
     276                && hdaBDLENeedsInterrupt(&BDLE))
    297277            {
    298                 HDABDLE BDLE;
    299                 int rc2 = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, 0 /* Entry */);
    300                 AssertRC(rc2);
    301 
    302278                /** @todo Implement / use a (dynamic) table once this gets more complicated. */
    303 
    304279#ifdef VBOX_WITH_INTEL_HDA
    305280                /* Intel ICH / PCH: 1 frame. */
     
    313288                    cfPosAdjust = 32;
    314289                }
    315                 else
    316290#endif
    317                     cfPosAdjust = pThis->cPosAdjustFrames;
    318291            }
    319292            else /* Go with the set default. */
     
    322295            if (cfPosAdjust)
    323296            {
     297                /* Also adjust the number of fragments, as the position adjustment buffer
     298                 * does not count as an own fragment as such.
     299                 *
     300                 * This e.g. can happen on (newer) Ubuntu guests which use
     301                 * 4 (IOC) + 4408 (IOC) + 4408 (IOC) + 4408 (IOC) + 4404 (= 17632) bytes,
     302                 * where the first buffer (4) is used as position adjustment.
     303                 *
     304                 * Only skip a fragment if the whole buffer fragment is used for
     305                 * position adjustment.
     306                 */
     307                if (   (cfPosAdjust * pStream->State.cbFrameSize) == BDLE.Desc.u32BufSize
     308                    && cFragments)
     309                {
     310                    cFragments--;
     311                }
     312
    324313                /* Initialize position adjustment counter. */
    325314                pStream->State.cPosAdjustFramesLeft = cfPosAdjust;
     
    328317        }
    329318
    330         LogFunc(("[SD%RU8] cfPosAdjust=%RU32\n", pStream->u8SD, cfPosAdjust));
     319        LogFunc(("[SD%RU8] cfPosAdjust=%RU32, cFragments=%RU8\n", pStream->u8SD, cfPosAdjust, cFragments));
     320
     321        /*
     322         * Set up data transfer transfer stuff.
     323         */
     324
     325        /* Calculate the fragment size the guest OS expects interrupt delivery at. */
     326        pStream->State.cbTransferSize = pStream->u32CBL / cFragments;
     327        Assert(pStream->State.cbTransferSize);
     328        Assert(pStream->State.cbTransferSize % pStream->State.cbFrameSize == 0);
     329
     330        /* Calculate the bytes we need to transfer to / from the stream's DMA per iteration.
     331         * This is bound to the device's Hz rate and thus to the (virtual) timing the device expects. */
     332        pStream->State.cbTransferChunk = (pStream->State.Cfg.Props.uHz / pThis->u16TimerHz) * pStream->State.cbFrameSize;
     333        Assert(pStream->State.cbTransferChunk);
     334        Assert(pStream->State.cbTransferChunk % pStream->State.cbFrameSize == 0);
     335
     336        /* Make sure that the transfer chunk does not exceed the overall transfer size. */
     337        if (pStream->State.cbTransferChunk > pStream->State.cbTransferSize)
     338            pStream->State.cbTransferChunk = pStream->State.cbTransferSize;
     339
     340        pStream->State.cbTransferProcessed        = 0;
     341        pStream->State.cTransferPendingInterrupts = 0;
     342
     343        const uint64_t cTicksPerHz = TMTimerGetFreq(pThis->pTimer) / pThis->u16TimerHz;
     344
     345        /* Calculate the timer ticks per byte for this stream. */
     346        pStream->State.cTicksPerByte = cTicksPerHz / pStream->State.cbTransferChunk;
     347        Assert(pStream->State.cTicksPerByte);
     348
     349        /* Calculate timer ticks per transfer. */
     350        pStream->State.cTransferTicks     = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
     351
     352        /* Initialize the transfer timestamps. */
     353        pStream->State.tsTransferLast     = 0;
     354        pStream->State.tsTransferNext     = 0;
     355
     356        LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \
     357                 "cbTransferSize=%RU32\n",
     358                 pStream->u8SD, pThis->u16TimerHz, cTicksPerHz, pStream->State.cTicksPerByte,
     359                 pStream->State.cbTransferChunk, pStream->State.cTransferTicks, pStream->State.cbTransferSize));
    331360
    332361        /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
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