VirtualBox

Changeset 82228 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Nov 26, 2019 8:58:08 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
135043
Message:

DevHDA,DevIchAc97,DevSB16: Don't stop attaching LUNs/drivers on VERR_AUDIO_BACKEND_INIT_FAILED, only on VERR_PDM_NO_ATTACHED_DRIVER or after 255 LUNs. Use new device helper for reconfguring a LUN to use the 'NullAudio' driver. bugref:9218

Location:
trunk/src/VBox/Devices/Audio
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHDA.cpp

    r81591 r82228  
    46574657}
    46584658
    4659 
    4660 /**
    4661  * Re-attaches (replaces) a driver with a new driver.
    4662  *
    4663  * This is only used by to attach the Null driver when it failed to attach the
    4664  * one that was configured.
     4659/**
     4660 * Replaces a driver with a the NullAudio drivers.
    46654661 *
    46664662 * @returns VBox status code.
    4667  * @param   pThis       Device instance to re-attach driver to.
    4668  * @param   pDrv        Driver instance used for attaching to.
    4669  *                      If NULL is specified, a new driver will be created and appended
    4670  *                      to the driver list.
    4671  * @param   uLUN        The logical unit which is being re-detached.
    4672  * @param   pszDriver   New driver name to attach.
    4673  */
    4674 static int hdaR3ReattachInternal(PHDASTATE pThis, PHDADRIVER pDrv, uint8_t uLUN, const char *pszDriver)
    4675 {
    4676     AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
    4677     AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
    4678 
    4679     int rc;
    4680 
    4681     if (pDrv)
    4682     {
    4683         rc = hdaR3DetachInternal(pThis, pDrv, 0 /* fFlags */);
    4684         if (RT_SUCCESS(rc))
    4685             rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
    4686 
    4687         if (RT_FAILURE(rc))
    4688             return rc;
    4689 
    4690         pDrv = NULL;
    4691     }
    4692 
    4693     PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
    4694     PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
    4695     PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/hda/0/");
    4696 
    4697     /* Remove LUN branch. */
    4698     CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
    4699 
    4700 #define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
    4701 
    4702     do
    4703     {
    4704         PCFGMNODE pLunL0;
    4705         rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN);        RC_CHECK();
    4706         rc = CFGMR3InsertString(pLunL0, "Driver",       "AUDIO");       RC_CHECK();
    4707         rc = CFGMR3InsertNode(pLunL0,   "Config/",       NULL);         RC_CHECK();
    4708 
    4709         PCFGMNODE pLunL1, pLunL2;
    4710         rc = CFGMR3InsertNode  (pLunL0, "AttachedDriver/", &pLunL1);    RC_CHECK();
    4711         rc = CFGMR3InsertNode  (pLunL1,  "Config/",        &pLunL2);    RC_CHECK();
    4712         rc = CFGMR3InsertString(pLunL1,  "Driver",          pszDriver); RC_CHECK();
    4713 
    4714         rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver);      RC_CHECK();
    4715 
    4716     } while (0);
    4717 
     4663 * @param   pThis       Device instance.
     4664 * @param   iLun        The logical unit which is being replaced.
     4665 */
     4666static int hdaR3ReconfigLunWithNullAudio(PHDASTATE pThis, unsigned iLun)
     4667{
     4668    int rc = PDMDevHlpDriverReconfigure2(pThis->pDevInsR3, iLun, "AUDIO", "NullAudio");
    47184669    if (RT_SUCCESS(rc))
    4719         rc = hdaR3AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    4720 
    4721     LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
    4722 
    4723 #undef RC_CHECK
    4724 
     4670        rc = hdaR3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4671    LogFunc(("pThis=%p, iLun=%u, rc=%Rrc\n", pThis, iLun, rc));
    47254672    return rc;
    47264673}
     
    50014948#endif
    50024949
    5003     uint8_t uLUN;
    5004     for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
    5005     {
    5006         LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
    5007         rc = hdaR3AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    5008         if (RT_FAILURE(rc))
    5009         {
    5010             if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    5011                 rc = VINF_SUCCESS;
    5012             else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
    5013             {
    5014                 hdaR3ReattachInternal(pThis, NULL /* pDrv */, uLUN, "NullAudio");
    5015                 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    5016                                            N_("Host audio backend initialization has failed. "
    5017                                               "Selecting the NULL audio backend with the consequence that no sound is audible"));
    5018                 /* Attaching to the NULL audio backend will never fail. */
    5019                 rc = VINF_SUCCESS;
    5020             }
    5021             else
    5022                 AssertRCReturn(rc, rc);
     4950    /*
     4951     * Attach drivers.  We ASSUME they are configured consecutively without any
     4952     * gaps, so we stop when we hit the first LUN w/o a driver configured.
     4953     */
     4954    for (unsigned iLun = 0; ; iLun++)
     4955    {
     4956        AssertBreak(iLun < UINT8_MAX);
     4957        LogFunc(("Trying to attach driver for LUN#%u ...\n", iLun));
     4958        rc = hdaR3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4959        if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     4960        {
     4961            LogFunc(("cLUNs=%u\n", iLun));
    50234962            break;
    50244963        }
    5025     }
    5026 
    5027     LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
    5028 
     4964        if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
     4965        {
     4966            hdaR3ReconfigLunWithNullAudio(pThis, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
     4967            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4968                                       N_("Host audio backend initialization has failed. Selecting the NULL audio backend with the consequence that no sound is audible"));
     4969        }
     4970        else
     4971            AssertLogRelMsgReturn(RT_SUCCESS(rc),  ("LUN#%u: rc=%Rrc\n", iLun, rc), rc);
     4972    }
     4973
     4974    /*
     4975     * Create the mixer.
     4976     */
    50294977    rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer);
    50304978    AssertRCReturn(rc, rc);
     
    51565104        {
    51575105            LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
    5158 
    51595106            hdaR3Reset(pDevIns);
    5160             hdaR3ReattachInternal(pThis, pDrv, pDrv->uLUN, "NullAudio");
    5161 
     5107            hdaR3ReconfigLunWithNullAudio(pThis, pDrv->uLUN);
    51625108            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    51635109                                       N_("No audio devices could be opened. "
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r81591 r82228  
    451451    /** Driver flags. */
    452452    PDMAUDIODRVFLAGS                   fFlags;
    453     uint32_t                           PaddingFlags;
    454453    /** LUN # to which this driver has been assigned. */
    455454    uint8_t                            uLUN;
    456455    /** Whether this driver is in an attached state or not. */
    457456    bool                               fAttached;
    458     uint8_t                            Padding[4];
     457    uint8_t                            abPadding[2];
    459458    /** Pointer to the description string passed to PDMDevHlpDriverAttach(). */
    460459    R3PTRTYPE(char *)                  pszDesc;
     
    39013900 * @returns VBox status code.
    39023901 * @param   pThis       AC'97 state.
    3903  * @param   uLUN        The logical unit which is being attached.
     3902 * @param   iLun        The logical unit which is being attached.
    39043903 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    39053904 * @param   ppDrv       Attached driver instance on success. Optional.
    39063905 */
    3907 static int ichac97R3AttachInternal(PAC97STATE pThis, unsigned uLUN, uint32_t fFlags, PAC97DRIVER *ppDrv)
     3906static int ichac97R3AttachInternal(PAC97STATE pThis, unsigned iLun, uint32_t fFlags, PAC97DRIVER *ppDrv)
    39083907{
    39093908    RT_NOREF(fFlags);
     
    39133912     */
    39143913    char *pszDesc;
    3915     if (RTStrAPrintf(&pszDesc, "Audio driver port (AC'97) for LUN #%u", uLUN) <= 0)
     3914    if (RTStrAPrintf(&pszDesc, "Audio driver port (AC'97) for LUN #%u", iLun) <= 0)
    39163915        AssertLogRelFailedReturn(VERR_NO_MEMORY);
    39173916
    39183917    PPDMIBASE pDrvBase;
    3919     int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, uLUN,
    3920                                    &pThis->IBase, &pDrvBase, pszDesc);
     3918    int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, iLun, &pThis->IBase, &pDrvBase, pszDesc);
    39213919    if (RT_SUCCESS(rc))
    39223920    {
     
    39263924            pDrv->pDrvBase   = pDrvBase;
    39273925            pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
    3928             AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
     3926            AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", iLun, rc));
    39293927            pDrv->pAC97State = pThis;
    3930             pDrv->uLUN       = uLUN;
     3928            pDrv->uLUN       = iLun;
    39313929            pDrv->pszDesc    = pszDesc;
    39323930
     
    39353933             * host backend. This might change in the future.
    39363934             */
    3937             if (pDrv->uLUN == 0)
     3935            if (iLun == 0)
    39383936                pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
    39393937
    3940             LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
     3938            LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", iLun, pDrv->pConnector, pDrv->fFlags));
    39413939
    39423940            /* Attach to driver list if not attached yet. */
     
    39543952    }
    39553953    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    3956         LogFunc(("No attached driver for LUN #%u\n", uLUN));
     3954        LogFunc(("No attached driver for LUN #%u\n", iLun));
    39573955
    39583956    if (RT_FAILURE(rc))
     
    39633961    }
    39643962
    3965     LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
     3963    LogFunc(("iLun=%u, fFlags=0x%x, rc=%Rrc\n", iLun, fFlags, rc));
    39663964    return rc;
    39673965}
     
    40264024
    40274025/**
    4028  * @interface_method_impl{PDMDEVREG,pfnAttach}
    4029  */
    4030 static DECLCALLBACK(int) ichac97R3Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
     4026 * @interface_method_impl{PDMDEVREGR3,pfnAttach}
     4027 */
     4028static DECLCALLBACK(int) ichac97R3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    40314029{
    40324030    PAC97STATE pThis = PDMDEVINS_2_DATA(pDevIns, PAC97STATE);
    40334031
    4034     LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
     4032    LogFunc(("iLUN=%u, fFlags=0x%x\n", iLUN, fFlags));
    40354033
    40364034    DEVAC97_LOCK(pThis);
    40374035
    40384036    PAC97DRIVER pDrv;
    4039     int rc2 = ichac97R3AttachInternal(pThis, uLUN, fFlags, &pDrv);
     4037    int rc2 = ichac97R3AttachInternal(pThis, iLUN, fFlags, &pDrv);
    40404038    if (RT_SUCCESS(rc2))
    40414039        rc2 = ichac97R3MixerAddDrv(pThis, pDrv);
     
    40524050 * @interface_method_impl{PDMDEVREG,pfnDetach}
    40534051 */
    4054 static DECLCALLBACK(void) ichac97R3Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
     4052static DECLCALLBACK(void) ichac97R3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    40554053{
    40564054    PAC97STATE pThis = PDMDEVINS_2_DATA(pDevIns, PAC97STATE);
    40574055
    4058     LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
     4056    LogFunc(("iLUN=%u, fFlags=0x%x\n", iLUN, fFlags));
    40594057
    40604058    DEVAC97_LOCK(pThis);
     
    40634061    RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, AC97DRIVER, Node)
    40644062    {
    4065         if (pDrv->uLUN == uLUN)
     4063        if (pDrv->uLUN == iLUN)
    40664064        {
    40674065            int rc2 = ichac97R3DetachInternal(pThis, pDrv, fFlags);
     
    40814079
    40824080/**
    4083  * Re-attaches (replaces) a driver with a new driver.
     4081 * Replaces a driver with a the NullAudio drivers.
    40844082 *
    40854083 * @returns VBox status code.
    40864084 * @param   pThis       Device instance.
    4087  * @param   pDrv        Driver instance used for attaching to.
    4088  *                      If NULL is specified, a new driver will be created and appended
    4089  *                      to the driver list.
    4090  * @param   uLUN        The logical unit which is being re-detached.
    4091  * @param   pszDriver   New driver name to attach.
    4092  */
    4093 static int ichac97R3ReattachInternal(PAC97STATE pThis, PAC97DRIVER pDrv, uint8_t uLUN, const char *pszDriver)
    4094 {
    4095     AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
    4096     AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
    4097 
    4098     int rc;
    4099 
    4100     if (pDrv)
    4101     {
    4102         rc = ichac97R3DetachInternal(pThis, pDrv, 0 /* fFlags */);
    4103         if (RT_SUCCESS(rc))
    4104             rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
    4105 
    4106         if (RT_FAILURE(rc))
    4107             return rc;
    4108 
    4109         RTStrFree(pDrv->pszDesc);
    4110         RTMemFree(pDrv);
    4111         pDrv = NULL;
    4112     }
    4113 
    4114     PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
    4115     PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
    4116     PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/ichac97/0/");
    4117 
    4118     /* Remove LUN branch. */
    4119     CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
    4120 
    4121 # define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
    4122 
    4123     do
    4124     {
    4125         PCFGMNODE pLunL0;
    4126         rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN);        RC_CHECK();
    4127         rc = CFGMR3InsertString(pLunL0, "Driver",       "AUDIO");       RC_CHECK();
    4128         rc = CFGMR3InsertNode(pLunL0,   "Config/",       NULL);         RC_CHECK();
    4129 
    4130         PCFGMNODE pLunL1, pLunL2;
    4131         rc = CFGMR3InsertNode  (pLunL0, "AttachedDriver/", &pLunL1);    RC_CHECK();
    4132         rc = CFGMR3InsertNode  (pLunL1,  "Config/",        &pLunL2);    RC_CHECK();
    4133         rc = CFGMR3InsertString(pLunL1,  "Driver",          pszDriver); RC_CHECK();
    4134 
    4135         rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver);      RC_CHECK();
    4136 
    4137     } while (0);
    4138 
     4085 * @param   iLun        The logical unit which is being replaced.
     4086 */
     4087static int ichac97R3ReconfigLunWithNullAudio(PAC97STATE pThis, unsigned iLun)
     4088{
     4089    int rc = PDMDevHlpDriverReconfigure2(pThis->pDevInsR3, iLun, "AUDIO", "NullAudio");
    41394090    if (RT_SUCCESS(rc))
    4140         rc = ichac97R3AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    4141 
    4142     LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
    4143 
    4144 # undef RC_CHECK
    4145 
     4091        rc = ichac97R3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4092    LogFunc(("pThis=%p, iLun=%u, rc=%Rrc\n", pThis, iLun, rc));
    41464093    return rc;
    41474094}
     
    43424289
    43434290    /*
    4344      * Attach driver.
     4291     * Attach drivers.  We ASSUME they are configured consecutively without any
     4292     * gaps, so we stop when we hit the first LUN w/o a driver configured.
    43454293     */
    4346     uint8_t uLUN;
    4347     for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
    4348     {
    4349         LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN));
    4350         rc = ichac97R3AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    4351         if (RT_FAILURE(rc))
    4352         {
    4353             if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    4354                 rc = VINF_SUCCESS;
    4355             else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
     4294    for (unsigned iLun = 0; ; iLun++)
     4295    {
     4296        AssertBreak(iLun < UINT8_MAX);
     4297        LogFunc(("Trying to attach driver for LUN#%u ...\n", iLun));
     4298        rc = ichac97R3AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     4299        if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     4300        {
     4301            LogFunc(("cLUNs=%u\n", iLun));
     4302            break;
     4303        }
     4304        if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
     4305        {
     4306            ichac97R3ReconfigLunWithNullAudio(pThis, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
     4307            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4308                                       N_("Host audio backend initialization has failed. "
     4309                                          "Selecting the NULL audio backend with the consequence that no sound is audible"));
     4310        }
     4311        else
     4312            AssertLogRelMsgReturn(RT_SUCCESS(rc),  ("LUN#%u: rc=%Rrc\n", iLun, rc), rc);
     4313    }
     4314
     4315    rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
     4316    AssertRCReturn(rc, rc);
     4317    rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
     4318    AssertRCReturn(rc, rc);
     4319    rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
     4320    AssertRCReturn(rc, rc);
     4321    rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOut);
     4322    AssertRCReturn(rc, rc);
     4323
     4324    /*
     4325     * Create all hardware streams.
     4326     */
     4327    for (unsigned i = 0; i < AC97_MAX_STREAMS; i++)
     4328    {
     4329        int rc2 = ichac97R3StreamCreate(pThis, &pThis->aStreams[i], i /* SD# */);
     4330        AssertRC(rc2);
     4331        if (RT_SUCCESS(rc))
     4332            rc = rc2;
     4333    }
     4334
     4335# ifdef VBOX_WITH_AUDIO_AC97_ONETIME_INIT
     4336    PAC97DRIVER pDrv;
     4337    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     4338    {
     4339        /*
     4340         * Only primary drivers are critical for the VM to run. Everything else
     4341         * might not worth showing an own error message box in the GUI.
     4342         */
     4343        if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
     4344            continue;
     4345
     4346        PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
     4347        AssertPtr(pCon);
     4348
     4349        bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
     4350        bool fValidMicIn  = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
     4351        bool fValidOut    = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
     4352
     4353        if (    !fValidLineIn
     4354             && !fValidMicIn
     4355             && !fValidOut)
     4356        {
     4357            LogRel(("AC97: Falling back to NULL backend (no sound audible)\n"));
     4358            ichac97R3Reset(pDevIns);
     4359            ichac97R3ReconfigLunWithNullAudio(pThis, iLun);
     4360            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4361                                       N_("No audio devices could be opened. "
     4362                                          "Selecting the NULL audio backend with the consequence that no sound is audible"));
     4363        }
     4364        else
     4365        {
     4366            bool fWarn = false;
     4367
     4368            PDMAUDIOBACKENDCFG backendCfg;
     4369            int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
     4370            if (RT_SUCCESS(rc2))
    43564371            {
    4357                 ichac97R3ReattachInternal(pThis, NULL /* pDrv */, uLUN, "NullAudio");
    4358                 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    4359                         N_("Host audio backend initialization has failed. Selecting the NULL audio backend "
    4360                             "with the consequence that no sound is audible"));
    4361                 /* Attaching to the NULL audio backend will never fail. */
    4362                 rc = VINF_SUCCESS;
    4363             }
    4364             break;
    4365         }
    4366     }
    4367 
    4368     LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
    4369 
    4370     if (RT_SUCCESS(rc))
    4371     {
    4372         rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
    4373         if (RT_SUCCESS(rc))
    4374         {
    4375             rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
    4376             AssertRC(rc);
    4377             rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
    4378             AssertRC(rc);
    4379             rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOut);
    4380             AssertRC(rc);
    4381         }
    4382     }
    4383 
    4384     if (RT_SUCCESS(rc))
    4385     {
    4386         /*
    4387          * Create all hardware streams.
    4388          */
    4389         for (unsigned i = 0; i < AC97_MAX_STREAMS; i++)
    4390         {
    4391             int rc2 = ichac97R3StreamCreate(pThis, &pThis->aStreams[i], i /* SD# */);
    4392             AssertRC(rc2);
    4393             if (RT_SUCCESS(rc))
    4394                 rc = rc2;
    4395         }
    4396 
    4397 # ifdef VBOX_WITH_AUDIO_AC97_ONETIME_INIT
    4398         PAC97DRIVER pDrv;
    4399         RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    4400         {
    4401             /*
    4402              * Only primary drivers are critical for the VM to run. Everything else
    4403              * might not worth showing an own error message box in the GUI.
    4404              */
    4405             if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
    4406                 continue;
    4407 
    4408             PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    4409             AssertPtr(pCon);
    4410 
    4411             bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
    4412             bool fValidMicIn  = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
    4413             bool fValidOut    = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
    4414 
    4415             if (    !fValidLineIn
    4416                  && !fValidMicIn
    4417                  && !fValidOut)
    4418             {
    4419                 LogRel(("AC97: Falling back to NULL backend (no sound audible)\n"));
    4420 
    4421                 ichac97R3Reset(pDevIns);
    4422                 ichac97R3ReattachInternal(pThis, pDrv, pDrv->uLUN, "NullAudio");
    4423 
    4424                 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    4425                     N_("No audio devices could be opened. Selecting the NULL audio backend "
    4426                        "with the consequence that no sound is audible"));
     4372                if (backendCfg.cMaxStreamsIn)
     4373                {
     4374                    /* If the audio backend supports two or more input streams at once,
     4375                     * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
     4376                    if (backendCfg.cMaxStreamsIn >= 2)
     4377                        fWarn = !fValidLineIn || !fValidMicIn;
     4378                    /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
     4379                     * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
     4380                     * One of the two simply is not in use then. */
     4381                    else if (backendCfg.cMaxStreamsIn == 1)
     4382                        fWarn = !fValidLineIn && !fValidMicIn;
     4383                    /* Don't warn if our backend is not able of supporting any input streams at all. */
     4384                }
     4385
     4386                if (   !fWarn
     4387                    && backendCfg.cMaxStreamsOut)
     4388                {
     4389                    fWarn = !fValidOut;
     4390                }
    44274391            }
    44284392            else
    44294393            {
    4430                 bool fWarn = false;
    4431 
    4432                 PDMAUDIOBACKENDCFG backendCfg;
    4433                 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
    4434                 if (RT_SUCCESS(rc2))
     4394                LogRel(("AC97: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
     4395                fWarn = true;
     4396            }
     4397
     4398            if (fWarn)
     4399            {
     4400                char   szMissingStreams[255] = "";
     4401                size_t len = 0;
     4402                if (!fValidLineIn)
    44354403                {
    4436                     if (backendCfg.cMaxStreamsIn)
    4437                     {
    4438                         /* If the audio backend supports two or more input streams at once,
    4439                          * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
    4440                         if (backendCfg.cMaxStreamsIn >= 2)
    4441                             fWarn = !fValidLineIn || !fValidMicIn;
    4442                         /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
    4443                          * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
    4444                          * One of the two simply is not in use then. */
    4445                         else if (backendCfg.cMaxStreamsIn == 1)
    4446                             fWarn = !fValidLineIn && !fValidMicIn;
    4447                         /* Don't warn if our backend is not able of supporting any input streams at all. */
    4448                     }
    4449 
    4450                     if (   !fWarn
    4451                         && backendCfg.cMaxStreamsOut)
    4452                     {
    4453                         fWarn = !fValidOut;
    4454                     }
     4404                    LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
     4405                    len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
    44554406                }
    4456                 else
     4407                if (!fValidMicIn)
    44574408                {
    4458                     LogRel(("AC97: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
    4459                     fWarn = true;
     4409                    LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
     4410                    len += RTStrPrintf(szMissingStreams + len,
     4411                                       sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
    44604412                }
    4461 
    4462                 if (fWarn)
     4413                if (!fValidOut)
    44634414                {
    4464                     char   szMissingStreams[255] = "";
    4465                     size_t len = 0;
    4466                     if (!fValidLineIn)
    4467                     {
    4468                         LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
    4469                         len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
    4470                     }
    4471                     if (!fValidMicIn)
    4472                     {
    4473                         LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
    4474                         len += RTStrPrintf(szMissingStreams + len,
    4475                                            sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
    4476                     }
    4477                     if (!fValidOut)
    4478                     {
    4479                         LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
    4480                         len += RTStrPrintf(szMissingStreams + len,
    4481                                            sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
    4482                     }
    4483 
    4484                     PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    4485                                                N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
    4486                                                   "output or depending on audio input may hang. Make sure your host audio device "
    4487                                                   "is working properly. Check the logfile for error messages of the audio "
    4488                                                   "subsystem"), szMissingStreams);
     4415                    LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
     4416                    len += RTStrPrintf(szMissingStreams + len,
     4417                                       sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
    44894418                }
     4419
     4420                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4421                                           N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
     4422                                              "output or depending on audio input may hang. Make sure your host audio device "
     4423                                              "is working properly. Check the logfile for error messages of the audio "
     4424                                              "subsystem"), szMissingStreams);
    44904425            }
    44914426        }
     4427    }
    44924428# endif /* VBOX_WITH_AUDIO_AC97_ONETIME_INIT */
    4493     }
    4494 
    4495     if (RT_SUCCESS(rc))
    4496         ichac97R3Reset(pDevIns);
    4497 
    4498     if (RT_SUCCESS(rc))
    4499     {
    4500         static const char * const s_apszNames[] =
    4501         {
    4502             "AC97 PI", "AC97 PO", "AC97 MC"
    4503         };
    4504         AssertCompile(RT_ELEMENTS(s_apszNames) == AC97_MAX_STREAMS);
    4505 
    4506         for (unsigned i = 0; i < AC97_MAX_STREAMS; i++)
    4507         {
    4508             /* Create the emulation timer (per stream).
    4509              *
    4510              * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's AC'97 driver
    4511              *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
    4512              *        instead of the LPIB registers.
    4513              */
    4514             rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, ichac97R3Timer, &pThis->aStreams[i],
    4515                                         TMTIMER_FLAGS_NO_CRIT_SECT, s_apszNames[i], &pThis->pTimerR3[i]);
    4516             AssertRCReturn(rc, rc);
    4517             pThis->pTimerR0[i] = TMTimerR0Ptr(pThis->pTimerR3[i]);
    4518             pThis->pTimerRC[i] = TMTimerRCPtr(pThis->pTimerR3[i]);
    4519 
    4520             /* Use our own critcal section for the device timer.
    4521              * That way we can control more fine-grained when to lock what. */
    4522             rc = TMR3TimerSetCritSect(pThis->pTimerR3[i], &pThis->CritSect);
    4523             AssertRCReturn(rc, rc);
    4524         }
    4525     }
    4526 
     4429
     4430    ichac97R3Reset(pDevIns);
     4431
     4432    static const char * const s_apszNames[] =
     4433    {
     4434        "AC97 PI", "AC97 PO", "AC97 MC"
     4435    };
     4436    AssertCompile(RT_ELEMENTS(s_apszNames) == AC97_MAX_STREAMS);
     4437
     4438    for (unsigned i = 0; i < AC97_MAX_STREAMS; i++)
     4439    {
     4440        /* Create the emulation timer (per stream).
     4441         *
     4442         * Note:  Use TMCLOCK_VIRTUAL_SYNC here, as the guest's AC'97 driver
     4443         *        relies on exact (virtual) DMA timing and uses DMA Position Buffers
     4444         *        instead of the LPIB registers.
     4445         */
     4446        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, ichac97R3Timer, &pThis->aStreams[i],
     4447                                    TMTIMER_FLAGS_NO_CRIT_SECT, s_apszNames[i], &pThis->pTimerR3[i]);
     4448        AssertRCReturn(rc, rc);
     4449        pThis->pTimerR0[i] = TMTimerR0Ptr(pThis->pTimerR3[i]);
     4450        pThis->pTimerRC[i] = TMTimerRCPtr(pThis->pTimerR3[i]);
     4451
     4452        /* Use our own critcal section for the device timer.
     4453         * That way we can control more fine-grained when to lock what. */
     4454        rc = TMR3TimerSetCritSect(pThis->pTimerR3[i], &pThis->CritSect);
     4455        AssertRCReturn(rc, rc);
     4456    }
     4457
     4458    /*
     4459     * Register statistics.
     4460     */
    45274461# ifdef VBOX_WITH_STATISTICS
    4528     if (RT_SUCCESS(rc))
    4529     {
    4530         /*
    4531          * Register statistics.
    4532          */
    4533         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer,        STAMTYPE_PROFILE, "/Devices/AC97/Timer",        STAMUNIT_TICKS_PER_CALL, "Profiling ichac97Timer.");
    4534         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn,           STAMTYPE_PROFILE, "/Devices/AC97/Input",        STAMUNIT_TICKS_PER_CALL, "Profiling input.");
    4535         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut,          STAMTYPE_PROFILE, "/Devices/AC97/Output",       STAMUNIT_TICKS_PER_CALL, "Profiling output.");
    4536         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead,    STAMTYPE_COUNTER, "/Devices/AC97/BytesRead"   , STAMUNIT_BYTES,          "Bytes read from AC97 emulation.");
    4537         PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/AC97/BytesWritten", STAMUNIT_BYTES,          "Bytes written to AC97 emulation.");
    4538     }
     4462    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer,        STAMTYPE_PROFILE, "Timer",        STAMUNIT_TICKS_PER_CALL, "Profiling ichac97Timer.");
     4463    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn,           STAMTYPE_PROFILE, "Input",        STAMUNIT_TICKS_PER_CALL, "Profiling input.");
     4464    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut,          STAMTYPE_PROFILE, "Output",       STAMUNIT_TICKS_PER_CALL, "Profiling output.");
     4465    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead,    STAMTYPE_COUNTER, "BytesRead"   , STAMUNIT_BYTES,          "Bytes read from AC97 emulation.");
     4466    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "BytesWritten", STAMUNIT_BYTES,          "Bytes written to AC97 emulation.");
    45394467# endif
    45404468
    4541     LogFlowFuncLeaveRC(rc);
    4542     return rc;
     4469    LogFlowFuncLeaveRC(VINF_SUCCESS);
     4470    return VINF_SUCCESS;
    45434471}
    45444472
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r82225 r82228  
    107107    /** Driver flags. */
    108108    PDMAUDIODRVFLAGS                   fFlags;
    109     uint32_t                           PaddingFlags;
    110109    /** LUN # to which this driver has been assigned. */
    111110    uint8_t                            uLUN;
    112111    /** Whether this driver is in an attached state or not. */
    113112    bool                               fAttached;
    114     uint8_t                            Padding[4];
     113    uint8_t                            Padding[2];
    115114    /** Pointer to attached driver base interface. */
    116115    R3PTRTYPE(PPDMIBASE)               pDrvBase;
     
    21642163                pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
    21652164
    2166             LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
     2165            LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
    21672166
    21682167            /* Attach to driver list if not attached yet. */
     
    22192218 * @interface_method_impl{PDMDEVREG,pfnAttach}
    22202219 */
    2221 static DECLCALLBACK(int) sb16Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
     2220static DECLCALLBACK(int) sb16Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    22222221{
    22232222    PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);
    22242223
    2225     LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
     2224    LogFunc(("iLUN=%u, fFlags=0x%x\n", iLUN, fFlags));
    22262225
    22272226    PSB16DRIVER pDrv;
    2228     int rc2 = sb16AttachInternal(pThis, uLUN, fFlags, &pDrv);
     2227    int rc2 = sb16AttachInternal(pThis, iLUN, fFlags, &pDrv);
    22292228    if (RT_SUCCESS(rc2))
    22302229        rc2 = sb16CreateDrvStream(pThis, &pThis->Out.Cfg, pDrv);
     
    22362235 * @interface_method_impl{PDMDEVREG,pfnDetach}
    22372236 */
    2238 static DECLCALLBACK(void) sb16Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
     2237static DECLCALLBACK(void) sb16Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    22392238{
    22402239    PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);
    22412240
    2242     LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
     2241    LogFunc(("iLUN=%u, fFlags=0x%x\n", iLUN, fFlags));
    22432242
    22442243    PSB16DRIVER pDrv, pDrvNext;
    22452244    RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, SB16DRIVER, Node)
    22462245    {
    2247         if (pDrv->uLUN == uLUN)
     2246        if (pDrv->uLUN == iLUN)
    22482247        {
    22492248            int rc2 = sb16DetachInternal(pThis, pDrv, fFlags);
     
    22532252                pDrv = NULL;
    22542253            }
    2255 
    22562254            break;
    22572255        }
     
    22602258
    22612259/**
    2262  * Re-attaches (replaces) a driver with a new driver.
     2260 * Replaces a driver with a the NullAudio drivers.
    22632261 *
    22642262 * @returns VBox status code.
    22652263 * @param   pThis       Device instance.
    2266  * @param   uLUN        The logical unit which is being re-detached.
    2267  * @param   pszDriver   New driver name to attach.
    2268  */
    2269 static int sb16Reattach(PSB16STATE pThis, uint8_t uLUN, const char *pszDriver)
    2270 {
    2271     AssertPtr(pThis);
    2272 
    2273     int rc = PDMDevHlpDriverReconfigure2(pThis->pDevInsR3, uLUN, "AUDIO", pszDriver);
     2264 * @param   iLun        The logical unit which is being replaced.
     2265 */
     2266static int sb16ReconfigLunWithNullAudio(PSB16STATE pThis, unsigned iLun)
     2267{
     2268    int rc = PDMDevHlpDriverReconfigure2(pThis->pDevInsR3, iLun, "AUDIO", "NullAudio");
    22742269    if (RT_SUCCESS(rc))
    2275         rc = sb16AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    2276 
    2277     LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
    2278 
     2270        rc = sb16AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     2271    LogFunc(("pThis=%p, iLun=%u, rc=%Rrc\n", pThis, iLun, rc));
    22792272    return rc;
    22802273}
     
    24232416
    24242417    /*
    2425      * Create timer(s), register & attach stuff.
     2418     * Create timers.
    24262419     */
    24272420    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIRQ, pThis,
    24282421                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IRQ timer", &pThis->pTimerIRQ);
    2429     if (RT_FAILURE(rc))
    2430         AssertMsgFailedReturn(("Error creating IRQ timer, rc=%Rrc\n", rc), rc);
    2431 
     2422    AssertRCReturn(rc, rc);
     2423    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis,
     2424                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->pTimerIO);
     2425    AssertRCReturn(rc, rc);
     2426    pThis->cTimerTicksIO = TMTimerGetFreq(pThis->pTimerIO) / uTimerHz;
     2427    pThis->uTimerTSIO    = TMTimerGet(pThis->pTimerIO);
     2428    LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicksIO, uTimerHz));
     2429
     2430    /*
     2431     * Register I/O and DMA.
     2432     */
    24322433    rc = PDMDevHlpIOPortRegister(pDevIns, pThis->port + 0x04,  2, pThis, mixer_write, mixer_read, NULL, NULL, "SB16");
    2433     if (RT_FAILURE(rc))
    2434         return rc;
     2434    AssertRCReturn(rc, rc);
    24352435    rc = PDMDevHlpIOPortRegister(pDevIns, pThis->port + 0x06, 10, pThis, dsp_write,   dsp_read,   NULL, NULL, "SB16");
    2436     if (RT_FAILURE(rc))
    2437         return rc;
     2436    AssertRCReturn(rc, rc);
    24382437
    24392438    rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, sb16DMARead, pThis);
    2440     if (RT_FAILURE(rc))
    2441         return rc;
     2439    AssertRCReturn(rc, rc);
    24422440    rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, sb16DMARead, pThis);
    2443     if (RT_FAILURE(rc))
    2444         return rc;
     2441    AssertRCReturn(rc, rc);
    24452442
    24462443    pThis->can_write = 1;
    24472444
     2445    /*
     2446     * Register Saved state.
     2447     */
    24482448    rc = PDMDevHlpSSMRegister3(pDevIns, SB16_SAVE_STATE_VERSION, sizeof(SB16STATE), sb16LiveExec, sb16SaveExec, sb16LoadExec);
    2449     if (RT_FAILURE(rc))
    2450         return rc;
     2449    AssertRCReturn(rc, rc);
    24512450
    24522451    /*
    2453      * Attach driver.
     2452     * Attach drivers.  We ASSUME they are configured consecutively without any
     2453     * gaps, so we stop when we hit the first LUN w/o a driver configured.
    24542454     */
    2455     uint8_t uLUN;
    2456     for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
    2457     {
    2458         LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN));
    2459         rc = sb16AttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
    2460         if (RT_FAILURE(rc))
     2455    for (unsigned iLun = 0; ; iLun++)
     2456    {
     2457        AssertBreak(iLun < UINT8_MAX);
     2458        LogFunc(("Trying to attach driver for LUN#%u ...\n", iLun));
     2459        rc = sb16AttachInternal(pThis, iLun, 0 /* fFlags */, NULL /* ppDrv */);
     2460        if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    24612461        {
    2462             if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    2463                 rc = VINF_SUCCESS;
    2464             else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
    2465             {
    2466                 sb16Reattach(pThis, uLUN, "NullAudio");
    2467                 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    2468                                            N_("Host audio backend initialization has failed. Selecting the NULL audio backend with the consequence that no sound is audible"));
    2469                 /* Attaching to the NULL audio backend will never fail. */
    2470                 rc = VINF_SUCCESS;
    2471             }
     2462            LogFunc(("cLUNs=%u\n", iLun));
    24722463            break;
    24732464        }
    2474     }
    2475 
    2476     LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
     2465        if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
     2466        {
     2467            sb16ReconfigLunWithNullAudio(pThis, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
     2468            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     2469                                       N_("Host audio backend initialization has failed. "
     2470                                          "Selecting the NULL audio backend with the consequence that no sound is audible"));
     2471        }
     2472        else
     2473            AssertLogRelMsgReturn(RT_SUCCESS(rc),  ("LUN#%u: rc=%Rrc\n", iLun, rc), rc);
     2474    }
    24772475
    24782476    sb16CmdResetLegacy(pThis);
     
    24892487            continue;
    24902488
     2489        /** @todo No input streams available for SB16 yet. */
     2490        if (!pDrv->Out.pStream)
     2491            continue;
     2492
    24912493        PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    24922494        AssertPtr(pCon);
    2493 
    2494         /** @todo No input streams available for SB16 yet. */
    2495 
    2496         if (!pDrv->Out.pStream)
    2497             continue;
    2498 
    2499         bool fValidOut = pCon->pfnStreamGetStatus(pCon, pDrv->Out.pStream) & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED;
    2500         if (!fValidOut)
     2495        if (   pCon == NULL /* paranoia */
     2496            || !(pCon->pfnStreamGetStatus(pCon, pDrv->Out.pStream) & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED))
    25012497        {
    25022498            LogRel(("SB16: Falling back to NULL backend (no sound audible)\n"));
    25032499
    25042500            sb16CmdResetLegacy(pThis);
    2505             sb16Reattach(pThis, pDrv->uLUN, "NullAudio");
     2501            sb16ReconfigLunWithNullAudio(pThis, pDrv->uLUN);
    25062502            pDrv = NULL; /* no longer valid */
    25072503
    25082504            PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    2509                                        N_("No audio devices could be opened. Selecting the NULL audio backend with the consequence that no sound is audible"));
     2505                                       N_("No audio devices could be opened. "
     2506                                          "Selecting the NULL audio backend with the consequence that no sound is audible"));
    25102507        }
    25112508    }
    25122509#endif
    25132510
    2514     if (RT_SUCCESS(rc))
    2515     {
    2516         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis,
    2517                                     TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->pTimerIO);
    2518         if (RT_SUCCESS(rc))
    2519         {
    2520             pThis->cTimerTicksIO = TMTimerGetFreq(pThis->pTimerIO) / uTimerHz;
    2521             pThis->uTimerTSIO    = TMTimerGet(pThis->pTimerIO);
    2522             LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicksIO, uTimerHz));
    2523         }
    2524         else
    2525             AssertMsgFailedReturn(("Error creating I/O timer, rc=%Rrc\n", rc), rc);
    2526     }
    2527 
     2511    /*
     2512     * Delete debug file.
     2513     */
    25282514#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
    25292515    RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "sb16WriteAudio.pcm");
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette