VirtualBox

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


Ignore:
Timestamp:
Jun 14, 2021 8:01:32 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145139
Message:

DevIchAc97: Addressed the incorrect LVI understanding from ichac97R3DbgPrintBdl used in ichac97R3StreamOpen. Explained why ichac97R3StreamFetchNextBdle will start with BDLE00 after a stream reset (PVI=0). Some paranoia. bugref:9890

File:
1 edited

Legend:

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

    r89687 r89691  
    832832 * @param   pStreamCC           The AC'97 stream, ring-3 state.
    833833 *
    834  * @remark  Updates CIV, PIV, BD and PICB.
     834 * @remarks Updates CIV, PIV, BD and PICB.
     835 *
     836 * @note    Both PIV and CIV will be zero after a stream reset, so the first
     837 *          time we advance the buffer position afterwards, CIV will remain zero
     838 *          and PIV becomes 1.  Thus we will start processing from BDLE00 and
     839 *          not BDLE01 as CIV=0 may lead you to think.
    835840 */
    836841static uint32_t ichac97R3StreamFetchNextBdle(PPDMDEVINS pDevIns, PAC97STREAM pStream, PAC97STREAMR3 pStreamCC)
     
    845850    {
    846851        /* Advance the buffer. */
    847         pStream->Regs.civ = pStream->Regs.piv;
     852        pStream->Regs.civ = pStream->Regs.piv % AC97_MAX_BDLE /* (paranoia) */;
    848853        pStream->Regs.piv = (pStream->Regs.piv + 1) % AC97_MAX_BDLE;
    849854
     
    873878        if (pStream->Regs.picb)
    874879            break;
    875         if (pStream->Regs.civ == pStream->Regs.lvi)
     880        if (pStream->Regs.civ == (pStream->Regs.lvi % AC97_MAX_BDLE /* (paranoia) */))
    876881        {
    877882            LogFunc(("BDLE%02u is zero length! Can't skip (CIV=LVI). %#RX32 %#RX32\n", pStream->Regs.civ, Bdle.addr, Bdle.ctl_len));
     
    10881093
    10891094    pRegs->picb     = 0;
    1090     pRegs->piv      = 0;
     1095    pRegs->piv      = 0; /* Note! Because this is also zero, we will actually start transferring with BDLE00. */
    10911096    pRegs->cr       = pRegs->cr & AC97_CR_DONT_CLEAR_MASK;
    10921097    pRegs->bd_valid = 0;
     
    18851890     *       up to and we cannot really make much of a plan out of it.
    18861891     */
    1887     /** @todo This is wrong! The valid range is CVI thru LVI. However, CVI is
    1888      *        typically reset to zero, I guess... */
    18891892    AC97BDLE aBdl[AC97_MAX_BDLE];
    18901893    RT_ZERO(aBdl);
    1891     unsigned const cBuffers = pStream->Regs.lvi + 1;
    1892     PDMDevHlpPCIPhysRead(pDevIns, pStream->Regs.bdbar, aBdl, sizeof(aBdl[0]) * cBuffers);
    1893 
    1894     uint32_t cSamplesMax   = 0;
    1895     uint32_t cSamplesMin   = UINT32_MAX;
    1896     uint32_t cSamplesCur   = 0;
    1897     uint32_t cSamplesTotal = 0;
    1898     for (unsigned i = 0; i < cBuffers; i++)
    1899     {
    1900         cSamplesCur   += aBdl[0].ctl_len & AC97_BD_LEN_MASK;
    1901         cSamplesTotal += aBdl[0].ctl_len & AC97_BD_LEN_MASK;
    1902         if (aBdl[0].ctl_len & AC97_BD_IOC)
     1894    PDMDevHlpPCIPhysRead(pDevIns, pStream->Regs.bdbar, aBdl, sizeof(aBdl));
     1895
     1896    uint8_t const bLvi          = pStream->Regs.lvi % AC97_MAX_BDLE /* paranoia */;
     1897    uint8_t const bCiv          = pStream->Regs.civ % AC97_MAX_BDLE /* paranoia */;
     1898    uint32_t      cSamplesMax   = 0;
     1899    uint32_t      cSamplesMin   = UINT32_MAX;
     1900    uint32_t      cSamplesCur   = 0;
     1901    uint32_t      cSamplesTotal = 0;
     1902    uint32_t      cBuffers      = 1;
     1903    for (uintptr_t i = bCiv; ; cBuffers++)
     1904    {
     1905        cSamplesTotal += aBdl[i].ctl_len & AC97_BD_LEN_MASK;
     1906        cSamplesCur   += aBdl[i].ctl_len & AC97_BD_LEN_MASK;
     1907        if (aBdl[i].ctl_len & AC97_BD_IOC)
    19031908        {
    19041909            if (cSamplesCur > cSamplesMax)
     
    19081913            cSamplesCur = 0;
    19091914        }
    1910     }
    1911 
    1912     if (cSamplesCur && cSamplesMax != 0)
    1913     {
    1914         LogFlowFunc(("Tail buffer w/o IOC, loops.\n"));
    1915         for (unsigned i = 0; i < cBuffers; i++)
    1916         {
    1917             cSamplesCur += aBdl[0].ctl_len & AC97_BD_LEN_MASK;
    1918             if (aBdl[0].ctl_len & AC97_BD_IOC)
    1919             {
    1920                 if (cSamplesCur > cSamplesMax)
    1921                     cSamplesMax = cSamplesCur;
    1922                 if (cSamplesCur < cSamplesMin)
    1923                     cSamplesMin = cSamplesCur;
    1924                 cSamplesCur = 0;
    1925                 break;
    1926             }
    1927         }
    1928     }
     1915
     1916        /* Advance. */
     1917        if (i != bLvi)
     1918            i = (i + 1) % RT_ELEMENTS(aBdl);
     1919        else
     1920            break;
     1921    }
     1922    if (!cSamplesCur)
     1923    { /* likely */ }
     1924    else if (!cSamplesMax)
     1925    {
     1926        LogFlowFunc(("%u buffers without IOC set, assuming %#x samples as the IOC period.\n", cBuffers, cSamplesMax));
     1927        cSamplesMin = cSamplesMax = cSamplesCur;
     1928    }
     1929    else if (cSamplesCur > cSamplesMax)
     1930    {
     1931        LogFlowFunc(("final buffer is without IOC, using open period as max (%#x vs current max %#x).\n", cSamplesCur, cSamplesMax));
     1932        cSamplesMax = cSamplesCur;
     1933    }
     1934    else
     1935        LogFlowFunc(("final buffer is without IOC, ignoring (%#x vs current max %#x).\n", cSamplesCur, cSamplesMax));
    19291936
    19301937    uint32_t const cbDmaMinBuf  = cSamplesMax * PDMAudioPropsSampleSize(&Cfg.Props) * 3; /* see further down */
    19311938    uint32_t const cMsDmaMinBuf = PDMAudioPropsBytesToMilli(&Cfg.Props, cbDmaMinBuf);
    19321939    LogRel3(("AC97: [SD%RU8] buffer length stats: total=%#x in %u buffers, min=%#x, max=%#x => min DMA buffer %u ms / %#x bytes\n",
    1933                  pStream->u8SD, cSamplesTotal, cBuffers, cSamplesMin, cSamplesMax, cMsDmaMinBuf, cbDmaMinBuf));
     1940             pStream->u8SD, cSamplesTotal, cBuffers, cSamplesMin, cSamplesMax, cMsDmaMinBuf, cbDmaMinBuf));
    19341941
    19351942    /*
     
    36643671            bool const fValid = bCiv <= bLvi
    36653672                              ? i >= bCiv && i <= bLvi
    3666                               : (i >= bCiv && i < RT_ELEMENTS(aBdl)) || i <= bLvi;
     3673                              : i >= bCiv || i <= bLvi;
    36673674
    36683675            uint32_t const cb = (aBdl[i].ctl_len & AC97_BD_LEN_MASK) * PDMAudioPropsSampleSize(&Props); /** @todo or frame size? OSDev says frame... */
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