- Timestamp:
- Jun 23, 2021 7:06:11 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 145327
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHda.cpp
r89861 r89869 54 54 55 55 #include "DevHda.h" 56 #include "DevHdaCommon.h"57 #include "DevHdaCodec.h"58 #include "DevHdaStream.h"59 56 60 57 #include "AudioHlp.h" … … 245 242 #endif 246 243 } HDADRIVER; 244 /** The HDA host driver backend. */ 245 typedef struct HDADRIVER *PHDADRIVER; 247 246 248 247 … … 1054 1053 * Calculate where the DMA engine should be according to the clock, if we can. 1055 1054 */ 1056 uint32_t const idxSched = pStreamShared->State.idxSchedule; 1057 if (idxSched < RT_MIN(RT_ELEMENTS(pStreamShared->State.aSchedule), pStreamShared->State.cSchedule)) 1055 uint32_t const cbFrame = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props); 1056 uint32_t const cbPeriod = pStreamShared->State.cbCurDmaPeriod; 1057 if (cbPeriod > cbFrame) 1058 1058 { 1059 uint32_t const cbPeriod = pStreamShared->State.aSchedule[idxSched].cbPeriod; 1060 uint32_t const cbFrame = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props); 1061 if (cbPeriod > cbFrame) 1059 AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod)); 1060 uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext; 1061 uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, pThis->aStreams[0].hTimer); /* only #0 works in r0 */ 1062 uint32_t cbFuture; 1063 if (tsNow < tsTransferNext) 1062 1064 { 1063 AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod)); 1064 uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext; 1065 uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer); 1066 uint32_t cbFuture; 1067 if (tsNow < tsTransferNext) 1068 { 1069 /** @todo ASSUMES nanosecond clock ticks, need to make this 1070 * resolution independent. */ 1071 cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow); 1072 cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame); 1073 } 1074 else 1075 { 1076 /* We've hit/overshot the timer deadline. Return to ring-3 if we're 1077 not already there to increase the chance that we'll help expidite 1078 the timer. If we're already in ring-3, do all but the last frame. */ 1079 # ifndef IN_RING3 1080 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n", 1081 tsNow, tsTransferNext)); 1082 return VINF_IOM_R3_MMIO_READ; 1083 # else 1084 cbFuture = cbPeriod - cbFrame; 1085 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n", 1086 tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame)); 1087 # endif 1088 } 1089 uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture); 1090 1091 /* 1092 * Should we transfer a little? Minimum is 64 bytes (semi-random, 1093 * suspect real hardware might be doing some cache aligned stuff, 1094 * which might soon get complicated if you take unaligned buffers 1095 * into consideration and which cache line size (128 bytes is just 1096 * as likely as 64 or 32 bytes)). 1097 */ 1098 uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal; 1099 if (cbDmaTotal + 64 <= offNow) 1100 { 1101 VBOXSTRICTRC rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared, offNow - cbDmaTotal); 1102 1103 /* LPIB is updated by hdaStreamDoOnAccessDmaOutput, so get the new value. */ 1104 uint32_t const uNewLpib = HDA_STREAM_REG(pThis, LPIB, uSD); 1105 *pu32Value = uNewLpib; 1106 1107 LogFlowFunc(("[SD%RU8] LPIB=%#RX32 (CBL=%#RX32 PrevLPIB=%#x offNow=%#x) rcStrict=%Rrc\n", uSD, 1108 uNewLpib, HDA_STREAM_REG(pThis, CBL, uSD), uLPIB, offNow, VBOXSTRICTRC_VAL(rcStrict) )); 1109 return rcStrict; 1110 } 1111 1112 /* 1113 * Do nothing, just return LPIB as it is. 1114 */ 1115 LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", uSD, cbDmaTotal, offNow)); 1065 /** @todo ASSUMES nanosecond clock ticks, need to make this 1066 * resolution independent. */ 1067 cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow); 1068 cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame); 1116 1069 } 1117 1070 else 1118 LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x!!\n", uSD, cbPeriod, cbFrame)); 1071 { 1072 /* We've hit/overshot the timer deadline. Return to ring-3 if we're 1073 not already there to increase the chance that we'll help expidite 1074 the timer. If we're already in ring-3, do all but the last frame. */ 1075 # ifndef IN_RING3 1076 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n", 1077 tsNow, tsTransferNext)); 1078 return VINF_IOM_R3_MMIO_READ; 1079 # else 1080 cbFuture = cbPeriod - cbFrame; 1081 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n", 1082 tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame)); 1083 # endif 1084 } 1085 uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture); 1086 1087 /* 1088 * Should we transfer a little? Minimum is 64 bytes (semi-random, 1089 * suspect real hardware might be doing some cache aligned stuff, 1090 * which might soon get complicated if you take unaligned buffers 1091 * into consideration and which cache line size (128 bytes is just 1092 * as likely as 64 or 32 bytes)). 1093 */ 1094 uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal; 1095 if (cbDmaTotal + 64 <= offNow) 1096 { 1097 VBOXSTRICTRC rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared, 1098 tsNow, offNow - cbDmaTotal); 1099 1100 /* LPIB is updated by hdaStreamDoOnAccessDmaOutput, so get the new value. */ 1101 uint32_t const uNewLpib = HDA_STREAM_REG(pThis, LPIB, uSD); 1102 *pu32Value = uNewLpib; 1103 1104 LogFlowFunc(("[SD%RU8] LPIB=%#RX32 (CBL=%#RX32 PrevLPIB=%#x offNow=%#x) rcStrict=%Rrc\n", uSD, 1105 uNewLpib, HDA_STREAM_REG(pThis, CBL, uSD), uLPIB, offNow, VBOXSTRICTRC_VAL(rcStrict) )); 1106 return rcStrict; 1107 } 1108 1109 /* 1110 * Do nothing, just return LPIB as it is. 1111 */ 1112 LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", uSD, cbDmaTotal, offNow)); 1119 1113 } 1120 1114 else 1121 LogFunc(("[SD%RU8] idxSched=%u cSchedule=%u!!\n", uSD, idxSched, pStreamShared->State.cSchedule));1115 LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x!!\n", uSD, cbPeriod, cbFrame)); 1122 1116 } 1123 1117 else … … 1137 1131 * Used by hdaRegReadWALCLK() and 'info hda'. 1138 1132 * 1139 * @returns The full wall clock value 1133 * @returns Strict VBox status code if @a fDoDma is @c true, otherwise 1134 * VINF_SUCCESS. 1140 1135 * @param pDevIns The device instance. 1141 1136 * @param pThis The shared HDA device state. 1142 */ 1143 static uint64_t hdaGetWallClock(PPDMDEVINS pDevIns, PHDASTATE pThis) 1137 * @param fDoDma Whether to consider doing DMA work or not. 1138 * @param puWallNow Where to return the current wall clock time. 1139 */ 1140 static VBOXSTRICTRC hdaQueryWallClock(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fDoDma, uint64_t *puWallNow) 1144 1141 { 1145 1142 /* … … 1175 1172 uint64_t tsDmaNow = tsNow; 1176 1173 for (size_t i = 0; i < RT_ELEMENTS(pThis->aStreams); i++) 1177 if ( pThis->aStreams[i].State.fRunning 1178 && pThis->aStreams[i].State.tsTransferLast < tsDmaNow 1179 && pThis->aStreams[i].State.tsTransferLast > tsStart) 1180 { 1181 tsDmaNow = pThis->aStreams[i].State.tsTransferLast; 1182 iDmaNow = (int)i; 1174 if (pThis->aStreams[i].State.fRunning) 1175 { 1176 #ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA 1177 /* Linux is reading WALCLK before one of the DMA position reads and 1178 we've already got the current time from TM, so check if we should 1179 do a little bit of DMA'ing here to help WALCLK ahead. */ 1180 if (fDoDma) 1181 { 1182 if (hdaGetDirFromSD((uint8_t)i) == PDMAUDIODIR_OUT) 1183 { 1184 VBOXSTRICTRC rcStrict = hdaStreamMaybeDoOnAccessDmaOutput(pDevIns, pThis, &pThis->aStreams[i], tsNow); 1185 if (rcStrict == VINF_SUCCESS) 1186 { /* likely */ } 1187 else 1188 return rcStrict; 1189 } 1190 } 1191 #endif 1192 1193 if ( pThis->aStreams[i].State.tsTransferLast < tsDmaNow 1194 && pThis->aStreams[i].State.tsTransferLast > tsStart) 1195 { 1196 tsDmaNow = pThis->aStreams[i].State.tsTransferLast; 1197 iDmaNow = (int)i; 1198 } 1183 1199 } 1184 1200 … … 1189 1205 Log3Func(("Returning %#RX64 - tsNow=%#RX64 tsDmaNow=%#RX64 (%d) -> %#RX64\n", 1190 1206 uWallClkNow, tsNow, tsDmaNow, iDmaNow, tsNow - tsDmaNow)); 1191 RT_NOREF(iDmaNow); 1192 return uWallClkNow; 1207 RT_NOREF(iDmaNow, fDoDma); 1208 *puWallNow = uWallClkNow; 1209 return VINF_SUCCESS; 1193 1210 } 1194 1211 1195 1212 static VBOXSTRICTRC hdaRegReadWALCLK(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 1196 1213 { 1197 RT_NOREF(pDevIns, iReg); 1198 *pu32Value = (uint32_t)hdaGetWallClock(pDevIns, pThis); 1199 return VINF_SUCCESS; 1214 uint64_t uWallNow = 0; 1215 VBOXSTRICTRC rcStrict = hdaQueryWallClock(pDevIns, pThis, true /*fDoDma*/, &uWallNow); 1216 if (rcStrict == VINF_SUCCESS) 1217 { 1218 *pu32Value = (uint32_t)uWallNow; 1219 return VINF_SUCCESS; 1220 } 1221 RT_NOREF(iReg); 1222 return rcStrict; 1200 1223 } 1201 1224 … … 1527 1550 uint64_t tsTransferNext = tsNow + pStreamShared->State.aSchedule[0].cPeriodTicks; 1528 1551 pStreamShared->State.tsTransferNext = tsTransferNext; /* legacy */ 1529 pStreamShared->State.cb TransferSize= pStreamShared->State.aSchedule[0].cbPeriod;1552 pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[0].cbPeriod; 1530 1553 Log3Func(("[SD%RU8] tsTransferNext=%RU64 (in %RU64)\n", 1531 1554 pStreamShared->u8SD, tsTransferNext, tsTransferNext - tsNow)); … … 2747 2770 { 2748 2771 # ifdef DEBUG 2749 PHDASTREAMDEBUG pStreamDbg = &pStream->Dbg;2750 2751 2772 const uint64_t tsNowNs = RTTimeNanoTS(); 2752 const uint32_t tsElapsedMs = (tsNowNs - pStream Dbg->tsWriteSlotBegin) / 1000 / 1000;2753 2754 uint64_t cWritesHz = ASMAtomicReadU64(&pStream Dbg->cWritesHz);2755 uint64_t cbWrittenHz = ASMAtomicReadU64(&pStream Dbg->cbWrittenHz);2773 const uint32_t tsElapsedMs = (tsNowNs - pStream->Dbg.tsWriteSlotBegin) / 1000 / 1000; 2774 2775 uint64_t cWritesHz = ASMAtomicReadU64(&pStream->Dbg.cWritesHz); 2776 uint64_t cbWrittenHz = ASMAtomicReadU64(&pStream->Dbg.cbWrittenHz); 2756 2777 2757 2778 if (tsElapsedMs >= (1000 / HDA_TIMER_HZ_DEFAULT)) … … 2761 2782 ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ_DEFAULT)); 2762 2783 2763 pStream Dbg->tsWriteSlotBegin = tsNowNs;2784 pStream->Dbg.tsWriteSlotBegin = tsNowNs; 2764 2785 2765 2786 cWritesHz = 0; … … 2770 2791 cbWrittenHz += cbBuf; 2771 2792 2772 ASMAtomicIncU64(&pStream Dbg->cWritesTotal);2773 ASMAtomicAddU64(&pStream Dbg->cbWrittenTotal, cbBuf);2774 2775 ASMAtomicWriteU64(&pStream Dbg->cWritesHz, cWritesHz);2776 ASMAtomicWriteU64(&pStream Dbg->cbWrittenHz, cbWrittenHz);2793 ASMAtomicIncU64(&pStream->Dbg.cWritesTotal); 2794 ASMAtomicAddU64(&pStream->Dbg.cbWrittenTotal, cbBuf); 2795 2796 ASMAtomicWriteU64(&pStream->Dbg.cWritesHz, cWritesHz); 2797 ASMAtomicWriteU64(&pStream->Dbg.cbWrittenHz, cbWrittenHz); 2777 2798 2778 2799 LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n", … … 2780 2801 2781 2802 LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n", 2782 pStream->u8SD, pStream Dbg->cWritesTotal, pStreamDbg->cbWrittenTotal,2783 ASMDivU64ByU32RetU32(pStream Dbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));2803 pStream->u8SD, pStream->Dbg.cWritesTotal, pStream->Dbg.cbWrittenTotal, 2804 ASMDivU64ByU32RetU32(pStream->Dbg.cbWrittenTotal, pStream->Dbg.cWritesTotal))); 2784 2805 # endif 2785 2806 … … 4187 4208 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]); 4188 4209 else 4189 pHlp->pfnPrintf(pHlp, "%s: 0x%RX64\n", g_aHdaRegMap[iHdaIndex].abbrev, hdaGetWallClock(pDevIns, pThis)); 4210 { 4211 uint64_t uWallNow = 0; 4212 hdaQueryWallClock(pDevIns, pThis, false /*fDoDma*/, &uWallNow); 4213 pHlp->pfnPrintf(pHlp, "%s: 0x%RX64\n", g_aHdaRegMap[iHdaIndex].abbrev, uWallNow); 4214 } 4190 4215 } 4191 4216 … … 5204 5229 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.offWrite, STAMTYPE_U64, STAMVISIBILITY_USED, STAMUNIT_BYTES, 5205 5230 "Virtual internal buffer write position.", "Stream%u/offWrite", idxStream); 5206 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.cb TransferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES,5207 "Bytes transfered per DMA timer callout.", "Stream%u/cb TransferSize", idxStream);5231 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.cbCurDmaPeriod, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_BYTES, 5232 "Bytes transfered per DMA timer callout.", "Stream%u/cbCurDmaPeriod", idxStream); 5208 5233 PDMDevHlpSTAMRegisterF(pDevIns, (void*)&pThis->aStreams[idxStream].State.fRunning, STAMTYPE_BOOL, STAMVISIBILITY_USED, STAMUNIT_BYTES, 5209 5234 "True if the stream is in RUN mode.", "Stream%u/fRunning", idxStream); -
trunk/src/VBox/Devices/Audio/DevHda.h
r89861 r89869 28 28 #include "AudioMixer.h" 29 29 30 #include "DevHdaCodec.h" 31 #include "DevHdaStream.h" 30 /* 31 * Compile time feature configuration. 32 */ 33 34 /** @def VBOX_HDA_WITH_ON_REG_ACCESS_DMA 35 * Enables doing DMA work on certain register accesses (LPIB, WALCLK) in 36 * addition to the DMA timer. All but the last frame can be done during 37 * register accesses (as we don't wish to leave the DMA timer w/o work to 38 * do in case that upsets it). */ 39 #if defined(DOXYGEN_RUNNING) || 0 40 # define VBOX_HDA_WITH_ON_REG_ACCESS_DMA 41 #endif 32 42 33 43 #ifdef DEBUG_andy … … 36 46 //# define HDA_STRICT 37 47 #endif 48 49 50 /* 51 * Common pointer types. 52 */ 53 /** Pointer to an HDA stream (SDI / SDO). */ 54 typedef struct HDASTREAMR3 *PHDASTREAMR3; 55 /** Pointer to a shared HDA device state. */ 56 typedef struct HDASTATE *PHDASTATE; 57 /** Pointer to a ring-3 HDA device state. */ 58 typedef struct HDASTATER3 *PHDASTATER3; 59 60 61 /* 62 * The rest of the headers. 63 */ 64 #include "DevHdaCommon.h" 65 #include "DevHdaStream.h" 66 #include "DevHdaCodec.h" 67 38 68 39 69 /** … … 277 307 } Dbg; 278 308 } HDASTATER3; 279 /** Pointer to a ring-3 HDA device state. */280 typedef HDASTATER3 *PHDASTATER3;281 309 282 310 -
trunk/src/VBox/Devices/Audio/DevHdaCodec.cpp
r89768 r89869 40 40 #include "VBoxDD.h" 41 41 #include "AudioMixer.h" 42 #include "DevHda.h" 42 43 #include "DevHdaCodec.h" 43 44 #include "DevHdaCommon.h" -
trunk/src/VBox/Devices/Audio/DevHdaCodec.h
r89810 r89869 22 22 #endif 23 23 24 #ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h 25 # error "Only include DevHda.h!" 26 #endif 27 24 28 #include <iprt/list.h> 25 26 29 #include "AudioMixer.h" 27 30 28 /** Pointer to a shared HDA device state. */29 typedef struct HDASTATE *PHDASTATE;30 /** Pointer to a ring-3 HDA device state. */31 typedef struct HDASTATER3 *PHDASTATER3;32 31 33 32 /** The ICH HDA (Intel) common codec state. */ … … 39 38 /** The ICH HDA (Intel) current context codec state. */ 40 39 typedef CTX_SUFF(PHDACODEC) PHDACODECCC; 41 42 /** The HDA host driver backend. */43 typedef struct HDADRIVER *PHDADRIVER;44 40 45 41 /** -
trunk/src/VBox/Devices/Audio/DevHdaCommon.cpp
r89406 r89869 34 34 #include "DevHda.h" 35 35 #include "DevHdaCommon.h" 36 #include "DevHdaStream.h"37 36 38 37 -
trunk/src/VBox/Devices/Audio/DevHdaCommon.h
r88235 r89869 25 25 #endif 26 26 27 #ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h 28 # error "Only include DevHda.h!" 29 #endif 30 27 31 #include "AudioMixer.h" 28 32 #include <VBox/log.h> /* LOG_ENABLED */ 29 30 /** Pointer to an HDA stream (SDI / SDO). */31 typedef struct HDASTREAMR3 *PHDASTREAMR3;32 33 33 34 34 -
trunk/src/VBox/Devices/Audio/DevHdaStream.cpp
r89865 r89869 34 34 35 35 #include "DevHda.h" 36 #include "DevHdaStream.h"37 36 38 37 #ifdef VBOX_WITH_DTRACE … … 649 648 return rc; 650 649 651 pStreamShared->State.cb TransferSize= pStreamShared->State.aSchedule[0].cbPeriod;650 pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[0].cbPeriod; 652 651 653 652 /* … … 1463 1462 PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf; 1464 1463 uint32_t cbLeft = cbToConsume; 1465 Assert(cbLeft == pStreamShared->State.cb TransferSize);1464 Assert(cbLeft == pStreamShared->State.cbCurDmaPeriod); 1466 1465 Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft)); 1467 1466 … … 1607 1606 */ 1608 1607 Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n", 1609 uSD, cbToConsume, pStreamShared->State.cb TransferSize, pStreamShared->State.offRead - cbToConsume,1608 uSD, cbToConsume, pStreamShared->State.cbCurDmaPeriod, pStreamShared->State.offRead - cbToConsume, 1610 1609 pStreamShared->State.cTransferPendingInterrupts)); 1611 1610 } … … 1684 1683 uint32_t cbLeft = cbToProduce; 1685 1684 # ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA 1686 Assert(cbLeft <= pStreamShared->State.cb TransferSize); /* a little pointless with the DMA'ing on LPIB read. */1685 Assert(cbLeft <= pStreamShared->State.cbCurDmaPeriod); /* a little pointless with the DMA'ing on LPIB read. */ 1687 1686 # else 1688 Assert(cbLeft == pStreamShared->State.cb TransferSize);1687 Assert(cbLeft == pStreamShared->State.cbCurDmaPeriod); 1689 1688 # endif 1690 1689 Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft)); … … 1868 1867 */ 1869 1868 Log3Func(("LEAVE - [SD%RU8] %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n", 1870 uSD, cbToProduce, pStreamShared->State.cb TransferSize, pStreamShared->State.offWrite - cbToProduce,1869 uSD, cbToProduce, pStreamShared->State.cbCurDmaPeriod, pStreamShared->State.offWrite - cbToProduce, 1871 1870 pStreamShared->State.cTransferPendingInterrupts)); 1872 1871 } 1873 1872 1874 1873 #endif /* IN_RING3 */ 1875 1876 1874 #ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA 1877 /** 1878 * Do DMA output transfer on LPIB register access. 1875 1876 /** 1877 * Do DMA output transfer on LPIB/WALCLK register access. 1879 1878 * 1880 1879 * @returns VINF_SUCCESS or VINF_IOM_R3_MMIO_READ. … … 1882 1881 * @param pThis The shared instance data. 1883 1882 * @param pStreamShared The shared stream data. 1883 * @param tsNow The current time on the timer clock. 1884 1884 * @param cbToTransfer How much to transfer. 1885 1885 */ 1886 VBOXSTRICTRC hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint32_t cbToTransfer) 1886 VBOXSTRICTRC hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, 1887 uint64_t tsNow, uint32_t cbToTransfer) 1887 1888 { 1888 1889 AssertReturn(cbToTransfer > 0, VINF_SUCCESS); … … 1992 1993 1993 1994 /* 1994 * Advance LPIB .1995 * Advance LPIB and update the last transfer time (for WALCLK). 1995 1996 */ 1997 pStreamShared->State.tsTransferLast = tsNow; 1996 1998 hdaStreamSetPositionAdd(pStreamShared, pDevIns, pThis, cbToTransfer - cbLeft); 1997 1999 } … … 2007 2009 return rc; 2008 2010 } 2011 2012 2013 /** 2014 * Consider doing DMA output transfer on LPIB/WALCLK register access. 2015 * 2016 * @returns VINF_SUCCESS or VINF_IOM_R3_MMIO_READ. 2017 * @param pDevIns The device instance. 2018 * @param pThis The shared instance data. 2019 * @param pStreamShared The shared stream data. 2020 * @param tsNow The current time on the timer clock. Used to do the 2021 * calculation. 2022 */ 2023 VBOXSTRICTRC hdaStreamMaybeDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, uint64_t tsNow) 2024 { 2025 Assert(pStreamShared->State.fRunning); /* caller should check this */ 2026 2027 /* 2028 * Calculate where the DMA engine should be according to the clock, if we can. 2029 */ 2030 uint32_t const cbFrame = PDMAudioPropsFrameSize(&pStreamShared->State.Cfg.Props); 2031 uint32_t const cbPeriod = pStreamShared->State.cbCurDmaPeriod; 2032 if (cbPeriod > cbFrame) 2033 { 2034 AssertMsg(pStreamShared->State.cbDmaTotal < cbPeriod, ("%#x vs %#x\n", pStreamShared->State.cbDmaTotal, cbPeriod)); 2035 uint64_t const tsTransferNext = pStreamShared->State.tsTransferNext; 2036 uint32_t cbFuture; 2037 if (tsNow < tsTransferNext) 2038 { 2039 /** @todo ASSUMES nanosecond clock ticks, need to make this 2040 * resolution independent. */ 2041 cbFuture = PDMAudioPropsNanoToBytes(&pStreamShared->State.Cfg.Props, tsTransferNext - tsNow); 2042 cbFuture = RT_MIN(cbFuture, cbPeriod - cbFrame); 2043 } 2044 else 2045 { 2046 /* We've hit/overshot the timer deadline. Return to ring-3 if we're 2047 not already there to increase the chance that we'll help expidite 2048 the timer. If we're already in ring-3, do all but the last frame. */ 2049 # ifndef IN_RING3 2050 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> VINF_IOM_R3_MMIO_READ\n", 2051 tsNow, tsTransferNext)); 2052 return VINF_IOM_R3_MMIO_READ; 2053 # else 2054 cbFuture = cbPeriod - cbFrame; 2055 LogFunc(("[SD%RU8] DMA period expired: tsNow=%RU64 >= tsTransferNext=%RU64 -> cbFuture=%#x (cbPeriod=%#x - cbFrame=%#x)\n", 2056 tsNow, tsTransferNext, cbFuture, cbPeriod, cbFrame)); 2057 # endif 2058 } 2059 uint32_t const offNow = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbPeriod - cbFuture); 2060 2061 /* 2062 * Should we transfer a little? Minimum is 64 bytes (semi-random, 2063 * suspect real hardware might be doing some cache aligned stuff, 2064 * which might soon get complicated if you take unaligned buffers 2065 * into consideration and which cache line size (128 bytes is just 2066 * as likely as 64 or 32 bytes)). 2067 */ 2068 uint32_t cbDmaTotal = pStreamShared->State.cbDmaTotal; 2069 if (cbDmaTotal + 64 <= offNow) 2070 { 2071 # ifdef LOG_ENABLED 2072 uint32_t const uOldLpib = HDA_STREAM_REG(pThis, CBL, pStreamShared->u8SD); 2073 # endif 2074 VBOXSTRICTRC rcStrict = hdaStreamDoOnAccessDmaOutput(pDevIns, pThis, pStreamShared, tsNow, offNow - cbDmaTotal); 2075 LogFlowFunc(("[SD%RU8] LPIB=%#RX32 -> LPIB=%#RX32 offNow=%#x rcStrict=%Rrc\n", pStreamShared->u8SD, 2076 uOldLpib, HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD), offNow, VBOXSTRICTRC_VAL(rcStrict) )); 2077 return rcStrict; 2078 } 2079 2080 /* 2081 * Do nothing. 2082 */ 2083 LogFlowFunc(("[SD%RU8] Skipping DMA transfer: cbDmaTotal=%#x offNow=%#x\n", pStreamShared->u8SD, cbDmaTotal, offNow)); 2084 } 2085 else 2086 LogFunc(("[SD%RU8] cbPeriod=%#x <= cbFrame=%#x\n", pStreamShared->u8SD, cbPeriod, cbFrame)); 2087 return VINF_SUCCESS; 2088 } 2089 2009 2090 #endif /* VBOX_HDA_WITH_ON_REG_ACCESS_DMA */ 2010 2011 2012 2091 #ifdef IN_RING3 2013 2092 … … 2240 2319 /* Some legacy stuff: */ 2241 2320 pStreamShared->State.tsTransferNext = tsTransferNext; 2242 pStreamShared->State.cb TransferSize= pStreamShared->State.aSchedule[idxSched].cbPeriod;2321 pStreamShared->State.cbCurDmaPeriod = pStreamShared->State.aSchedule[idxSched].cbPeriod; 2243 2322 2244 2323 return tsNow; -
trunk/src/VBox/Devices/Audio/DevHdaStream.h
r89861 r89869 22 22 #endif 23 23 24 #include "DevHdaCommon.h" 24 #ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h 25 # error "Only include DevHda.h!" 26 #endif 25 27 26 28 … … 83 85 #endif 84 86 } HDASTREAMDEBUG; 85 typedef HDASTREAMDEBUG *PHDASTREAMDEBUG;86 87 87 88 /** … … 132 133 * Can be 0 if no next transfer is scheduled. */ 133 134 uint64_t tsTransferNext; 134 /** T otal transfer size (in bytes) of atransfer period. */135 uint32_t cb TransferSize;135 /** The size of the current DMA transfer period. */ 136 uint32_t cbCurDmaPeriod; 136 137 /** The size of an average transfer. */ 137 138 uint32_t cbAvgTransfer; … … 324 325 */ 325 326 VBOXSTRICTRC hdaStreamDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShared, 326 uint32_t cbToTransfer); 327 uint64_t tsNow, uint32_t cbToTransfer); 328 VBOXSTRICTRC hdaStreamMaybeDoOnAccessDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, 329 PHDASTREAM pStreamShared, uint64_t tsNow); 327 330 /** @} */ 328 331
Note:
See TracChangeset
for help on using the changeset viewer.