Changeset 89771 in vbox
- Timestamp:
- Jun 18, 2021 12:58:07 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r89770 r89771 988 988 * @param pStream The AC'97 stream to update (shared). 989 989 * @param pStreamCC The AC'97 stream to update (ring-3). 990 * @param cbToProcessMax Maximum of data (in bytes) to process. 990 * @param cbToProcess The max amount of data to process (i.e. 991 * put into / remove from the circular buffer). 992 * Unless something is going seriously wrong, this 993 * will always be transfer size for the current 994 * period. The current period will never be 995 * larger than what can be stored in the current 996 * buffer (i.e. what PICB indicates). 997 * @param tsNowNs The current RTTimeNano() value. 991 998 * @param fWriteSilence Whether to write silence if this is an input 992 999 * stream (done while waiting for backend to get … … 995 1002 */ 996 1003 static int ichac97R3StreamTransfer(PPDMDEVINS pDevIns, PAC97STATE pThis, PAC97STREAM pStream, 997 PAC97STREAMR3 pStreamCC, uint32_t cbToProcess Max, bool fWriteSilence, bool fInput)998 { 999 if (RT_LIKELY(cbToProcess Max> 0))1000 Assert(PDMAudioPropsIsSizeAligned(&pStreamCC->State.Cfg.Props, cbToProcess Max));1004 PAC97STREAMR3 pStreamCC, uint32_t cbToProcess, bool fWriteSilence, bool fInput) 1005 { 1006 if (RT_LIKELY(cbToProcess > 0)) 1007 Assert(PDMAudioPropsIsSizeAligned(&pStreamCC->State.Cfg.Props, cbToProcess)); 1001 1008 else 1002 1009 return VINF_SUCCESS; … … 1032 1039 else 1033 1040 { 1041 /** @todo Stop DMA timer when DCH is set. */ 1034 1042 if (pRegs->sr & AC97_SR_DCH) 1035 1043 { … … 1051 1059 } 1052 1060 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 /* 1061 /* 0x1ba*2 = 0x374 (884) 0x3c0 1070 1062 * Transfer loop. 1071 1063 */ 1064 #ifdef LOG_ENABLED 1072 1065 uint32_t cbProcessedTotal = 0; 1066 #endif 1073 1067 int rc = VINF_SUCCESS; 1074 1068 PRTCIRCBUF pCircBuf = pStreamCC->State.pCircBuf; 1075 1069 AssertReturnStmt(pCircBuf, ichac97R3StreamUnlock(pStreamCC), VINF_SUCCESS); 1076 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? */ 1082 { 1083 Log3Func(("Fresh buffer descriptor %RU8 is empty, addr=%#x, len=%#x, skipping\n", 1084 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len)); 1085 if (pRegs->civ == pRegs->lvi) 1086 { 1087 pRegs->sr |= AC97_SR_DCH; /** @todo r=andy Also set CELV? */ 1088 pThis->bup_flag = 0; 1089 1090 rc = VINF_EOF; 1091 break; 1092 } 1093 1094 pRegs->sr &= ~AC97_SR_CELV; 1095 if (ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC)) 1096 ichac97StreamUpdateSR(pDevIns, pThis, pStream, pRegs->sr | AC97_SR_BCIS); 1097 continue; 1098 } 1099 1100 uint32_t cbChunk = cbLeft; 1070 Assert((uint32_t)pRegs->picb * PDMAudioPropsSampleSize(&pStreamCC->State.Cfg.Props) >= cbToProcess); 1071 Log3Func(("[SD%RU8] cbToProcess=%#x PICB=%#x/%#x\n", 1072 pStream->u8SD, cbToProcess, pRegs->picb, pRegs->picb * PDMAudioPropsSampleSize(&pStreamCC->State.Cfg.Props))); 1073 1074 while (cbToProcess > 0) 1075 { 1076 uint32_t cbChunk = cbToProcess; 1101 1077 1102 1078 /* … … 1163 1139 1164 1140 Assert(PDMAudioPropsIsSizeAligned(&pStreamCC->State.Cfg.Props, cbChunk)); 1165 Assert(cbChunk <= cbLeft); 1166 1141 Assert(cbChunk <= cbToProcess); 1142 1143 /* 1144 * Advance. 1145 */ 1146 pRegs->picb -= cbChunk / PDMAudioPropsSampleSize(&pStreamCC->State.Cfg.Props); 1147 pRegs->bd.addr += cbChunk; 1148 cbToProcess -= cbChunk; 1149 #ifdef LOG_ENABLED 1167 1150 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; 1172 1173 LogFlowFunc(("[SD%RU8] cbChunk=%RU32, cbLeft=%RU32, cbTotal=%RU32, rc=%Rrc\n", 1174 pStream->u8SD, cbChunk, cbLeft, cbProcessedTotal, rc)); 1175 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). */ 1178 if (!pRegs->picb) 1151 #endif 1152 LogFlowFunc(("[SD%RU8] cbChunk=%#x, cbToProcess=%#x, cbTotal=%#x picb=%#x\n", 1153 pStream->u8SD, cbChunk, cbToProcess, cbProcessedTotal, pRegs->picb)); 1154 } 1155 1156 /* 1157 * Fetch a new buffer descriptor if we've exhausted the current one. 1158 */ 1159 if (!pRegs->picb) 1160 { 1161 uint32_t fNewSr = pRegs->sr & ~AC97_SR_CELV; 1162 1163 if (pRegs->bd.ctl_len & AC97_BD_IOC) 1164 fNewSr |= AC97_SR_BCIS; 1165 1166 if (pRegs->civ != pRegs->lvi) 1167 fNewSr |= ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC); 1168 else 1179 1169 { 1180 uint32_t new_sr = pRegs->sr & ~AC97_SR_CELV; 1181 1182 if (pRegs->bd.ctl_len & AC97_BD_IOC) 1183 { 1184 new_sr |= AC97_SR_BCIS; 1185 } 1186 1187 if (pRegs->civ == pRegs->lvi) 1188 { 1189 /* Did we run out of data? */ 1190 LogFunc(("Underrun CIV (%RU8) == LVI (%RU8)\n", pRegs->civ, pRegs->lvi)); 1191 1192 new_sr |= AC97_SR_LVBCI | AC97_SR_DCH | AC97_SR_CELV; 1193 pThis->bup_flag = (pRegs->bd.ctl_len & AC97_BD_BUP) ? BUP_LAST : 0; 1194 1195 rc = VINF_EOF; 1196 } 1197 else 1198 new_sr |= ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC); 1199 1200 ichac97StreamUpdateSR(pDevIns, pThis, pStream, new_sr); 1170 LogFunc(("Underrun CIV (%RU8) == LVI (%RU8)\n", pRegs->civ, pRegs->lvi)); 1171 fNewSr |= AC97_SR_LVBCI | AC97_SR_DCH | AC97_SR_CELV; 1172 pThis->bup_flag = (pRegs->bd.ctl_len & AC97_BD_BUP) ? BUP_LAST : 0; 1173 /** @todo r=bird: The bup_flag isn't cleared anywhere else. We should probably 1174 * do what the spec says, and keep writing zeros (silence). 1175 * Alternatively, we could hope the guest will pause the DMA engine 1176 * immediately after seeing this condition, in which case we should 1177 * stop the DMA timer from being re-armed. */ 1201 1178 } 1202 1179 1203 /* All data processed? */ 1204 if (rc == VINF_EOF) 1205 break; 1180 ichac97StreamUpdateSR(pDevIns, pThis, pStream, fNewSr); 1206 1181 } 1207 1182 1208 1183 ichac97R3StreamUnlock(pStreamCC); 1209 1210 1184 LogFlowFuncLeaveRC(rc); 1211 1185 return rc; … … 2821 2795 * create a lock order violation with the virtual sync time lock otherwise. 2822 2796 */ 2823 /** @todo is ichac97R3StreamTransferUpdate called here? */2797 ichac97R3StreamTransferUpdate(pDevIns, pStream, pStreamCC); 2824 2798 uint64_t const cTicksToDeadline = pStreamCC->State.cTransferTicks; 2825 2799
Note:
See TracChangeset
for help on using the changeset viewer.