Changeset 89680 in vbox
- Timestamp:
- Jun 14, 2021 1:25:44 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r89664 r89680 25 25 #include <VBox/vmm/pdmaudioifs.h> 26 26 #include <VBox/vmm/pdmaudioinline.h> 27 #include <VBox/AssertGuest.h> 27 28 28 29 #include <iprt/assert.h> … … 129 130 130 131 #define AC97_BD_LEN_MASK 0xFFFF /**< Mask for the BDL buffer length. */ 132 133 #define AC97_BD_LEN_CTL_MBZ UINT32_C(0x3fff0000) /**< Must-be-zero mask for AC97BDLE.ctl_len. */ 131 134 132 135 #define AC97_MAX_BDLE 32 /**< Maximum number of BDLEs. */ … … 820 823 821 824 /** 822 * Fetches the current BDLE (Buffer Descriptor List Entry) of an AC'97 audio stream. 823 * 824 * @returns VBox status code. 825 * Fetches the next buffer descriptor (BDLE) updating the stream registers. 826 * 827 * This will skip zero length descriptors. 828 * 829 * @returns Zero, or AC97_SR_BCIS if skipped zero length buffer with IOC set. 825 830 * @param pDevIns The device instance. 826 831 * @param pStream AC'97 stream to fetch BDLE for. 827 * 828 * @remark Uses CIV as BDLE index. 829 */ 830 static void ichac97R3StreamFetchBDLE(PPDMDEVINS pDevIns, PAC97STREAM pStream) 831 { 832 PAC97BMREGS pRegs = &pStream->Regs; 833 834 AC97BDLE BDLE; 835 PDMDevHlpPCIPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * sizeof(AC97BDLE), &BDLE, sizeof(AC97BDLE)); 836 pRegs->bd_valid = 1; 837 # ifndef RT_LITTLE_ENDIAN 838 # error "Please adapt the code (audio buffers are little endian)!" 839 # else 840 pRegs->bd.addr = RT_H2LE_U32(BDLE.addr & ~3); 841 pRegs->bd.ctl_len = RT_H2LE_U32(BDLE.ctl_len); 842 # endif 843 pRegs->picb = pRegs->bd.ctl_len & AC97_BD_LEN_MASK; 844 LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes), bup=%RTbool, ioc=%RTbool\n", 845 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16, 846 pRegs->bd.ctl_len & AC97_BD_LEN_MASK, 847 (pRegs->bd.ctl_len & AC97_BD_LEN_MASK) << 1, /** @todo r=andy Assumes 16bit samples. */ 848 RT_BOOL(pRegs->bd.ctl_len & AC97_BD_BUP), 849 RT_BOOL(pRegs->bd.ctl_len & AC97_BD_IOC))); 850 /** @todo r=bird: Several of the specificiation states that zero length BDL 851 * entries are okay, as long as they aren't at the head or end. We 852 * should simply skip up to 30 empty ones, because otherwise the timer 853 * locking falls flat on its face. */ 832 * @param pStreamCC The AC'97 stream, ring-3 state. 833 * 834 * @remark Updates CIV, PIV, BD and PICB. 835 */ 836 static uint32_t ichac97R3StreamFetchNextBdle(PPDMDEVINS pDevIns, PAC97STREAM pStream, PAC97STREAMR3 pStreamCC) 837 { 838 RT_NOREF(pStreamCC); 839 uint32_t fSrBcis = 0; 840 841 /* 842 * Loop for skipping zero length entries. 843 */ 844 for (;;) 845 { 846 /* Advance the buffer. */ 847 pStream->Regs.civ = pStream->Regs.piv; 848 pStream->Regs.piv = (pStream->Regs.piv + 1) % AC97_MAX_BDLE; 849 850 /* Load it. */ 851 AC97BDLE Bdle = { 0, 0 }; 852 PDMDevHlpPCIPhysRead(pDevIns, pStream->Regs.bdbar + pStream->Regs.civ * sizeof(AC97BDLE), &Bdle, sizeof(AC97BDLE)); 853 pStream->Regs.bd_valid = 1; 854 pStream->Regs.bd.addr = RT_H2LE_U32(Bdle.addr) & ~3; 855 pStream->Regs.bd.ctl_len = RT_H2LE_U32(Bdle.ctl_len); 856 pStream->Regs.picb = pStream->Regs.bd.ctl_len & AC97_BD_LEN_MASK; 857 858 LogFlowFunc(("BDLE%02u: %#RX32 L %#x / LB %#x, ctl=%#06x\n", 859 pStream->Regs.civ, pStream->Regs.bd.addr, pStream->Regs.bd.ctl_len & AC97_BD_LEN_MASK, 860 (pStream->Regs.bd.ctl_len & AC97_BD_LEN_MASK) * PDMAudioPropsSampleSize(&pStreamCC->State.Cfg.Props), 861 pStream->Regs.bd.ctl_len >> 16, 862 pStream->Regs.bd.ctl_len & AC97_BD_IOC ? " ioc" : "", 863 pStream->Regs.bd.ctl_len & AC97_BD_BUP ? " bup" : "")); 864 865 /* Complain about any reserved bits set in CTL and ADDR: */ 866 ASSERT_GUEST_MSG(!(pStream->Regs.bd.ctl_len & AC97_BD_LEN_CTL_MBZ), 867 ("Reserved bits set: %#RX32\n", pStream->Regs.bd.ctl_len)); 868 ASSERT_GUEST_MSG(!(RT_H2LE_U32(Bdle.addr) & 3), 869 ("Reserved addr bits set: %#RX32\n", RT_H2LE_U32(Bdle.addr) )); 870 871 /* If the length is non-zero or if we've reached LVI, we're done regardless 872 of what's been loaded. Otherwise, we skip zero length buffers. */ 873 if (pStream->Regs.picb) 874 break; 875 if (pStream->Regs.civ == pStream->Regs.lvi) 876 { 877 LogFunc(("BDLE%02u is zero length! Can't skip (CIV=LVI). %#RX32 %#RX32\n", pStream->Regs.civ, Bdle.addr, Bdle.ctl_len)); 878 break; 879 } 880 LogFunc(("BDLE%02u is zero length! Skipping. %#RX32 %#RX32\n", pStream->Regs.civ, Bdle.addr, Bdle.ctl_len)); 881 882 /* If the buffer has IOC set, make sure it's triggered by the caller. */ 883 if ( (pStream->Regs.bd.ctl_len & AC97_BD_IOC) 884 && (pStream->Regs.bd.ctl_len & AC97_BD_IOC)) 885 fSrBcis |= AC97_SR_BCIS; 886 } 887 888 /* 1.2.4.2 PCM Buffer Restrictions (in 302349-003) - #1 */ 889 ASSERT_GUEST_MSG(!(pStream->Regs.picb & 1), 890 ("Odd lengths buffers are not allowed: %#x (%d) samples\n", pStream->Regs.picb, pStream->Regs.picb)); 891 892 /* 1.2.4.2 PCM Buffer Restrictions (in 302349-003) - #2 */ 893 ASSERT_GUEST_MSG(pStream->Regs.picb > 0, ("Zero length buffers not allowed to terminate list (LVI=%u CIV=%u)\n", 894 pStream->Regs.lvi, pStream->Regs.civ)); 895 896 return fSrBcis; 854 897 } 855 898 … … 2613 2656 2614 2657 pRegs->sr &= ~AC97_SR_CELV; 2615 pRegs->civ = pRegs->piv; 2616 pRegs->piv = (pRegs->piv + 1) % AC97_MAX_BDLE; 2617 2618 ichac97R3StreamFetchBDLE(pDevIns, pStream); 2658 if (ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC)) 2659 ichac97StreamUpdateSR(pDevIns, pThis, pStream, pRegs->sr | AC97_SR_BCIS); 2619 2660 continue; 2620 2661 } … … 2717 2758 } 2718 2759 else 2719 { 2720 pRegs->civ = pRegs->piv; 2721 pRegs->piv = (pRegs->piv + 1) % AC97_MAX_BDLE; 2722 ichac97R3StreamFetchBDLE(pDevIns, pStream); 2723 } 2760 new_sr |= ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC); 2724 2761 2725 2762 ichac97StreamUpdateSR(pDevIns, pThis, pStream, new_sr); … … 3001 3038 Log3Func(("[SD%RU8] Enable\n", pStream->u8SD)); 3002 3039 3003 pRegs->civ = pRegs->piv;3004 pRegs->piv = (pRegs->piv + 1) % AC97_MAX_BDLE;3005 3006 3040 pRegs->sr &= ~AC97_SR_DCH; 3007 3041 3008 /* Fetch the initial BDLE descriptor. */3009 ichac97R3StreamFetchBDLE(pDevIns, pStream);3042 if (ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC)) 3043 ichac97StreamUpdateSR(pDevIns, pThis, pStream, pRegs->sr | AC97_SR_BCIS); 3010 3044 # ifdef LOG_ENABLED 3011 3045 if (LogIsFlowEnabled())
Note:
See TracChangeset
for help on using the changeset viewer.