Changeset 67429 in vbox
- Timestamp:
- Jun 15, 2017 4:23:13 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r67265 r67429 814 814 * 815 815 * @returns Amount of bytes ready to be read from the sink. 816 * @param pSink Sink to return number of available samples for.816 * @param pSink Sink to return number of available bytes for. 817 817 */ 818 818 uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink) … … 826 826 return 0; 827 827 828 uint32_t cbReadable ;828 uint32_t cbReadable = 0; 829 829 830 830 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 831 831 # error "Implement me!" 832 832 #else 833 /* Get the time delta and calculate the bytes that need to be processed. 834 * 835 * Example for 16 bit, 44.1KhZ, stereo: 836 * 16 bits per sample x 44.100 samples per second = 705.600 bits per second x 2 channels 837 * = 1.411.200 bits per second of stereo. 838 */ 839 uint64_t tsDeltaMS = RTTimeMilliTS() - pSink->tsLastUpdatedMS; 840 841 cbReadable = ((DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8) / 1000 /* s to ms */) * tsDeltaMS; 842 843 Log3Func(("[%s] Bitrate is %RU32 bytes/s -> %RU64ms / %RU32 bytes elapsed\n", 844 pSink->pszName, DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8, tsDeltaMS, cbReadable)); 833 /* The hosts sets the pace -- 834 * so we try to find the maximum of readable data of all connected streams to this sink. */ 835 PAUDMIXSTREAM pMixStream; 836 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 837 { 838 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 839 { 840 Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName)); 841 continue; 842 } 843 844 cbReadable = RT_MAX(cbReadable, 845 pMixStream->pConn->pfnStreamGetReadable(pMixStream->pConn, pMixStream->pStream)); 846 847 break; /** @todo For now we only support recording by the first stream added. */ 848 } 845 849 #endif 846 850 … … 858 862 * 859 863 * @returns Amount of bytes ready to be written to the sink. 860 * @param pSink Sink to return number of available samples for.864 * @param pSink Sink to return number of available bytes for. 861 865 */ 862 866 uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink) … … 870 874 return 0; 871 875 872 uint32_t cbWritable;873 874 876 if ( !(pSink->fStatus & AUDMIXSINK_STS_RUNNING) 875 877 || pSink->fStatus & AUDMIXSINK_STS_PENDING_DISABLE) 876 878 { 877 cbWritable = 0; 878 } 879 else 880 { 879 return 0; 880 } 881 882 uint32_t cbWritable = 0; 883 881 884 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 882 885 # error "Implement me!" 883 886 #else 884 /* Get the time delta and calculate the bytes that need to be processed. 885 * 886 * Example for 16 bit, 44.1KhZ, stereo: 887 * 16 bits per sample x 44.100 samples per second = 705.600 bits per second x 2 channels 888 * = 1.411.200 bits per second of stereo. 889 */ 890 uint64_t tsDeltaMS = RTTimeMilliTS() - pSink->tsLastUpdatedMS; 891 892 cbWritable = ((DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8) / 1000 /* s to ms */) * tsDeltaMS; 893 894 Log3Func(("[%s] Bitrate is %RU32 bytes/s -> %RU64ms / %RU32 bytes elapsed\n", 895 pSink->pszName, DrvAudioHlpCalcBitrate(&pSink->PCMProps) / 8, tsDeltaMS, cbWritable)); 887 /* The hosts sets the pace -- 888 * so we try to find the minimum of writable data to all connected streams to this sink. */ 889 PAUDMIXSTREAM pMixStream; 890 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 891 { 892 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 893 { 894 Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName)); 895 continue; 896 } 897 898 const uint32_t cbWritableStream = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream); 899 900 if (cbWritable < cbWritableStream) 901 cbWritable = cbWritableStream; 902 903 break; /** @todo For now the first stream sets the pace. */ 904 } 896 905 #endif 897 }898 906 899 907 Log3Func(("[%s] cbWritable=%RU32\n", pSink->pszName, cbWritable)); -
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r67425 r67429 26 26 #define LOG_GROUP LOG_GROUP_DEV_HDA 27 27 #include <VBox/log.h> 28 28 29 #include <VBox/vmm/pdmdev.h> 29 30 #include <VBox/vmm/pdmaudioifs.h> … … 73 74 * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */ 74 75 //# define HDA_USE_DMA_ACCESS_HANDLER_WRITING 76 77 /* Useful to debug the device' timing. */ 78 //#define HDA_DEBUG_TIMING 79 80 /* To debug silence coming from the guest in form of audio gaps. 81 * Very crude implementation for now. */ 82 //#define HDA_DEBUG_SILENCE 75 83 76 84 #if defined(VBOX_WITH_HP_HDA) … … 103 111 #endif 104 112 105 /** Default timer frequency (in Hz). */ 113 /** Default timer frequency (in Hz). 114 * 115 * Note: Keep in mind that the Hz rate has nothing to do with samples rates 116 * or DMA / interrupt timing -- it's purely needed in order to drive 117 * the data flow at a constant (and sufficient) rate. 118 * 119 * Lowering this value can ask for trouble, as backends then can run 120 * into data underruns. */ 106 121 #define HDA_TIMER_HZ 200 107 122 … … 159 174 | (((iss) & 0xF) << 8) \ 160 175 | (((bss) & 0x1F) << 3) \ 161 | (((bds) & 0x3) << 1) \176 | (((bds) & 0x3) << 2) \ 162 177 | ((b64sup) & 1)) 163 178 … … 1025 1040 static int hdaStreamRead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead); 1026 1041 //static int hdaStreamWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten); 1042 static void hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fAsync); 1027 1043 # ifdef HDA_USE_DMA_ACCESS_HANDLER 1028 1044 static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream); … … 1328 1344 } 1329 1345 1330 1346 /** 1347 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by 1348 * updating its associated LPIB register and DMA position buffer (if enabled). 1349 * 1350 * @returns Set LPIB value. 1351 * @param pThis HDA state. 1352 * @param pStream HDA stream to update read / write position for. 1353 */ 1331 1354 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB) 1332 1355 { … … 1349 1372 { 1350 1373 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), 1351 (pThis->u64DPBase & DPBASE_ADDR_MASK)+ (pStream->u8SD * 2 * sizeof(uint32_t)),1374 pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)), 1352 1375 (void *)&u32LPIB, sizeof(uint32_t)); 1353 1376 AssertRC(rc2); … … 1384 1407 AssertRC(rc2); 1385 1408 } 1386 1387 #if 01388 /**1389 * Fetches the next BDLE to use for a stream.1390 *1391 * @return IPRT status code.1392 */1393 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream, bool *pfWrapAround)1394 {1395 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1396 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1397 1398 NOREF(pThis);1399 1400 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);1401 1402 LogFlowFuncEnter();1403 1404 # ifdef LOG_ENABLED1405 uint32_t const uOldBDLE = pStream->State.uCurBDLE;1406 # endif1407 1408 PHDABDLE pBDLE = &pStream->State.BDLE;1409 bool fWrapAround = false;1410 1411 AssertMsg(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize, ("BDLE not finished yet: %R[bdle]\n", pBDLE));1412 1413 /*1414 * Switch to the next BDLE entry and do a wrap around1415 * if we reached the end of the Buffer Descriptor List (BDL).1416 */1417 pStream->State.uCurBDLE++;1418 if (pStream->State.uCurBDLE == pStream->u16LVI + 1)1419 {1420 pStream->State.uCurBDLE = 0;1421 fWrapAround = true;1422 }1423 1424 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);1425 1426 /* Fetch the next BDLE entry. */1427 int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);1428 if (RT_SUCCESS(rc))1429 {1430 LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",1431 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));1432 1433 if (pfWrapAround)1434 *pfWrapAround = fWrapAround;1435 }1436 1437 return rc;1438 }1439 #endif1440 1409 1441 1410 … … 1626 1595 return VINF_SUCCESS; 1627 1596 } 1597 1598 #ifdef IN_RING3 1599 /** 1600 * Reschedules pending interrupts for all audio streams which have complete 1601 * audio periods but did not have the chance to issue their (pending) interrupts yet. 1602 * 1603 * @param pThis The HDA device state. 1604 */ 1605 static void hdaReschedulePendingInterrupts(PHDASTATE pThis) 1606 { 1607 bool fInterrupt = false; 1608 1609 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i) 1610 { 1611 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i); 1612 1613 if ( hdaStreamPeriodIsComplete (&pStream->State.Period) 1614 && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period) 1615 && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */)) 1616 { 1617 fInterrupt = true; 1618 break; 1619 } 1620 } 1621 1622 LogFunc(("fInterrupt=%RTbool\n", fInterrupt)); 1623 1624 if (fInterrupt) 1625 { 1626 #ifndef DEBUG 1627 hdaProcessInterrupt(pThis); 1628 #else 1629 hdaProcessInterrupt(pThis, __FUNCTION__); 1630 #endif 1631 } 1632 } 1633 #endif 1628 1634 1629 1635 /** … … 1862 1868 if (RT_FAILURE(rc)) 1863 1869 AssertRCReturn(rc, rc); 1870 1864 1871 return rc; 1865 1872 } … … 2007 2014 HDA_STREAM_REG(pThis, CBL, uSD) = 0; 2008 2015 HDA_STREAM_REG(pThis, LVI, uSD) = 0; 2009 HDA_STREAM_REG(pThis, FMT, uSD) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ, 2010 HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT, 2011 HDA_SDFMT_CHAN_STEREO); 2016 HDA_STREAM_REG(pThis, FMT, uSD) = 0; 2012 2017 HDA_STREAM_REG(pThis, BDPU, uSD) = 0; 2013 2018 HDA_STREAM_REG(pThis, BDPL, uSD) = 0; … … 2032 2037 #endif 2033 2038 2039 /* Report that we're done resetting this stream. */ 2040 HDA_STREAM_REG(pThis, CTL, uSD) = 0; 2041 2034 2042 LogFunc(("[SD%RU8] Reset\n", uSD)); 2035 2043 … … 2222 2230 2223 2231 # endif /* defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND) */ 2224 2225 # if 0 /* currently unused */2226 static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout)2227 {2228 AssertPtrReturn(pStream, VERR_INVALID_POINTER);2229 2230 LogFlowFunc(("[SD%RU8]: msTimeout=%RU32\n", pStream->u8SD, msTimeout));2231 return RTSemEventWait(pStream->State.hStateChangedEvent, msTimeout);2232 }2233 # endif /* currently unused */2234 2235 2232 #endif /* IN_RING3 */ 2236 2233 … … 2363 2360 static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value) 2364 2361 { 2365 const uint8_t u 8Strm= HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);2366 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, u 8Strm);2362 const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg); 2363 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, uSD); 2367 2364 #ifdef LOG_ENABLED 2368 const uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, u 8Strm);2369 LogFlowFunc(("[SD%RU8] : LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, u32CBL));2365 const uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, uSD); 2366 LogFlowFunc(("[SD%RU8] LPIB=%RU32, CBL=%RU32\n", uSD, u32LPIB, u32CBL)); 2370 2367 #endif 2371 2368 … … 2580 2577 { 2581 2578 #ifdef IN_RING3 2582 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */2583 return VINF_SUCCESS;2584 2585 2579 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, CBL, iReg)); 2586 2580 if (!pStream) … … 2592 2586 2593 2587 pStream->u32CBL = u32Value; 2594 2595 /* Reset BDLE state. */2596 RT_ZERO(pStream->State.BDLE);2597 pStream->State.uCurBDLE = 0;2598 2588 2599 2589 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value); … … 2608 2598 #endif /* IN_RING3 */ 2609 2599 } 2610 2611 #ifdef IN_RING32612 /**2613 * Reschedules pending interrupts for all audio streams which have complete2614 * audio periods but did not have the chance to issue their (pending) interrupts yet.2615 *2616 * @param pThis The HDA device state.2617 */2618 static void hdaReschedulePendingInterrupts(PHDASTATE pThis)2619 {2620 bool fInterrupt = false;2621 2622 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)2623 {2624 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);2625 2626 if ( hdaStreamPeriodIsComplete (&pStream->State.Period)2627 && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period)2628 && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))2629 {2630 fInterrupt = true;2631 break;2632 }2633 }2634 2635 LogFunc(("fInterrupt=%RTbool\n", fInterrupt));2636 2637 if (fInterrupt)2638 {2639 #ifndef DEBUG2640 hdaProcessInterrupt(pThis);2641 #else2642 hdaProcessInterrupt(pThis, __FUNCTION__);2643 #endif2644 }2645 }2646 #endif2647 2600 2648 2601 static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value) … … 2666 2619 LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n", 2667 2620 uSD, fRun, fInRun, fReset, fInReset, u32Value)); 2668 2669 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */2670 return VINF_SUCCESS; /* Always return success to the MMIO handler. */2671 2621 2672 2622 /* … … 2837 2787 } 2838 2788 # endif 2839 2840 /* Reset BDLE state. */2841 RT_ZERO(pStream->State.BDLE);2842 pStream->State.uCurBDLE = 0;2843 2789 2844 2790 int rc2 = hdaRegWriteU16(pThis, iReg, u32Value); … … 3319 3265 { 3320 3266 #ifdef IN_RING3 3321 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */3322 return VINF_SUCCESS;3323 3324 3267 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value); 3325 3268 AssertRC(rc2); … … 3332 3275 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD), 3333 3276 HDA_STREAM_REG(pThis, BDPU, uSD)); 3334 AssertMsg(pStream->u64BDLBase, ("BDL base invalid\n"));3335 3336 /* Reset BDLE state. */3337 RT_ZERO(pStream->State.BDLE);3338 pStream->State.uCurBDLE = 0;3339 3277 3340 3278 # ifdef HDA_USE_DMA_ACCESS_HANDLER … … 3465 3403 case HDA_REG_DPLBASE: 3466 3404 { 3467 pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);3468 pThis->u64DPBase |= pThis->au32Regs[iRegMem];3405 pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK; 3406 Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */ 3469 3407 3470 3408 /* Also make sure to handle the DMA position enable bit. */ 3471 pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));3472 LogRel 2(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));3409 pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0); 3410 LogRel(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled")); 3473 3411 break; 3474 3412 } 3475 3413 case HDA_REG_DPUBASE: 3476 pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF); 3477 pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32); 3414 pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]); 3478 3415 break; 3479 3416 default: … … 3733 3670 /** @todo Compare u16Entry with LVI. */ 3734 3671 3735 int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + u16Entry * sizeof(HDABDLEDESC),3672 int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), 3736 3673 &pBDLE->Desc, sizeof(pBDLE->Desc)); 3737 if (RT_FAILURE(rc)) 3738 return rc; 3739 3740 /* Set internal state. */ 3741 pBDLE->State.u32BufOff = 0; 3742 pBDLE->State.u32BDLIndex = u16Entry; 3674 3675 if (RT_SUCCESS(rc)) 3676 { 3677 /* Reset internal state. */ 3678 RT_ZERO(pBDLE->State); 3679 pBDLE->State.u32BDLIndex = u16Entry; 3680 } 3681 3682 Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc)); 3683 3743 3684 3744 3685 return VINF_SUCCESS; 3745 3686 } 3746 3747 /**3748 * Tells whether a given BDLE is complete or not.3749 *3750 * @return true if BDLE is complete, false if not.3751 * @param pBDLE BDLE to retrieve status for.3752 */3753 static bool hdaBDLEIsComplete(PHDABDLE pBDLE)3754 {3755 bool fIsComplete = false;3756 3757 if ( !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */3758 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))3759 {3760 Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);3761 fIsComplete = true;3762 }3763 3764 Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));3765 3766 return fIsComplete;3767 }3768 3769 /**3770 * Tells whether a given BDLE needs an interrupt or not.3771 *3772 * @return true if BDLE needs an interrupt, false if not.3773 * @param pBDLE BDLE to retrieve status for.3774 */3775 static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)3776 {3777 return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);3778 }3779 3780 #if 03781 /**3782 * Returns the number of outstanding stream data bytes which need to be processed3783 * by the DMA engine assigned to this stream.3784 *3785 * @return Number of bytes for the DMA engine to process.3786 */3787 DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbMax)3788 {3789 AssertPtrReturn(pThis, 0);3790 AssertPtrReturn(pStream, 0);3791 AssertReturn (cbMax, 0);3792 3793 PHDABDLE pBDLE = &pStream->State.BDLE;3794 3795 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);3796 Assert(u32LPIB <= pStream->u32CBL);3797 3798 /* Do we have space left in the CBL at all? */3799 uint32_t cbData = pStream->u32CBL - u32LPIB;3800 3801 /* Limit to the available free space of the current BDLE. */3802 cbData = RT_MIN(cbData, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);3803 3804 /* Make sure we only transfer as many bytes as requested. */3805 cbData = RT_MIN(cbData, cbMax);3806 3807 if (pBDLE->State.cbBelowFIFOW)3808 {3809 /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?3810 * No need to read data from DMA then. */3811 if (cbData > pBDLE->State.cbBelowFIFOW)3812 {3813 /* Subtract the amount of bytes that still would fit in the stream's FIFO3814 * and therefore do not need to be processed by DMA. */3815 cbData -= pBDLE->State.cbBelowFIFOW;3816 }3817 }3818 3819 AssertMsg((cbData % 2 == 0), ("Transfer size invalid: %RU32\n", cbData));3820 3821 Log3Func(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbData=%RU32, %R[bdle]\n", pStream->u8SD,3822 pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS,3823 cbData, pBDLE));3824 3825 return cbData;3826 }3827 3828 DECLINLINE(void) hdaBDLEUpdate(PHDABDLE pBDLE, uint32_t cbData, uint32_t cbProcessed)3829 {3830 AssertPtrReturnVoid(pBDLE);3831 3832 if (!cbData || !cbProcessed)3833 return;3834 3835 Assert(pBDLE->Desc.u32BufSize >= cbProcessed);3836 3837 /* Fewer than cbBelowFIFOW bytes were copied.3838 * Probably we need to move the buffer, but it is rather hard to imagine a situation3839 * where it might happen. */3840 AssertMsg((cbProcessed == pBDLE->State.cbBelowFIFOW + cbData), /* we assume that we write the entire buffer including unreported bytes */3841 ("cbProcessed=%RU32 != pBDLE->State.cbBelowFIFOW=%RU32 + cbData=%RU32\n",3842 cbProcessed, pBDLE->State.cbBelowFIFOW, cbData));3843 3844 #if 03845 if ( pBDLE->State.cbBelowFIFOW3846 && pBDLE->State.cbBelowFIFOW <= cbWritten)3847 {3848 LogFlowFunc(("BDLE(cbUnderFifoW:%RU32, off:%RU32, size:%RU32)\n",3849 pBDLE->State.cbBelowFIFOW, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize));3850 }3851 #endif3852 3853 pBDLE->State.cbBelowFIFOW -= RT_MIN(pBDLE->State.cbBelowFIFOW, cbProcessed);3854 Assert(pBDLE->State.cbBelowFIFOW == 0);3855 3856 /* We always increment the position of DMA buffer counter because we're always reading3857 * into an intermediate buffer. */3858 Assert(pBDLE->Desc.u32BufSize >= (pBDLE->State.u32BufOff + cbProcessed));3859 pBDLE->State.u32BufOff += cbProcessed;3860 3861 LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE));3862 }3863 #endif3864 3687 3865 3688 #ifdef IN_RING3 … … 3931 3754 } 3932 3755 3756 3933 3757 /** 3934 3758 * Destroys a given stream mapping. … … 3946 3770 } 3947 3771 } 3772 3948 3773 3949 3774 /** … … 3972 3797 #endif /* IN_RING3 */ 3973 3798 3974 #if 03975 DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStream)3976 {3977 AssertPtrReturn(pThis, false);3978 AssertPtrReturn(pStream, false);3979 3980 PHDABDLE pBDLE = &pStream->State.BDLE;3981 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);3982 3983 /* Did we reach the CBL (Cyclic Buffer List) limit? */3984 bool fCBLLimitReached = u32LPIB >= pStream->u32CBL;3985 3986 /* Do we need to use the next BDLE entry? Either because we reached3987 * the CBL limit or our internal DMA buffer is full. */3988 bool fNeedsNextBDLE = ( fCBLLimitReached3989 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize));3990 3991 Assert(u32LPIB <= pStream->u32CBL);3992 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);3993 3994 LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, fCBLLimitReached=%RTbool, fNeedsNextBDLE=%RTbool, %R[bdle]\n",3995 pStream->u8SD, u32LPIB, pStream->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE));3996 3997 return fNeedsNextBDLE;3998 }3999 #endif4000 3799 4001 3800 /** … … 4016 3815 } 4017 3816 4018 PHDABDLE pBDLE = &pStream->State.BDLE; 4019 4020 uint32_t cbFree = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff); 4021 4022 Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 -> cbFree=%RU32 %R[bdle]\n", pStream->u8SD, 4023 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbFree, pBDLE)); 4024 return cbFree; 4025 } 3817 /* Determine how much for the current BDL entry we have left to transfer. */ 3818 PHDABDLE pBDLE = &pStream->State.BDLE; 3819 const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff); 3820 3821 /* Determine how much we (still) can stuff in the stream's internal FIFO. */ 3822 const uint32_t cbCircBuf = (uint32_t)RTCircBufFree(pStream->State.pCircBuf); 3823 3824 uint32_t cbToTransfer = cbBDLE; 3825 3826 /* Make sure that we don't transfer more than our FIFO can hold at the moment. 3827 * As the host sets the overall pace it needs to process some of the FIFO data first before 3828 * we can issue a new DMA data transfer. */ 3829 if (cbToTransfer > cbCircBuf) 3830 cbToTransfer = cbCircBuf; 3831 3832 Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD, 3833 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE)); 3834 return cbToTransfer; 3835 } 3836 4026 3837 4027 3838 DECLINLINE(void) hdaStreamTransferInc(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc) … … 4041 3852 } 4042 3853 4043 #if 04044 DECLINLINE(void) hdaStreamTransferUpdate(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)4045 {4046 AssertPtrReturnVoid(pThis);4047 AssertPtrReturnVoid(pStream);4048 4049 if (!cbInc) /* Nothing to do? Bail out early. */4050 return;4051 4052 /*4053 * If we're below the FIFO watermark (SDFIFOW), it's expected that HDA4054 * doesn't fetch anything via DMA, so just update LPIB.4055 * (ICH6 datasheet 18.2.38).4056 */4057 PHDABDLE pBDLE = &pStream->State.BDLE;4058 if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */4059 {4060 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc;4061 4062 Log3Func(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",4063 pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), u32LPIB, pStream->u32CBL));4064 4065 hdaStreamUpdateLPIB(pThis, pStream, u32LPIB);4066 }4067 }4068 4069 static bool hdaBDLEIsComplete(PHDABDLE pBDLE, bool *pfInterrupt)4070 {4071 AssertPtrReturn(pBDLE, true);4072 4073 bool fInterrupt = false;4074 bool fIsComplete = false;4075 4076 /* Check if the current BDLE entry is complete (full). */4077 if (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize)4078 {4079 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);4080 4081 if (/* IOC (Interrupt On Completion) bit set? */4082 pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC4083 /* All data put into the DMA FIFO? */4084 && pBDLE->State.cbBelowFIFOW == 04085 )4086 {4087 fInterrupt = true;4088 }4089 4090 fIsComplete = true;4091 }4092 4093 if (pfInterrupt)4094 *pfInterrupt = fInterrupt;4095 4096 LogFlowFunc(("%R[bdle] fIsComplete=%RTbool, fInterrupt=%RTbool\n", pBDLE, fIsComplete, fInterrupt));4097 4098 return fIsComplete;4099 }4100 #endif4101 3854 4102 3855 /** … … 4845 4598 4846 4599 /** 4600 * Tells whether a given BDLE is complete or not. 4601 * 4602 * @return true if BDLE is complete, false if not. 4603 * @param pBDLE BDLE to retrieve status for. 4604 */ 4605 static bool hdaBDLEIsComplete(PHDABDLE pBDLE) 4606 { 4607 bool fIsComplete = false; 4608 4609 if ( !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */ 4610 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize)) 4611 { 4612 Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize); 4613 fIsComplete = true; 4614 } 4615 4616 Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE")); 4617 4618 return fIsComplete; 4619 } 4620 4621 4622 /** 4623 * Tells whether a given BDLE needs an interrupt or not. 4624 * 4625 * @return true if BDLE needs an interrupt, false if not. 4626 * @param pBDLE BDLE to retrieve status for. 4627 */ 4628 static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE) 4629 { 4630 return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC); 4631 } 4632 4633 /** 4847 4634 * Writes audio data from an HDA input stream's FIFO to its associated DMA area. 4848 4635 * … … 5014 4801 #endif 5015 4802 5016 #if 0 5017 uint32_t cbWritten = 0; 5018 int rc2 = hdaStreamWrite(pThis, pStreamLineIn, &cbWritten); 5019 if ( RT_SUCCESS(rc2) 5020 && cbWritten) 5021 { 5022 rc2 = hdaStreamTransfer(pThis, pStreamLineIn, cbWritten); 5023 AssertRC(rc2); 5024 } 5025 5026 #ifdef VBOX_WITH_AUDIO_HDA_MIC_IN 5027 rc2 = hdaStreamWrite(pThis, pStreamMicIn, &cbWritten); 5028 if ( RT_SUCCESS(rc2) 5029 && cbWritten) 5030 { 5031 rc2 = hdaStreamTransfer(pThis, pStreamMicIn, cbWritten); 5032 AssertRC(rc2); 5033 } 5034 #endif 5035 #endif 5036 5037 int rc2; 5038 5039 /* Is the sink ready to be written to? If so, how much? */ 5040 uint32_t cbToWrite = AudioMixerSinkGetWritable(pThis->SinkFront.pMixSink); 5041 if (cbToWrite) 5042 { 5043 rc2 = hdaStreamTransfer(pThis, pStreamFront, cbToWrite); 5044 AssertRC(rc2); 5045 5046 if (hdaStreamGetDataSize(pStreamFront)) 5047 { 5048 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5049 /* Let the asynchronous thread know that there is some new data to process. */ 5050 hdaStreamAsyncIONotify(pThis, pStreamFront); 5051 #else 5052 /* Read audio data from the HDA stream and write to the backends. */ 5053 rc2 = hdaStreamRead(pThis, pStreamFront, cbToWrite, NULL /* pcbRead */); 5054 AssertRC(rc2); 5055 #endif 5056 } 5057 } 5058 5059 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5060 /* 5061 * Update all mixer sinks here (synchronously). 5062 * For async I/O this is done in the stream's specific async I/O thread. 5063 */ 5064 rc2 = AudioMixerSinkUpdate(pThis->SinkFront.pMixSink); 5065 AssertRC(rc2); 5066 5067 # ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND 5068 rc2 = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink); 5069 AssertRC(rc2); 5070 5071 rc2 = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink); 5072 AssertRC(rc2); 5073 /** @todo Check for stream interleaving and only call hdaStreamDoDMA() if required! */ 5074 5075 /* 5076 * Only call hdaTransfer if CenterLFE and/or Rear are on different SDs, 5077 * otherwise we have to use the interleaved streams support for getting the data 5078 * out of the Front sink (depending on the mapping layout). 5079 */ 5080 # endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */ 5081 #endif /* !VBOX_WITH_AUDIO_HDA_ASYNC_IO */ 4803 hdaStreamUpdate(pThis, pStreamFront, true /* fSync */); 5082 4804 } 5083 4805 … … 5086 4808 #endif 5087 4809 5088 #if 05089 /**5090 * Does a single DMA transfer for a specific HDA stream (SDI/SDO).5091 * This either can be a read or write operation, depending on the HDA stream.5092 *5093 * @returns IPRT status code.5094 * @param pThis HDA state.5095 * @param pStream HDA stream to do the DMA transfer for.5096 * @param pvBuf Pointer to buffer data to write data to / read data from.5097 * @param cbBuf Size of buffer (in bytes).5098 * @param cbToProcess Size (in bytes) to transfer (read/write).5099 * @param pcbProcessed Size (in bytes) transferred (read/written). Optional.5100 */5101 static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf,5102 uint32_t cbToProcess, uint32_t *pcbProcessed)5103 {5104 AssertPtrReturn(pThis, VERR_INVALID_POINTER);5105 AssertPtrReturn(pStream, VERR_INVALID_POINTER);5106 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);5107 AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER);5108 /* pcbProcessed is optional. */5109 5110 if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */5111 {5112 if (pcbProcessed)5113 *pcbProcessed = 0;5114 return VINF_SUCCESS;5115 }5116 5117 bool fProceed = true;5118 5119 Log3Func(("[SD%RU8] %R[sdsts] cbToProcess=%RU32\n",5120 pStream->u8SD, HDA_STREAM_REG(pThis, STS, pStream->u8SD), cbToProcess));5121 5122 /* Is the stream not in a running state currently? */5123 if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))5124 fProceed = false;5125 /* Is the BCIS (Buffer Completion Interrupt Status) flag set? Then we have to wait and skip. */5126 else if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_SDSTS_BCIS))5127 fProceed = false;5128 5129 if (!fProceed)5130 {5131 #ifdef HDA_DEBUG_DMA5132 Log3Func(("[SD%RU8] DMA: Skip\n", pStream->u8SD));5133 #endif5134 if (pcbProcessed)5135 *pcbProcessed = 0;5136 return VINF_SUCCESS;5137 }5138 5139 int rc = VINF_SUCCESS;5140 5141 #ifdef HDA_DEBUG_DMA5142 Log3Func(("[SD%RU8] DMA: Start\n", pStream->u8SD));5143 #endif5144 5145 /* Sanity checks. */5146 Assert(pStream->u8SD <= HDA_MAX_STREAMS);5147 Assert(pStream->u64BDLBase);5148 Assert(pStream->u32CBL);5149 5150 /* State sanity checks. */5151 Assert(pStream->State.fInReset == false);5152 Assert(HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) <= pStream->u32CBL);5153 5154 bool fSendInterrupt = false;5155 5156 /* Only do one FIFO size at a time. */5157 uint32_t cbLeft = RT_MIN(pStream->u16FIFOS, RT_MIN(cbToProcess, cbBuf));5158 uint32_t cbTotal = 0;5159 uint32_t cbChunk = 0;5160 uint32_t cbChunkProcessed = 0;5161 5162 #ifdef HDA_DEBUG_DMA5163 LogFunc(("[SD%RU8] DMA: cbToProcess=%RU32, cbLeft=%RU32\n", pStream->u8SD, cbToProcess, cbLeft));5164 #endif5165 5166 /* Get the maximum number of BDL entries. */5167 uint16_t cBDLE = pStream->u16LVI + 1;5168 5169 while ( cbLeft5170 && cBDLE--)5171 {5172 cbChunk = hdaStreamGetTransferSize(pThis, pStream, cbLeft);5173 cbChunkProcessed = 0;5174 5175 PHDABDLE pBDLE = &pStream->State.BDLE;5176 5177 if (cbChunk)5178 {5179 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */5180 {5181 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),5182 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,5183 (uint8_t *)pvBuf + cbTotal, cbChunk);5184 }5185 else /* Input (SDI). */5186 {5187 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns),5188 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,5189 (uint8_t *)pvBuf + cbTotal, cbChunk);5190 }5191 5192 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA5193 RTFILE fh;5194 RTFileOpen(&fh,5195 hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT5196 ? VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm" : VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",5197 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);5198 RTFileWrite(fh, (uint8_t *)pvBuf + cbTotal, cbChunk, NULL);5199 RTFileClose(fh);5200 #endif5201 }5202 5203 cbChunkProcessed = cbChunk;5204 5205 hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);5206 5207 LogFunc(("[SD%RU8] DMA: Entry %RU32 Pos %RU32/%RU32 Chunk %RU32\n",5208 pStream->u8SD, pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize, cbChunk));5209 5210 Assert(cbLeft >= cbChunkProcessed);5211 cbLeft -= cbChunkProcessed;5212 cbTotal += cbChunkProcessed;5213 Assert(cbTotal <= cbToProcess);5214 5215 hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);5216 5217 #ifdef HDA_DEBUG_DMA5218 LogFunc(("[SD%RU8] DMA: LPIB %RU32 Pos %RU32 Left %RU32\n",5219 pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbTotal, cbLeft));5220 #endif5221 bool fNeedsInterrupt = false;5222 bool fBDLEIsComplete = hdaBDLEIsComplete(pBDLE, &fNeedsInterrupt);5223 5224 if (fNeedsInterrupt)5225 fSendInterrupt = true;5226 5227 if (fBDLEIsComplete)5228 {5229 /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */5230 if (hdaStreamNeedsNextBDLE(pThis, pStream))5231 {5232 bool fWrapAround;5233 rc = hdaStreamGetNextBDLE(pThis, pStream, &fWrapAround);5234 if ( RT_SUCCESS(rc)5235 && fWrapAround)5236 {5237 hdaStreamUpdateLPIB(pThis, pStream, 0);5238 }5239 }5240 }5241 5242 if (RT_FAILURE(rc))5243 break;5244 }5245 5246 Log3Func(("[SD%RU8]: cbLeft=%RU32, rc=%Rrc\n", pStream->u8SD, cbLeft, rc));5247 5248 if (fSendInterrupt)5249 {5250 #ifdef HDA_DEBUG_DMA5251 Log3Func(("[SD%RU8] DMA: Interrupt\n", pStream->u8SD));5252 #endif5253 /**5254 * Set the BCIS (Buffer Completion Interrupt Status) flag as the5255 * last byte of data for the current descriptor has been fetched5256 * from memory and put into the DMA FIFO.5257 *5258 * Speech synthesis works fine on Mac Guest if this bit isn't set5259 * but in general sound quality gets worse.5260 *5261 * This must be set in *any* case.5262 */5263 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;5264 Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));5265 5266 #ifndef DEBUG5267 hdaProcessInterrupt(pThis);5268 #else5269 hdaProcessInterrupt(pThis, __FUNCTION__);5270 #endif5271 }5272 5273 if (RT_SUCCESS(rc))5274 {5275 if (pcbProcessed)5276 *pcbProcessed = cbTotal;5277 }5278 5279 #ifdef HDA_DEBUG_DMA5280 Log3Func(("[SD%RU8] DMA: End\n", pStream->u8SD));5281 #endif5282 5283 return rc;5284 }5285 #endif5286 5287 4810 /** 5288 4811 * Retrieves the available size of (buffered) audio data (in bytes) of a given HDA stream. … … 5298 4821 return 0; 5299 4822 5300 return (uint32_t)RTCircBuf Size(pStream->State.pCircBuf);4823 return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf); 5301 4824 } 5302 4825 … … 5364 4887 #endif 5365 4888 4889 5366 4890 /** 5367 4891 * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink. … … 5466 4990 break; 5467 4991 5468 PHDAMIXERSINK pSink = pStream->pMixSink;5469 5470 4992 rc2 = RTCritSectEnter(&pAIO->CritSect); 5471 4993 if (RT_SUCCESS(rc2)) … … 5477 4999 } 5478 5000 5479 uint32_t cbToProcess; 5480 uint32_t cbProcessed = 0; 5481 5482 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 5483 { 5484 cbToProcess = (uint32_t)RTCircBufUsed(pCircBuf); 5485 if (cbToProcess) 5486 rc2 = hdaStreamRead(pThis, pStream, cbToProcess, &cbProcessed); 5487 } 5488 else /* Input (SDI). */ 5489 { 5490 #if 0 5491 cbToProcess = (uint32_t)RTCircBufFree(pCircBuf); 5492 if (cbToProcess) 5493 rc2 = hdaStreamWrite(pThis, pStream, cbToProcess, &cbProcessed); 5494 #endif 5495 } 5496 5497 if ( pSink 5498 && RT_SUCCESS(rc2)) 5499 { 5500 rc2 = AudioMixerSinkUpdate(pSink->pMixSink); 5501 } 5001 hdaStreamUpdate(pThis, pStream, false /* fSync */); 5502 5002 5503 5003 int rc3 = RTCritSectLeave(&pAIO->CritSect); … … 5731 5231 Assert(pStream->u8SD <= HDA_MAX_STREAMS); 5732 5232 Assert(pStream->u64BDLBase); 5233 Assert(pStream->u32CBL); 5733 5234 5734 5235 /* State sanity checks. */ … … 5747 5248 5748 5249 const uint32_t cbElapsed = hdaStreamTransferGetElapsed(pThis, pStream); 5250 Assert(cbElapsed); /* Paranoia. */ 5749 5251 5750 5252 /* Limit the data to read, as this routine could be delayed and therefore 5751 5253 * report wrong (e.g. too much) cbElapsed bytes. */ 5752 5254 uint32_t cbLeft = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax); 5753 Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */5754 5255 5755 5256 Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n", 5756 5257 pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft)); 5757 5258 5758 Log2Func(("[SD%RU8]\n", pStream->u8SD));5759 5760 while (cbLeft >> 1) /** @todo Define frame size? */5259 Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */ 5260 5261 while (cbLeft) 5761 5262 { 5762 5263 uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft); 5264 if (!cbChunk) 5265 break; 5266 5763 5267 uint32_t cbDMA = 0; 5764 #if 1 5268 5765 5269 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 5766 5270 { … … 5797 5301 hdaStreamTransferInc(pThis, pStream, cbDMA); 5798 5302 5799 uint32_t framesDMA = cbDMA / 4; /** @todo Define frame size? */5303 uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE; 5800 5304 5801 5305 /* Add the transferred frames to the period. */ … … 5887 5391 5888 5392 hdaStreamPeriodUnlock(pPeriod); 5889 #else 5890 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 5891 { 5892 STAM_PROFILE_START(&pThis->StatOut, a); 5893 5894 /* 5895 * Read from DMA. 5896 */ 5897 5898 uint8_t abFIFO[HDA_FIFO_MAX + 1]; 5899 size_t offFIFO = 0; 5900 5901 /* Do one DMA transfer with FIFOS size at a time. */ 5902 rc2 = hdaStreamDoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), (uint32_t)pStream->u16FIFOS /* cbToProcess */, &cbDMA); 5393 5394 Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc)); 5395 5396 if (RT_FAILURE(rc)) 5397 LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc)); 5398 5399 hdaStreamUnlock(pStream); 5400 5401 return VINF_SUCCESS; 5402 } 5403 5404 /** 5405 * Updates a HDA stream by doing its required data transfers. 5406 * The host sink(s) set the overall pace. 5407 * 5408 * This routine is called by both, the synchronous and the asynchronous, implementations. 5409 * 5410 * @param pThis HDA state. 5411 * @param pStream HDA stream to update. 5412 * @param fSync Whether to use this function in an synchronous 5413 * or asynchronous context. 5414 */ 5415 static void hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fSync) 5416 { 5417 PAUDMIXSINK pSink = NULL; 5418 if ( pStream->pMixSink 5419 && pStream->pMixSink->pMixSink) 5420 { 5421 pSink = pStream->pMixSink->pMixSink; 5422 } 5423 5424 if (!pSink) /* No sink available? Bail out. */ 5425 return; 5426 5427 int rc2; 5428 5429 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */ 5430 { 5431 /* Is the sink ready to be written (guest output data) to? If so, by how much? */ 5432 const uint32_t cbWritable = AudioMixerSinkGetWritable(pSink); 5433 5434 if ( fSync 5435 && cbWritable) 5436 { 5437 /* When running synchronously, do the DMA data transfers here. 5438 * Otherwise this will be done in the device timer. */ 5439 rc2 = hdaStreamTransfer(pThis, pStream, cbWritable); 5903 5440 AssertRC(rc2); 5904 5441 5905 uint32_t cbDMALeft = cbDMA;5906 5907 while ( cbDMALeft5908 && RTCircBufFree(pCircBuf))5909 {5910 void *pvDst;5911 size_t cbDst;5912 5913 RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvDst, &cbDst);5914 5915 if (cbDst)5916 {5917 memcpy(pvDst, abFIFO + offFIFO, cbDst);5918 5919 offFIFO += cbDst;5920 Assert(offFIFO <= sizeof(abFIFO));5921 }5922 5923 RTCircBufReleaseWriteBlock(pCircBuf, cbDst);5924 5925 Assert(cbDst <= cbDMALeft);5926 cbDMALeft -= (uint32_t)cbDst;5927 }5928 5929 AssertMsg(cbDMALeft == 0, ("%RU32 bytes of DMA data left, CircBuf=%zu/%zu\n",5930 cbDMALeft, RTCircBufUsed(pCircBuf), RTCircBufSize(pCircBuf)));5931 5932 /*5933 * Process backends.5934 */5935 5936 uint32_t cbUsed = (uint32_t)RTCircBufUsed(pCircBuf);5937 if (cbUsed)5938 {5939 5442 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5940 /* Let the asynchronous thread know that there is some new data to process. */ 5941 hdaStreamAsyncIONotify(pThis, pStream); 5942 #else 5943 /* Read audio data from the HDA stream and write to the backends. */ 5944 rc2 = hdaStreamRead(pThis, pStream, cbUsed, NULL /* pcbRead */); 5945 AssertRC(rc2); 5946 #endif 5947 } 5948 5949 /* All DMA transfers done for now? */ 5950 if ( !cbDMA 5951 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5952 /* All data read *and* processed for now? */ 5953 && RTCircBufUsed(pCircBuf) == 0 5954 #endif 5955 ) 5956 { 5957 fDone = true; 5958 } 5959 5960 #ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5961 rc2 = AudioMixerSinkUpdate(pSink->pMixSink); 5443 rc2 = hdaStreamAsyncIONotify(pThis, pStream); 5962 5444 AssertRC(rc2); 5963 5445 #endif 5964 STAM_PROFILE_STOP(&pThis->StatOut, a);5965 } 5966 else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI).*/5967 {5968 STAM_PROFILE_START(&pThis->StatIn, a);5969 5970 /*5971 * Process backends.5972 */5973 5974 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO 5975 /* Let the asynchronous thread know that there is some new data to process. */5976 hdaStreamAsyncIONotify(pThis, pStream);5977 #else 5978 rc2 = AudioMixerSinkUpdate(pSink->pMixSink);5446 } 5447 5448 /* How much (guest output) data is available at the moment? */ 5449 AssertPtr(pStream->State.pCircBuf); 5450 uint32_t cbToWrite = hdaStreamGetDataSize(pStream); 5451 5452 /* Do not write more than the sink can hold at the moment. 5453 * The host sets the overall pace. */ 5454 if (cbToWrite > cbWritable) 5455 cbToWrite = cbWritable; 5456 5457 if (cbToWrite) 5458 { 5459 /* Read (guest output) data and write it to the stream's sink. */ 5460 rc2 = hdaStreamRead(pThis, pStream, cbToWrite, NULL /* pcbWritten */); 5979 5461 AssertRC(rc2); 5980 5981 /* Write read data from the backend to the HDA stream. */ 5982 rc2 = hdaStreamWrite(pThis, pStream, pStream->u16FIFOS, NULL /* pcbWritten */); 5462 } 5463 5464 if (fSync) 5465 { 5466 /* When running synchronously, update the associated sink here. 5467 * Otherwise this will be done in the device timer. */ 5468 rc2 = AudioMixerSinkUpdate(pSink); 5983 5469 AssertRC(rc2); 5984 #endif 5985 /* 5986 * Write to DMA. 5987 */ 5988 5989 void *pvSrc; 5990 size_t cbSrc; 5991 5992 RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc); 5993 5994 if (cbSrc) 5995 { 5996 /* Do one DMA transfer with FIFOS size at a time. */ 5997 rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbDMA); 5998 AssertRC(rc2); 5999 } 6000 6001 RTCircBufReleaseReadBlock(pCircBuf, cbDMA); 6002 6003 /* All DMA transfers done for now? */ 6004 if (!cbDMA) 6005 fDone = true; 6006 6007 STAM_PROFILE_STOP(&pThis->StatIn, a); 6008 } 6009 else 6010 AssertFailed(); 6011 6012 if (++cTransfers == UINT8_MAX) /* Failsafe counter. */ 6013 fDone = true; 6014 } /* while !fDone */ 6015 6016 #ifdef VBOX_STRICT 6017 AssertMsg(cTransfers < UINT8_MAX, ("HDA: Update for SD#%RU8 ran for too long\n", pStream->u8SD)); 6018 #endif 6019 #endif 6020 6021 Log2Func(("[SD%RU8] End\n", pStream->u8SD)); 6022 6023 hdaStreamUnlock(pStream); 6024 6025 return VINF_SUCCESS; 5470 } 5471 5472 } 5473 else /* Input (SDI). */ 5474 { 5475 #if 0 5476 cbToProcess = (uint32_t)RTCircBufFree(pCircBuf); 5477 if (cbToProcess) 5478 rc2 = hdaStreamWrite(pThis, pStream, cbToProcess, &cbProcessed); 5479 #endif 5480 } 6026 5481 } 6027 5482 #endif /* IN_RING3 */ … … 6324 5779 Assert(enmType == PCI_ADDRESS_SPACE_MEM); 6325 5780 int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/, 6326 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU, 5781 IOMMMIO_FLAGS_READ_DWORD 5782 | IOMMMIO_FLAGS_WRITE_PASSTHRU, 6327 5783 hdaMMIOWrite, hdaMMIORead, "HDA"); 5784 6328 5785 if (RT_FAILURE(rc)) 6329 5786 return rc; … … 6355 5812 { 6356 5813 RT_NOREF(pDevIns); 6357 #ifdef DEBUG5814 #ifdef VBOX_STRICT 6358 5815 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 6359 5816 #endif 6360 LogFlowFunc(("[SD%RU8]\n", pStrm->u8SD)); 5817 5818 Log2Func(("[SD%RU8]\n", pStrm->u8SD)); 6361 5819 6362 5820 /* Save stream ID. */ … … 6368 5826 AssertRCReturn(rc, rc); 6369 5827 6370 #ifdef DEBUG/* Sanity checks. */5828 #ifdef VBOX_STRICT /* Sanity checks. */ 6371 5829 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8SD), 6372 5830 HDA_STREAM_REG(pThis, BDPU, pStrm->u8SD)); … … 6374 5832 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStrm->u8SD); 6375 5833 6376 hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);6377 6378 5834 Assert(u64BaseDMA == pStrm->u64BDLBase); 6379 5835 Assert(u16LVI == pStrm->u16LVI); … … 6389 5845 AssertRCReturn(rc, rc); 6390 5846 6391 #ifdef DEBUG/* Sanity checks. */5847 #ifdef VBOX_STRICT /* Sanity checks. */ 6392 5848 PHDABDLE pBDLE = &pStrm->State.BDLE; 6393 5849 if (u64BaseDMA) … … 8043 7499 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaDbgInfo); 8044 7500 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaDbgInfoBDLE); 8045 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastr m", "HDA stream info. (hdastrm [stream number])",hdaDbgInfoStream);7501 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaDbgInfoStream); 8046 7502 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaDbgInfoCodecNodes); 8047 7503 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaDbgInfoCodecSelector); -
trunk/src/VBox/Devices/Makefile.kmk
r67400 r67429 581 581 # Disabled for AC'97 for now. 582 582 #VBoxDD_DEFS += VBOX_WITH_AUDIO_AC97_ASYNC_IO 583 VBoxDD_DEFS += VBOX_WITH_AUDIO_HDA_ASYNC_IO583 #VBoxDD_DEFS += VBOX_WITH_AUDIO_HDA_ASYNC_IO 584 584 585 585 # Not yet enabled: Callbacks for the device emulation to let the backends
Note:
See TracChangeset
for help on using the changeset viewer.