Changeset 64572 in vbox for trunk/src/VBox
- Timestamp:
- Nov 4, 2016 12:54:38 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r64404 r64572 179 179 #define HDA_REG_STATESTS 7 /* 0x0E */ 180 180 #define HDA_RMX_STATESTS 7 181 #define HDA_STATES _SCSF 0x7181 #define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */ 182 182 183 183 #define HDA_REG_GSTS 8 /* 0x10-0x11*/ … … 477 477 * Other values not listed are not supported. 478 478 */ 479 /** Maximum FIFO size (in bytes). */ 480 #define HDA_FIFO_MAX 256 481 479 482 #define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */ 480 483 #define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */ … … 566 569 * Used to check if we need fill up the FIFO again. */ 567 570 uint32_t cbBelowFIFOW; 568 /** The buffer descriptor's internal DMA buffer. */569 uint8_t au8FIFO[HDA_SDOFIFO_256B + 1];570 571 /** Current offset in DMA buffer (in bytes).*/ 571 572 uint32_t u32BufOff; … … 603 604 /** Number of audio channels in this stream. */ 604 605 uint8_t cChannels; 605 /** Array audio channels. */606 /** Array of audio channels. */ 606 607 R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels; 608 /** Circular buffer holding for holding audio data for this mapping. */ 607 609 R3PTRTYPE(PRTCIRCBUF) pCircBuf; 608 610 } HDASTREAMMAPPING, *PHDASTREAMMAPPING; … … 616 618 * maximum (cBDLE) is reached. */ 617 619 uint16_t uCurBDLE; 618 /** Stop indicator. */619 volatile bool fDoStop;620 /** Flag indicating whether this stream is in an621 * active (operative) state or not. */622 volatile bool fActive;623 620 /** Flag indicating whether this stream currently is 624 621 * in reset mode and therefore not acccessible by the guest. */ 625 622 volatile bool fInReset; 626 623 /** Unused, padding. */ 627 bool fPadding;624 uint32_t Padding0; 628 625 /** Critical section to serialize access. */ 629 626 RTCRITSECT CritSect; 630 /** Event signalling that the stream's state has been changed. */631 RTSEMEVENT hStateChangedEvent;632 627 /** This stream's data mapping. */ 633 628 HDASTREAMMAPPING Mapping; 634 629 /** Current BDLE (Buffer Descriptor List Entry). */ 635 630 HDABDLE BDLE; 631 /** Circular buffer (FIFO) for holding DMA'ed data. */ 632 R3PTRTYPE(PRTCIRCBUF) pCircBuf; 636 633 } HDASTREAMSTATE, *PHDASTREAMSTATE; 637 634 … … 659 656 660 657 /** 661 * Structure for keeping a HDA stream state. 658 * Structure for keeping a HDA stream (SDI / SDO). 659 * 660 * Note: This HDA stream has nothing to do with a regular audio stream handled 661 * by the audio connector or the audio mixer. This HDA stream is a serial data in/out 662 * stream (SDI/SDO) defined in hardware and can contain multiple audio streams 663 * in one single SDI/SDO (interleaving streams). 664 * 665 * How a specific SDI/SDO is mapped to our internal audio streams relies on the 666 * stream channel mappings. 662 667 * 663 668 * Contains only register values which do *not* change until a … … 678 683 /** FIFO Size (FIFOS). 679 684 * Maximum number of bytes that may have been DMA'd into 680 * memory but not yet transmitted on the link. 681 * 682 * Must be a power of two. */ 685 * memory but not yet transmitted on the link. */ 683 686 uint16_t u16FIFOS; 687 /** FIFO Watermark. */ 688 uint16_t u16FIFOW; 684 689 /** Last Valid Index (SDnLVI). */ 685 690 uint16_t u16LVI; 686 uint16_t Padding1[ 3];691 uint16_t Padding1[2]; 687 692 /** Pointer to HDA sink this stream is attached to. */ 688 693 R3PTRTYPE(PHDAMIXERSINK) pMixSink; … … 827 832 * Used to calculate the time actually elapsed between two timer callbacks. */ 828 833 uint64_t uTimerTS; 834 uint64_t uTimerMS; 829 835 #endif 830 836 #ifdef VBOX_WITH_STATISTICS … … 892 898 */ 893 899 static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 894 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);895 900 static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); 896 901 static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); 897 //static int hdaRegReadSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); - unused898 //static int hdaRegWriteSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - unused899 //static int hdaRegWriteINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - implementation not found.900 902 static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 901 903 static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); … … 905 907 static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 906 908 static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 909 static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 907 910 static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 908 911 static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); … … 917 920 static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 918 921 static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 919 //static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - unused 920 //static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - unused 922 static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 923 static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 921 924 static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); 922 925 static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); … … 945 948 /** @} */ 946 949 950 /** @name Stream functions. 951 * @{ 952 */ 947 953 #ifdef IN_RING3 948 static void hdaStreamDestroy(PHDASTREAM pStream); 949 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive); 950 //static int hdaStreamStart(PHDASTREAM pStream); - unused 951 static int hdaStreamStop(PHDASTREAM pStream); 952 /*static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout); - currently unused */ 953 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed); 954 #endif 955 954 static void hdaStreamDestroy(PHDASTREAM pStream); 955 static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t cbToProcess, uint32_t *pcbProcessed); 956 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive); 957 static int hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream); 958 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB); 959 #endif /* IN_RING3 */ 960 /** @} */ 961 962 /** @name Stream mapping functions. 963 * @{ 964 */ 956 965 #ifdef IN_RING3 957 static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg); 958 static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping); 959 static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping); 960 #endif 961 966 static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg); 967 static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping); 968 static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping); 969 #endif /* IN_RING3 */ 970 /** @} */ 971 972 /** @name HDA device functions. 973 * @{ 974 */ 975 #ifdef IN_RING3 976 static void hdaDoTransfers(PHDASTATE pThis); 977 #endif /* IN_RING3 */ 978 static int hdaProcessInterrupt(PHDASTATE pThis); 979 /** @} */ 980 981 /** @name BDLE (Buffer Descriptor List Entry) functions. 982 * @{ 983 */ 962 984 #ifdef IN_RING3 963 985 static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry); 964 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);965 986 # ifdef LOG_ENABLED 966 987 static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE); 967 988 # endif 968 #endif 969 static int hdaProcessInterrupt(PHDASTATE pThis); 970 971 /* 972 * Timer routines.989 #endif /* IN_RING3 */ 990 /** @} */ 991 992 /** @name Timer functions. 993 * @{ 973 994 */ 974 995 #if !defined(VBOX_WITH_AUDIO_HDA_CALLBACKS) && defined(IN_RING3) 975 static void hdaTimerMaybeStart(PHDASTATE pThis); 976 static void hdaTimerMaybeStop(PHDASTATE pThis); 977 #endif 996 static void hdaTimerMaybeStart(PHDASTATE pThis); 997 static void hdaTimerMaybeStop(PHDASTATE pThis); 998 #endif 999 /** @} */ 978 1000 979 1001 … … 1001 1023 { offset, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , HDA_REG_IDX_STRM(name, CTL) , #name " Stream Descriptor Control" }, \ 1002 1024 /* Offset 0x83 (SD0) */ \ 1003 { offset + 0x3, 0x00001, 0x000000 1C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS) , #name " Status" }, \1025 { offset + 0x3, 0x00001, 0x0000003C, 0x0000001C, hdaRegReadU8 , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS) , #name " Status" }, \ 1004 1026 /* Offset 0x84 (SD0) */ \ 1005 1027 { offset + 0x4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadLPIB, hdaRegWriteU32 , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \ … … 1009 1031 { offset + 0xC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16, hdaRegWriteSDLVI , HDA_REG_IDX_STRM(name, LVI) , #name " Last Valid Index" }, \ 1010 1032 /* Reserved: FIFO Watermark. ** @todo Document this! */ \ 1011 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWrite U16,HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \1033 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \ 1012 1034 /* Offset 0x90 (SD0) */ \ 1013 { offset + 0x10, 0x00002, 0x000000FF, 0x000000 00, hdaRegReadU16, hdaRegWriteU16,HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \1035 { offset + 0x10, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16, hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \ 1014 1036 /* Offset 0x92 (SD0) */ \ 1015 1037 { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16, hdaRegWriteSDFMT , HDA_REG_IDX_STRM(name, FMT) , #name " Stream Format" }, \ … … 1061 1083 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */ 1062 1084 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INSTRMPAY) }, /* Input Stream Payload Capability */ 1063 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWrite U32, HDA_REG_IDX(INTCTL) }, /* Interrupt Control */1064 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegRead INTSTS, hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */1085 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWriteINTCTL , HDA_REG_IDX(INTCTL) }, /* Interrupt Control */ 1086 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */ 1065 1087 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK , hdaRegWriteUnimpl , HDA_REG_IDX_LOCAL(WALCLK) }, /* Wall Clock Counter */ 1066 1088 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */ … … 1133 1155 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex), 1134 1156 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW), 1135 SSMFIELD_ENTRY (HDABDLESTATE, au8FIFO),1157 SSMFIELD_ENTRY_OLD(FIFO, 256), 1136 1158 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff), 1137 1159 SSMFIELD_ENTRY_TERM() … … 1143 1165 SSMFIELD_ENTRY_OLD(cBDLE, 2), 1144 1166 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE), 1145 SSMFIELD_ENTRY (HDASTREAMSTATE, fDoStop),1146 SSMFIELD_ENTRY (HDASTREAMSTATE, fActive),1167 SSMFIELD_ENTRY_OLD(fDoStop, 1), 1168 SSMFIELD_ENTRY_OLD(fActive, 1), 1147 1169 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset), 1148 1170 SSMFIELD_ENTRY_TERM() … … 1157 1179 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff) 1158 1180 }; 1159 1160 #ifdef IN_RING31161 1162 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)1163 {1164 AssertPtrReturn(pThis, 0);1165 AssertPtrReturn(pStream, 0);1166 1167 Assert(u32LPIB <= pStream->u32CBL);1168 1169 LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",1170 pStream->u8SD, u32LPIB, pThis->fDMAPosition));1171 1172 /* Update LPIB in any case. */1173 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;1174 1175 /* Do we need to tell the current DMA position? */1176 if (pThis->fDMAPosition)1177 {1178 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),1179 (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)),1180 (void *)&u32LPIB, sizeof(uint32_t));1181 AssertRC(rc2);1182 }1183 1184 return u32LPIB;1185 }1186 1181 1187 1182 … … 1218 1213 1219 1214 1220 # if defined(IN_RING3) && (defined(DEBUG) || defined(VBOX_HDA_WITH_FIFO))1221 1215 /** 1222 1216 * Retrieves the number of bytes of a FIFOW register. … … 1238 1232 return cb; 1239 1233 } 1240 #endif 1234 1235 1236 #ifdef IN_RING3 1237 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB) 1238 { 1239 AssertPtrReturn(pThis, 0); 1240 AssertPtrReturn(pStream, 0); 1241 1242 AssertMsg(u32LPIB <= pStream->u32CBL, 1243 ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL)); 1244 1245 u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL); 1246 1247 LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n", 1248 pStream->u8SD, u32LPIB, pThis->fDMAPosition)); 1249 1250 /* Update LPIB in any case. */ 1251 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB; 1252 1253 /* Do we need to tell the current DMA position? */ 1254 if (pThis->fDMAPosition) 1255 { 1256 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), 1257 (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)), 1258 (void *)&u32LPIB, sizeof(uint32_t)); 1259 AssertRC(rc2); 1260 } 1261 1262 return u32LPIB; 1263 } 1241 1264 1242 1265 … … 1246 1269 * @return IPRT status code. 1247 1270 */ 1248 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream )1271 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream, bool *pfWrapAround) 1249 1272 { 1250 1273 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 1261 1284 # endif 1262 1285 1263 PHDABDLE pBDLE = &pStream->State.BDLE; 1286 PHDABDLE pBDLE = &pStream->State.BDLE; 1287 bool fWrapAround = false; 1288 1289 AssertMsg(pBDLE->State.u32BufOff == pBDLE->u32BufSize, ("BDLE not finished yet: %R[bdle]\n", pBDLE)); 1264 1290 1265 1291 /* … … 1271 1297 { 1272 1298 pStream->State.uCurBDLE = 0; 1273 1274 hdaStreamUpdateLPIB(pThis, pStream, 0); 1299 fWrapAround = true; 1275 1300 } 1276 1301 … … 1279 1304 /* Fetch the next BDLE entry. */ 1280 1305 int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE); 1281 1282 LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n", 1283 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE)); 1306 if (RT_SUCCESS(rc)) 1307 { 1308 LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n", 1309 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE)); 1310 1311 if (pfWrapAround) 1312 *pfWrapAround = fWrapAround; 1313 } 1314 1284 1315 return rc; 1285 1316 } 1286 1317 1318 1319 /** 1320 * Returns the HDA stream of specified stream descriptor number. 1321 * 1322 * @return Pointer to HDA stream, or NULL if none found. 1323 */ 1324 DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD) 1325 { 1326 AssertPtrReturn(pThis, NULL); 1327 AssertReturn(uSD <= HDA_MAX_STREAMS, NULL); 1328 1329 if (uSD >= HDA_MAX_STREAMS) 1330 return NULL; 1331 1332 return &pThis->aStreams[uSD]; 1333 } 1334 1335 1336 /** 1337 * Returns the HDA stream of specified HDA sink. 1338 * 1339 * @return Pointer to HDA stream, or NULL if none found. 1340 */ 1341 DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink) 1342 { 1343 AssertPtrReturn(pThis, NULL); 1344 AssertPtrReturn(pSink, NULL); 1345 1346 /** @todo Do something with the channel mapping here? */ 1347 return hdaStreamFromSD(pThis, pSink->uSD); 1348 } 1349 1350 /** 1351 * Retrieves the minimum number of bytes accumulated/free in the 1352 * FIFO before the controller will start a fetch/eviction of data. 1353 * 1354 * Uses SDFIFOW (FIFO Watermark Register). 1355 * 1356 * @return Number of bytes accumulated/free in the FIFO. 1357 */ 1358 DECLINLINE(uint8_t) hdaStreamGetFIFOW(PHDASTATE pThis, PHDASTREAM pStream) 1359 { 1360 AssertPtrReturn(pThis, 0); 1361 AssertPtrReturn(pStream, 0); 1362 1363 # ifdef VBOX_HDA_WITH_FIFO 1364 return hdaSDFIFOWToBytes(HDA_STREAM_REG(pThis, FIFOW, pStream->u8SD)); 1365 # else 1366 return 0; 1367 # endif 1368 } 1369 1370 #endif /* IN_RING3 */ 1287 1371 1288 1372 /** … … 1308 1392 } 1309 1393 1310 1311 /** 1312 * Returns the HDA stream of specified stream descriptor number. 1313 * 1314 * @return Pointer to HDA stream, or NULL if none found. 1315 */ 1316 DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD) 1317 { 1318 AssertPtrReturn(pThis, NULL); 1319 AssertReturn(uSD <= HDA_MAX_STREAMS, NULL); 1320 1321 if (uSD >= HDA_MAX_STREAMS) 1322 return NULL; 1323 1324 return &pThis->aStreams[uSD]; 1325 } 1326 1327 1328 /** 1329 * Returns the HDA stream of specified HDA sink. 1330 * 1331 * @return Pointer to HDA stream, or NULL if none found. 1332 */ 1333 DECLINLINE(PHDASTREAM) hdaGetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink) 1334 { 1335 AssertPtrReturn(pThis, NULL); 1336 AssertPtrReturn(pSink, NULL); 1337 1338 /** @todo Do something with the channel mapping here? */ 1339 return hdaStreamFromSD(pThis, pSink->uSD); 1340 } 1341 1342 /** 1343 * Retrieves the minimum number of bytes accumulated/free in the 1344 * FIFO before the controller will start a fetch/eviction of data. 1345 * 1346 * Uses SDFIFOW (FIFO Watermark Register). 1347 * 1348 * @return Number of bytes accumulated/free in the FIFO. 1349 */ 1350 DECLINLINE(uint8_t) hdaStreamGetFIFOW(PHDASTATE pThis, PHDASTREAM pStream) 1351 { 1352 AssertPtrReturn(pThis, 0); 1353 AssertPtrReturn(pStream, 0); 1354 1355 # ifdef VBOX_HDA_WITH_FIFO 1356 return hdaSDFIFOWToBytes(HDA_STREAM_REG(pThis, FIFOW, pStream->u8SD)); 1357 # else 1358 return 0; 1359 # endif 1360 } 1361 1362 #endif /* IN_RING3 */ 1394 static void hdaUpdateINTSTS(PHDASTATE pThis) 1395 { 1396 uint32_t intSts = 0; 1397 1398 if (/* Response Overrun Interrupt Status (ROIS) */ 1399 HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS) 1400 /* Response Interrupt */ 1401 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL) 1402 /* SDIN State Change Status Flags (SCSF) */ 1403 || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK)) 1404 { 1405 intSts |= RT_BIT(30); /* Touch Controller Interrupt Status (CIS). */ 1406 } 1407 1408 #define HDA_MARK_STREAM(x) \ 1409 if ( (INTCTL_SX(pThis, x)) \ 1410 && ( (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \ 1411 || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \ 1412 || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)) \ 1413 ) \ 1414 ) \ 1415 { \ 1416 Log3Func(("[SD%RU8] Marked\n", x)); \ 1417 intSts |= RT_BIT(x); \ 1418 } 1419 1420 HDA_MARK_STREAM(0); 1421 HDA_MARK_STREAM(1); 1422 HDA_MARK_STREAM(2); 1423 HDA_MARK_STREAM(3); 1424 HDA_MARK_STREAM(4); 1425 HDA_MARK_STREAM(5); 1426 HDA_MARK_STREAM(6); 1427 HDA_MARK_STREAM(7); 1428 1429 #undef HDA_MARK_STREAM 1430 1431 if (intSts) 1432 intSts |= RT_BIT(31); /* Touch Global Interrupt Status (GIS). */ 1433 1434 HDA_REG(pThis, INTSTS) = intSts; 1435 1436 Log3Func(("INTSTS=%x\n", intSts)); 1437 } 1363 1438 1364 1439 static int hdaProcessInterrupt(PHDASTATE pThis) 1365 1440 { 1366 #define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \ 1367 ( INTCTL_SX((pThis), num) \ 1368 && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) 1441 hdaUpdateINTSTS(pThis); 1369 1442 1370 1443 int iLevel = 0; 1371 1444 1372 /** @todo Optimize IRQ handling. */ 1373 1374 if (/* Controller Interrupt Enable (CIE). */ 1375 HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE) 1376 && ( HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL) 1377 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS) 1378 || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN)))) 1379 { 1445 /* Global Interrupt Status (GIS) touched? */ 1446 if (HDA_REG_FLAG_VALUE(pThis, INTSTS, GIS)) 1380 1447 iLevel = 1; 1381 } 1382 1383 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0) 1384 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 1) 1385 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 2) 1386 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 3) 1387 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4) 1388 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 5) 1389 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 6) 1390 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 7)) 1391 { 1392 iLevel = 1; 1393 } 1394 1448 1449 Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel)); 1450 1451 /* Global Interrupt Enable (GIE) set? */ 1395 1452 if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE)) 1396 { 1397 Log3Func(("Level=%d\n", iLevel)); 1398 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , iLevel); 1399 } 1400 1401 #undef IS_INTERRUPT_OCCURED_AND_ENABLED 1453 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel); 1402 1454 1403 1455 return VINF_SUCCESS; … … 1638 1690 AssertReturn(uSD <= HDA_MAX_STREAMS, VERR_INVALID_PARAMETER); 1639 1691 1640 int rc = RTSemEventCreate(&pStream->State.hStateChangedEvent); 1641 if (RT_SUCCESS(rc)) 1642 rc = RTCritSectInit(&pStream->State.CritSect); 1643 1692 int rc = RTCritSectInit(&pStream->State.CritSect); 1644 1693 if (RT_SUCCESS(rc)) 1645 1694 { … … 1647 1696 pStream->pMixSink = NULL; 1648 1697 1649 pStream->State.fActive = false;1650 1698 pStream->State.fInReset = false; 1651 pStream->State.fDoStop = false; 1652 } 1699 } 1700 1701 if (RT_SUCCESS(rc)) 1702 rc = RTCircBufCreate(&pStream->State.pCircBuf, HDA_FIFO_MAX); 1653 1703 1654 1704 LogFlowFunc(("uSD=%RU8\n", uSD)); … … 1662 1712 LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD)); 1663 1713 1664 int rc2 = hdaStreamStop(pStream); 1714 hdaStreamMapDestroy(&pStream->State.Mapping); 1715 1716 int rc2 = RTCritSectDelete(&pStream->State.CritSect); 1665 1717 AssertRC(rc2); 1666 1718 1667 hdaStreamMapDestroy(&pStream->State.Mapping); 1668 1669 rc2 = RTCritSectDelete(&pStream->State.CritSect); 1670 AssertRC(rc2); 1671 1672 if (pStream->State.hStateChangedEvent != NIL_RTSEMEVENT) 1673 { 1674 rc2 = RTSemEventDestroy(pStream->State.hStateChangedEvent); 1675 AssertRC(rc2); 1676 pStream->State.hStateChangedEvent = NIL_RTSEMEVENT; 1719 if (pStream->State.pCircBuf) 1720 { 1721 RTCircBufDestroy(pStream->State.pCircBuf); 1722 pStream->State.pCircBuf = NULL; 1677 1723 } 1678 1724 … … 1739 1785 RT_ZERO(pStream->State.BDLE); 1740 1786 pStream->State.uCurBDLE = 0; 1787 1788 if (pStream->State.pCircBuf) 1789 RTCircBufReset(pStream->State.pCircBuf); 1790 #if 0 1791 RT_ZERO(pStream->State.abFIFO); 1792 pStream->State.cbFIFOUsed = 0; 1793 pStream->State.cbFIFOOff = 0; 1794 #endif 1741 1795 1742 1796 /* … … 1747 1801 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */ 1748 1802 HDA_STREAM_REG(pThis, CTL, uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)); 1749 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */ 1750 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B; 1803 /* 1804 * ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39. 1805 * BUT: Windows guests seem to read the FIFOS but define a DMA region which does not fit to that FIFO size 1806 * (e.g. 1792 bytes DMA region vs. 192 bytes FIFOS). 1807 * This will lead to crackling and corrupted sound -- so define a 256 bytes FIOS for output streams here per default. 1808 */ 1809 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_256B; 1751 1810 /* See 18.2.38: Always defaults to 0x4 (32 bytes). */ 1752 1811 HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B; … … 1763 1822 AssertRC(rc2); 1764 1823 1765 /* Report that we're done resetting this stream. */1766 HDA_STREAM_REG(pThis, CTL, uSD) = 0;1767 1768 1824 /* Exit reset state. */ 1769 1825 ASMAtomicXchgBool(&pStream->State.fInReset, false); 1770 1826 } 1771 1827 1772 # if 0 /* unused */1773 static bool hdaStreamIsActive(PHDASTATE pThis, PHDASTREAM pStream)1774 {1775 AssertPtrReturn(pThis, false);1776 AssertPtrReturn(pStream, false);1777 1778 bool fActive = pStream->State.fActive;1779 1780 LogFlowFunc(("SD=%RU8, fActive=%RTbool\n", pStream->u8SD, fActive));1781 return fActive;1782 }1783 # endif1784 1785 1828 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive) 1786 1829 { … … 1789 1832 1790 1833 LogFlowFunc(("[SD%RU8]: fActive=%RTbool, pMixSink=%p\n", pStream->u8SD, fActive, pStream->pMixSink)); 1791 1792 if (pStream->State.fActive == fActive) /* No change required? */1793 {1794 LogFlowFunc(("[SD%RU8]: No change\n", pStream->u8SD));1795 return VINF_SUCCESS;1796 }1797 1834 1798 1835 int rc = VINF_SUCCESS; … … 1815 1852 return rc; 1816 1853 } 1817 1818 pStream->State.fActive = fActive;1819 1854 1820 1855 /* Second, see if we need to start or stop the timer. */ … … 1852 1887 AssertRC(rc2); 1853 1888 } 1854 }1855 1856 # if 0 /** @todo hdaStreamStart is unused */1857 static int hdaStreamStart(PHDASTREAM pStream)1858 {1859 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1860 1861 ASMAtomicXchgBool(&pStream->State.fDoStop, false);1862 ASMAtomicXchgBool(&pStream->State.fActive, true);1863 1864 LogFlowFuncLeave();1865 return VINF_SUCCESS;1866 }1867 # endif /* unused */1868 1869 static int hdaStreamStop(PHDASTREAM pStream)1870 {1871 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1872 1873 /* Already in stopped state? */1874 bool fActive = ASMAtomicReadBool(&pStream->State.fActive);1875 if (!fActive)1876 return VINF_SUCCESS;1877 1878 # if 0 /** @todo Does not work (yet), as EMT deadlocks then. */1879 /*1880 * Wait for the stream to stop.1881 */1882 ASMAtomicXchgBool(&pStream->State.fDoStop, true);1883 1884 int rc = hdaStreamWaitForStateChange(pStream, 60 * 1000 /* ms timeout */);1885 fActive = ASMAtomicReadBool(&pStream->State.fActive);1886 if ( /* Waiting failed? */1887 RT_FAILURE(rc)1888 /* Stream is still active? */1889 || fActive)1890 {1891 AssertRC(rc);1892 LogRel(("HDA: Warning: Unable to stop stream %RU8 (state: %s), rc=%Rrc\n",1893 pStream->u8Strm, fActive ? "active" : "stopped", rc));1894 }1895 # else1896 int rc = VINF_SUCCESS;1897 # endif1898 1899 LogFlowFuncLeaveRC(rc);1900 return rc;1901 1889 } 1902 1890 … … 2147 2135 static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2148 2136 { 2149 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx; 2150 2151 uint32_t v = pThis->au32Regs[iRegMem]; 2152 uint32_t nv = u32Value & HDA_STATES_SCSF; 2153 pThis->au32Regs[iRegMem] &= ~(v & nv); /* write of 1 clears corresponding bit */ 2154 return VINF_SUCCESS; 2155 } 2156 2157 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 2158 { 2159 RT_NOREF_PV(iReg); 2160 2161 uint32_t v = 0; 2162 if ( HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS) 2163 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL) 2164 || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI) 2165 || HDA_REG(pThis, STATESTS)) 2166 { 2167 v |= RT_BIT(30); /* Touch CIS. */ 2168 } 2169 2170 #define HDA_MARK_STREAM(x) \ 2171 if (/* Descriptor Error */ \ 2172 (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \ 2173 /* FIFO Error */ \ 2174 || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \ 2175 /* Buffer Completion Interrupt Status */ \ 2176 || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) \ 2177 { \ 2178 Log3Func(("[SD%RU8] BCIS: Marked\n", x)); \ 2179 v |= RT_BIT(x); \ 2180 } 2181 2182 HDA_MARK_STREAM(0); 2183 HDA_MARK_STREAM(1); 2184 HDA_MARK_STREAM(2); 2185 HDA_MARK_STREAM(3); 2186 HDA_MARK_STREAM(4); 2187 HDA_MARK_STREAM(5); 2188 HDA_MARK_STREAM(6); 2189 HDA_MARK_STREAM(7); 2190 2191 #undef HDA_MARK_STREAM 2192 2193 /* "OR" bit of all interrupt status bits. */ 2194 v |= v ? RT_BIT(31) : 0; 2195 2196 *pu32Value = v; 2197 return VINF_SUCCESS; 2137 uint32_t v = HDA_REG_IND(pThis, iReg); 2138 uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK; 2139 2140 HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */ 2141 2142 return hdaProcessInterrupt(pThis); 2143 } 2144 2145 static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2146 { 2147 RT_NOREF(iReg); 2148 2149 HDA_REG(pThis, INTCTL) = u32Value; 2150 2151 return hdaProcessInterrupt(pThis); 2198 2152 } 2199 2153 … … 2221 2175 return VINF_SUCCESS; 2222 2176 } 2223 2224 #if 0 /** @todo hdaRegReadSSYNC & hdaRegWriteSSYNC are unused */2225 2226 static int hdaRegReadSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)2227 {2228 RT_NOREF_PV(iReg);2229 2230 /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */2231 *pu32Value = HDA_REG(pThis, SSYNC);2232 LogFlowFunc(("%RU32\n", *pu32Value));2233 return VINF_SUCCESS;2234 }2235 2236 static int hdaRegWriteSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)2237 {2238 LogFlowFunc(("%RU32\n", u32Value));2239 return hdaRegWriteU32(pThis, iReg, u32Value);2240 }2241 2242 #endif /* unused */2243 2177 2244 2178 static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) … … 2340 2274 { 2341 2275 #ifdef IN_RING3 2276 /* 2277 * Some guests write too much (that is, 32-bit with the top 8 bit being junk) 2278 * instead of 24-bit required for SDCTL. So just mask this here to be safe. 2279 */ 2280 u32Value = (u32Value & 0x00ffffff); 2281 2342 2282 bool fRun = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 2343 2283 bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); … … 2346 2286 bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)); 2347 2287 2288 /* Get the stream descriptor. */ 2289 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg); 2290 2291 LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n", 2292 uSD, fRun, fInRun, fReset, fInReset, u32Value)); 2293 2348 2294 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */ 2349 2295 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2350 2351 /* Get the stream descriptor. */2352 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);2353 2296 2354 2297 /* … … 2382 2325 AssertRC(rc2); 2383 2326 2384 LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",2385 uSD, fRun, fInRun, fReset, fInReset, u32Value));2386 2387 2327 if (fInReset) 2388 2328 { … … 2401 2341 2402 2342 LogFunc(("[SD%RU8]: Guest initiated enter to stream reset\n", pStream->u8SD)); 2343 2403 2344 hdaStreamReset(pThis, pStream); 2404 2345 } … … 2422 2363 } 2423 2364 } 2424 2425 if (!fInRun && !fRun) 2426 hdaStreamInit(pThis, pStream, pStream->u8SD);2427 }2365 } 2366 2367 rc2 = hdaRegWriteU24(pThis, iReg, u32Value); 2368 AssertRC(rc2); 2428 2369 2429 2370 /* Make sure to handle interrupts here as well. */ 2430 2371 hdaProcessInterrupt(pThis); 2431 2432 rc2 = hdaRegWriteU24(pThis, iReg, u32Value);2433 AssertRC(rc2);2434 2372 2435 2373 hdaRegWriteSDUnlock(pStream); … … 2443 2381 static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2444 2382 { 2445 uint32_t v = HDA_REG_IND(pThis, iReg); 2446 /* Clear (zero) FIFOE and DESE bits when writing 1 to it. */ 2447 v &= ~(u32Value & v); 2448 2449 HDA_REG_IND(pThis, iReg) = v; 2383 uint32_t v = HDA_REG_IND(pThis, iReg); 2384 2385 /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */ 2386 HDA_REG_IND(pThis, iReg) &= ~(u32Value & v); 2387 2388 LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg))); 2450 2389 2451 2390 hdaProcessInterrupt(pThis); 2452 return VINF_SUCCESS; 2391 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2453 2392 } 2454 2393 … … 2459 2398 return VINF_SUCCESS; 2460 2399 2461 PHDASTREAM pStream = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, LVI, iReg)); 2400 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg); 2401 2402 PHDASTREAM pStream = hdaStreamFromSD(pThis, uSD); 2462 2403 if (!pStream) 2463 2404 { 2464 LogFunc(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", HDA_SD_NUM_FROM_REG(pThis, CTL, iReg), u32Value));2405 AssertMsgFailed(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", uSD, u32Value)); 2465 2406 return hdaRegWriteU16(pThis, iReg, u32Value); 2466 2407 } 2467 2408 2468 2409 int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value); 2469 AssertRC(rc2); 2470 2471 /** @todo Validate LVI. */ 2472 pStream->u16LVI = u32Value; 2473 2474 /* Reset BDLE state. */ 2475 RT_ZERO(pStream->State.BDLE); 2476 pStream->State.uCurBDLE = 0; 2477 2478 rc2 = hdaRegWriteU16(pThis, iReg, u32Value); 2479 AssertRC(rc2); 2480 2481 LogFlowFunc(("[SD%RU8]: LVI=%RU32\n", pStream->u8SD, u32Value)); 2482 hdaRegWriteSDUnlock(pStream); 2410 if (RT_SUCCESS(rc2)) 2411 { 2412 /** @todo Validate LVI. */ 2413 pStream->u16LVI = u32Value; 2414 LogFunc(("[SD%RU8]: Updating LVI to %RU32\n", uSD, pStream->u16LVI)); 2415 2416 /* Reset BDLE state. */ 2417 RT_ZERO(pStream->State.BDLE); 2418 pStream->State.uCurBDLE = 0; 2419 2420 rc2 = hdaRegWriteU16(pThis, iReg, u32Value); 2421 AssertRC(rc2); 2422 2423 hdaRegWriteSDUnlock(pStream); 2424 } 2425 else 2426 LogRel(("HDA: Warning: Guest tried to write LVI to running stream #%RU8, ignoring\n", uSD)); 2483 2427 2484 2428 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ … … 2490 2434 } 2491 2435 2492 #if 0 /** @todo hdaRegWriteSDFIFOW & hdaRegWriteSDFIFOS are unused */2493 2436 static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2494 2437 { 2495 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg); 2496 /** @todo Only allow updating FIFOS if RUN bit is 0? */ 2497 uint32_t u32FIFOW = 0; 2438 #ifdef IN_RING3 2439 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg); 2498 2440 2499 2441 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_IN) /* FIFOW for input streams only. */ 2500 2442 { 2501 LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to stream #%RU8, ignoring\n", uSD));2443 LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", uSD)); 2502 2444 return VINF_SUCCESS; 2503 2445 } 2504 2446 2505 switch (u32Value) 2506 { 2507 case HDA_SDFIFOW_8B: 2508 case HDA_SDFIFOW_16B: 2509 case HDA_SDFIFOW_32B: 2510 u32FIFOW = u32Value; 2511 break; 2512 default: 2513 LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n", 2514 u32Value, uSD)); 2515 u32FIFOW = HDA_SDFIFOW_32B; 2516 break; 2517 } 2518 2519 if (u32FIFOW) 2520 { 2521 LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, hdaSDFIFOSToBytes(u32FIFOW))); 2522 /** @todo Update internal stream state with new FIFOS. */ 2523 2524 return hdaRegWriteU16(pThis, iReg, u32FIFOW); 2525 } 2526 2527 return VINF_SUCCESS; /* Never reached. */ 2447 PHDASTREAM pStream = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg)); 2448 if (!pStream) 2449 { 2450 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOW on non-attached stream (0x%x)\n", uSD, u32Value)); 2451 return hdaRegWriteU16(pThis, iReg, u32Value); 2452 } 2453 2454 int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value); 2455 if (RT_SUCCESS(rc2)) 2456 { 2457 uint32_t u32FIFOW = 0; 2458 2459 switch (u32Value) 2460 { 2461 case HDA_SDFIFOW_8B: 2462 case HDA_SDFIFOW_16B: 2463 case HDA_SDFIFOW_32B: 2464 u32FIFOW = u32Value; 2465 break; 2466 default: 2467 LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n", 2468 u32Value, uSD)); 2469 AssertFailed(); 2470 u32FIFOW = HDA_SDFIFOW_32B; 2471 break; 2472 } 2473 2474 if (u32FIFOW) 2475 { 2476 pStream->u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW); 2477 LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, pStream->u16FIFOW)); 2478 2479 rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOW); 2480 AssertRC(rc2); 2481 } 2482 2483 hdaRegWriteSDUnlock(pStream); 2484 } 2485 else 2486 LogRel(("HDA: Warning: Guest tried to write FIFOW to running stream #%RU8, ignoring\n", uSD)); 2487 2488 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2489 #else /* !IN_RING3 */ 2490 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value); 2491 return VINF_IOM_R3_MMIO_WRITE; 2492 #endif /* IN_RING3 */ 2528 2493 } 2529 2494 2530 2495 /** 2531 * @note This method could be called for changing value on Output Streams 2532 * only (ICH6 datasheet 18.2.39). 2496 * @note This method could be called for changing value on Output Streams only (ICH6 datasheet 18.2.39). 2533 2497 */ 2534 2498 static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) 2535 2499 { 2536 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg); 2537 /** @todo Only allow updating FIFOS if RUN bit is 0? */ 2538 uint32_t u32FIFOS = 0; 2500 #ifdef IN_RING3 2501 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg); 2539 2502 2540 2503 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_OUT) /* FIFOS for output streams only. */ 2541 2504 { 2542 LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to stream #%RU8, ignoring\n", uSD));2505 LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to input stream #%RU8, ignoring\n", uSD)); 2543 2506 return VINF_SUCCESS; 2544 2507 } 2545 2508 2546 switch(u32Value) 2547 { 2548 case HDA_SDOFIFO_16B: 2549 case HDA_SDOFIFO_32B: 2550 case HDA_SDOFIFO_64B: 2551 case HDA_SDOFIFO_128B: 2552 case HDA_SDOFIFO_192B: 2553 u32FIFOS = u32Value; 2554 break; 2555 2556 case HDA_SDOFIFO_256B: /** @todo r=andy Investigate this. */ 2557 LogFunc(("256-bit is unsupported, HDA is switched into 192-bit mode\n")); 2558 /* Fall through is intentional. */ 2559 default: 2560 LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n", 2561 u32Value, uSD)); 2562 u32FIFOS = HDA_SDOFIFO_192B; 2563 break; 2564 } 2565 2566 if (u32FIFOS) 2567 { 2568 LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", 2569 HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg), hdaSDFIFOSToBytes(u32FIFOS))); 2570 /** @todo Update internal stream state with new FIFOS. */ 2571 2572 return hdaRegWriteU16(pThis, iReg, u32FIFOS); 2573 } 2574 2575 return VINF_SUCCESS; 2576 } 2577 2578 #endif /* unused */ 2509 PHDASTREAM pStream = hdaStreamFromSD(pThis, uSD); 2510 if (!pStream) 2511 { 2512 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOS on non-attached stream (0x%x)\n", uSD, u32Value)); 2513 return hdaRegWriteU16(pThis, iReg, u32Value); 2514 } 2515 2516 int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value); 2517 if (RT_SUCCESS(rc2)) 2518 { 2519 uint32_t u32FIFOS = 0; 2520 2521 switch(u32Value) 2522 { 2523 case HDA_SDOFIFO_16B: 2524 case HDA_SDOFIFO_32B: 2525 case HDA_SDOFIFO_64B: 2526 case HDA_SDOFIFO_128B: 2527 case HDA_SDOFIFO_192B: 2528 case HDA_SDOFIFO_256B: 2529 u32FIFOS = u32Value; 2530 break; 2531 2532 default: 2533 LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n", 2534 u32Value, uSD)); 2535 AssertFailed(); 2536 u32FIFOS = HDA_SDOFIFO_192B; 2537 break; 2538 } 2539 2540 if (u32FIFOS) 2541 { 2542 pStream->u16FIFOS = hdaSDFIFOSToBytes(u32FIFOS); 2543 LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", uSD, pStream->u16FIFOS)); 2544 2545 rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOS); 2546 AssertRC(rc2); 2547 } 2548 2549 hdaRegWriteSDUnlock(pStream); 2550 } 2551 else 2552 LogRel(("HDA: Warning: Guest tried to write FIFOS to running stream #%RU8, ignoring\n", uSD)); 2553 2554 return VINF_SUCCESS; /* Always return success to the MMIO handler. */ 2555 #else /* !IN_RING3 */ 2556 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value); 2557 return VINF_IOM_R3_MMIO_WRITE; 2558 #endif /* IN_RING3 */ 2559 } 2579 2560 2580 2561 #ifdef IN_RING3 … … 3242 3223 AssertPtrReturn(pThis, 0); 3243 3224 AssertPtrReturn(pStream, 0); 3244 3245 if (!cbMax) 3246 return 0; 3225 AssertReturn (cbMax, 0); 3247 3226 3248 3227 PHDABDLE pBDLE = &pStream->State.BDLE; … … 3251 3230 Assert(u32LPIB <= pStream->u32CBL); 3252 3231 3253 uint32_t cbFree = pStream->u32CBL - u32LPIB; 3254 if (cbFree) 3255 { 3256 /* Limit to the available free space of the current BDLE. */ 3257 cbFree = RT_MIN(cbFree, pBDLE->u32BufSize - pBDLE->State.u32BufOff); 3258 3259 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */ 3260 cbFree = RT_MIN(cbFree, uint32_t(pStream->u16FIFOS)); 3261 3262 /* Make sure we only transfer as many bytes as requested. */ 3263 cbFree = RT_MIN(cbFree, cbMax); 3264 3265 if (pBDLE->State.cbBelowFIFOW) 3232 uint32_t cbData = pStream->u32CBL - u32LPIB; 3233 AssertMsg(cbData, ("No CBL space left (%RU32/%RU32): %R[bdle]\n", pStream->u32CBL, u32LPIB, pBDLE)); 3234 3235 /* Limit to the available free space of the current BDLE. */ 3236 cbData = RT_MIN(cbData, pBDLE->u32BufSize - pBDLE->State.u32BufOff); 3237 AssertMsg(cbData, ("No BDLE space left (%RU32/%RU32): %R[bdle]\n", pBDLE->State.u32BufOff, pBDLE->u32BufSize, pBDLE)); 3238 3239 /* Make sure we only transfer as many bytes as requested. */ 3240 cbData = RT_MIN(cbData, cbMax); 3241 3242 if (pBDLE->State.cbBelowFIFOW) 3243 { 3244 /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy? 3245 * No need to read data from DMA then. */ 3246 if (cbData > pBDLE->State.cbBelowFIFOW) 3266 3247 { 3267 /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy? 3268 * No need to read data from DMA then. */ 3269 if (cbFree > pBDLE->State.cbBelowFIFOW) 3270 { 3271 /* Subtract the amount of bytes that still would fit in the stream's FIFO 3272 * and therefore do not need to be processed by DMA. */ 3273 cbFree -= pBDLE->State.cbBelowFIFOW; 3274 } 3248 /* Subtract the amount of bytes that still would fit in the stream's FIFO 3249 * and therefore do not need to be processed by DMA. */ 3250 cbData -= pBDLE->State.cbBelowFIFOW; 3275 3251 } 3276 3252 } 3277 3253 3278 LogFlowFunc(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbFree=%RU32, %R[bdle]\n", pStream->u8SD, 3279 pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS, cbFree, pBDLE)); 3280 return cbFree; 3254 AssertMsg((cbData % 2 == 0), ("Transfer size invalid: %RU32\n", cbData)); 3255 3256 Log3Func(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbData=%RU32, %R[bdle]\n", pStream->u8SD, 3257 pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS, 3258 cbData, pBDLE)); 3259 3260 return cbData; 3281 3261 } 3282 3262 … … 3287 3267 if (!cbData || !cbProcessed) 3288 3268 return; 3269 3270 Assert(pBDLE->u32BufSize >= cbProcessed); 3289 3271 3290 3272 /* Fewer than cbBelowFIFOW bytes were copied. … … 3309 3291 /* We always increment the position of DMA buffer counter because we're always reading 3310 3292 * into an intermediate buffer. */ 3311 pBDLE->State.u32BufOff += cbData;3312 Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);3293 Assert(pBDLE->u32BufSize >= (pBDLE->State.u32BufOff + cbProcessed)); 3294 pBDLE->State.u32BufOff += cbProcessed; 3313 3295 3314 3296 LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE)); … … 3454 3436 AssertPtrReturnVoid(pStream); 3455 3437 3456 LogFlowFunc(("[SD%RU8]: cbInc=%RU32\n", pStream->u8SD, cbInc));3457 3458 //Assert(cbInc <= pStream->u16FIFOS);3459 3460 3438 if (!cbInc) /* Nothing to do? Bail out early. */ 3461 3439 return; 3462 3463 PHDABDLE pBDLE = &pStream->State.BDLE;3464 3440 3465 3441 /* … … 3468 3444 * (ICH6 datasheet 18.2.38). 3469 3445 */ 3446 PHDABDLE pBDLE = &pStream->State.BDLE; 3470 3447 if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */ 3471 3448 { 3472 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD); 3473 3474 AssertMsg(((u32LPIB + cbInc) <= pStream->u32CBL), 3475 ("[SD%RU8] Increment (%RU32) exceeds CBL (%RU32): LPIB (%RU32)\n", 3476 pStream->u8SD, cbInc, pStream->u32CBL, u32LPIB)); 3477 3478 u32LPIB = RT_MIN(u32LPIB + cbInc, pStream->u32CBL); 3479 3480 LogFlowFunc(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n", 3481 pStream->u8SD, 3482 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc, 3483 pStream->u32CBL)); 3449 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc; 3450 3451 Log3Func(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n", 3452 pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), u32LPIB, pStream->u32CBL)); 3484 3453 3485 3454 hdaStreamUpdateLPIB(pThis, pStream, u32LPIB); … … 3487 3456 } 3488 3457 3489 static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStream, bool *pfInterrupt) 3490 { 3491 AssertPtrReturn(pThis, true); 3492 AssertPtrReturn(pStream, true); 3458 static bool hdaBDLEIsComplete(PHDABDLE pBDLE, bool *pfInterrupt) 3459 { 3460 AssertPtrReturn(pBDLE, true); 3493 3461 3494 3462 bool fInterrupt = false; 3495 3463 bool fIsComplete = false; 3496 3497 PHDABDLE pBDLE = &pStream->State.BDLE;3498 #ifdef LOG_ENABLED3499 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);3500 #endif3501 3464 3502 3465 /* Check if the current BDLE entry is complete (full). */ … … 3511 3474 ) 3512 3475 { 3513 LogFlowFunc(("[SD%RU8]: %R[bdle] => COMPLETE\n", pStream->u8SD, pBDLE)); 3514 3515 /* 3516 * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set 3517 * we need to generate an interrupt. 3518 */ 3519 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)) 3520 fInterrupt = true; 3476 fInterrupt = true; 3521 3477 } 3522 3478 … … 3527 3483 *pfInterrupt = fInterrupt; 3528 3484 3529 LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, fIsComplete=%RTbool, fInterrupt=%RTbool, %R[bdle]\n", 3530 pStream->u8SD, u32LPIB, pStream->u32CBL, fIsComplete, fInterrupt, pBDLE)); 3485 LogFlowFunc(("%R[bdle] fIsComplete=%RTbool, fInterrupt=%RTbool\n", pBDLE, fIsComplete, fInterrupt)); 3531 3486 3532 3487 return fIsComplete; 3533 3488 } 3534 3489 3490 #if 0 3535 3491 /** 3536 3492 * hdaReadAudio - copies samples from audio backend to DMA. … … 3584 3540 #ifdef HDA_DEBUG_DUMP_PCM_DATA 3585 3541 RTFILE fh; 3586 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio -hda.pcm",3542 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio.pcm", 3587 3543 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 3588 3544 RTFileWrite(fh, pBDLE->State.au8FIFO, cbRead, NULL); … … 3656 3612 #ifdef HDA_DEBUG_DUMP_PCM_DATA 3657 3613 RTFILE fh; 3658 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio -hda.pcm",3614 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm", 3659 3615 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 3660 3616 RTFileWrite(fh, pvBuf, cbBuf, NULL); … … 3714 3670 AssertRC(rc2); 3715 3671 #endif 3672 3716 3673 /* 3717 3674 * Write data to according mixer sinks. … … 3721 3678 AssertRC(rc2); 3722 3679 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 3723 rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,3680 rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE, AUDMIXOP_COPY, pvDataCenterLFE, (uint32_t)cbDataCenterLFE, 3724 3681 NULL /* pcbWritten */); 3725 3682 AssertRC(rc2); 3726 rc2 = AudioMixerSinkWrite(pThis->SinkRear, AUDMIXOP_COPY, pvDataRear, cbDataRear,3683 rc2 = AudioMixerSinkWrite(pThis->SinkRear, AUDMIXOP_COPY, pvDataRear, (uint32_t)cbDataRear, 3727 3684 NULL /* pcbWritten */); 3728 3685 AssertRC(rc2); … … 3745 3702 else 3746 3703 { 3704 AssertFailed(); 3705 3747 3706 Assert(pBDLE->State.u32BufOff + cbWritten <= pBDLE->u32BufSize); 3748 3707 pBDLE->State.u32BufOff += cbWritten; … … 3756 3715 } 3757 3716 3758 //Assert(cbWritten <= pStream->u16FIFOS);3717 Assert(cbWritten <= pStream->u16FIFOS); 3759 3718 3760 3719 if (RT_SUCCESS(rc)) … … 3769 3728 return rc; 3770 3729 } 3730 #endif 3771 3731 3772 3732 /** … … 4129 4089 static void hdaTimerMaybeStart(PHDASTATE pThis) 4130 4090 { 4131 if (pThis->cStreamsActive == 0) /* Only start the timer if there a re noactive streams. */4091 if (pThis->cStreamsActive == 0) /* Only start the timer if there at least is one active streams. */ 4132 4092 return; 4133 4093 … … 4137 4097 LogFlowFuncEnter(); 4138 4098 4139 Log FlowFunc(("Starting timer\n"));4099 LogRel2(("HDA: Starting transfers\n")); 4140 4100 4141 4101 /* Set timer flag. */ … … 4145 4105 pThis->uTimerTS = TMTimerGet(pThis->pTimer); 4146 4106 4147 /* Fire off timer. */4148 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);4107 /* Start transfers. */ 4108 hdaDoTransfers(pThis); 4149 4109 } 4150 4110 … … 4157 4117 return; 4158 4118 4159 Log FlowFunc(("Stopping timer\n"));4119 LogRel2(("HDA: Stopping transfers\n")); 4160 4120 4161 4121 /* Set timer flag. */ … … 4163 4123 } 4164 4124 4165 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 4166 { 4167 RT_NOREF(pDevIns); 4168 PHDASTATE pThis = (PHDASTATE)pvUser; 4169 Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE)); 4170 AssertPtr(pThis); 4125 static void hdaDoTransfers(PHDASTATE pThis) 4126 { 4127 AssertPtrReturnVoid(pThis); 4171 4128 4172 4129 STAM_PROFILE_START(&pThis->StatTimer, a); 4173 4130 4174 uint64_t cTicksNow = TMTimerGet(pT imer);4175 4176 Log FlowFuncEnter();4131 uint64_t cTicksNow = TMTimerGet(pThis->pTimer); 4132 4133 Log4Func(("Timer enter\n")); 4177 4134 4178 4135 /* Update current time timestamp. */ … … 4183 4140 bool fKickTimer = false; 4184 4141 4185 PHDASTREAM pStreamLineIn = hda GetStreamFromSink(pThis, &pThis->SinkLineIn);4142 PHDASTREAM pStreamLineIn = hdaSinkGetStream(pThis, &pThis->SinkLineIn); 4186 4143 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 4187 PHDASTREAM pStreamMicIn = hda GetStreamFromSink(pThis, &pThis->SinkMicIn);4188 #endif 4189 PHDASTREAM pStreamFront = hda GetStreamFromSink(pThis, &pThis->SinkFront);4144 PHDASTREAM pStreamMicIn = hdaSinkGetStream(pThis, &pThis->SinkMicIn); 4145 #endif 4146 PHDASTREAM pStreamFront = hdaSinkGetStream(pThis, &pThis->SinkFront); 4190 4147 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 4191 4148 /** @todo See note below. */ 4192 4149 #endif 4193 4150 4194 uint32_t cbToProcess; 4195 int rc = AudioMixerSinkUpdate(pThis->SinkLineIn.pMixSink); 4196 if (RT_SUCCESS(rc)) 4197 { 4198 cbToProcess = AudioMixerSinkGetReadable(pThis->SinkLineIn.pMixSink); 4199 if (cbToProcess) 4200 { 4201 rc = hdaTransfer(pThis, pStreamLineIn, cbToProcess, NULL /* pcbProcessed */); 4202 fKickTimer |= RT_SUCCESS(rc); 4203 } 4204 } 4205 4151 hdaStreamUpdate(pThis, pStreamLineIn); 4206 4152 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 4207 rc = AudioMixerSinkUpdate(pThis->SinkMicIn.pMixSink); 4208 if (RT_SUCCESS(rc)) 4209 { 4210 cbToProcess = AudioMixerSinkGetReadable(pThis->SinkMicIn.pMixSink); 4211 if (cbToProcess) 4212 { 4213 rc = hdaTransfer(pThis, pStreamMicIn, cbToProcess, NULL /* pcbProcessed */); 4214 fKickTimer |= RT_SUCCESS(rc); 4215 } 4216 } 4217 #endif 4153 hdaStreamUpdate(pThis, pStreamMicIn); 4154 #endif 4155 hdaStreamUpdate(pThis, pStreamFront); 4156 4218 4157 4219 4158 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 4220 rc = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink); 4221 if (RT_SUCCESS(rc)) 4222 { 4223 4224 } 4225 4226 rc = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink); 4227 if (RT_SUCCESS(rc)) 4228 { 4229 4230 } 4231 /** @todo Check for stream interleaving and only call hdaTransfer() if required! */ 4159 rc2 = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink); 4160 AssertRC(rc2); 4161 4162 rc2 = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink); 4163 AssertRC(rc2); 4164 /** @todo Check for stream interleaving and only call hdaStreamDoDMA() if required! */ 4232 4165 4233 4166 /* … … 4237 4170 */ 4238 4171 #endif 4239 rc = AudioMixerSinkUpdate(pThis->SinkFront.pMixSink); 4240 if (RT_SUCCESS(rc)) 4241 { 4242 cbToProcess = AudioMixerSinkGetWritable(pThis->SinkFront.pMixSink); 4243 if (cbToProcess) 4244 { 4245 rc = hdaTransfer(pThis, pStreamFront, cbToProcess, NULL /* pcbProcessed */); 4246 fKickTimer |= RT_SUCCESS(rc); 4247 } 4248 } 4172 4173 /* Do we need to kick the timer again? */ 4174 if ( AudioMixerSinkIsActive(pThis->SinkFront.pMixSink) 4175 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 4176 || AudioMixerSinkIsActive(pThis->SinkCenterLFE.pMixSink) 4177 || AudioMixerSinkIsActive(pThis->SinkRear.pMixSink) 4178 #endif 4179 || AudioMixerSinkIsActive(pThis->SinkLineIn.pMixSink) 4180 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 4181 || AudioMixerSinkIsActive(pThis->SinkMicIn.pMixSink) 4182 #endif 4183 ) 4184 { 4185 fKickTimer = true; 4186 } 4187 4188 pThis->uTimerMS = RTTimeMilliTS(); 4249 4189 4250 4190 if ( ASMAtomicReadBool(&pThis->fTimerActive) … … 4257 4197 } 4258 4198 4259 LogFlowFuncLeave();4260 4261 4199 STAM_PROFILE_STOP(&pThis->StatTimer, a); 4200 } 4201 4202 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 4203 { 4204 RT_NOREF(pDevIns, pTimer); 4205 4206 PHDASTATE pThis = (PHDASTATE)pvUser; 4207 Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE)); 4208 AssertPtr(pThis); 4209 4210 hdaDoTransfers(pThis); 4262 4211 } 4263 4212 … … 4278 4227 AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_INPUT), VERR_INVALID_PARAMETER); 4279 4228 4280 return hda Transfer(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);4229 return hdaStreamDoDMA(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead); 4281 4230 } 4282 4231 … … 4297 4246 PHDASTATE pThis = pCtx->pThis; 4298 4247 4299 int rc = hda Transfer(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);4248 int rc = hdaStreamDoDMA(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten); 4300 4249 if ( RT_SUCCESS(rc) 4301 4250 && pData->cbOutWritten) … … 4312 4261 #endif /* VBOX_WITH_AUDIO_HDA_CALLBACKS */ 4313 4262 4314 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed) 4315 { 4316 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 4317 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 4263 #ifdef DEBUG_andy 4264 # define HDA_DEBUG_DMA 4265 #endif 4266 4267 /** 4268 * Does a single DMA transfer for a specific HDA stream (SDI/SDO). 4269 * This either can be a read or write operation, depending on the HDA stream. 4270 * 4271 * @returns IPRT status code. 4272 * @param pThis HDA state. 4273 * @param pStream HDA stream to do the DMA transfer for. 4274 * @param pvBuf Pointer to buffer data to write data to / read data from. 4275 * @param cbBuf Size of buffer (in bytes). 4276 * @param cbToProcess Size (in bytes) to transfer (read/write). 4277 * @param pcbProcessed Size (in bytes) transferred (read/written). Optional. 4278 */ 4279 static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, 4280 uint32_t cbToProcess, uint32_t *pcbProcessed) 4281 { 4282 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 4283 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 4284 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 4285 AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER); 4318 4286 /* pcbProcessed is optional. */ 4319 4287 4320 4288 if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */ 4321 4289 { 4322 LogFlowFunc(("HDA in reset mode, skipping\n"));4323 4324 4290 if (pcbProcessed) 4325 4291 *pcbProcessed = 0; … … 4328 4294 4329 4295 bool fProceed = true; 4330 int rc = RTCritSectEnter(&pStream->State.CritSect); 4331 if (RT_FAILURE(rc)) 4332 return rc; 4333 4334 Log3Func(("[SD%RU8] fActive=%RTbool, cbToProcess=%RU32\n", pStream->u8SD, pStream->State.fActive, cbToProcess)); 4335 4336 /* Stop request received? */ 4337 if ( !pStream->State.fActive 4338 || pStream->State.fDoStop) 4339 { 4340 pStream->State.fActive = false; 4341 4342 rc = RTSemEventSignal(pStream->State.hStateChangedEvent); 4343 AssertRC(rc); 4344 4296 4297 Log3Func(("[SD%RU8] %R[sdsts] cbToProcess=%RU32\n", 4298 pStream->u8SD, HDA_STREAM_REG(pThis, STS, pStream->u8SD), cbToProcess)); 4299 4300 /* Is the stream not in a running state currently? */ 4301 if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))) 4345 4302 fProceed = false; 4346 } 4347 /* Is the stream not in a running state currently? */ 4348 else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))) 4303 /* Is the BCIS (Buffer Completion Interrupt Status) flag set? Then we have to wait and skip. */ 4304 else if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) 4349 4305 fProceed = false; 4350 /* Nothing to process? */4351 else if (!cbToProcess)4352 fProceed = false;4353 4354 if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))4355 {4356 Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));4357 fProceed = false;4358 }4359 4306 4360 4307 if (!fProceed) 4361 4308 { 4362 Log3Func(("[SD%RU8]: Skipping\n", pStream->u8SD)); 4363 4364 rc = RTCritSectLeave(&pStream->State.CritSect); 4365 AssertRC(rc); 4366 4309 #ifdef HDA_DEBUG_DMA 4310 Log3Func(("DMA: Skip\n")); 4311 #endif 4367 4312 if (pcbProcessed) 4368 4313 *pcbProcessed = 0; 4369 4314 return VINF_SUCCESS; 4370 4315 } 4316 4317 int rc = VINF_SUCCESS; 4318 4319 #ifdef HDA_DEBUG_DMA 4320 Log3Func(("DMA: Start\n")); 4321 #endif 4371 4322 4372 4323 /* Sanity checks. */ … … 4379 4330 Assert(HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) <= pStream->u32CBL); 4380 4331 4381 bool fInterrupt = false; 4382 4383 #ifdef DEBUG_andy 4384 //# define DEBUG_SIMPLE 4385 #endif 4386 4387 #ifdef DEBUG_SIMPLE 4388 uint8_t u8FIFO[_16K+1]; 4389 size_t u8FIFOff = 0; 4390 #endif 4391 4392 uint32_t cbLeft = cbToProcess; 4332 bool fSendInterrupt = false; 4333 4334 /* Only do one FIFO size at a time. */ 4335 uint32_t cbLeft = RT_MIN(pStream->u16FIFOS, RT_MIN(cbToProcess, cbBuf)); 4393 4336 uint32_t cbTotal = 0; 4394 4337 uint32_t cbChunk = 0; 4395 4338 uint32_t cbChunkProcessed = 0; 4396 4339 4397 /* Set the FIFORDY bit on the stream while doing the transfer. */ 4398 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 4399 4400 while (cbLeft) 4401 { 4402 /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */ 4403 if (hdaStreamNeedsNextBDLE(pThis, pStream)) 4404 { 4405 rc = hdaStreamGetNextBDLE(pThis, pStream); 4406 if (RT_FAILURE(rc)) 4407 break; 4408 } 4409 4340 #ifdef HDA_DEBUG_DMA 4341 LogFunc(("DMA: cbToProcess=%RU32, cbLeft=%RU32\n", cbToProcess, cbLeft)); 4342 #endif 4343 4344 /* Get the maximum number of BDL entries. */ 4345 uint16_t cBDLE = pStream->u16LVI + 1; 4346 4347 while ( cbLeft 4348 && cBDLE--) 4349 { 4410 4350 cbChunk = hdaStreamGetTransferSize(pThis, pStream, cbLeft); 4411 4351 cbChunkProcessed = 0; 4412 4352 4413 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)4414 rc = hdaReadAudio(pThis, pStream, cbChunk, &cbChunkProcessed); 4415 else4353 PHDABDLE pBDLE = &pStream->State.BDLE; 4354 4355 if (cbChunk) 4416 4356 { 4417 #ifndef DEBUG_SIMPLE 4418 rc = hdaWriteAudio(pThis, pStream, cbChunk, &cbChunkProcessed); 4419 #else 4420 void *pvBuf = u8FIFO + u8FIFOff; 4421 int32_t cbBuf = cbChunk; 4422 4423 PHDABDLE pBDLE = &pStream->State.BDLE; 4424 4425 if (cbBuf) 4426 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), 4427 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 4428 pvBuf, cbBuf); 4429 4430 cbChunkProcessed = cbChunk; 4431 4432 hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed); 4433 4434 u8FIFOff += cbChunkProcessed; 4435 Assert((u8FIFOff & 1) == 0); 4436 Assert(u8FIFOff <= sizeof(u8FIFO)); 4357 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 4358 { 4359 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), 4360 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 4361 (uint8_t *)pvBuf + cbTotal, cbChunk); 4362 } 4363 else /* Input (SDI). */ 4364 { 4365 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), 4366 pBDLE->u64BufAdr + pBDLE->State.u32BufOff, 4367 (uint8_t *)pvBuf + cbTotal, cbChunk); 4368 } 4369 4370 #ifdef HDA_DEBUG_DUMP_PCM_DATA 4371 RTFILE fh; 4372 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaDMA.pcm", 4373 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 4374 RTFileWrite(fh, (uint8_t *)pvBuf + cbTotal, cbChunk, NULL); 4375 RTFileClose(fh); 4437 4376 #endif 4438 4377 } 4439 4378 4440 if (RT_FAILURE(rc)) 4441 break; 4442 4443 hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed); 4379 cbChunkProcessed = cbChunk; 4380 4381 hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed); 4382 4383 LogFunc(("DMA: Entry %RU32 Pos %RU32/%RU32 Chunk %RU32\n", 4384 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->u32BufSize, cbChunk)); 4444 4385 4445 4386 Assert(cbLeft >= cbChunkProcessed); 4446 4387 cbLeft -= cbChunkProcessed; 4447 4388 cbTotal += cbChunkProcessed; 4448 4449 if (rc == VINF_EOF) 4389 Assert(cbTotal <= cbToProcess); 4390 4391 hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed); 4392 4393 #ifdef HDA_DEBUG_DMA 4394 LogFunc(("DMA: LPIB %RU32 Pos %RU32 Left %RU32\n", HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbTotal, cbLeft)); 4395 #endif 4396 bool fNeedsInterrupt = false; 4397 bool fBDLEIsComplete = hdaBDLEIsComplete(pBDLE, &fNeedsInterrupt); 4398 4399 if (fNeedsInterrupt) 4400 fSendInterrupt = true; 4401 4402 if (fBDLEIsComplete) 4403 { 4404 /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */ 4405 if (hdaStreamNeedsNextBDLE(pThis, pStream)) 4406 { 4407 bool fWrapAround; 4408 rc = hdaStreamGetNextBDLE(pThis, pStream, &fWrapAround); 4409 if ( RT_SUCCESS(rc) 4410 && fWrapAround) 4411 { 4412 hdaStreamUpdateLPIB(pThis, pStream, 0); 4413 } 4414 } 4415 } 4416 4417 if (RT_FAILURE(rc)) 4450 4418 break; 4451 4452 if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt)) 4453 break; 4454 } 4455 4456 /* Remove the FIFORDY bit again. */ 4457 HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 4458 4459 LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8SD, cbTotal, cbToProcess, rc)); 4460 4461 #ifdef DEBUG_SIMPLE 4462 # ifdef HDA_DEBUG_DUMP_PCM_DATA 4463 RTFILE fh; 4464 RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm", 4465 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 4466 RTFileWrite(fh, u8FIFO, u8FIFOff, NULL); 4467 RTFileClose(fh); 4468 # endif 4469 4470 AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, u8FIFO, u8FIFOff, 4471 NULL /* pcbWritten */); 4472 #endif /* DEBUG_SIMPLE */ 4473 4474 if (fInterrupt) 4475 { 4419 } 4420 4421 Log3Func(("[SD%RU8]: cbLeft=%RU32, rc=%Rrc\n", pStream->u8SD, cbLeft, rc)); 4422 4423 if (fSendInterrupt) 4424 { 4425 #ifdef HDA_DEBUG_DMA 4426 Log3Func(("DMA: Interrupt\n")); 4427 #endif 4476 4428 /** 4477 4429 * Set the BCIS (Buffer Completion Interrupt Status) flag as the … … 4485 4437 */ 4486 4438 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); 4487 Log3Func(("[SD%RU8]: BCIS : Set\n", pStream->u8SD));4439 Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD)); 4488 4440 4489 4441 hdaProcessInterrupt(pThis); … … 4496 4448 } 4497 4449 4498 int rc2 = RTCritSectLeave(&pStream->State.CritSect); 4499 if (RT_SUCCESS(rc)) 4500 rc = rc2; 4450 #ifdef HDA_DEBUG_DMA 4451 Log3Func(("DMA: End\n")); 4452 #endif 4453 4454 return rc; 4455 } 4456 4457 /** 4458 * Updates a HDA stream according to its usage. 4459 * 4460 * For an SDO (output) stream this means reading DMA data from the device to 4461 * the connected audio sink(s). 4462 * 4463 * For an SDI (input) stream this is reading audio data from the connected 4464 * audio sink(s) and writing it as DMA data to the device. 4465 * 4466 * @returns IPRT status code. 4467 * @param pThis HDA state. 4468 * @param pStream HDA stream to update. 4469 */ 4470 static int hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream) 4471 { 4472 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 4473 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 4474 4475 PHDAMIXERSINK pSink = pStream->pMixSink; 4476 if (!pSink) 4477 return VINF_SUCCESS; 4478 4479 PAUDMIXSINK pMixSink = pSink->pMixSink; 4480 AssertPtr(pSink); 4481 4482 if (AudioMixerSinkIsActive(pMixSink) == false) 4483 return VINF_SUCCESS; 4484 4485 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf; 4486 AssertPtr(pCircBuf); 4487 4488 void *pvSrc, *pvDst; 4489 size_t cbSrc, cbDst; 4490 4491 int rc = VINF_SUCCESS; 4492 4493 uint32_t cbToProcess = _16K; /** @todo Tweak this. Later. */ 4494 4495 while (cbToProcess >= pStream->u16FIFOS) 4496 { 4497 uint32_t cbProcessed; 4498 int rc2; 4499 4500 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 4501 { 4502 if (RTCircBufUsed(pCircBuf) == 0) 4503 { 4504 Assert(pStream->u16FIFOS); 4505 RTCircBufAcquireWriteBlock(pCircBuf, pStream->u16FIFOS, &pvDst, &cbDst); 4506 4507 /* Do one DMA transfer with FIFOS size at a time. */ 4508 rc2 = hdaStreamDoDMA(pThis, pStream, pvDst, cbDst, cbDst /* cbToProcess */, &cbProcessed); 4509 AssertRC(rc2); 4510 4511 RTCircBufReleaseWriteBlock(pCircBuf, cbProcessed); 4512 4513 if (!cbProcessed) 4514 break; 4515 } 4516 4517 if (RTCircBufUsed(pCircBuf)) 4518 { 4519 RTCircBufAcquireReadBlock(pCircBuf, RTCircBufUsed(pCircBuf), &pvSrc, &cbSrc); 4520 Assert(cbDst); 4521 4522 rc2 = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, cbSrc, &cbProcessed); 4523 AssertRC(rc2); 4524 4525 RTCircBufReleaseReadBlock(pCircBuf, cbSrc); 4526 } 4527 } 4528 else /* Input (SDI). */ 4529 { 4530 Assert(pStream->u16FIFOS); 4531 if (RTCircBufUsed(pCircBuf)) 4532 { 4533 RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc); 4534 4535 /* Do one DMA transfer with FIFOS size at a time. */ 4536 rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, cbSrc, cbSrc /* cbToProcess */, &cbProcessed); 4537 AssertRC(rc2); 4538 4539 RTCircBufReleaseReadBlock(pCircBuf, cbSrc); 4540 4541 if (!cbProcessed) 4542 break; 4543 } 4544 4545 if (RTCircBufUsed(pCircBuf) < pStream->u16FIFOS) 4546 { 4547 RTCircBufAcquireWriteBlock(pCircBuf, pStream->u16FIFOS, &pvDst, &cbDst); 4548 Assert(cbDst); 4549 4550 rc2 = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, cbDst, &cbProcessed); 4551 AssertRC(rc2); 4552 4553 RTCircBufReleaseWriteBlock(pCircBuf, cbDst); 4554 } 4555 } 4556 4557 rc2 = AudioMixerSinkUpdate(pSink->pMixSink); 4558 AssertRC(rc2); 4559 4560 cbToProcess -= RT_MIN(cbToProcess, cbProcessed); 4561 } 4501 4562 4502 4563 return rc; … … 4986 5047 rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */ \ 4987 5048 AssertRCReturn(rc, rc); \ 4988 rc = SSMR3 GetMem(pSSM, &x.State.au8FIFO, sizeof(x.State.au8FIFO));\5049 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO */ \ 4989 5050 AssertRCReturn(rc, rc); \ 4990 5051 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */ \ … … 5097 5158 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */ 5098 5159 AssertRC(rc); 5099 rc = SSMR3GetMem(pSSM, 5100 &pStrm->State.BDLE.State.au8FIFO, 5101 sizeof(pStrm->State.BDLE.State.au8FIFO)); /* au8FIFO */ 5160 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO, deprecated */ 5102 5161 AssertRC(rc); 5103 5162 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.u32BufOff); /* u32BufOff */ … … 5109 5168 { 5110 5169 rc = SSMR3Skip(pSSM, sizeof(uint32_t) /* cbBelowFIFOW */ 5111 + sizeof(uint8_t) * 256 /* au8FIFO*/5170 + sizeof(uint8_t) * 256 /* FIFO, deprecated */ 5112 5171 + sizeof(uint32_t) /* u32BufOff */ 5113 5172 + sizeof(uint32_t)); /* End marker */ … … 5508 5567 */ 5509 5568 if (pThis->SinkFront.pMixSink) 5510 AudioMixerSink Ctl(pThis->SinkFront.pMixSink, AUDMIXSINKCMD_DISABLE);5569 AudioMixerSinkReset(pThis->SinkFront.pMixSink); 5511 5570 # ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5512 5571 if (pThis->SinkMicIn.pMixSink) 5513 AudioMixerSink Ctl(pThis->SinkMicIn.pMixSink, AUDMIXSINKCMD_DISABLE);5572 AudioMixerSinkReset(pThis->SinkMicIn.pMixSink); 5514 5573 # endif 5515 5574 if (pThis->SinkLineIn.pMixSink) 5516 AudioMixerSink Ctl(pThis->SinkLineIn.pMixSink, AUDMIXSINKCMD_DISABLE);5575 AudioMixerSinkReset(pThis->SinkLineIn.pMixSink); 5517 5576 # ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 5518 5577 if (pThis->SinkCenterLFE.pMixSink) 5519 AudioMixerSink Ctl(pThis->SinkCenterLFE.pMixSink, AUDMIXSINKCMD_DISABLE);5578 AudioMixerSinkReset(pThis->SinkCenterLFE.pMixSink); 5520 5579 if (pThis->SinkRear.pMixSink) 5521 AudioMixerSink Ctl(pThis->SinkRear.pMixSink, AUDMIXSINKCMD_DISABLE);5580 AudioMixerSinkReset(pThis->SinkRear.pMixSink); 5522 5581 # endif 5523 5582 … … 5837 5896 #ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS 5838 5897 uint16_t uTimerHz; 5839 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);5898 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */); 5840 5899 if (RT_FAILURE(rc)) 5841 5900 return PDMDEV_SET_ERROR(pDevIns, rc, … … 6263 6322 if (RT_SUCCESS(rc)) 6264 6323 { 6265 /* Startthe emulation timer. */6324 /* Create the emulation timer. */ 6266 6325 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis, 6267 6326 TMTIMER_FLAGS_NO_CRIT_SECT, "DevHDA", &pThis->pTimer); … … 6273 6332 pThis->uTimerTS = TMTimerGet(pThis->pTimer); 6274 6333 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz)); 6275 6276 hdaTimerMaybeStart(pThis);6277 6334 } 6278 6335 } … … 6322 6379 } 6323 6380 # endif 6381 6382 #ifdef HDA_DEBUG_DUMP_PCM_DATA 6383 RTFileDelete(HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaDMA.pcm"); 6384 #endif 6324 6385 6325 6386 LogFlowFuncLeaveRC(rc); -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r64419 r64572 1908 1908 GEN_CHECK_OFF(HDABDLESTATE, u32BDLIndex); 1909 1909 GEN_CHECK_OFF(HDABDLESTATE, cbBelowFIFOW); 1910 GEN_CHECK_OFF(HDABDLESTATE, au8FIFO);1911 1910 GEN_CHECK_OFF(HDABDLESTATE, u32BufOff); 1912 1911 … … 1919 1918 GEN_CHECK_SIZE(HDASTREAMSTATE); 1920 1919 GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE); 1920 GEN_CHECK_OFF(HDASTREAMSTATE, fInReset); 1921 GEN_CHECK_OFF(HDASTREAMSTATE, CritSect); 1922 GEN_CHECK_OFF(HDASTREAMSTATE, Mapping); 1921 1923 GEN_CHECK_OFF(HDASTREAMSTATE, BDLE); 1924 GEN_CHECK_OFF(HDASTREAMSTATE, pCircBuf); 1922 1925 1923 1926 GEN_CHECK_SIZE(HDASTREAM);
Note:
See TracChangeset
for help on using the changeset viewer.