Changeset 53830 in vbox
- Timestamp:
- Jan 15, 2015 3:44:12 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 97643
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r53567 r53830 38 38 static void audioMixBufFreeBuf(PPDMAUDIOMIXBUF pMixBuf); 39 39 static inline void audioMixBufPrint(PPDMAUDIOMIXBUF pMixBuf); 40 static void audioMixBufReset(PPDMAUDIOMIXBUF pMixBuf);41 40 42 41 typedef uint32_t (AUDMIXBUF_FN_CONVFROM) (PPDMAUDIOSAMPLE paDst, const void *pvSrc, size_t cbSrc, uint32_t cSamples); … … 51 50 { 52 51 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 53 AssertReturn(cSamplesToRead, VERR_INVALID_PARAMETER);54 52 AssertPtrReturn(ppvSamples, VERR_INVALID_POINTER); 55 53 AssertPtrReturn(pcSamplesRead, VERR_INVALID_POINTER); 56 54 57 55 int rc; 56 57 if (!cSamplesToRead) 58 { 59 *pcSamplesRead = 0; 60 return VINF_SUCCESS; 61 } 58 62 59 63 uint32_t cSamplesRead; … … 86 90 * 87 91 * @param pMixBuf 88 * @param cSamples 92 * @param cSamplesToClear 89 93 */ 90 void audioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples )91 { 92 LogFlowFunc(("cSamples=%RU32\n", cSamples ));94 void audioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear) 95 { 96 LogFlowFunc(("cSamples=%RU32\n", cSamplesToClear)); 93 97 LogFlowFunc(("%s: offReadWrite=%RU32, cProcessed=%RU32\n", 94 98 pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed)); … … 98 102 { 99 103 LogFlowFunc(("\t%s: cMixed=%RU32 -> %RU32\n", 100 pIter->pszName, pIter->cMixed, pIter->cMixed - cSamples ));101 102 Assert(pIter->cMixed >= cSamples );103 pIter->cMixed -= cSamples ;104 pIter->pszName, pIter->cMixed, pIter->cMixed - cSamplesToClear)); 105 106 Assert(pIter->cMixed >= cSamplesToClear); 107 pIter->cMixed -= cSamplesToClear; 104 108 pIter->offReadWrite = 0; 105 109 } 106 110 107 uint32_t cLeft = RT_MIN(cSamples , pMixBuf->cSamples);111 uint32_t cLeft = RT_MIN(cSamplesToClear, pMixBuf->cSamples); 108 112 uint32_t offClear; 109 113 … … 149 153 } 150 154 155 /** @todo Rename this function! Too confusing in combination with audioMixBufFreeBuf(). */ 151 156 uint32_t audioMixBufFree(PPDMAUDIOMIXBUF pMixBuf) 152 157 { … … 593 598 594 599 pMixBuf->offReadWrite = 0; 595 pMixBuf->cMixed = 0;596 pMixBuf->cProcessed = 0;600 pMixBuf->cMixed = 0; 601 pMixBuf->cProcessed = 0; 597 602 598 603 /* Prevent division by zero. … … 841 846 static inline void audioMixBufPrint(PPDMAUDIOMIXBUF pMixBuf) 842 847 { 843 #ifdef DEBUG 848 #ifdef DEBUG_DISABLED 844 849 PPDMAUDIOMIXBUF pParent = pMixBuf; 845 850 if (pMixBuf->pParent) … … 1020 1025 } 1021 1026 1022 staticvoid audioMixBufReset(PPDMAUDIOMIXBUF pMixBuf)1027 void audioMixBufReset(PPDMAUDIOMIXBUF pMixBuf) 1023 1028 { 1024 1029 AssertPtrReturnVoid(pMixBuf); … … 1027 1032 1028 1033 pMixBuf->offReadWrite = 0; 1029 pMixBuf->cMixed = 0;1030 pMixBuf->cProcessed = 0;1034 pMixBuf->cMixed = 0; 1035 pMixBuf->cProcessed = 0; 1031 1036 1032 1037 RT_BZERO(pMixBuf->pSamples, AUDIOMIXBUF_S2B(pMixBuf, pMixBuf->cSamples)); -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r53442 r53830 52 52 inline uint32_t audioMixBufBytesToSamples(PPDMAUDIOMIXBUF pMixBuf); 53 53 void audioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf); 54 void audioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples );54 void audioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear); 55 55 uint32_t audioMixBufFree(PPDMAUDIOMIXBUF pMixBuf); 56 56 size_t audioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf); … … 66 66 int audioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, size_t cbBuf, uint32_t *pcRead); 67 67 int audioMixBufReadCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, size_t cbBuf, uint32_t *pcRead); 68 void audioMixBufReset(PPDMAUDIOMIXBUF pMixBuf); 68 69 uint32_t audioMixBufSize(PPDMAUDIOMIXBUF pMixBuf); 69 70 size_t audioMixBufSizeBytes(PPDMAUDIOMIXBUF pMixBuf); -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r53624 r53830 23 23 24 24 #include <iprt/assert.h> 25 #include <iprt/mem.h> 26 #include <iprt/string.h> 27 #include <iprt/uuid.h> 25 #ifdef IN_RING3 26 # include <iprt/mem.h> 27 # include <iprt/string.h> 28 # include <iprt/uuid.h> 29 #endif 28 30 29 31 #include "VBoxDD.h" … … 37 39 #endif 38 40 39 /*40 41 #ifdef LOG_GROUP 41 42 #undef LOG_GROUP … … 43 44 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 44 45 #include <VBox/log.h> 45 */46 46 47 47 /******************************************************************************* … … 212 212 213 213 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 214 typedef struct AC97INPUTSTREAM 215 { 216 /** PCM line input stream. */ 217 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn; 218 /** Mixer handle for line input stream. */ 219 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn; 220 } AC97INPUTSTREAM, *PAC97INPUTSTREAM; 221 222 typedef struct AC97OUTPUTSTREAM 223 { 224 /** PCM output stream. */ 225 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut; 226 } AC97OUTPUTSTREAM, *PAC97OUTPUTSTREAM; 227 214 228 /** 215 229 * Struct for maintaining a host backend driver. … … 218 232 typedef struct AC97DRIVER 219 233 { 234 union 235 { 236 /** Node for storing this driver in our device driver 237 * list of AC97STATE. */ 238 RTLISTNODE Node; 239 struct 240 { 241 R3PTRTYPE(void *) dummy1; 242 R3PTRTYPE(void *) dummy2; 243 } dummy; 244 }; 245 220 246 /** Pointer to AC97 controller (state). */ 221 PAC97STATEpAC97State;247 R3PTRTYPE(PAC97STATE) pAC97State; 222 248 /** Driver flags. */ 223 249 PDMAUDIODRVFLAGS Flags; 250 uint32_t PaddingFlags; 224 251 /** LUN # to which this driver has been assigned. */ 225 252 uint8_t uLUN; … … 227 254 * host backend. */ 228 255 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 229 /** PCM input stream. */ 230 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn; 231 /** Mixer handle for input stream. */ 232 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn; 233 /** PCM output stream. */ 234 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut; 235 /** PCM microphone input stream. */ 236 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmMic; 237 /** Mixer handle for output stream. */ 238 R3PTRTYPE(PAUDMIXSTREAM) phStrmMic; 239 } AC97DRIVER; 240 /** Pointer to a AC97 driver. */ 241 typedef AC97DRIVER *PAC97DRIVER; 256 /** Stream for line input. */ 257 AC97INPUTSTREAM LineIn; 258 /** Stream for mic input. */ 259 AC97INPUTSTREAM MicIn; 260 /** Stream for output. */ 261 AC97OUTPUTSTREAM Out; 262 /** Number of samples to play (output), needed 263 * for the timer routine. */ 264 uint32_t cSamplesLive; 265 } AC97DRIVER, *PAC97DRIVER; 242 266 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 243 267 … … 246 270 /** The PCI device state. */ 247 271 PCIDevice PciDev; 248 249 /** Audio stuff. */250 272 /** Global Control (Bus Master Control Register) */ 251 273 uint32_t glob_cnt; … … 259 281 uint8_t mixer_data[256]; 260 282 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 261 /** Number of active + allocated LUNs. Each 262 * LUN has an AC'97 driver assigned. */ 263 uint8_t cLUNs; 264 /** Array of active AC'97 drivers. */ 265 R3PTRTYPE(PAC97DRIVER) paDrv[32]; 283 /** The emulation timer for handling the attached 284 * LUN drivers. */ 285 PTMTIMERR3 pTimer; 286 /** Timer ticks for handling the LUN drivers. */ 287 uint64_t uTicks; 288 # ifdef VBOX_WITH_STATISTICS 289 STAMPROFILE StatTimer; 290 STAMCOUNTER StatBytesRead; 291 STAMCOUNTER StatBytesWritten; 292 # endif 293 /** List of associated LUN drivers. */ 294 RTLISTANCHOR lstDrv; 266 295 /** The device' software mixer. */ 267 296 R3PTRTYPE(PAUDIOMIXER) pMixer; … … 289 318 /** Base port of the I/O space region. */ 290 319 RTIOPORT IOPortBase[2]; 320 /** Pointer to temporary scratch read/write buffer. */ 321 R3PTRTYPE(uint8_t *) pvReadWriteBuf; 322 /** Size of the temporary scratch read/write buffer. */ 323 uint32_t cbReadWriteBuf; 291 324 } AC97STATE; 292 325 /** Pointer to the AC97 device state. */ 293 326 typedef AC97STATE *PAC97STATE; 327 328 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 294 329 295 330 #define ICHAC97STATE_2_DEVINS(a_pAC97) ((a_pAC97)->pDevIns) … … 334 369 335 370 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 336 static void ichac97OutputCallback(void *pvContext, uint32_t cbFree); 337 static void ichac97InputCallback(void *pvContext, uint32_t cbAvail); 338 static void ichac97MicInCallback(void *pvContext, uint32_t cbAvail); 371 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 372 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed); 339 373 #else 340 374 static void ichac97OutputCallback(void *pvContext, int cbFree); … … 429 463 430 464 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 465 PAC97DRIVER pDrv; 431 466 switch (bm_index) 432 467 { 433 468 case PI_INDEX: 434 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)435 p This->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector,436 pThis->paDrv[lun]->pStrmIn, RT_BOOL(on));469 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 470 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 471 pDrv->LineIn.pStrmIn, RT_BOOL(on)); 437 472 break; 438 473 439 474 case PO_INDEX: 440 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)441 p This->paDrv[lun]->pConnector->pfnEnableOut(pThis->paDrv[lun]->pConnector,442 pThis->paDrv[lun]->pStrmOut, RT_BOOL(on));475 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 476 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, 477 pDrv->Out.pStrmOut, RT_BOOL(on)); 443 478 break; 444 479 445 480 case MC_INDEX: 446 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)447 p This->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector,448 pThis->paDrv[lun]->pStrmMic, RT_BOOL(on));481 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 482 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 483 pDrv->MicIn.pStrmIn, RT_BOOL(on)); 449 484 break; 450 485 … … 514 549 515 550 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 551 PAC97DRIVER pDrv; 552 uint8_t uLUN = 0; 553 516 554 if (freq) 517 555 { … … 527 565 switch (index) 528 566 { 529 case PI_INDEX: /* PCM in */ 530 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 567 case PI_INDEX: /* Line input. */ 568 { 569 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 531 570 { 532 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.pi", lun) <= 0)571 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.pi", uLUN) <= 0) 533 572 { 534 573 rc = VERR_NO_MEMORY; … … 536 575 } 537 576 538 rc = p This->paDrv[lun]->pConnector->pfnOpenIn(pThis->paDrv[lun]->pConnector,539 540 ichac97InputCallback, pThis->paDrv[lun]/* pvContext */,541 542 &pThis->paDrv[lun]->pStrmIn);543 LogFlowFunc(("LUN#%RU8: Opened line input with rc=%Rrc\n", lun, rc));577 rc = pDrv->pConnector->pfnOpenIn(pDrv->pConnector, 578 pszDesc, PDMAUDIORECSOURCE_LINE_IN, 579 NULL, pDrv /* pvContext */, 580 &streamCfg, 581 &pDrv->LineIn.pStrmIn); 582 LogFlowFunc(("LUN#%RU8: Opened line input with rc=%Rrc\n", uLUN, rc)); 544 583 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 545 584 { 546 audioMixerRemoveStream(pThis->pSinkLineIn, p This->paDrv[lun]->phStrmIn);585 audioMixerRemoveStream(pThis->pSinkLineIn, pDrv->LineIn.phStrmIn); 547 586 rc = audioMixerAddStreamIn(pThis->pSinkLineIn, 548 p This->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmIn,587 pDrv->pConnector, pDrv->LineIn.pStrmIn, 549 588 0 /* uFlags */, 550 &p This->paDrv[lun]->phStrmIn);589 &pDrv->LineIn.phStrmIn); 551 590 } 552 591 553 592 RTStrFree(pszDesc); 593 uLUN++; 554 594 } 555 595 break; 556 557 case PO_INDEX: /* PCM out */ 558 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 596 } 597 598 case PO_INDEX: /* Output. */ 599 { 600 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 559 601 { 560 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.po", lun) <= 0)602 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.po", uLUN) <= 0) 561 603 { 562 604 rc = VERR_NO_MEMORY; … … 564 606 } 565 607 566 rc = pThis->paDrv[lun]->pConnector->pfnOpenOut(pThis->paDrv[lun]->pConnector, pszDesc, 567 ichac97OutputCallback, pThis->paDrv[lun] /* pvContext */, 568 &streamCfg, 569 &pThis->paDrv[lun]->pStrmOut); 570 LogFlowFunc(("LUN#%RU8: Opened output with rc=%Rrc\n", lun, rc)); 608 rc = pDrv->pConnector->pfnOpenOut(pDrv->pConnector, pszDesc, 609 NULL, pDrv /* pvContext */, 610 &streamCfg, 611 &pDrv->Out.pStrmOut); 612 LogFlowFunc(("LUN#%RU8: Opened output with rc=%Rrc\n", uLUN, rc)); 613 571 614 RTStrFree(pszDesc); 615 uLUN++; 572 616 } 573 617 break; 618 } 574 619 575 620 case MC_INDEX: /* Mic in */ 576 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 621 { 622 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 577 623 { 578 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.mc", lun) <= 0)624 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.mc", uLUN) <= 0) 579 625 { 580 626 rc = VERR_NO_MEMORY; … … 582 628 } 583 629 584 rc = p This->paDrv[lun]->pConnector->pfnOpenIn(pThis->paDrv[lun]->pConnector,585 586 ichac97MicInCallback, pThis->paDrv[lun]/* pvContext */,587 588 &pThis->paDrv[lun]->pStrmMic);589 LogFlowFunc(("LUN#%RU8: Opened mic input with rc=%Rrc\n", lun, rc));630 rc = pDrv->pConnector->pfnOpenIn(pDrv->pConnector, 631 pszDesc, PDMAUDIORECSOURCE_MIC, 632 NULL, pDrv /* pvContext */, 633 &streamCfg, 634 &pDrv->MicIn.pStrmIn); 635 LogFlowFunc(("LUN#%RU8: Opened mic input with rc=%Rrc\n", uLUN, rc)); 590 636 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 591 637 { 592 audioMixerRemoveStream(pThis->pSinkMicIn, p This->paDrv[lun]->phStrmMic);638 audioMixerRemoveStream(pThis->pSinkMicIn, pDrv->MicIn.phStrmIn); 593 639 rc = audioMixerAddStreamIn(pThis->pSinkMicIn, 594 p This->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmMic,640 pDrv->pConnector, pDrv->MicIn.pStrmIn, 595 641 0 /* uFlags */, 596 &p This->paDrv[lun]->phStrmMic);642 &pDrv->MicIn.phStrmIn); 597 643 } 598 644 599 645 RTStrFree(pszDesc); 646 uLUN++; 600 647 } 601 648 break; 649 } 602 650 603 651 default: 604 652 AssertMsgFailed(("Unsupported index %d\n", index)); 653 rc = VERR_NOT_SUPPORTED; 605 654 break; 606 655 } … … 611 660 { 612 661 case PI_INDEX: 613 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 662 { 663 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 614 664 { 615 pThis->paDrv[lun]->pConnector->pfnCloseIn(pThis->paDrv[lun]->pConnector, 616 pThis->paDrv[lun]->pStrmIn); 617 audioMixerRemoveStream(pThis->pSinkLineIn, 618 pThis->paDrv[lun]->phStrmIn); 619 pThis->paDrv[lun]->pStrmIn = NULL; 620 pThis->paDrv[lun]->phStrmIn = NULL; 665 pDrv->pConnector->pfnCloseIn(pDrv->pConnector, pDrv->LineIn.pStrmIn); 666 audioMixerRemoveStream(pThis->pSinkLineIn,pDrv->LineIn.phStrmIn); 667 668 pDrv->LineIn.pStrmIn = NULL; 669 pDrv->LineIn.phStrmIn = NULL; 621 670 } 622 671 623 672 LogFlowFunc(("Closed line input\n")); 624 673 break; 674 } 625 675 626 676 case PO_INDEX: 627 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 677 { 678 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 628 679 { 629 pThis->paDrv[lun]->pConnector->pfnCloseOut(pThis->paDrv[lun]->pConnector, 630 pThis->paDrv[lun]->pStrmOut); 631 pThis->paDrv[lun]->pStrmOut = NULL; 680 pDrv->pConnector->pfnCloseOut(pDrv->pConnector, pDrv->Out.pStrmOut); 681 pDrv->Out.pStrmOut = NULL; 632 682 } 633 683 634 684 LogFlowFunc(("Closed output\n")); 635 685 break; 686 } 636 687 637 688 case MC_INDEX: 638 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 689 { 690 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 639 691 { 640 pThis->paDrv[lun]->pConnector->pfnCloseIn(pThis->paDrv[lun]->pConnector, 641 pThis->paDrv[lun]->pStrmMic); 642 audioMixerRemoveStream(pThis->pSinkMicIn, 643 pThis->paDrv[lun]->phStrmMic); 644 pThis->paDrv[lun]->pStrmMic = NULL; 645 pThis->paDrv[lun]->phStrmMic = NULL; 692 pDrv->pConnector->pfnCloseIn(pDrv->pConnector, pDrv->MicIn.pStrmIn); 693 audioMixerRemoveStream(pThis->pSinkMicIn, pDrv->MicIn.phStrmIn); 694 695 pDrv->MicIn.pStrmIn = NULL; 696 pDrv->MicIn.phStrmIn = NULL; 646 697 } 647 698 648 LogFlowFunc(("Closed mic input\n"));699 LogFlowFunc(("Closed microphone input\n")); 649 700 break; 701 } 650 702 651 703 default: … … 738 790 739 791 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 740 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)741 pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector,742 pThis->paDrv[lun]->pStrmIn, fEnable);792 PAC97DRIVER pDrv; 793 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 794 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, fEnable); 743 795 #else 744 796 AUD_set_active_in(pThis->voice_pi, active[PI_INDEX]); … … 752 804 753 805 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 754 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 755 pThis->paDrv[lun]->pConnector->pfnEnableOut(pThis->paDrv[lun]->pConnector, 756 pThis->paDrv[lun]->pStrmOut, fEnable); 806 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 807 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, fEnable); 757 808 #else 758 809 AUD_set_active_out(pThis->voice_po, active[PO_INDEX]); … … 766 817 767 818 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 768 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 769 pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector, 770 pThis->paDrv[lun]->pStrmMic, fEnable); 819 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 820 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, fEnable); 771 821 #else 772 822 AUD_set_active_in(pThis->voice_mc, active[MC_INDEX]); … … 788 838 lvol = 255 * lvol / VOL_MASK; 789 839 840 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 841 PAC97DRIVER pDrv; 842 #endif 843 790 844 #ifdef SOFT_VOLUME 791 845 if (index == AC97_Master_Volume_Mute) 792 846 { 793 847 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 794 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 795 { 796 pThis->paDrv[lun]->pConnector->pfnIsSetOutVolume(pThis->paDrv[lun]->pConnector, 797 pThis->paDrv[lun]->pStrmOut, 798 RT_BOOL(mute), lvol, rvol); 799 } 848 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 849 pDrv->pConnector->pfnIsSetOutVolume(pDrv->pConnector, pDrv->Out.pStrmOut, RT_BOOL(mute), lvol, rvol); 800 850 # else 801 851 AUD_set_volume_out(pThis->voice_po, mute, lvol, rvol); … … 805 855 { 806 856 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 807 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 808 { 809 /** @todo In SetVolume no passing audmixerctl_in as its not used in DrvAudio.c */ 810 pThis->paDrv[lun]->pConnector->pfnSetVolume(pThis->paDrv[lun]->pConnector, 811 RT_BOOL(mute), lvol, rvol); 857 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 858 { 859 /** @todo In SetVolume no passing audmixerctl_in as its not used in DrvAudio.cpp. */ 860 pDrv->pConnector->pfnSetVolume(pDrv->pConnector, RT_BOOL(mute), lvol, rvol); 812 861 } 813 862 # else … … 817 866 #else /* !SOFT_VOLUME */ 818 867 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 819 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 820 pThis->paDrv[lun]->pConnector->pfnSetVolume(pThis->paDrv[lun]->pConnector, 821 RT_BOOL(mute), lvol, rvol); 868 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 869 pDrv->pConnector->pfnSetVolume(pDrv->pConnector, RT_BOOL(mute), lvol, rvol); 822 870 # else 823 871 AUD_set_volume(mt, &mute, &lvol, &rvol); … … 901 949 902 950 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 903 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 904 { 905 pThis->paDrv[lun]->phStrmIn = NULL; 906 pThis->paDrv[lun]->phStrmMic = NULL; 951 PAC97DRIVER pDrv; 952 953 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 954 { 955 pDrv->LineIn.phStrmIn = NULL; 956 pDrv->MicIn.phStrmIn = NULL; 907 957 } 908 958 … … 992 1042 } 993 1043 994 static int ichac97WriteAudio(PAC97STATE pThis, PAC97BMREG pReg, int max, int *stop)1044 static int ichac97WriteAudio(PAC97STATE pThis, PAC97BMREG pReg, uint32_t cbMax, uint32_t *pcbWritten) 995 1045 { 996 1046 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 997 1047 998 uint8_t tmpbuf[_4K]; 999 uint32_t addr = pReg->bd.addr; 1000 uint32_t written = 0; 1001 uint32_t to_copy = 0; 1002 1003 uint32_t temp = RT_MIN((uint32_t)pReg->picb << 1, (uint32_t)max); 1004 if (!temp) 1005 { 1006 *stop = 1; 1007 return 0; 1008 } 1048 uint32_t addr = pReg->bd.addr; 1049 uint32_t cbWrittenTotal = 0; 1050 uint32_t cbToRead; 1051 1052 uint32_t cbToWrite = RT_MIN((uint32_t)(pReg->picb << 1), cbMax); 1053 if (!cbToWrite) 1054 return VERR_NO_DATA; 1009 1055 1010 1056 int rc = VINF_SUCCESS; 1011 1057 1012 while (temp) 1013 { 1014 uint32_t copied; 1015 to_copy = RT_MIN(temp, sizeof(tmpbuf)); 1016 PDMDevHlpPhysRead(pDevIns, addr, tmpbuf, to_copy); /** @todo Check rc? */ 1058 LogFlowFunc(("pReg=%p, cbMax=%RU32\n", pReg, cbMax)); 1059 1060 while (cbToWrite) 1061 { 1062 uint32_t cbWritten; 1063 uint32_t cbWrittenMin = UINT32_MAX; 1064 1065 cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf); 1066 PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */ 1017 1067 1018 1068 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1019 # ifdef DEBUG_LUN1020 uint8_t lun = DEBUG_LUN_NUM;1021 # else1022 1069 /* Just multiplex the output to the connected backends. 1023 1070 * No need to utilize the virtual mixer here (yet). */ 1024 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 1025 { 1026 # endif 1027 rc = pThis->paDrv[lun]->pConnector->pfnWrite(pThis->paDrv[lun]->pConnector, 1028 pThis->paDrv[lun]->pStrmOut, 1029 tmpbuf, to_copy, &copied); 1030 if (RT_FAILURE(rc)) 1071 PAC97DRIVER pDrv; 1072 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1073 { 1074 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1075 pThis->pvReadWriteBuf, cbToRead, &cbWritten); 1076 if (RT_FAILURE(rc2)) 1031 1077 continue; 1032 # ifndef DEBUG_LUN 1033 } 1034 # endif 1078 1079 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 1080 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin)); 1081 } 1035 1082 #else 1036 c opied = AUD_write(pThis->voice_po, tmpbuf, to_copy);1083 cbWrittenMin = AUD_write(pThis->voice_po, pThis->pvReadWriteBuf, cbToRead); 1037 1084 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1038 LogFlowFunc((" to_copy=%RU32, copied=%RU32, temp=%RU32, temp_left=%RU32\n",1039 to_copy, copied, temp, temp - copied));1040 1041 if (!c opied)1042 { 1043 *stop = 1;1085 LogFlowFunc(("\tcbToRead=%RU32, cbWrittenMin=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n", 1086 cbToRead, cbWrittenMin, cbToWrite, cbToWrite - cbWrittenMin)); 1087 1088 if (!cbWrittenMin) 1089 { 1090 rc = VERR_NO_DATA; 1044 1091 break; 1045 1092 } 1046 temp -= copied; 1047 addr += copied; 1048 written += copied; 1049 } 1050 1051 if (!temp) 1052 { 1053 if (to_copy < 4) 1054 { 1055 LogFlowFunc(("whoops\n")); 1056 pThis->last_samp = 0; 1057 } 1058 else 1059 pThis->last_samp = *(uint32_t *)&tmpbuf[to_copy - 4]; 1093 1094 Assert(cbWrittenMin != UINT32_MAX); 1095 Assert(cbToWrite >= cbWrittenMin); 1096 cbToWrite -= cbWrittenMin; 1097 addr += cbWrittenMin; 1098 cbWrittenTotal += cbWrittenMin; 1060 1099 } 1061 1100 1062 1101 pReg->bd.addr = addr; 1063 1102 1064 LogFlowFunc(("written=%RU32\n", written)); 1065 return written; 1066 } 1067 1068 static void ichac97WriteBUP(PAC97STATE pThis, int elapsed) 1103 if (RT_SUCCESS(rc)) 1104 { 1105 if (!cbToWrite) /* All data written? */ 1106 { 1107 if (cbToRead < 4) 1108 { 1109 AssertMsgFailed(("Unable to save last written sample, cbToRead < 4 (is %RU32)\n", cbToRead)); 1110 pThis->last_samp = 0; 1111 } 1112 else 1113 pThis->last_samp = *(uint32_t *)&pThis->pvReadWriteBuf[cbToRead - 4]; 1114 } 1115 } 1116 1117 if (RT_SUCCESS(rc)) 1118 { 1119 if (pcbWritten) 1120 *pcbWritten = cbWrittenTotal; 1121 } 1122 1123 LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc)); 1124 return rc; 1125 } 1126 1127 static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed) 1069 1128 { 1070 1129 if (!(pThis->bup_flag & BUP_SET)) … … 1083 1142 } 1084 1143 1085 int written = 0; 1086 1087 while (elapsed) 1088 { 1089 unsigned int temp = RT_MIN((unsigned int)elapsed, sizeof(pThis->silence)); 1090 uint32_t copied; 1091 while (temp) 1144 while (cbElapsed) 1145 { 1146 uint32_t cbWrittenMin = UINT32_MAX; 1147 1148 uint32_t cbToWrite = RT_MIN(cbElapsed, (uint32_t)sizeof(pThis->silence)); 1149 while (cbToWrite) 1092 1150 { 1093 1151 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1094 # ifdef DEBUG_LUN 1095 uint8_t lun = DEBUG_LUN_NUM; 1096 # else 1097 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 1152 PAC97DRIVER pDrv; 1153 uint32_t cbWritten; 1154 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1098 1155 { 1099 # endif 1100 int rc2 = pThis->paDrv[lun]->pConnector->pfnWrite(pThis->paDrv[lun]->pConnector, 1101 pThis->paDrv[lun]->pStrmOut, 1102 pThis->silence, temp, &copied); 1156 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 1157 pThis->silence, cbToWrite, &cbWritten); 1103 1158 if (RT_FAILURE(rc2)) 1104 1159 continue; 1105 # ifndef DEBUG_LUN 1160 1161 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 1106 1162 } 1107 # endif1108 1163 #else 1109 c opied = AUD_write(pThis->voice_po, pThis->silence, temp);1164 cbWrittenMin = AUD_write(pThis->voice_po, pThis->silence, cbToWrite); 1110 1165 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1111 1166 1112 if (!c opied)1167 if (!cbWrittenMin) 1113 1168 return; 1114 temp -= copied; 1115 elapsed -= copied; 1116 written += copied; 1117 } 1118 } 1119 } 1120 1121 static int ichac97ReadAudio(PAC97STATE pThis, PAC97BMREG pReg, int max, int *stop) 1122 { 1123 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 1169 1170 Assert(cbToWrite >= cbWrittenMin); 1171 cbToWrite -= cbWrittenMin; 1172 Assert(cbElapsed >= cbWrittenMin); 1173 cbElapsed -= cbWrittenMin; 1174 } 1175 } 1176 } 1177 1178 static int ichac97ReadAudio(PAC97STATE pThis, PAC97BMREG pReg, uint32_t cbMax, uint32_t *pcbWritten) 1179 { 1180 AssertReturn(cbMax, VERR_INVALID_PARAMETER); 1181 1182 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis); 1183 1184 int rc = VINF_SUCCESS; 1124 1185 1125 1186 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER … … 1129 1190 AssertPtr(pSink); 1130 1191 1131 int rc; 1132 uint32_t cbRead; 1133 1134 size_t cbMixBuf = max * sizeof(uint8_t); 1135 Assert(cbMixBuf); 1192 uint32_t cbRead = 0; 1193 1194 size_t cbMixBuf = cbMax; 1136 1195 uint32_t cbToRead = RT_MIN(pReg->picb << 1, cbMixBuf); 1196 1197 if (!cbToRead) 1198 return VERR_NO_DATA; 1137 1199 1138 1200 uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbMixBuf); … … 1146 1208 pReg->bd.addr += cbRead; 1147 1209 } 1148 else1149 *stop = 1;1150 1210 1151 1211 RTMemFree(pvMixBuf); 1152 1212 } 1153 1213 else 1154 *stop = 1; 1155 1156 if (*stop) 1157 cbRead = 0; 1158 1159 return cbRead; 1214 rc = VERR_NO_MEMORY; 1215 1216 if (RT_SUCCESS(rc)) 1217 { 1218 Assert(cbRead); 1219 if (pcbWritten) 1220 *pcbWritten = cbRead; 1221 } 1222 1223 return rc; 1160 1224 #else 1161 1225 uint32_t addr = pReg->bd.addr; … … 1166 1230 SWVoiceIn *voice = (pReg - pThis->bm_regs) == MC_INDEX ? pThis->voice_mc : pThis->voice_pi; 1167 1231 1168 temp = audio_MIN(temp, (uint32_t) max);1232 temp = audio_MIN(temp, (uint32_t)cbMax); 1169 1233 if (!temp) 1170 { 1171 *stop = 1; 1172 return 0; 1173 } 1234 return VERR_NO_DATA; 1174 1235 1175 1236 uint8_t tmpbuf[4096]; … … 1181 1242 if (!acquired) 1182 1243 { 1183 *stop = 1;1244 rc = VERR_GENERAL_FAILURE; /* Not worth fixing anymore. */ 1184 1245 break; 1185 1246 } … … 1191 1252 1192 1253 pReg->bd.addr = addr; 1193 return nread; 1254 1255 if (RT_SUCCESS(rc)) 1256 { 1257 if (pcbWritten) 1258 *pcbWritten = nread; 1259 } 1260 1261 return rc; 1194 1262 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1195 1263 } 1196 1264 1197 1265 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1198 static void ichac97TransferAudio(PAC97DRIVER pDrv, int index, int elapsed) 1199 #else 1200 static void ichac97TransferAudio(PAC97STATE pThis, int index, int elapsed) 1266 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1267 { 1268 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE); 1269 AssertPtr(pThis); 1270 1271 STAM_PROFILE_START(&pThis->StatTimer, a); 1272 1273 int rc = VINF_SUCCESS; 1274 1275 uint32_t cbInMax = 0; 1276 uint32_t cbOutMin = UINT32_MAX; 1277 1278 PAC97DRIVER pDrv; 1279 uint32_t cbIn, cbOut; 1280 1281 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1282 { 1283 if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut)) 1284 continue; 1285 1286 rc = pDrv->pConnector->pfnQueryData(pDrv->pConnector, /** @todo Rename QueryStatus */ 1287 &cbIn, &cbOut, &pDrv->cSamplesLive); 1288 if (RT_SUCCESS(rc)) 1289 { 1290 if (cbIn || cbOut) 1291 LogFlowFunc(("\tLUN#%RU8: cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, cbIn, cbOut)); 1292 1293 cbInMax = RT_MAX(cbInMax, cbIn); 1294 cbOutMin = RT_MIN(cbOutMin, cbOut); 1295 } 1296 else 1297 pDrv->cSamplesLive = 0; 1298 } 1299 1300 /* 1301 * Playback. 1302 */ 1303 if (cbOutMin) 1304 { 1305 Assert(cbOutMin != UINT32_MAX); 1306 ichac97TransferAudio(pThis, PO_INDEX, cbOutMin); /** @todo Add rc! */ 1307 } 1308 else 1309 { 1310 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1311 { 1312 if (pDrv->cSamplesLive) 1313 pDrv->pConnector->pfnPlayOut(pDrv->pConnector); 1314 } 1315 } 1316 1317 /* 1318 * Recording. 1319 */ 1320 if (cbInMax) 1321 ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */ 1322 1323 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 1324 1325 STAM_PROFILE_STOP(&pThis->StatTimer, a); 1326 } 1201 1327 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1202 { 1203 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1204 PAC97STATE pThis = pDrv->pAC97State; 1205 1206 if (pDrv->uLUN != 0) /* Only LUN 0 can write and read from the device. */ 1207 return; 1208 /** @todo Fix this limitation by implementing a virtual mixer. */ 1209 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1328 1329 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed) 1330 { 1331 LogFlowFunc(("pThis=%p, index=%d, cbElapsed=%RU32\n", pThis, index, cbElapsed)); 1210 1332 1211 1333 PAC97BMREG pReg = &pThis->bm_regs[index]; … … 1217 1339 { 1218 1340 case PO_INDEX: 1219 ichac97WriteBUP(pThis, elapsed);1341 ichac97WriteBUP(pThis, cbElapsed); 1220 1342 break; 1221 1343 … … 1225 1347 } 1226 1348 1227 return; 1228 } 1229 1230 int written = 0; 1231 int stop = 0; 1232 1233 while ((elapsed >> 1) && !stop) 1234 { 1235 int temp; 1236 1349 return VINF_SUCCESS; 1350 } 1351 1352 int rc; 1353 uint32_t cbWrittenTotal = 0; 1354 1355 while ((cbElapsed >> 1)) 1356 { 1237 1357 if (!pReg->bd_valid) 1238 1358 { … … 1260 1380 } 1261 1381 1382 uint32_t cbWritten; 1262 1383 switch (index) 1263 1384 { 1264 1385 case PO_INDEX: 1265 temp = ichac97WriteAudio(pThis, pReg, elapsed, &stop); 1266 written += temp; 1267 elapsed -= temp; 1268 Assert((temp & 1) == 0); /* Else the following shift won't work */ 1269 pReg->picb -= (temp >> 1); 1386 { 1387 rc = ichac97WriteAudio(pThis, pReg, cbElapsed, &cbWritten); 1388 if (RT_SUCCESS(rc)) 1389 { 1390 cbWrittenTotal += cbWritten; 1391 cbElapsed -= cbWritten; 1392 Assert((cbWritten & 1) == 0); /* Else the following shift won't work */ 1393 pReg->picb -= (cbWritten >> 1); 1394 } 1270 1395 break; 1396 } 1271 1397 1272 1398 case PI_INDEX: 1273 1399 case MC_INDEX: 1274 temp = ichac97ReadAudio(pThis, pReg, elapsed, &stop); 1275 elapsed -= temp; 1276 Assert((temp & 1) == 0); /* Else the following shift won't work */ 1277 pReg->picb -= (temp >> 1); 1400 { 1401 rc = ichac97ReadAudio(pThis, pReg, cbElapsed, &cbWritten); 1402 if (RT_SUCCESS(rc)) 1403 { 1404 cbElapsed -= cbWritten; 1405 Assert((cbWritten & 1) == 0); /* Else the following shift won't work */ 1406 pReg->picb -= (cbWritten >> 1); 1407 } 1278 1408 break; 1409 } 1279 1410 1280 1411 default: 1281 AssertMsgFailed(("Index % d not supported\n", index));1412 AssertMsgFailed(("Index %ld not supported\n", index)); 1282 1413 break; 1283 1414 } 1284 LogFlowFunc(("pReg->picb = %d\n", pReg->picb)); 1415 1416 LogFlowFunc(("pReg->picb=%RU16, cbWrittenTotal=%RU32\n", pReg->picb, cbWrittenTotal)); 1285 1417 1286 1418 if (!pReg->picb) … … 1297 1429 LogFlowFunc(("Underrun civ (%d) == lvi (%d)\n", pReg->civ, pReg->lvi)); 1298 1430 new_sr |= SR_LVBCI | SR_DCH | SR_CELV; 1299 stop = 1;1300 1431 pThis->bup_flag = (pReg->bd.ctl_len & BD_BUP) ? BUP_LAST : 0; 1432 1433 rc = VERR_NO_DATA; 1301 1434 } 1302 1435 else … … 1309 1442 ichac97UpdateStatus(pThis, pReg, new_sr); 1310 1443 } 1311 } 1312 } 1313 1314 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1315 static void ichac97InputCallback(void *pvContext, uint32_t cbAvail) 1316 { 1317 PAC97DRIVER pThis = (PAC97DRIVER)pvContext; 1318 ichac97TransferAudio(pThis, PI_INDEX, cbAvail); 1319 } 1320 #else 1444 1445 if (RT_FAILURE(rc)) 1446 { 1447 if (rc == VERR_NO_DATA) 1448 rc = VINF_SUCCESS; 1449 1450 break; 1451 } 1452 } 1453 1454 LogFlowFuncLeaveRC(rc); 1455 return rc; 1456 } 1457 1458 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 1321 1459 static void ichac97InputCallback(void *pvContext, int cbAvail) 1322 1460 { 1323 1461 ichac97TransferAudio((AC97STATE *)pvContext, PI_INDEX, cbAvail); 1324 1462 } 1325 #endif 1326 1327 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1328 static void ichac97MicInCallback(void *pvContext, uint32_t cbAvail) 1329 { 1330 PAC97DRIVER pThis = (PAC97DRIVER)pvContext; 1331 ichac97TransferAudio(pThis, MC_INDEX, cbAvail); 1332 } 1333 #else 1463 1334 1464 static void ichac97MicInCallback(void *pvContext, int cbAvail) 1335 1465 { 1336 1466 ichac97TransferAudio((AC97STATE *)pvContext, MC_INDEX, cbAvail); 1337 1467 } 1338 #endif 1339 1340 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1341 static void ichac97OutputCallback(void *pvContext, uint32_t cbFree) 1342 { 1343 PAC97DRIVER pThis = (PAC97DRIVER)pvContext; 1344 ichac97TransferAudio(pThis, PO_INDEX, cbFree); 1345 } 1346 #else 1468 1347 1469 static void ichac97OutputCallback(void *pvContext, int cbFree) 1348 1470 { … … 1865 1987 } 1866 1988 1867 1989 #ifdef IN_RING3 1868 1990 /** 1869 1991 * @callback_method_impl{FNSSMDEVSAVEEXEC} … … 1896 2018 1897 2019 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1898 /* Writing only host backend values here and ignore data for other backends 1899 * like VRDE and video recording. LUN 0 always is the host backend. */ 1900 if (pThis->cLUNs >= 1) 1901 { 1902 PPDMIAUDIOCONNECTOR pCon = pThis->paDrv[0]->pConnector; 2020 PAC97DRIVER pDrv; 2021 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 2022 { 2023 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 1903 2024 AssertPtr(pCon); 1904 active[PI_INDEX] = pCon->pfnIsActiveIn(pCon, pThis->paDrv[0]->pStrmIn) ? 1 : 0; 1905 active[PO_INDEX] = pCon->pfnIsActiveOut(pCon, pThis->paDrv[0]->pStrmOut) ? 1 : 0; 1906 active[MC_INDEX] = pCon->pfnIsActiveIn(pCon, pThis->paDrv[0]->pStrmMic) ? 1 : 0; 1907 } 1908 else 1909 RT_ZERO(active); 2025 active[PI_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->LineIn.pStrmIn) ? 1 : 0; 2026 active[PO_INDEX] = pCon->pfnIsActiveOut(pCon, pDrv->Out.pStrmOut) ? 1 : 0; 2027 active[MC_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->MicIn.pStrmIn) ? 1 : 0; 2028 } 1910 2029 #else 1911 2030 active[PI_INDEX] = AUD_is_active_in( pThis->voice_pi) ? 1 : 0; … … 2025 2144 2026 2145 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2027 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 2028 { 2029 if (pThis->paDrv[lun]) 2030 { 2031 RTMemFree(pThis->paDrv[lun]); 2032 pThis->paDrv[lun] = NULL; 2033 } 2034 } 2035 2036 pThis->cLUNs = 0; 2146 PAC97DRIVER pDrv; 2147 while (!RTListIsEmpty(&pThis->lstDrv)) 2148 { 2149 pDrv = RTListGetFirst(&pThis->lstDrv, AC97DRIVER, Node); 2150 2151 RTListNodeRemove(&pDrv->Node); 2152 RTMemFree(pDrv); 2153 } 2037 2154 2038 2155 if (pThis->pMixer) … … 2042 2159 } 2043 2160 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2161 2162 if (pThis->pvReadWriteBuf) 2163 { 2164 RTMemFree(pThis->pvReadWriteBuf); 2165 pThis->pvReadWriteBuf = NULL; 2166 pThis->cbReadWriteBuf = 0; 2167 } 2044 2168 2045 2169 return VINF_SUCCESS; … … 2098 2222 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY; 2099 2223 2100 LogFunc(("LUN #%u: pCon=%p, drvFlags=0x%x\n", 2101 uLUN, pDrv->pConnector, pDrv->Flags)); 2102 2103 pThis->paDrv[uLUN] = pDrv; 2104 pThis->cLUNs++; 2224 LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags)); 2225 2226 /* Attach to driver list. */ 2227 RTListAppend(&pThis->lstDrv, &pDrv->Node); 2105 2228 } 2106 2229 else … … 2190 2313 */ 2191 2314 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2192 /* We support 32 LUNs max. This should be enough for now. */ 2193 for (uint8_t lun = 0; lun < 32 ; lun++) 2194 { 2195 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", lun)); 2196 rc = ichac97Attach(pDevIns, lun, PDM_TACH_FLAGS_NOT_HOT_PLUG); 2315 RTListInit(&pThis->lstDrv); 2316 2317 uint8_t uLUN = 0; 2318 do 2319 { 2320 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN)); 2321 rc = ichac97Attach(pDevIns, uLUN++, PDM_TACH_FLAGS_NOT_HOT_PLUG); 2197 2322 if (RT_FAILURE(rc)) 2198 2323 { … … 2201 2326 break; 2202 2327 } 2203 } 2204 2205 LogRel(("AC97: %RU8 LUN(s) attached\n", pThis->cLUNs)); 2328 2329 } while (0); 2330 2331 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc)); 2206 2332 #else 2207 2333 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port"); … … 2221 2347 2222 2348 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2223 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 2224 { 2225 if (!pThis->paDrv[lun]->pConnector->pfnIsInputOK(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmIn)) 2226 LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU32!\n", lun)); 2227 if (!pThis->paDrv[lun]->pConnector->pfnIsOutputOK(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmOut)) 2228 LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU32!\n", lun)); 2229 if (!pThis->paDrv[lun]->pConnector->pfnIsInputOK(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmMic)) 2230 LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", lun)); 2231 } 2232 2233 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 2234 { 2235 PAC97DRIVER pDrv = pThis->paDrv[lun]; 2236 AssertPtr(pDrv); 2237 2238 /* Only primary drivers are critical for the VM to run. Everything else 2239 * might not worth showing an own error message box in the GUI. */ 2349 PAC97DRIVER pDrv; 2350 uLUN = 0; 2351 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 2352 { 2353 if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->LineIn.pStrmIn)) 2354 LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU32!\n", uLUN)); 2355 if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut)) 2356 LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU32!\n", uLUN)); 2357 if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->MicIn.pStrmIn)) 2358 LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", uLUN)); 2359 2360 uLUN++; 2361 } 2362 2363 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 2364 { 2365 /* 2366 * Only primary drivers are critical for the VM to run. Everything else 2367 * might not worth showing an own error message box in the GUI. 2368 */ 2240 2369 if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY)) 2241 2370 continue; 2242 2371 2243 PPDMIAUDIOCONNECTOR pCon = p This->paDrv[lun]->pConnector;2372 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 2244 2373 AssertPtr(pCon); 2245 if ( !pCon->pfnIsInputOK (pCon, pDrv-> pStrmIn)2246 && !pCon->pfnIsOutputOK(pCon, pDrv-> pStrmOut)2247 && !pCon->pfnIsInputOK (pCon, pDrv-> pStrmMic))2248 { 2249 LogRel(("AC97: SelectingNULL driver\n"));2374 if ( !pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn) 2375 && !pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut) 2376 && !pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn)) 2377 { 2378 LogRel(("AC97: Falling back to NULL driver\n")); 2250 2379 2251 2380 /* Was not able initialize *any* stream. 2252 2381 * Select the NULL audio driver instead. */ 2253 pCon->pfnCloseIn (pCon, pDrv-> pStrmIn);2254 pCon->pfnCloseOut(pCon, pDrv-> pStrmOut);2255 pCon->pfnCloseIn (pCon, pDrv-> pStrmMic);2256 2257 pDrv-> pStrmOut = NULL;2258 pDrv-> pStrmIn = NULL;2259 pDrv-> pStrmMic= NULL;2382 pCon->pfnCloseIn (pCon, pDrv->LineIn.pStrmIn); 2383 pCon->pfnCloseOut(pCon, pDrv->Out.pStrmOut); 2384 pCon->pfnCloseIn (pCon, pDrv->MicIn.pStrmIn); 2385 2386 pDrv->Out.pStrmOut = NULL; 2387 pDrv->LineIn.pStrmIn = NULL; 2388 pDrv->MicIn.pStrmIn = NULL; 2260 2389 2261 2390 pCon->pfnInitNull(pCon); … … 2266 2395 "with the consequence that no sound is audible")); 2267 2396 } 2268 else if ( !pCon->pfnIsInputOK (pCon, pDrv-> pStrmIn)2269 || !pCon->pfnIsOutputOK(pCon, pDrv-> pStrmOut)2270 || !pCon->pfnIsInputOK (pCon, pDrv-> pStrmMic))2271 { 2272 char szMissingStreams[ 128];2397 else if ( !pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn) 2398 || !pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut) 2399 || !pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn)) 2400 { 2401 char szMissingStreams[255]; 2273 2402 size_t len = 0; 2274 if (!pCon->pfnIsInputOK (pCon, pDrv-> pStrmIn))2403 if (!pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn)) 2275 2404 len = RTStrPrintf(szMissingStreams, 2276 2405 sizeof(szMissingStreams), "PCM Input"); 2277 if (!pCon->pfnIsOutputOK(pCon, pDrv-> pStrmOut))2406 if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut)) 2278 2407 len += RTStrPrintf(szMissingStreams + len, 2279 2408 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output"); 2280 if (!pCon->pfnIsInputOK (pCon, pDrv-> pStrmMic))2409 if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn)) 2281 2410 len += RTStrPrintf(szMissingStreams + len, 2282 sizeof(szMissingStreams) - len, len ? ", PCM Mic " : "PCM Mic");2411 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone"); 2283 2412 2284 2413 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding", … … 2335 2464 } 2336 2465 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2466 2467 if (RT_SUCCESS(rc)) 2468 { 2469 pThis->cbReadWriteBuf = _4K; /** @todo Make this configurable. */ 2470 pThis->pvReadWriteBuf = (uint8_t *)RTMemAlloc(pThis->cbReadWriteBuf); 2471 if (!pThis->pvReadWriteBuf) 2472 rc = VERR_NO_MEMORY; 2473 } 2474 2475 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2476 if (RT_SUCCESS(rc)) 2477 { 2478 /* Start the emulation timer. */ 2479 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis, 2480 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer); 2481 AssertRCReturn(rc, rc); 2482 2483 if (RT_SUCCESS(rc)) 2484 { 2485 pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 200; /** Hz. @todo Make this configurable! */ 2486 if (pThis->uTicks < 100) 2487 pThis->uTicks = 100; 2488 LogFunc(("Timer ticks=%RU64\n", pThis->uTicks)); 2489 2490 /* Fire off timer. */ 2491 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 2492 } 2493 } 2494 2495 # ifdef VBOX_WITH_STATISTICS 2496 if (RT_SUCCESS(rc)) 2497 { 2498 /* 2499 * Register statistics. 2500 */ 2501 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/AC97/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer."); 2502 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/AC97/BytesRead" , STAMUNIT_BYTES, "Bytes read from AC97 emulation."); 2503 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/AC97/BytesWritten", STAMUNIT_BYTES, "Bytes written to AC97 emulation."); 2504 } 2505 # endif 2506 2507 #endif 2337 2508 2338 2509 return VINF_SUCCESS; … … 2393 2564 PDM_DEVREG_VERSION 2394 2565 }; 2566 2567 #endif /* !IN_RING3 */ 2568 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */ 2569 -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r53624 r53830 58 58 59 59 #ifdef DEBUG 60 #define DEBUG_LUN60 //#define DEBUG_LUN 61 61 # ifdef DEBUG_LUN 62 62 # define DEBUG_LUN_NUM 0 … … 562 562 563 563 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 564 typedef struct HDAINPUTSTREAM 565 { 566 /** PCM line input stream. */ 567 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn; 568 /** Mixer handle for line input stream. */ 569 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn; 570 } HDAINPUTSTREAM, *PHDAINPUTSTREAM; 571 572 typedef struct HDAOUTPUTSTREAM 573 { 574 /** PCM output stream. */ 575 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut; 576 } HDAOUTPUTSTREAM, *PHDAOUTPUTSTREAM; 577 564 578 /** 565 579 * Struct for maintaining a host backend driver. … … 567 581 * HDA codec. The HDA controller does the actual multiplexing 568 582 * of HDA codec data to various host backend drivers then. 583 * 584 * This HDA device uses a timer in order to synchronize all 585 * read/write accesses across all attached LUNs / backends. 569 586 */ 570 587 typedef struct HDADRIVER 571 588 { 572 RTLISTNODE Node; 589 union 590 { 591 /** Node for storing this driver in our device driver 592 * list of HDASTATE. */ 593 RTLISTNODE Node; 594 struct 595 { 596 R3PTRTYPE(void *) dummy1; 597 R3PTRTYPE(void *) dummy2; 598 } dummy; 599 }; 600 573 601 /** Pointer to HDA controller (state). */ 574 PHDASTATEpHDAState;602 R3PTRTYPE(PHDASTATE) pHDAState; 575 603 /** Driver flags. */ 576 604 PDMAUDIODRVFLAGS Flags; 605 uint8_t u32Padding0[3]; 577 606 /** LUN to which this driver has been assigned. */ 578 607 uint8_t uLUN; … … 580 609 * host backend. */ 581 610 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 582 /** PCM line input stream. */ 583 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn; 584 /** Mixer handle for line input stream. */ 585 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn; 586 /** PCM microphone input stream. */ 587 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmMic; 588 /** Mixer handle for microphone input stream. */ 589 R3PTRTYPE(PAUDMIXSTREAM) phStrmMic; 590 /** PCM output stream. */ 591 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pGstStrmOut; 611 /** Stream for line input. */ 612 HDAINPUTSTREAM LineIn; 613 /** Stream for mic input. */ 614 HDAINPUTSTREAM MicIn; 615 /** Stream for output. */ 616 HDAOUTPUTSTREAM Out; 617 /** Number of samples to play (output), needed 618 * for the timer routine. */ 619 uint32_t cSamplesLive; 592 620 } HDADRIVER, *PHDADRIVER; 593 621 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ … … 639 667 bool fRCEnabled; 640 668 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 641 /** Number of active + allocated LUNs. Each 642 * LUN has a HDA driver assigned. */ 643 uint8_t cLUNs; 644 uint8_t au8PaddingLUNs[4]; 645 /** The HDA codec to use. */ 669 /** The emulation timer for handling the attached 670 * LUN drivers. */ 671 PTMTIMERR3 pTimer; 672 /** Timer ticks for handling the LUN drivers. */ 673 uint64_t uTicks; 674 # ifdef VBOX_WITH_STATISTICS 675 STAMPROFILE StatTimer; 676 STAMCOUNTER StatBytesRead; 677 STAMCOUNTER StatBytesWritten; 678 # endif 679 /** Pointer to HDA codec to use. */ 646 680 R3PTRTYPE(PHDACODEC) pCodec; 647 /** Array of active HDA drivers. */ 648 R3PTRTYPE(PHDADRIVER) paDrv[32]; 681 union 682 { 683 /** List of associated LUN drivers. */ 684 RTLISTANCHOR lstDrv; 685 struct 686 { 687 R3PTRTYPE(void *) dummy1; 688 R3PTRTYPE(void *) dummy2; 689 } dummy; 690 }; 649 691 /** The device' software mixer. */ 650 692 R3PTRTYPE(PAUDIOMIXER) pMixer; 651 /** Audio sink for line input. */693 /** Audio mixer sink for line input. */ 652 694 R3PTRTYPE(PAUDMIXSINK) pSinkLineIn; 653 /** Audio sink for microphone input. */695 /** Audio mixer sink for microphone input. */ 654 696 R3PTRTYPE(PAUDMIXSINK) pSinkMicIn; 655 #else 656 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pDrv; 697 #else /* !VBOX_WITH_PDM_AUDIO_DRIVER */ 657 698 /** The HDA codec to use. */ 658 699 R3PTRTYPE(PHDACODEC) pCodec; … … 662 703 uint8_t u8Counter; 663 704 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 664 uint8_t au8Padding[ 4];705 uint8_t au8Padding[7]; 665 706 #else 666 707 uint8_t au8Padding[7]; … … 718 759 719 760 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 720 static void hdaTransfer(PHDADRIVER pDrv, ENMSOUNDSOURCE enmSrc, uint32_t cbAvail); 761 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); 762 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbAvail); 721 763 #else 722 static voidhdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSource, int cbAvail);764 static int hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSource, int cbAvail); 723 765 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 724 766 … … 1529 1571 { 1530 1572 Assert((!fReset && !fInReset)); 1573 1574 PHDADRIVER pDrv; 1531 1575 switch (iReg) 1532 1576 { 1533 1577 case HDA_REG_SD0CTL: 1534 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER1535 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)1536 p This->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector,1537 pThis->paDrv[lun]->pStrmIn, fRun);1538 # else1578 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1579 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 1580 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 1581 pDrv->LineIn.pStrmIn, fRun); 1582 # else 1539 1583 AUD_set_active_in(pThis->pCodec->SwVoiceIn, fRun); 1540 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */1584 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1541 1585 break; 1542 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER1543 # ifdef VBOX_WITH_HDA_MIC_IN1586 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1587 # ifdef VBOX_WITH_HDA_MIC_IN 1544 1588 case HDA_REG_SD2CTL: 1545 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)1546 p This->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector,1547 pThis->paDrv[lun]->pStrmMic, fRun);1548 # endif1549 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */1589 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 1590 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, 1591 pDrv->MicIn.pStrmIn, fRun); 1592 # endif 1593 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1550 1594 break; 1551 1595 case HDA_REG_SD4CTL: 1552 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER1553 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)1554 p This->paDrv[lun]->pConnector->pfnEnableOut(pThis->paDrv[lun]->pConnector,1555 pThis->paDrv[lun]->pGstStrmOut, fRun);1556 # else1596 # ifdef VBOX_WITH_PDM_AUDIO_DRIVER 1597 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 1598 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, 1599 pDrv->Out.pStrmOut, fRun); 1600 # else 1557 1601 AUD_set_active_out(pThis->pCodec->SwVoiceOut, fRun); 1558 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */1602 # endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 1559 1603 break; 1560 1604 default: … … 1565 1609 #else /* !IN_RING3 */ 1566 1610 return VINF_IOM_R3_MMIO_WRITE; 1567 #endif 1611 #endif /* IN_RING3 */ 1568 1612 } 1569 1613 … … 1768 1812 return rc; 1769 1813 1814 PHDADRIVER pDrv; 1770 1815 switch (iReg) 1771 1816 { 1772 1817 case HDA_REG_SD0FMT: 1773 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)1818 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 1774 1819 rc = hdaCodecOpenStream(pThis->pCodec, PI_INDEX, &as); 1775 1820 break; … … 1777 1822 # ifdef VBOX_WITH_HDA_MIC_IN 1778 1823 case HDA_REG_SD2FMT: 1779 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)1824 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 1780 1825 rc = hdaCodecOpenStream(pThis->pCodec, MC_INDEX, &as); 1781 1826 break; … … 1850 1895 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */ 1851 1896 LogFunc(("IC:%x\n", cmd)); 1852 # if 0 1853 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 1854 { 1855 rc = pThis->pCodec[lun]->pfnLookup(pThis->pCodec[lun], 1856 HDA_CODEC_CMD(cmd, lun), 1857 &pfn); 1858 if (RT_SUCCESS(rc)) 1859 { 1860 AssertPtr(pfn); 1861 rc = pfn(pThis->pCodec[lun], 1862 HDA_CODEC_CMD(cmd, lun), &resp); 1863 if (RT_FAILURE(rc)) 1864 break; 1865 } 1866 } 1867 # else 1897 1868 1898 rc = pThis->pCodec->pfnLookup(pThis->pCodec, 1869 1899 HDA_CODEC_CMD(cmd, 0 /* LUN */), … … 1873 1903 rc = pfn(pThis->pCodec, 1874 1904 HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp); 1875 # endif1876 1877 1905 if (RT_FAILURE(rc)) 1878 1906 AssertRCReturn(rc, rc); 1907 1879 1908 HDA_REG(pThis, IR) = (uint32_t)resp; 1880 1909 LogFunc(("IR:%x\n", HDA_REG(pThis, IR))); … … 2008 2037 uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit) 2009 2038 { 2010 uint32_t cb2Copy;2011 2039 /* 2012 2040 * Number of bytes depends on the current position in buffer (u32BdleCviLen-u32BdleCviPos) 2013 2041 */ 2014 2042 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */ 2015 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;2043 uint32_t cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos; 2016 2044 /* 2017 2045 * we may increase the counter in range of [0, FIFOS + 1] … … 2169 2197 * but "reports bytes" when all conditions are met (FIFOW). 2170 2198 */ 2171 static uint32_t hdaReadAudio(PHDASTATE pThis, PAUDMIXSINK pSink, PHDABDLEDESC pBdle,2199 static uint32_t hdaReadAudio(PHDASTATE pThis, PAUDMIXSINK pSink, 2172 2200 PHDASTREAMTRANSFERDESC pStreamDesc, 2173 uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit) 2174 { 2201 uint32_t u32CblLimit, uint32_t *pcbAvail, uint32_t *pcbRead) 2202 { 2203 PHDABDLEDESC pBdle = &pThis->StInBdle; /** @todo Add support for mic in. */ 2204 2205 int rc; 2175 2206 uint32_t cbTransferred = 0; 2176 2207 2177 2208 LogFlowFunc(("CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); 2178 2209 2179 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *p u32Avail, u32CblLimit);2210 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pcbAvail, u32CblLimit); 2180 2211 if (!cb2Copy) 2181 2212 { 2182 2213 /* If we enter here we can't report "unreported bits". */ 2183 *fStop = true;2214 rc = VERR_NO_DATA; 2184 2215 } 2185 2216 else 2186 2217 { 2187 2218 uint32_t cbRead = 0; 2188 intrc = audioMixerProcessSinkIn(pSink, pBdle->au8HdaBuffer, cb2Copy, &cbRead);2219 rc = audioMixerProcessSinkIn(pSink, pBdle->au8HdaBuffer, cb2Copy, &cbRead); 2189 2220 if (RT_SUCCESS(rc)) 2190 2221 { 2222 Assert(cbRead); 2223 2191 2224 /* 2192 2225 * Write the HDA DMA buffer. … … 2197 2230 2198 2231 /* Don't see any reason why cb2Copy would differ from cbRead. */ 2199 Assert((cbRead == cb2Copy && (*p u32Avail) >= cb2Copy)); /* sanity */2232 Assert((cbRead == cb2Copy && (*pcbAvail) >= cb2Copy)); /* sanity */ 2200 2233 2201 2234 if (pBdle->cbUnderFifoW + cbRead > hdaFifoWToSz(pThis, 0)) 2202 hdaBackendReadTransferReported(pBdle, cb2Copy, cbRead, &cbTransferred, p u32Avail);2235 hdaBackendReadTransferReported(pBdle, cb2Copy, cbRead, &cbTransferred, pcbAvail); 2203 2236 else 2204 2237 { 2205 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbRead, p u32Avail);2206 *fStop = true;2238 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbRead, pcbAvail); 2239 rc = VERR_NO_DATA; 2207 2240 } 2208 2241 } 2209 else2210 *fStop = true;2211 2242 } 2212 2243 2213 2244 Assert((cbTransferred <= (SDFIFOS(pThis, 0) + 1))); 2214 LogFunc(("CVI(pos:%RU32, len:%RU32), cbTransferred: %RU32\n", 2215 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred)); 2216 return cbTransferred; 2245 LogFunc(("CVI(pos:%RU32, len:%RU32), cbTransferred=%RU32, rc=%Rrc\n", 2246 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred, rc)); 2247 2248 if (RT_SUCCESS(rc)) 2249 *pcbRead = cbTransferred; 2250 2251 return rc; 2217 2252 } 2218 2253 #else … … 2220 2255 { 2221 2256 PHDABDLEDESC pBdle = &pThis->StInBdle; 2257 2222 2258 uint32_t cbTransferred = 0; 2223 2259 uint32_t cb2Copy = 0; … … 2235 2271 * read from backend input line to the last unreported position or at the begining. 2236 2272 */ 2237 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER2238 //cbBackendCopy = pThis->pDrv[0]->pfnRead(pThis->pDrv[0], pThis->pCodec[0]->SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);2239 //cbBackendCopy = pThis->pDrv[0]->pfnRead(pThis->pDrv[0], pThis->pCodec[1]->SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);2240 #else2241 2273 cbBackendCopy = AUD_read(pThis->pCodec->SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy); 2242 #endif 2274 2243 2275 /* 2244 2276 * write the HDA DMA buffer 2245 2277 */ 2246 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy); 2278 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, 2279 cbBackendCopy); 2280 STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbBackendCopy); 2247 2281 2248 2282 /* Don't see any reason why cb2Copy would differ from cbBackendCopy */ … … 2264 2298 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2265 2299 2266 static uint32_t hdaWriteAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit) 2300 static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t u32CblLimit, 2301 uint32_t *pcbAvail, uint32_t *pcbWritten) 2267 2302 { 2268 2303 PHDABDLEDESC pBdle = &pThis->StOutBdle; 2304 2305 int rc; 2306 2269 2307 uint32_t cbTransferred = 0; 2270 uint32_t cbWrittenM ax= 0; /* local byte counter, how many bytes copied to backend */2308 uint32_t cbWrittenMin = 0; /* local byte counter, how many bytes copied to backend */ 2271 2309 2272 2310 LogFunc(("CVI(cvi:%RU32, pos:%RU32, len:%RU32)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen)); 2273 2311 2274 2312 /* Local byte counter (on local buffer). */ 2275 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *p u32Avail, u32CblLimit);2313 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pcbAvail, u32CblLimit); 2276 2314 2277 2315 /* … … 2280 2318 */ 2281 2319 if (!cb2Copy) 2282 *fStop = true; 2320 { 2321 rc = VERR_NO_DATA; 2322 } 2283 2323 else 2284 2324 { … … 2286 2326 pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, 2287 2327 pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy); 2328 STAM_COUNTER_ADD(&pThis->StatBytesRead, cb2Copy); 2288 2329 2289 2330 /* … … 2293 2334 { 2294 2335 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2295 int rc;2296 2336 uint32_t cbWritten; 2297 # ifdef DEBUG_LUN 2298 uint8_t lun = DEBUG_LUN_NUM; 2299 # else 2300 for (uint8_t lun = 0; lun < 1; lun++)2337 cbWrittenMin = UINT32_MAX; 2338 2339 PHDADRIVER pDrv; 2340 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2301 2341 { 2302 # endif 2303 rc = pThis->paDrv[lun]->pConnector->pfnWrite(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pGstStrmOut, 2304 pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW, 2305 &cbWritten); 2306 # ifndef DEBUG_LUN 2307 if (RT_FAILURE(rc)) 2308 continue; 2309 # endif 2310 cbWrittenMax = RT_MAX(cbWrittenMax, cbWritten); 2311 # ifndef DEBUG_LUN 2342 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut)) 2343 { 2344 rc = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut, 2345 pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW, 2346 &cbWritten); 2347 if (RT_FAILURE(rc)) 2348 continue; 2349 } 2350 else /* Stream disabled, just assume all was copied. */ 2351 cbWritten = cb2Copy; 2352 2353 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten); 2354 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin)); 2312 2355 } 2313 # endif 2356 2357 if (cbWrittenMin == UINT32_MAX) 2358 cbWrittenMin = 0; 2314 2359 #else 2315 cbWrittenM ax= AUD_write (pThis->pCodec->SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);2360 cbWrittenMin = AUD_write (pThis->pCodec->SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW); 2316 2361 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2317 2362 2318 hdaBackendWriteTransferReported(pBdle, cb2Copy, cbWrittenM ax, &cbTransferred, pu32Avail);2363 hdaBackendWriteTransferReported(pBdle, cb2Copy, cbWrittenMin, &cbTransferred, pcbAvail); 2319 2364 } 2320 2365 else … … 2322 2367 /* Not enough bytes to be processed and reported, we'll try our luck next time around. */ 2323 2368 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cb2Copy, NULL); 2324 *fStop = true;2369 rc = VERR_NO_DATA; 2325 2370 } 2326 2371 } 2327 2372 2328 2373 Assert(cbTransferred <= SDFIFOS(pThis, 4) + 1); 2329 LogFunc(("CVI(pos:%RU32, len:%RU32, cbTransferred:%RU32)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred)); 2330 return cbTransferred; 2374 LogFunc(("CVI(pos:%RU32, len:%RU32, cbTransferred:%RU32), rc=%Rrc\n", 2375 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred, rc)); 2376 2377 if (RT_SUCCESS(rc)) 2378 *pcbWritten = cbTransferred; 2379 2380 return rc; 2331 2381 } 2332 2382 … … 2382 2432 2383 2433 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2384 # ifdef VBOX_WITH_HDA_MIC_IN2385 static void hdaMicInputCallback(void *pvDrv, uint32_t cbAvail)2386 {2387 PHDADRIVER pThis = (PHDADRIVER)pvDrv;2388 hdaTransfer(pThis, MC_INDEX, cbAvail);2389 }2390 # endif /* VBOX_WITH_HDA_MIC_IN */2391 2392 static void hdaLineInputCallback(void *pvDrv, uint32_t cbAvail)2393 {2394 PHDADRIVER pThis = (PHDADRIVER)pvDrv;2395 hdaTransfer(pThis, PI_INDEX, cbAvail);2396 }2397 2398 static void hdaOutputCallback(void *pvDrv, uint32_t cbFree)2399 {2400 PHDADRIVER pThis = (PHDADRIVER)pvDrv;2401 hdaTransfer(pThis, PO_INDEX, cbFree);2402 }2403 2404 2434 static DECLCALLBACK(int) hdaOpenIn(PHDASTATE pThis, 2405 2435 const char *pszName, PDMAUDIORECSOURCE enmRecSource, 2406 2436 PPDMAUDIOSTREAMCFG pCfg) 2407 2437 { 2408 PDMAUDIOCALLBACK_FN pfnCallback;2409 2438 PAUDMIXSINK pSink; 2410 2439 … … 2413 2442 # ifdef VBOX_WITH_HDA_MIC_IN 2414 2443 case PDMAUDIORECSOURCE_MIC: 2415 pfnCallback = hdaMicInputCallback;2416 2444 pSink = pThis->pSinkMicIn; 2417 2445 break; 2418 2446 # endif 2419 2447 case PDMAUDIORECSOURCE_LINE_IN: 2420 pfnCallback = hdaLineInputCallback;2421 2448 pSink = pThis->pSinkLineIn; 2422 2449 break; … … 2429 2456 char *pszDesc; 2430 2457 2431 Assert(pThis->cLUNs);2432 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)2433 { 2434 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", lun, pszName) <= 0)2458 PHDADRIVER pDrv; 2459 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2460 { 2461 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0) 2435 2462 { 2436 2463 rc = VERR_NO_MEMORY; … … 2438 2465 } 2439 2466 2440 PHDADRIVER pDrv = pThis->paDrv[lun];2441 2467 rc = pDrv->pConnector->pfnOpenIn(pDrv->pConnector, 2442 2468 pszDesc, enmRecSource, 2443 pfnCallback /* fnCallback */, pDrv/* pvCallback */,2469 NULL /* fnCallback */, NULL /* pvCallback */, 2444 2470 pCfg, 2445 &pDrv-> pStrmIn);2446 LogFlowFunc(("LUN#%RU8: Opened input \"%s\", with rc=%Rrc\n", lun, pszDesc, rc));2471 &pDrv->LineIn.pStrmIn); 2472 LogFlowFunc(("LUN#%RU8: Opened input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc)); 2447 2473 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */ 2448 2474 { 2449 audioMixerRemoveStream(pSink, pDrv-> phStrmIn);2475 audioMixerRemoveStream(pSink, pDrv->LineIn.phStrmIn); 2450 2476 rc = audioMixerAddStreamIn(pSink, 2451 pDrv->pConnector, pDrv-> pStrmIn,2452 0 /* uFlags */, &pDrv-> phStrmIn);2477 pDrv->pConnector, pDrv->LineIn.pStrmIn, 2478 0 /* uFlags */, &pDrv->LineIn.phStrmIn); 2453 2479 } 2454 2480 … … 2463 2489 const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 2464 2490 { 2465 int rc; 2466 2467 Assert(pThis->cLUNs); 2468 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 2469 { 2470 PHDADRIVER pDrv = pThis->paDrv[lun]; 2471 rc = pDrv->pConnector->pfnOpenOut(pDrv->pConnector, pszName, 2472 hdaOutputCallback /* fnCallback */, pDrv /* pvCallback */, 2473 pCfg, 2474 &pDrv->pGstStrmOut); 2491 int rc = VINF_SUCCESS; 2492 2493 PHDADRIVER pDrv; 2494 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2495 { 2496 int rc2 = pDrv->pConnector->pfnOpenOut(pDrv->pConnector, pszName, 2497 NULL /* fnCallback */, pDrv /* pvCallback */, 2498 pCfg, 2499 &pDrv->Out.pStrmOut); 2500 if (RT_FAILURE(rc2)) 2501 { 2502 LogFunc(("LUN#%RU8: Opening stream \"%s\" failed, rc=%Rrc\n", pDrv->uLUN, pszName, rc2)); 2503 if (RT_SUCCESS(rc)) 2504 rc = rc2; 2505 /* Keep going. */ 2506 } 2475 2507 } 2476 2508 … … 2482 2514 bool fMute, uint8_t uVolLeft, uint8_t uVolRight) 2483 2515 { 2484 int rc; 2485 2486 Assert(pThis->cLUNs); 2487 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 2488 { 2489 PHDADRIVER pDrv = pThis->paDrv[lun]; 2490 rc = pDrv->pConnector->pfnSetVolume(pDrv->pConnector, 2491 fMute, uVolLeft, uVolRight); 2516 int rc = VINF_SUCCESS; 2517 2518 PHDADRIVER pDrv; 2519 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2520 { 2521 int rc2 = pDrv->pConnector->pfnSetVolume(pDrv->pConnector, 2522 fMute, uVolLeft, uVolRight); 2523 if (RT_FAILURE(rc2)) 2524 { 2525 LogFunc(("Failed for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2)); 2526 if (RT_SUCCESS(rc)) 2527 rc = rc2; 2528 /* Keep going. */ 2529 } 2492 2530 } 2493 2531 … … 2498 2536 2499 2537 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2500 static DECLCALLBACK(void) hdaTransfer(PHDADRIVER pDrv, 2501 ENMSOUNDSOURCE enmSrc, uint32_t cbAvail) 2502 { 2503 AssertPtrReturnVoid(pDrv); 2504 PHDASTATE pThis = pDrv->pHDAState; 2505 2506 LogFlowFunc(("pDrv=%p (LUN #%RU8), enmSrc=%ld, cbAvail=%RU32\n", 2507 pDrv, pDrv->uLUN, enmSrc, cbAvail)); 2538 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 2539 { 2540 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 2541 AssertPtr(pThis); 2542 2543 STAM_PROFILE_START(&pThis->StatTimer, a); 2544 2545 int rc = VINF_SUCCESS; 2546 2547 uint32_t cbInMax = 0; 2548 uint32_t cbOutMin = UINT32_MAX; 2549 2550 PHDADRIVER pDrv; 2551 uint32_t cbIn, cbOut; 2552 #ifdef DEBUG_LUN 2553 uint8_t uLUN = 0; 2554 #endif 2555 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2556 { 2557 if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut)) 2558 continue; 2559 2560 rc = pDrv->pConnector->pfnQueryData(pDrv->pConnector, /** @todo Rename QueryStatus */ 2561 &cbIn, &cbOut, &pDrv->cSamplesLive); 2562 if (RT_SUCCESS(rc)) 2563 { 2564 #ifdef DEBUG_LUN 2565 LogFlowFunc(("\tLUN#%RU8: cbIn=%RU32, cbOut=%RU32\n", uLUN, cbIn, cbOut)); 2566 #endif 2567 cbInMax = RT_MAX(cbInMax, cbIn); 2568 cbOutMin = RT_MIN(cbOutMin, cbOut); 2569 } 2570 else 2571 pDrv->cSamplesLive = 0; 2572 2573 #ifdef DEBUG_LUN 2574 uLUN++; 2575 #endif 2576 } 2577 2578 /* 2579 * Playback. 2580 */ 2581 if (cbOutMin) 2582 { 2583 Assert(cbOutMin != UINT32_MAX); 2584 hdaTransfer(pThis, PO_INDEX, cbOutMin); /** @todo Add rc! */ 2585 } 2586 else 2587 { 2588 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 2589 { 2590 if (pDrv->cSamplesLive) 2591 pDrv->pConnector->pfnPlayOut(pDrv->pConnector); 2592 } 2593 } 2594 2595 /* 2596 * Recording. 2597 */ 2598 if (cbInMax) 2599 hdaTransfer(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */ 2600 2601 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 2602 2603 STAM_PROFILE_STOP(&pThis->StatTimer, a); 2604 } 2605 2606 static DECLCALLBACK(int) hdaTransfer(PHDASTATE pThis, 2607 ENMSOUNDSOURCE enmSrc, uint32_t cbAvail) 2608 { 2609 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2610 2611 LogFlowFunc(("pThis=%p, cbAvail=%RU32\n", pThis, cbAvail)); 2508 2612 #else 2509 static DECLCALLBACK( void) hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSrc, int cbAvail)2510 { 2511 AssertPtrReturnVoid(pCodec );2613 static DECLCALLBACK(int) hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSrc, int cbAvail) 2614 { 2615 AssertPtrReturnVoid(pCodec, VERR_INVALID_POINTER); 2512 2616 PHDASTATE pThis = pCodec->pHDAState; 2617 AssertPtrReturnVoid(pThis, VERR_INVALID_POINTER); 2513 2618 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2619 int rc; 2620 2514 2621 uint8_t u8Strm; 2515 2622 PHDABDLEDESC pBdle; … … 2541 2648 default: 2542 2649 AssertMsgFailed(("Unknown source index %ld\n", enmSrc)); 2543 return ;2650 return VERR_NOT_SUPPORTED; 2544 2651 } 2545 2652 … … 2547 2654 hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc); 2548 2655 2549 bool fStop = false; 2550 while (cbAvail && !fStop) 2656 while (cbAvail) 2551 2657 { 2552 2658 Assert( (StreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)) … … 2568 2674 PAUDMIXSINK pSink; 2569 2675 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2570 uint32_t cb ;2676 uint32_t cbWritten; 2571 2677 switch (enmSrc) 2572 2678 { … … 2574 2680 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2575 2681 pSink = pThis->pSinkLineIn; 2576 cb = hdaReadAudio(pThis, pSink, pBdle, &StreamDesc, &cbAvail, &fStop, u32CblLimit);2682 rc = hdaReadAudio(pThis, pSink, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten); 2577 2683 #else 2578 cb = hdaReadAudio(pThis, &StreamDesc, (uint32_t *)&cbAvail, &fStop, u32CblLimit);2684 rc = hdaReadAudio(pThis, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten); 2579 2685 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2580 2686 break; 2581 2687 case PO_INDEX: 2582 2688 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 2583 cb = hdaWriteAudio(pThis, &StreamDesc, &cbAvail, &fStop, u32CblLimit);2689 rc = hdaWriteAudio(pThis, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten); 2584 2690 #else 2585 cb = hdaWriteAudio(pThis, &StreamDesc, (uint32_t *)&cbAvail, &fStop, u32CblLimit);2691 rc = hdaWriteAudio(pThis, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten); 2586 2692 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2587 2693 break; … … 2590 2696 case MC_INDEX: 2591 2697 pSink = pThis->pSinkMicIn; 2592 cb = hdaReadAudio(pThis, pSink, pBdle, &StreamDesc, &cbAvail, &fStop, u32CblLimit);2698 rc = hdaReadAudio(pThis, pSink, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten); 2593 2699 break; 2594 2700 # endif 2595 2701 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 2596 2702 default: 2597 cb = 0; 2598 fStop = true; 2599 AssertMsgFailedReturnVoid(("Unsupported source index %d\n", enmSrc)); 2703 AssertMsgFailed(("Unsupported source index %ld\n", enmSrc)); 2704 rc = VERR_NOT_SUPPORTED; 2600 2705 break; 2601 2706 } 2602 Assert(cb <= StreamDesc.u32Fifos + 1);2707 Assert(cbWritten <= StreamDesc.u32Fifos + 1); 2603 2708 *StreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY); 2604 2709 2605 2710 /* Process end of buffer condition. */ 2606 hdaStreamCounterUpdate(pThis, pBdle, &StreamDesc, cb); 2607 fStop = !fStop ? !hdaDoNextTransferCycle(pThis, pBdle, &StreamDesc) : fStop; 2608 } 2711 hdaStreamCounterUpdate(pThis, pBdle, &StreamDesc, cbWritten); 2712 2713 if ( !hdaDoNextTransferCycle(pThis, pBdle, &StreamDesc) 2714 || RT_FAILURE(rc)) 2715 { 2716 if (rc == VERR_NO_DATA) /* No more data to process. */ 2717 rc = VINF_SUCCESS; 2718 2719 break; 2720 } 2721 } 2722 2723 return rc; 2609 2724 } 2610 2725 #endif /* IN_RING3 */ … … 2871 2986 else 2872 2987 { 2873 LogRel((" Invalid write access @0x%x!\n", offReg));2988 LogRel(("HDA: Invalid write access @0x%x!\n", offReg)); 2874 2989 cbReg = 1; 2875 2990 } … … 3016 3131 { 3017 3132 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 3133 3018 3134 /* Save Codec nodes states */ 3019 #if 03020 /** @todo Handle LUNs > 0! */3021 hdaCodecSaveState(pThis->pCodec[0], pSSM);3022 #else3023 3135 hdaCodecSaveState(pThis->pCodec, pSSM); 3024 #endif3025 3136 3026 3137 /* Save MMIO registers */ … … 3049 3160 * Load Codec nodes states. 3050 3161 */ 3051 #if 03052 /** @todo Handle LUNs > 0! */3053 int rc = hdaCodecLoadState(pThis->pCodec[0], pSSM, uVersion);3054 #else3055 3162 int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion); 3056 #endif3057 3163 if (RT_FAILURE(rc)) 3058 3164 return rc; … … 3119 3225 */ 3120 3226 bool fEnableIn = RT_BOOL(SDCTL(pThis, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 3227 #ifdef VBOX_WITH_HDA_MIC_IN 3121 3228 bool fEnableMicIn = RT_BOOL(SDCTL(pThis, 2) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 3229 #endif 3122 3230 bool fEnableOut = RT_BOOL(SDCTL(pThis, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)); 3123 3231 3124 3232 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 3125 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 3126 { 3127 rc = pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmIn, 3128 fEnableIn); 3233 PHDADRIVER pDrv; 3234 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3235 { 3236 rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, 3237 fEnableIn); 3129 3238 if (RT_FAILURE(rc)) 3130 3239 break; 3131 rc = pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmMic, 3132 fEnableMicIn); 3240 # ifdef VBOX_WITH_HDA_MIC_IN 3241 rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, 3242 fEnableMicIn); 3133 3243 if (RT_FAILURE(rc)) 3134 3244 break; 3135 rc = pThis->paDrv[lun]->pConnector->pfnEnableOut(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pGstStrmOut, 3136 fEnableOut); 3245 # endif 3246 rc = pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, 3247 fEnableOut); 3137 3248 if (RT_FAILURE(rc)) 3138 3249 break; … … 3315 3426 } 3316 3427 3428 3317 3429 /** 3318 3430 * @callback_method_impl{FNDBGFHANDLERDEV} … … 3321 3433 { 3322 3434 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 3323 #if 0 3324 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 3325 { 3326 if (pThis->pCodec[lun]->pfnCodecDbgListNodes) 3327 pThis->pCodec[lun]->pfnCodecDbgListNodes(pThis->pCodec[lun], pHlp, pszArgs); 3328 else 3329 pHlp->pfnPrintf(pHlp, "Codec implementation for LUN #%RU8 doesn't provide corresponding callback\n", lun); 3330 } 3331 #else 3435 3332 3436 if (pThis->pCodec->pfnCodecDbgListNodes) 3333 3437 pThis->pCodec->pfnCodecDbgListNodes(pThis->pCodec, pHlp, pszArgs); 3334 3438 else 3335 3439 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n"); 3336 #endif3337 3440 } 3338 3441 … … 3344 3447 { 3345 3448 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 3346 #if 0 3347 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++) 3348 { 3349 if (pThis->pCodec[lun]->pfnCodecDbgSelector) 3350 pThis->pCodec[lun]->pfnCodecDbgSelector(pThis->pCodec[lun], pHlp, pszArgs); 3351 else 3352 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n"); 3353 } 3354 #else 3449 3355 3450 if (pThis->pCodec->pfnCodecDbgSelector) 3356 3451 pThis->pCodec->pfnCodecDbgSelector(pThis->pCodec, pHlp, pszArgs); 3357 3452 else 3358 3453 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n"); 3359 #endif3360 3454 } 3361 3455 … … 3404 3498 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 3405 3499 /* Stop any audio currently playing. */ 3406 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)3407 {3408 pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmIn,3409 3500 PHDADRIVER pDrv; 3501 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node) 3502 { 3503 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, false /* Disable */); 3410 3504 /* Ignore rc. */ 3411 pThis->paDrv[lun]->pConnector->pfnEnableIn(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pStrmMic, 3412 false /* Disable */); 3505 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, false /* Disable */); 3413 3506 /* Ditto. */ 3414 pThis->paDrv[lun]->pConnector->pfnEnableOut(pThis->paDrv[lun]->pConnector, pThis->paDrv[lun]->pGstStrmOut, 3415 false /* Disable */); 3507 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, false /* Disable */); 3416 3508 /* Ditto. */ 3417 3509 } … … 3443 3535 if (u8Strm == 0) 3444 3536 pBdle = &pThis->StInBdle; 3537 # ifdef VBOX_WITH_HDA_MIC_IN 3445 3538 else if (u8Strm == 2) 3446 3539 pBdle = &pThis->StMicBdle; 3540 # endif 3447 3541 else if(u8Strm == 4) 3448 3542 pBdle = &pThis->StOutBdle; … … 3458 3552 } 3459 3553 3460 /* emulation of codec "wake up" (HDA spec 5.5.1 and 6.5)*/3554 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */ 3461 3555 HDA_REG(pThis, STATESTS) = 0x1; 3462 3556 3463 Log Func(("Reset finished\n"));3557 LogRel(("HDA: Reset\n")); 3464 3558 } 3465 3559 … … 3471 3565 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 3472 3566 3567 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 3568 PHDADRIVER pDrv; 3569 while (!RTListIsEmpty(&pThis->lstDrv)) 3570 { 3571 pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node); 3572 3573 RTListNodeRemove(&pDrv->Node); 3574 RTMemFree(pDrv); 3575 } 3576 3577 if (pThis->pMixer) 3578 { 3579 audioMixerDestroy(pThis->pMixer); 3580 pThis->pMixer = NULL; 3581 } 3582 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */ 3583 3473 3584 if (pThis->pCodec) 3474 3585 { … … 3479 3590 pThis->pCodec = NULL; 3480 3591 } 3481 3482 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER3483 for (uint8_t lun = 0; lun < pThis->cLUNs; lun++)3484 {3485 if (pThis->paDrv[lun])3486 {3487 RTMemFree(pThis->paDrv[lun]);3488 pThis->paDrv[lun] = NULL;3489 }3490 }3491 3492 if (pThis->pMixer)3493 {3494 audioMixerDestroy(pThis->pMixer);3495 pThis->pMixer = NULL;3496 }3497 3498 pThis->cLUNs = 0;3499 #else3500 if (pThis->pCodec)3501 {3502 int rc = hdaCodecDestruct(pThis->pCodec);3503 AssertRC(rc);3504 3505 RTMemFree(pThis->pCodec);3506 pThis->pCodec = NULL;3507 }3508 #endif /* VBOX_WITH_PDM_AUDIO_DRIVER */3509 3592 3510 3593 RTMemFree(pThis->pu32CorbBuf); … … 3542 3625 */ 3543 3626 char *pszDesc = NULL; 3544 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN 3627 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0) 3545 3628 AssertMsgReturn(pszDesc, 3546 3629 ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN), … … 3556 3639 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR); 3557 3640 AssertMsg(pDrv->pConnector != NULL, 3558 ("Configuration error: LUN 3641 ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", 3559 3642 uLUN, rc)); 3560 3643 pDrv->pHDAState = pThis; 3561 pDrv->uLUN = uLUN;3644 pDrv->uLUN = uLUN; 3562 3645 3563 3646 /* … … 3568 3651 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY; 3569 3652 3570 LogFunc(("LUN #%u: pCon=%p, drvFlags=0x%x\n", 3571 uLUN, pDrv->pConnector, pDrv->Flags)); 3572 3573 pThis->paDrv[uLUN] = pDrv; 3574 pThis->cLUNs++; 3653 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags)); 3654 3655 /* Attach to driver list. */ 3656 RTListAppend(&pThis->lstDrv, &pDrv->Node); 3575 3657 } 3576 3658 else 3577 3659 rc = VERR_NO_MEMORY; 3578 3660 } 3579 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 3661 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER 3662 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) 3580 3663 { 3581 3664 LogFunc(("No attached driver for LUN #%u\n", uLUN)); … … 3587 3670 RTStrFree(pszDesc); 3588 3671 3589 LogFunc((" iLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));3672 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc)); 3590 3673 return rc; 3591 3674 } … … 3741 3824 3742 3825 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 3743 /* We support 32 LUNs max. This should be enough for now. */ 3744 for (uint8_t lun = 0; lun < 32 ; lun++) 3745 { 3746 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", lun)); 3747 rc = hdaAttach(pDevIns, lun, PDM_TACH_FLAGS_NOT_HOT_PLUG); 3826 RTListInit(&pThis->lstDrv); 3827 3828 unsigned uLUN = 0; 3829 do 3830 { 3831 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN)); 3832 rc = hdaAttach(pDevIns, uLUN++, PDM_TACH_FLAGS_NOT_HOT_PLUG); 3748 3833 if (RT_FAILURE(rc)) 3749 3834 { 3750 3835 if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 3751 3836 rc = VINF_SUCCESS; 3837 3752 3838 break; 3753 3839 } 3754 } 3840 3841 } while (RT_SUCCESS(rc)); 3755 3842 3756 3843 if (RT_SUCCESS(rc)) … … 3780 3867 } 3781 3868 3782 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", pThis->cLUNs, rc));3869 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc)); 3783 3870 #else 3784 3871 /* … … 3825 3912 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */ 3826 3913 3914 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER 3827 3915 pThis->pCodec->pfnTransfer = hdaTransfer; 3828 pThis->pCodec->pfnReset = hdaCodecReset; 3916 #endif 3917 pThis->pCodec->pfnReset = hdaCodecReset; 3829 3918 } 3830 3919 … … 3903 3992 #endif 3904 3993 3905 /* The final entry is a full dword, no gaps! Allows shortcuts. */3994 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */ 3906 3995 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0, 3907 3996 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size)); 3908 3997 } 3909 3998 } 3999 4000 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER 4001 if (RT_SUCCESS(rc)) 4002 { 4003 /* Start the emulation timer. */ 4004 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis, 4005 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchHda", &pThis->pTimer); 4006 AssertRCReturn(rc, rc); 4007 4008 if (RT_SUCCESS(rc)) 4009 { 4010 /** @todo Investigate why sounds is getting corrupted if the "ticks" value is too 4011 * low, e.g. "PDMDevHlpTMTimeVirtGetFreq / 200". */ 4012 pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */ 4013 if (pThis->uTicks < 100) 4014 pThis->uTicks = 100; 4015 LogFunc(("Timer ticks=%RU64\n", pThis->uTicks)); 4016 4017 /* Fire off timer. */ 4018 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 4019 } 4020 } 4021 4022 # ifdef VBOX_WITH_STATISTICS 4023 if (RT_SUCCESS(rc)) 4024 { 4025 /* 4026 * Register statistics. 4027 */ 4028 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer."); 4029 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation."); 4030 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation."); 4031 } 4032 # endif 4033 4034 #endif 3910 4035 3911 4036 LogFlowFuncLeaveRC(rc); -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r53624 r53830 884 884 } 885 885 886 LogFlowFunc((" pvBuf=%p, cbBuf=%zu, cWritten=%RU32 (%zubytes), cMixed=%RU32, rc=%Rrc\n",886 LogFlowFunc(("Written pvBuf=%p, cbBuf=%zu, cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n", 887 887 pvBuf, cbBuf, cWritten, AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cWritten), 888 888 cMixed, rc)); … … 984 984 } 985 985 986 static int drvAudioPlayOut(PDRVAUDIO pThis) 987 { 986 static DECLCALLBACK(int) drvAudioQueryData(PPDMIAUDIOCONNECTOR pInterface, 987 uint32_t *pcbAvailIn, uint32_t *pcbFreeOut, 988 uint32_t *pcSamplesLive) 989 { 990 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 991 992 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 993 994 int rc = VINF_SUCCESS; 995 uint32_t cSamplesLive = 0; 996 988 997 /* 989 * P rocess all enabled host output streams.998 * Playback. 990 999 */ 1000 uint32_t cbFreeOut = UINT32_MAX; 1001 991 1002 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 992 1003 while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut))) 993 1004 { 994 1005 uint32_t cStreamsLive; 995 uint32_tcSamplesLive = drvAudioHstOutSamplesLive(pHstStrmOut, &cStreamsLive);1006 cSamplesLive = drvAudioHstOutSamplesLive(pHstStrmOut, &cStreamsLive); 996 1007 if (!cStreamsLive) 997 1008 cSamplesLive = 0; … … 1009 1020 pHstStrmOut->fEnabled = false; 1010 1021 pHstStrmOut->fPendingDisable = false; 1022 1023 LogFunc(("%p: Disabling stream\n", pHstStrmOut)); 1011 1024 } 1012 1025 else 1013 LogFlowFunc(("Backend vetoed closing output stream, rc=%Rrc\n", rc2)); 1026 LogFunc(("%p: Backend vetoed against closing output stream, rc=%Rrc\n", 1027 pHstStrmOut, rc2)); 1014 1028 1015 1029 continue; 1016 1030 } 1031 1032 LogFlowFunc(("%p: Has %RU32 live samples\n", pHstStrmOut, cSamplesLive)); 1017 1033 1018 1034 /* … … 1026 1042 if (!cSamplesLive) 1027 1043 { 1028 LogFlowFunc(("No live samples available\n")); 1029 1030 uint32_t cbFree; 1044 uint32_t cbFree2 = UINT32_MAX; 1031 1045 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 1032 1046 { … … 1035 1049 /* Tell the sound device emulation how many samples are free 1036 1050 * so that it can start writing PCM data to us. */ 1037 cbFree = AUDIOMIXBUF_S2B_RATIO(&pGstStrmOut->MixBuf, 1038 audioMixBufFree(&pGstStrmOut->MixBuf)); 1039 if (cbFree) 1040 { 1041 LogFlowFunc(("cbFree=%RU32\n", cbFree)); 1042 pGstStrmOut->Callback.fn(pGstStrmOut->Callback.pvContext, cbFree); 1043 } 1051 cbFree2 = RT_MIN(cbFree2, AUDIOMIXBUF_S2B_RATIO(&pGstStrmOut->MixBuf, 1052 audioMixBufFree(&pGstStrmOut->MixBuf))); 1044 1053 } 1045 1054 } 1055 1056 cbFreeOut = RT_MIN(cbFreeOut, cbFree2); 1057 continue; 1058 } 1059 } 1060 1061 /* 1062 * Recording. 1063 */ 1064 uint32_t cbAvailIn = 0; 1065 1066 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 1067 while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn))) 1068 { 1069 /* Call the host backend to capture the audio input data. */ 1070 uint32_t cSamplesCaptured; 1071 int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn, 1072 &cSamplesCaptured); 1073 if (RT_FAILURE(rc2)) 1074 continue; 1075 1076 PPDMAUDIOGSTSTRMIN pGstStrmIn = pHstStrmIn->pGstStrmIn; 1077 AssertPtrBreak(pGstStrmIn); 1078 1079 if (pGstStrmIn->State.fActive) 1080 { 1081 cbAvailIn = RT_MAX(cbAvailIn, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, 1082 audioMixBufMixed(&pHstStrmIn->MixBuf))); 1083 } 1084 } 1085 1086 if (RT_SUCCESS(rc)) 1087 { 1088 if (cbFreeOut == UINT32_MAX) 1089 cbFreeOut = 0; 1090 1091 if (pcbAvailIn) 1092 *pcbAvailIn = cbAvailIn; 1093 1094 if (pcbFreeOut) 1095 *pcbFreeOut = cbFreeOut; 1096 1097 if (pcSamplesLive) 1098 *pcSamplesLive = cSamplesLive; 1099 } 1100 1101 return rc; 1102 } 1103 1104 static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface) 1105 { 1106 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1107 /* pcbFree is optional. */ 1108 1109 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1110 1111 int rc = VINF_SUCCESS; 1112 1113 /* 1114 * Process all enabled host output streams. 1115 */ 1116 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 1117 while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut))) 1118 { 1119 uint32_t cStreamsLive; 1120 uint32_t cSamplesLive = drvAudioHstOutSamplesLive(pHstStrmOut, &cStreamsLive); 1121 if (!cStreamsLive) 1122 cSamplesLive = 0; 1123 1124 /* Has this stream marked as disabled but there still were guest streams relying 1125 * on it? Check if this stream now can be closed and do so, if possible. */ 1126 if ( pHstStrmOut->fPendingDisable 1127 && !cStreamsLive) 1128 { 1129 /* Stop playing the current (pending) stream. */ 1130 int rc2 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, 1131 PDMAUDIOSTREAMCMD_DISABLE); 1132 if (RT_SUCCESS(rc2)) 1133 { 1134 pHstStrmOut->fEnabled = false; 1135 pHstStrmOut->fPendingDisable = false; 1136 1137 LogFunc(("\t%p: Disabling stream\n", pHstStrmOut)); 1138 } 1139 else 1140 LogFunc(("\t%p: Backend vetoed against closing output stream, rc=%Rrc\n", 1141 rc2, pHstStrmOut)); 1046 1142 1047 1143 continue; … … 1051 1147 int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, 1052 1148 &cSamplesPlayed); 1053 LogFlowFunc((" %p: cStreamsLive=%RU32, cSamplesLive=%RU32, cSamplesPlayed=%RU32, rc=%Rrc\n",1149 LogFlowFunc(("\t%p: cStreamsLive=%RU32, cSamplesLive=%RU32, cSamplesPlayed=%RU32, rc=%Rrc\n", 1054 1150 pHstStrmOut, cStreamsLive, cSamplesLive, cSamplesPlayed, rc2)); 1055 1151 1056 1152 bool fNeedsCleanup = false; 1057 uint32_t cbFree; 1153 1154 PPDMAUDIOGSTSTRMOUT pGstStrmOut; 1058 1155 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 1059 1156 { … … 1068 1165 && !pGstStrmOut->Callback.fn; 1069 1166 } 1070 1071 if (pGstStrmOut->State.fActive)1072 {1073 /* Tell the device emulation how many samples are free so that it can start1074 * writing PCM data to us. */1075 cbFree = AUDIOMIXBUF_S2B_RATIO(&pGstStrmOut->MixBuf,1076 audioMixBufFree(&pGstStrmOut->MixBuf));1077 if (cbFree)1078 {1079 LogFlowFunc(("cbFree=%RU32\n", cbFree));1080 pGstStrmOut->Callback.fn(pGstStrmOut->Callback.pvContext, cbFree);1081 }1082 }1083 1167 } 1084 1168 … … 1087 1171 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 1088 1172 { 1089 if ( !pGstStrmOut->State.fActive 1090 && !pGstStrmOut->Callback.fn) 1091 { 1173 if (!pGstStrmOut->State.fActive) 1092 1174 drvAudioDestroyGstOut(pThis, pGstStrmOut); 1093 }1094 1175 } 1095 1176 } 1096 1177 } 1097 1178 1098 return VINF_SUCCESS; 1099 } 1100 1101 /** 1102 * Notifies the device emulation of newly available (captured) host input data. 1103 * 1104 * @return IPRT status code. 1105 * @param pThis Pointer to audio driver instance. 1106 */ 1107 static int drvAudioSendIn(PDRVAUDIO pThis) 1108 { 1109 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1110 1111 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 1112 while ((pHstStrmIn = drvAudioFindNextEnabledHstIn(pThis, pHstStrmIn))) 1113 { 1114 /* Call the host backend to capture the audio input data. */ 1115 uint32_t cSamplesCaptured; 1116 int rc2 = pThis->pHostDrvAudio->pfnCaptureIn(pThis->pHostDrvAudio, pHstStrmIn, 1117 &cSamplesCaptured); 1118 if (RT_FAILURE(rc2)) 1119 continue; 1120 1121 PPDMAUDIOGSTSTRMIN pGstStrmIn = pHstStrmIn->pGstStrmIn; 1122 AssertPtrBreak(pGstStrmIn); 1123 1124 if (pGstStrmIn->State.fActive) 1125 { 1126 uint32_t cbData = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, 1127 audioMixBufMixed(&pHstStrmIn->MixBuf)); 1128 if (cbData) 1129 { 1130 /* 1131 * Tell the device emulation how many audio input bytes are available 1132 * to process (and to write to the device itself). 1133 */ 1134 LogFlowFunc(("cbData=%RU32\n", cbData)); 1135 pGstStrmIn->Callback.fn(pGstStrmIn->Callback.pvContext, cbData); 1136 } 1137 } 1138 } 1139 1140 return VINF_SUCCESS; 1141 } 1142 1143 static void drvAudioTimer(PDRVAUDIO pThis) 1144 { 1145 drvAudioPlayOut(pThis); 1146 drvAudioSendIn(pThis); 1147 1148 AssertPtr(pThis->pTimer); 1149 int rc = TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks); 1150 AssertRC(rc); 1179 return rc; 1151 1180 } 1152 1181 … … 1255 1284 } 1256 1285 1257 static DECLCALLBACK(void) drvAudioTimerHelper(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)1258 {1259 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);1260 drvAudioTimer(pThis);1261 }1262 1263 1286 static struct audio_option audio_options[] = 1264 1287 { … … 1316 1339 RTListInit(&pThis->lstHstStrmOut); 1317 1340 1318 int rc ;1341 int rc = VINF_SUCCESS; 1319 1342 1320 1343 /* Get the configuration data from the selected backend (if available). */ … … 1322 1345 if (RT_LIKELY(pThis->pHostDrvAudio->pfnGetConf)) 1323 1346 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg); 1324 else1325 AssertMsgFailed(("No audio backend configuration given\n"));1326 1347 1327 1348 if (RT_SUCCESS(rc)) 1328 1349 { 1329 LogFlowFunc(("Creating timer ...\n")); 1330 rc = PDMDrvHlpTMTimerCreate(pDrvIns, TMCLOCK_VIRTUAL, drvAudioTimerHelper, 1331 pThis, TMTIMER_FLAGS_DEFAULT_CRIT_SECT, 1332 "Audio emulation timer", &pThis->pTimer); 1333 if (RT_FAILURE(rc)) 1334 { 1335 LogFlowFunc(("Failed to create timer, rc=%Rrc\n", rc)); 1336 return rc; 1337 } 1338 } 1339 1340 rc = drvAudioProcessOptions(pCfgHandle, "AUDIO", audio_options); 1341 /** @todo Check for invalid options? */ 1342 1343 pThis->cFreeOutputStreams = conf.fixed_out.cStreams; 1344 pThis->cFreeInputStreams = conf.fixed_in.cStreams; 1345 1346 if (!pThis->cFreeOutputStreams) 1347 { 1348 LogFlowFunc(("Bogus number of playback voices %d, setting to 1\n", 1349 pThis->cFreeOutputStreams)); 1350 pThis->cFreeOutputStreams = 1; 1351 } 1352 1353 if (!pThis->cFreeInputStreams) 1354 { 1355 LogFlowFunc(("Bogus number of capture voices %d, setting to 1\n", 1356 pThis->cFreeInputStreams)); 1357 pThis->cFreeInputStreams = 1; 1358 } 1359 1360 /* Initialization of audio buffers. Create ring buffer of 768 each. */ 1361 rc = RTCircBufCreate(&pThis->pAudioWriteBuf, 768 * 1024); 1362 if (RT_SUCCESS(rc)) 1363 { 1364 /* Allocating space for about 500 msec of audio data 48KHz, 128 bit sample 1365 * (guest format - PDMHOSTSTEREOSAMPLE) and dual channel. 1366 */ 1367 rc = RTCircBufCreate(&pThis->pAudioReadBuf, 768 * 1024); 1350 rc = drvAudioProcessOptions(pCfgHandle, "AUDIO", audio_options); 1351 /** @todo Check for invalid options? */ 1352 1353 pThis->cFreeOutputStreams = conf.fixed_out.cStreams; 1354 pThis->cFreeInputStreams = conf.fixed_in.cStreams; 1355 1356 if (!pThis->cFreeOutputStreams) 1357 pThis->cFreeOutputStreams = 1; 1358 1359 if (!pThis->cFreeInputStreams) 1360 pThis->cFreeInputStreams = 1; 1368 1361 } 1369 1362 … … 1374 1367 rc = drvAudioHostInit(pCfgHandle, pThis); 1375 1368 1376 if (RT_SUCCESS(rc))1377 {1378 if (conf.period.hz <= 0)1379 pThis->uTicks = 100; /* Don't stress CPU too much. */1380 else1381 pThis->uTicks = PDMDrvHlpTMGetVirtualFreq(pDrvIns) / conf.period.hz;1382 }1383 1384 if ( RT_SUCCESS(rc)1385 && pThis->pTimer)1386 {1387 LogFlowFunc(("Timer ticks=%RU64, hz=%d\n", pThis->uTicks, conf.period.hz));1388 1389 /* Fire off timer. */1390 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);1391 }1392 else1393 {1394 if (pThis->pTimer)1395 TMR3TimerDestroy(pThis->pTimer);1396 }1397 1398 1369 LogFlowFuncLeaveRC(rc); 1399 1370 return rc; … … 1404 1375 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1405 1376 NOREF(pThis); 1377 1378 LogRel(("Audio: Using NULL driver; no sound will be audible\n")); 1406 1379 1407 1380 /* Nothing to do here yet. */ … … 1862 1835 pDrvIns->IBase.pfnQueryInterface = drvAudioQueryInterface; 1863 1836 /* IAudio. */ 1837 pThis->IAudioConnector.pfnQueryData = drvAudioQueryData; 1864 1838 pThis->IAudioConnector.pfnRead = drvAudioRead; 1865 1839 pThis->IAudioConnector.pfnWrite = drvAudioWrite; … … 1875 1849 pThis->IAudioConnector.pfnOpenIn = drvAudioOpenIn; 1876 1850 pThis->IAudioConnector.pfnOpenOut = drvAudioOpenOut; 1851 pThis->IAudioConnector.pfnPlayOut = drvAudioPlayOut; 1877 1852 pThis->IAudioConnector.pfnIsActiveIn = drvAudioIsActiveIn; 1878 1853 pThis->IAudioConnector.pfnIsActiveOut = drvAudioIsActiveOut;
Note:
See TracChangeset
for help on using the changeset viewer.