VirtualBox

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


Ignore:
Timestamp:
Jun 18, 2021 12:21:50 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145222
Message:

DevIchAc97: Added statistics on some special DMA transfer cases. Added some todos in same code. bugref:9890

File:
1 edited

Legend:

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

    r89768 r89770  
    401401    /** Number of bytes involved in unresolved flow errors. */
    402402    STAMCOUNTER             StatDmaFlowErrorBytes;
     403    STAMCOUNTER             StatDmaSkippedDch;
     404    STAMCOUNTER             StatDmaSkippedPendingBcis;
    403405    STAMPROFILE             StatStart;
    404406    STAMPROFILE             StatReset;
     
    10041006    PAC97BMREGS pRegs = &pStream->Regs;
    10051007
    1006     if (!(pRegs->sr & AC97_SR_DCH)) /* Controller halted? */
    1007     { /* not halted - likely */ }
     1008    /*
     1009     * Check that the controller is not halted (DCH) and that the buffer
     1010     * completion interrupt isn't pending.
     1011     */
     1012    /** @todo r=bird: Why do we not just barge ahead even when BCIS is set?  Can't
     1013     *        find anything in spec indicating that we shouldn't.  Linux shouldn't
     1014     *        care if be bundle IOCs, as it checks how many steps we've taken using
     1015     *        CIV.  The Windows AC'97 sample driver doesn't care at all, since it
     1016     *        just sets LIV to CIV-1  (thought that's probably not what the real
     1017     *        windows driver does)...
     1018     *
     1019     *        This is not going to sound good if it happens often enough, because
     1020     *        each time we'll lose one DMA period (exact length depends on the
     1021     *        buffer here).
     1022     *
     1023     *        If we're going to keep this hack, there should be a
     1024     *        PDMDevHlpTimerSetRelative call arm-ing the DMA timer to fire shortly
     1025     *        after BCIS is cleared.  Otherwise, we might lag behind even more
     1026     *        before we get stuff going again.
     1027     *
     1028     *        I just wish there was some clear reasoning in the source code for
     1029     *        weird shit like this.  This is just random voodoo.  Sigh^3! */
     1030    if (!(pRegs->sr & (AC97_SR_DCH | AC97_SR_BCIS))) /* Controller halted? */
     1031    { /* not halted nor does it have pending interrupt - likely */ }
    10081032    else
    10091033    {
    1010         if (pRegs->cr & AC97_CR_RPBM) /* Bus master operation starts. */
     1034        if (pRegs->sr & AC97_SR_DCH)
    10111035        {
    1012             switch (pStream->u8SD)
    1013             {
    1014                 case AC97SOUNDSOURCE_PO_INDEX:
    1015                     /*ichac97R3WriteBUP(pThis, cbToProcess);*/
    1016                     break;
    1017 
    1018                 default:
    1019                     break;
    1020             }
     1036            STAM_REL_COUNTER_INC(&pStreamCC->State.StatDmaSkippedDch);
     1037            LogFunc(("[SD%RU8] DCH set\n", pStream->u8SD));
     1038        }
     1039        if (pRegs->sr & AC97_SR_BCIS)
     1040        {
     1041            STAM_REL_COUNTER_INC(&pStreamCC->State.StatDmaSkippedPendingBcis);
     1042            LogFunc(("[SD%RU8] BCIS set\n", pStream->u8SD));
     1043        }
     1044        if ((pRegs->cr & AC97_CR_RPBM) /* Bus master operation started. */ && !fInput)
     1045        {
     1046            /*ichac97R3WriteBUP(pThis, cbToProcess);*/
    10211047        }
    10221048
     
    10251051    }
    10261052
    1027     /* BCIS flag still set? Skip iteration. */
    1028 /** @todo combine with the above test. */
    1029     if (!(pRegs->sr & AC97_SR_BCIS))
    1030     { /* likely */ }
    1031     else
    1032     {
    1033         /** @todo counter   */
    1034         Log3Func(("[SD%RU8] BCIS set\n", pStream->u8SD));
    1035 
    1036         ichac97R3StreamUnlock(pStreamCC);
    1037         return VINF_SUCCESS;
    1038     }
    1039 
    1040     uint32_t cbLeft           = RT_MIN((uint32_t)(pRegs->picb << 1), cbToProcessMax); /** @todo r=andy Assumes 16bit samples. */
    1041     uint32_t cbProcessedTotal = 0;
    1042 
    1043     PRTCIRCBUF pCircBuf = pStreamCC->State.pCircBuf;
     1053    /*
     1054     * How much to transfer.
     1055     */
     1056    /** @todo r=bird: This is wrong, isn't it?  We should just transfer
     1057     *        cbToProcessMax.  The caller does a RT_MIN(cbPeriod, buffer), so
     1058     *        we'll get the min number of bytes to transfer in.  It should equal
     1059     *        PICB, but it doesn't technically have to and the loop below seems to
     1060     *        think we can work with PICB=0, which this code here contratradicts.
     1061     *
     1062     *        When it was introduced in r108022, it might've made some sense...
     1063     *
     1064     *        Which is inconsistent.  I hate inconsistencies. */
     1065    uint32_t cbLeft           = pRegs->picb * PDMAudioPropsSampleSize(&pStreamCC->State.Cfg.Props);
     1066    cbLeft = RT_MIN(cbLeft, cbToProcessMax);
     1067    Log3Func(("[SD%RU8] cbToProcessMax=%#x cbLeft=%#x\n", pStream->u8SD, cbToProcessMax, cbLeft));
     1068
     1069    /*
     1070     * Transfer loop.
     1071     */
     1072    uint32_t   cbProcessedTotal = 0;
     1073    int        rc               = VINF_SUCCESS;
     1074    PRTCIRCBUF pCircBuf         = pStreamCC->State.pCircBuf;
    10441075    AssertReturnStmt(pCircBuf, ichac97R3StreamUnlock(pStreamCC), VINF_SUCCESS);
    10451076
    1046     int rc = VINF_SUCCESS;
    1047 
    1048     Log3Func(("[SD%RU8] cbToProcessMax=%RU32, cbLeft=%RU32\n", pStream->u8SD, cbToProcessMax, cbLeft));
    1049 
    1050     while (cbLeft)
    1051     {
    1052         if (!pRegs->picb) /* Got a new buffer descriptor, that is, the position is 0? */
     1077    while (cbLeft > 0)
     1078    {
     1079        /** @todo as mentioned above, this is utter non-sense as it won't _ever_ be
     1080         *        taken, given that cbLeft == PICB * 2. */
     1081        if (!pRegs->picb) /* Get a new buffer descriptor, that is, the position is 0? */
    10531082        {
    10541083            Log3Func(("Fresh buffer descriptor %RU8 is empty, addr=%#x, len=%#x, skipping\n",
     
    11331162        }
    11341163
    1135         if (cbChunk)
    1136         {
    1137             Assert(PDMAudioPropsIsSizeAligned(&pStreamCC->State.Cfg.Props, cbChunk));
    1138             Assert(cbChunk <= cbLeft);
    1139 
    1140             cbProcessedTotal     += cbChunk;
    1141             Assert(cbProcessedTotal <= cbToProcessMax);
    1142             cbLeft               -= cbChunk;
    1143             pRegs->picb          -= (cbChunk >> 1); /** @todo r=andy Assumes 16bit samples. */
    1144             pRegs->bd.addr       += cbChunk;
    1145         }
     1164        Assert(PDMAudioPropsIsSizeAligned(&pStreamCC->State.Cfg.Props, cbChunk));
     1165        Assert(cbChunk <= cbLeft);
     1166
     1167        cbProcessedTotal     += cbChunk;
     1168        Assert(cbProcessedTotal <= cbToProcessMax);
     1169        cbLeft               -= cbChunk;
     1170        pRegs->picb          -= (cbChunk >> 1); /** @todo r=andy Assumes 16bit samples. */
     1171        pRegs->bd.addr       += cbChunk;
    11461172
    11471173        LogFlowFunc(("[SD%RU8] cbChunk=%RU32, cbLeft=%RU32, cbTotal=%RU32, rc=%Rrc\n",
    11481174                     pStream->u8SD, cbChunk, cbLeft, cbProcessedTotal, rc));
    11491175
     1176        /** @todo r=bird: again, given that cbLeft == PICB * 2, we could put this
     1177         *        outside the loop and save a lot of clutter (VINF_EOF). */
    11501178        if (!pRegs->picb)
    11511179        {
     
    45514579                                   "Number of bytes of silence added to cope with underruns.", "Stream%u/DMABufferSilence", idxStream);
    45524580        }
     4581        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aStreams[idxStream].State.StatDmaSkippedDch, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     4582                               "DMA transfer period skipped, controller halted (DCH).", "Stream%u/DMASkippedDch", idxStream);
     4583        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aStreams[idxStream].State.StatDmaSkippedPendingBcis, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     4584                               "DMA transfer period skipped because of BCIS pending.", "Stream%u/DMASkippedPendingBCIS", idxStream);
    45534585
    45544586        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aStreams[idxStream].State.StatStart, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette