VirtualBox

Changeset 59078 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 10, 2015 3:56:27 PM (9 years ago)
Author:
vboxsync
Message:

Audio/AC97: Fixed stream initialization / handling, also >= 2 VCPUs, cleanup.

File:
1 edited

Legend:

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

    r58983 r59078  
    4141*   Defined Constants And Macros                                                                                                 *
    4242*********************************************************************************************************************************/
    43 #undef LOG_VOICES
    4443
    4544#ifdef DEBUG
     
    5857#endif
    5958
    60 #define SR_FIFOE RT_BIT(4)          /* rwc, fifo error */
    61 #define SR_BCIS  RT_BIT(3)          /* rwc, buffer completion interrupt status */
    62 #define SR_LVBCI RT_BIT(2)          /* rwc, last valid buffer completion interrupt */
    63 #define SR_CELV  RT_BIT(1)          /* ro, current equals last valid */
    64 #define SR_DCH   RT_BIT(0)          /* ro, controller halted */
     59#define SR_FIFOE RT_BIT(4)          /* rwc, FIFO error. */
     60#define SR_BCIS  RT_BIT(3)          /* rwc, Buffer completion interrupt status. */
     61#define SR_LVBCI RT_BIT(2)          /* rwc, Last valid buffer completion interrupt. */
     62#define SR_CELV  RT_BIT(1)          /* ro,  Current equals last valid. */
     63#define SR_DCH   RT_BIT(0)          /* ro,  Controller halted. */
    6564#define SR_VALID_MASK (RT_BIT(5) - 1)
    6665#define SR_WCLEAR_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
     
    6867#define SR_INT_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
    6968
    70 #define CR_IOCE  RT_BIT(4)         /* rw */
    71 #define CR_FEIE  RT_BIT(3)         /* rw */
    72 #define CR_LVBIE RT_BIT(2)         /* rw */
     69#define CR_IOCE  RT_BIT(4)         /* rw,   Interrupt On Completion Enable. */
     70#define CR_FEIE  RT_BIT(3)         /* rw    FIFO Error Interrupt Enable. */
     71#define CR_LVBIE RT_BIT(2)         /* rw    */
    7372#define CR_RR    RT_BIT(1)         /* rw */
    7473#define CR_RPBM  RT_BIT(0)         /* rw */
     
    184183#define AD_MISC_HPSEL       RT_BIT(10)  /* PCM (front) goes to headphone outputs. */
    185184
     185#define ICHAC97STATE_2_DEVINS(a_pAC97)   ((a_pAC97)->pDevInsR3)
     186
     187enum
     188{
     189    BUP_SET  = RT_BIT(0),
     190    BUP_LAST = RT_BIT(1)
     191};
     192
     193/** Emits registers for a specific (Native Audio Bus Master BAR) NABMBAR. */
     194#define AC97_NABMBAR_REGS(prefix, off) \
     195    enum {                             \
     196        prefix ## _BDBAR = off,        \
     197        prefix ## _CIV   = off + 4,    \
     198        prefix ## _LVI   = off + 5,    \
     199        prefix ## _SR    = off + 6,    \
     200        prefix ## _PICB  = off + 8,    \
     201        prefix ## _PIV   = off + 10,   \
     202        prefix ## _CR    = off + 11    \
     203    }
     204
     205#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     206typedef enum
     207{
     208    PI_INDEX = 0, /** PCM in */
     209    PO_INDEX,     /** PCM out */
     210    MC_INDEX,     /** Mic in */
     211    LAST_INDEX
     212} AC97SOUNDSOURCE;
     213
     214AC97_NABMBAR_REGS(PI, PI_INDEX * 16);
     215AC97_NABMBAR_REGS(PO, PO_INDEX * 16);
     216AC97_NABMBAR_REGS(MC, MC_INDEX * 16);
     217#endif
     218
     219enum
     220{
     221    /** NABMBAR: Global Control Register. */
     222    GLOB_CNT = 0x2c,
     223    /** NABMBAR Global Status. */
     224    GLOB_STA = 0x30,
     225    /** Codec Access Semaphore Register. */
     226    CAS      = 0x34
     227};
     228
     229#define AC97_PORT2IDX(a_idx)   ( ((a_idx) >> 4) & 3 )
     230
    186231/*********************************************************************************************************************************
    187232*   Structures and Typedefs                                                                                                      *
    188233*********************************************************************************************************************************/
     234
    189235/**
    190  * Buffer descriptor.
     236 * Buffer Descriptor List Entry (BDLE).
    191237 */
    192 typedef struct BD
     238typedef struct AC97BDLE
    193239{
    194240    uint32_t addr;
    195241    uint32_t ctl_len;
    196 } BD;
    197 
    198 typedef struct AC97BusMasterRegs
    199 {
    200     uint32_t bdbar;             /**< rw 0, buffer descriptor list base address register */
    201     uint8_t  civ;               /**< ro 0, current index value */
    202     uint8_t  lvi;               /**< rw 0, last valid index */
    203     uint16_t sr;                /**< rw 1, status register */
    204     uint16_t picb;              /**< ro 0, position in current buffer */
    205     uint8_t  piv;               /**< ro 0, prefetched index value */
    206     uint8_t  cr;                /**< rw 0, control register */
    207     int      bd_valid;          /**< initialized? */
    208     BD       bd;                /**< buffer descriptor */
    209 } AC97BusMasterRegs;
    210 /** Pointer to a AC97 bus master register. */
    211 typedef AC97BusMasterRegs *PAC97BMREG;
     242} AC97BDLE, *PAC97BDLE;
     243
     244/**
     245 * Bus master register set for an audio stream.
     246 */
     247typedef struct AC97BMREGS
     248{
     249    uint32_t bdbar;             /** rw 0, Buffer Descriptor List: BAR (Base Address Register). */
     250    uint8_t  civ;               /** ro 0, Current index value. */
     251    uint8_t  lvi;               /** rw 0, Last valid index. */
     252    uint16_t sr;                /** rw 1, Status register. */
     253    uint16_t picb;              /** ro 0, Position in current buffer. */
     254    uint8_t  piv;               /** ro 0, Prefetched index value. */
     255    uint8_t  cr;                /** rw 0, Control register. */
     256    int      bd_valid;          /** Whether current BDLE is initialized or not. */
     257    AC97BDLE bd;                /** Current Buffer Descriptor List Entry (BDLE). */
     258} AC97BMREGS, *PAC97BMREGS;
     259
     260/**
     261 * Internal state of an AC97 stream.
     262 */
     263typedef struct AC97STREAMSTATE
     264{
     265    /* Nothing yet. */
     266} AC97STREAMSTATE, *PAC97STREAMSTATE;
     267
     268/**
     269 * Structure for keeping an AC97 stream state.
     270 *
     271 * Contains only register values which do *not* change until a
     272 * stream reset occurs.
     273 */
     274typedef struct AC97STREAM
     275{
     276    /** Stream number (SDn). */
     277    uint8_t         u8Strm;
     278    /** Bus master registers of this stream. */
     279    AC97BMREGS      Regs;
     280    /** Internal state of this stream. */
     281    AC97STREAMSTATE State;
     282} AC97STREAM, *PAC97STREAM;
    212283
    213284typedef struct AC97INPUTSTREAM
     
    268339    /** The PCI device state. */
    269340    PCIDevice               PciDev;
     341    /** R3 Pointer to the device instance. */
     342    PPDMDEVINSR3            pDevInsR3;
    270343    /** Global Control (Bus Master Control Register) */
    271344    uint32_t                glob_cnt;
     
    275348    uint32_t                cas;
    276349    uint32_t                last_samp;
    277     /** Bus Master Control Registers for PCM in, PCM out, and Mic in */
    278     AC97BusMasterRegs       bm_regs[3];
    279350    uint8_t                 mixer_data[256];
     351    /** Stream state for line-in. */
     352    AC97STREAM              StrmStLineIn;
     353    /** Stream state for microphone-in. */
     354    AC97STREAM              StrmStMicIn;
     355    /** Stream state for output. */
     356    AC97STREAM              StrmStOut;
    280357#ifndef VBOX_WITH_AUDIO_CALLBACKS
    281358    /** The emulation timer for handling the attached
     
    307384    uint8_t                 silence[128];
    308385    int                     bup_flag;
    309     /** Pointer to the device instance. */
    310     PPDMDEVINSR3            pDevIns;
    311386    /** Pointer to the attached audio driver. */
    312387    PPDMIBASE               pDrvBase;
     
    321396    /** Codec model. */
    322397    uint32_t                uCodecModel;
    323 } AC97STATE;
    324 /** Pointer to the AC97 device state. */
    325 typedef AC97STATE *PAC97STATE;
     398} AC97STATE, *PAC97STATE;
    326399
    327400#ifdef VBOX_WITH_STATISTICS
     
    331404#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    332405
    333 #define ICHAC97STATE_2_DEVINS(a_pAC97)   ((a_pAC97)->pDevIns)
    334 
    335 enum
    336 {
    337     BUP_SET  = RT_BIT(0),
    338     BUP_LAST = RT_BIT(1)
    339 };
    340 
    341 #define MKREGS(prefix, start)                   \
    342     enum {                                      \
    343         prefix ## _BDBAR = start,               \
    344         prefix ## _CIV   = start + 4,           \
    345         prefix ## _LVI   = start + 5,           \
    346         prefix ## _SR    = start + 6,           \
    347         prefix ## _PICB  = start + 8,           \
    348         prefix ## _PIV   = start + 10,          \
    349         prefix ## _CR    = start + 11           \
    350     }
    351 
    352 enum
    353 {
    354     PI_INDEX = 0,    /* PCM in */
    355     PO_INDEX,        /* PCM out */
    356     MC_INDEX,        /* Mic in */
    357     LAST_INDEX
    358 };
    359 
    360 MKREGS (PI, PI_INDEX * 16);
    361 MKREGS (PO, PO_INDEX * 16);
    362 MKREGS (MC, MC_INDEX * 16);
    363 
    364 enum
    365 {
    366     GLOB_CNT = 0x2c,
    367     GLOB_STA = 0x30,
    368     CAS      = 0x34
    369 };
    370 
    371 #define GET_BM(a_idx)   ( ((a_idx) >> 4) & 3 )
    372 
     406DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
     407static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
    373408#ifndef VBOX_WITH_AUDIO_CALLBACKS
    374409static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
    375410#endif
    376 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed);
     411static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed);
    377412
    378413static void ichac97WarmReset(PAC97STATE pThis)
     
    387422
    388423/** Fetches the buffer descriptor at _CIV. */
    389 static void ichac97FetchBufDesc(PAC97STATE pThis, PAC97BMREG pReg)
    390 {
    391     PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
     424static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStrmSt)
     425{
     426    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
     427    PAC97BMREGS pRegs   = &pStrmSt->Regs;
     428
    392429    uint32_t u32[2];
    393430
    394     PDMDevHlpPhysRead(pDevIns, pReg->bdbar + pReg->civ * 8, &u32[0], sizeof(u32));
    395     pReg->bd_valid   = 1;
     431    PDMDevHlpPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * 8, &u32[0], sizeof(u32));
     432    pRegs->bd_valid   = 1;
    396433#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
    397434# error Please adapt the code (audio buffers are little endian)!
    398435#else
    399     pReg->bd.addr    = RT_H2LE_U32(u32[0] & ~3);
    400     pReg->bd.ctl_len = RT_H2LE_U32(u32[1]);
     436    pRegs->bd.addr    = RT_H2LE_U32(u32[0] & ~3);
     437    pRegs->bd.ctl_len = RT_H2LE_U32(u32[1]);
    401438#endif
    402     pReg->picb       = pReg->bd.ctl_len & 0xffff;
     439    pRegs->picb       = pRegs->bd.ctl_len & 0xffff;
    403440    LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
    404                   pReg->civ, pReg->bd.addr, pReg->bd.ctl_len >> 16,
    405                   pReg->bd.ctl_len & 0xffff, (pReg->bd.ctl_len & 0xffff) << 1));
     441                  pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16,
     442                  pRegs->bd.ctl_len & 0xffff, (pRegs->bd.ctl_len & 0xffff) << 1));
    406443}
    407444
     
    409446 * Update the BM status register
    410447 */
    411 static void ichac97UpdateStatus(PAC97STATE pThis, PAC97BMREG pReg, uint32_t new_sr)
     448static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t new_sr)
    412449{
    413450    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    414     int event = 0;
    415     int level = 0;
     451    PAC97BMREGS pRegs   = &pStrmSt->Regs;
     452
     453    bool fSignal   = false;
     454    bool iIrqLevel;
     455
    416456    uint32_t new_mask = new_sr & SR_INT_MASK;
    417     uint32_t old_mask = pReg->sr  & SR_INT_MASK;
     457    uint32_t old_mask = pRegs->sr  & SR_INT_MASK;
     458
    418459    static uint32_t const masks[] = { GS_PIINT, GS_POINT, GS_MINT };
    419460
    420461    if (new_mask ^ old_mask)
    421462    {
    422         /** @todo is IRQ deasserted when only one of status bits is cleared? */
     463        /** @todo Is IRQ deasserted when only one of status bits is cleared? */
    423464        if (!new_mask)
    424465        {
    425             event = 1;
    426             level = 0;
    427         }
    428         else if ((new_mask & SR_LVBCI) && (pReg->cr & CR_LVBIE))
    429         {
    430             event = 1;
    431             level = 1;
    432         }
    433         else if ((new_mask & SR_BCIS) && (pReg->cr & CR_IOCE))
    434         {
    435             event = 1;
    436             level = 1;
    437         }
    438     }
    439 
    440     pReg->sr = new_sr;
    441 
    442     LogFlowFunc(("IOC%d LVB%d sr=%#x event=%d level=%d\n",
    443                  pReg->sr & SR_BCIS, pReg->sr & SR_LVBCI, pReg->sr, event, level));
    444 
    445     if (event)
    446     {
    447         if (level)
    448             pThis->glob_sta |= masks[pReg - pThis->bm_regs];
     466            fSignal   = true;
     467            iIrqLevel = 0;
     468        }
     469        else if ((new_mask & SR_LVBCI) && (pRegs->cr & CR_LVBIE))
     470        {
     471            fSignal   = true;
     472            iIrqLevel = 1;
     473        }
     474        else if ((new_mask & SR_BCIS) && (pRegs->cr & CR_IOCE))
     475        {
     476            fSignal   = true;
     477            iIrqLevel = 1;
     478        }
     479    }
     480
     481    pRegs->sr = new_sr;
     482
     483    LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, iIrqLevel=%d\n",
     484                 pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iIrqLevel));
     485
     486    if (fSignal)
     487    {
     488        if (iIrqLevel)
     489            pThis->glob_sta |=  masks[pStrmSt->u8Strm];
    449490        else
    450             pThis->glob_sta &= ~masks[pReg - pThis->bm_regs];
    451 
    452         LogFlowFunc(("set irq level=%d\n", !!level));
    453         PDMDevHlpPCISetIrq(pDevIns, 0, !!level);
    454     }
    455 }
    456 
    457 static void ichac97StreamSetActive(PAC97STATE pThis, int bm_index, int on)
    458 {
    459     AssertPtrReturnVoid(pThis);
    460 
    461     LogFlowFunc(("index=%d, on=%d\n", bm_index, on));
     491            pThis->glob_sta &= ~masks[pStrmSt->u8Strm];
     492
     493        LogFlowFunc(("set irq level=%d\n", !!iIrqLevel));
     494        PDMDevHlpPCISetIrq(pDevIns, 0, !!iIrqLevel);
     495    }
     496}
     497
     498static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fActive)
     499{
     500    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     501    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     502
     503    LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStrmSt->u8Strm, fActive));
     504
     505    int rc = VINF_SUCCESS;
    462506
    463507    PAC97DRIVER pDrv;
    464     switch (bm_index)
     508    switch (pStrmSt->u8Strm)
    465509    {
    466510        case PI_INDEX:
    467              RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    468                 pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
    469                                               pDrv->LineIn.pStrmIn, RT_BOOL(on));
     511            RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     512            {
     513                int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
     514                                                        pDrv->LineIn.pStrmIn, fActive);
     515                if (RT_SUCCESS(rc))
     516                    rc = rc2;
     517            }
    470518            break;
    471519
    472520        case PO_INDEX:
    473521            RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    474                 pDrv->pConnector->pfnEnableOut(pDrv->pConnector,
    475                                                pDrv->Out.pStrmOut, RT_BOOL(on));
     522            {
     523                int rc2 = pDrv->pConnector->pfnEnableOut(pDrv->pConnector,
     524                                                         pDrv->Out.pStrmOut, fActive);
     525                if (RT_SUCCESS(rc))
     526                    rc = rc2;
     527            }
    476528            break;
    477529
    478530        case MC_INDEX:
    479531            RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    480                 pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
    481                                               pDrv->MicIn.pStrmIn, RT_BOOL(on));
     532            {
     533                int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
     534                                                        pDrv->MicIn.pStrmIn, fActive);
     535                if (RT_SUCCESS(rc))
     536                    rc = rc2;
     537            }
    482538            break;
    483539
    484540        default:
    485             AssertMsgFailed(("Wrong index %d\n", bm_index));
    486             break;
    487     }
    488 }
    489 
    490 static void ichac97ResetBMRegs(PAC97STATE pThis, PAC97BMREG pReg)
    491 {
    492     LogFlowFunc(("reset_bm_regs\n"));
    493     pReg->bdbar    = 0;
    494     pReg->civ      = 0;
    495     pReg->lvi      = 0;
    496     /** @todo do we need to do that? */
    497     ichac97UpdateStatus(pThis, pReg, SR_DCH);
    498     pReg->picb     = 0;
    499     pReg->piv      = 0;
    500     pReg->cr       = pReg->cr & CR_DONT_CLEAR_MASK;
    501     pReg->bd_valid = 0;
    502     ichac97StreamSetActive(pThis, pReg - pThis->bm_regs, 0);
     541            AssertMsgFailed(("Wrong index %RU32\n", pStrmSt->u8Strm));
     542            rc = VERR_NOT_SUPPORTED;
     543            break;
     544    }
     545
     546    return rc;
     547}
     548
     549static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStrmSt)
     550{
     551    AssertPtrReturnVoid(pThis);
     552    AssertPtrReturnVoid(pStrmSt);
     553
     554    LogFlowFuncEnter();
     555
     556    PAC97BMREGS pRegs = &pStrmSt->Regs;
     557
     558    pRegs->bdbar    = 0;
     559    pRegs->civ      = 0;
     560    pRegs->lvi      = 0;
     561
     562    ichac97StreamUpdateStatus(pThis, pStrmSt, SR_DCH); /** @todo Do we need to do that? */
     563
     564    pRegs->picb     = 0;
     565    pRegs->piv      = 0;
     566    pRegs->cr       = pRegs->cr & CR_DONT_CLEAR_MASK;
     567    pRegs->bd_valid = 0;
     568
     569    int rc = ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
     570    AssertRC(rc);
     571
    503572    RT_ZERO(pThis->silence);
    504573}
    505574
    506 static void ichac97MixerStore(PAC97STATE pThis, uint32_t i, uint16_t v)
    507 {
    508     if (i + 2 > sizeof(pThis->mixer_data))
    509     {
    510         LogFlowFunc(("mixer_store: index %d out of bounds %d\n", i, sizeof(pThis->mixer_data)));
     575static void ichac97MixerSet(PAC97STATE pThis, uint32_t u8Idx, uint16_t v)
     576{
     577    if (u8Idx + 2 > sizeof(pThis->mixer_data))
     578    {
     579        AssertMsgFailed(("Index %RU8 out of bounds(%zu)\n", u8Idx, sizeof(pThis->mixer_data)));
    511580        return;
    512581    }
    513582
    514     pThis->mixer_data[i + 0] = v & 0xff;
    515     pThis->mixer_data[i + 1] = v >> 8;
    516 }
    517 
    518 static uint16_t ichac97MixerLoad(PAC97STATE pThis, uint32_t i)
    519 {
    520     uint16_t val;
    521 
    522     if (i + 2 > sizeof(pThis->mixer_data))
    523     {
    524         LogFlowFunc(("mixer_load: index %d out of bounds %d\n", i, sizeof(pThis->mixer_data)));
    525         val = 0xffff;
     583    pThis->mixer_data[u8Idx + 0] = RT_LO_U8(v);
     584    pThis->mixer_data[u8Idx + 1] = RT_HI_U8(v);
     585}
     586
     587static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t u8Idx)
     588{
     589    uint16_t uVal;
     590
     591    if (u8Idx + 2 > sizeof(pThis->mixer_data))
     592    {
     593        AssertMsgFailed(("Index %RU8 out of bounds (%zu)\n", u8Idx, sizeof(pThis->mixer_data)));
     594        uVal = UINT16_MAX;
    526595    }
    527596    else
    528         val = pThis->mixer_data[i + 0] | (pThis->mixer_data[i + 1] << 8);
    529 
    530     return val;
    531 }
    532 
    533 static void ichac97OpenStream(PAC97STATE pThis, int index, uint16_t freq)
    534 {
    535     LogFlowFunc(("index=%d, freq=%RU16\n", index, freq));
     597        uVal = RT_MAKE_U16(pThis->mixer_data[u8Idx + 0], pThis->mixer_data[u8Idx + 1]);
     598
     599    return uVal;
     600}
     601
     602static DECLCALLBACK(void) ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
     603{
     604    NOREF(pThis);
     605    NOREF(enmRecSource);
     606    LogFlowFuncEnter();
     607}
     608
     609static DECLCALLBACK(void) ichac97CloseOut(PAC97STATE pThis)
     610{
     611    NOREF(pThis);
     612    LogFlowFuncEnter();
     613}
     614
     615static int ichac97OpenIn(PAC97STATE pThis,
     616                         const char *pszName, PDMAUDIORECSOURCE enmRecSource,
     617                         PPDMAUDIOSTREAMCFG pCfg)
     618{
     619    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     620    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     621    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
     622
     623    PAUDMIXSINK pSink;
     624    switch (enmRecSource)
     625    {
     626        case PDMAUDIORECSOURCE_MIC:
     627            pSink = pThis->pSinkMicIn;
     628            break;
     629        case PDMAUDIORECSOURCE_LINE_IN:
     630            pSink = pThis->pSinkLineIn;
     631            break;
     632        default:
     633            AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
     634            return VERR_NOT_SUPPORTED;
     635    }
     636
     637    int rc = VINF_SUCCESS;
     638
     639    PAC97DRIVER pDrv;
     640    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     641    {
     642        char *pszDesc;
     643        if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
     644        {
     645            rc = VERR_NO_MEMORY;
     646            break;
     647        }
     648
     649        PAC97INPUTSTREAM pStrmIn;
     650        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
     651            pStrmIn = &pDrv->MicIn;
     652        else
     653            pStrmIn = &pDrv->LineIn;
     654
     655        rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);
     656
     657        LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
     658        if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
     659        {
     660            AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn);
     661            rc = AudioMixerAddStreamIn(pSink,
     662                                       pDrv->pConnector, pStrmIn->pStrmIn,
     663                                       0 /* uFlags */, &pStrmIn->phStrmIn);
     664        }
     665
     666        RTStrFree(pszDesc);
     667    }
     668
     669    LogFlowFuncLeaveRC(rc);
     670    return rc;
     671}
     672
     673static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     674{
     675    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     676    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     677    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
     678
     679    int rc = VINF_SUCCESS;
     680    char *pszDesc;
     681
     682    PAC97DRIVER pDrv;
     683    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     684    {
     685        if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
     686                         pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
     687        {
     688            rc = VERR_NO_MEMORY;
     689            break;
     690        }
     691
     692        rc = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
     693        LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
     694        if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
     695        {
     696            AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
     697            rc = AudioMixerAddStreamOut(pThis->pSinkOutput,
     698                                        pDrv->pConnector, pDrv->Out.pStrmOut,
     699                                        0 /* uFlags */, &pDrv->Out.phStrmOut);
     700        }
     701
     702        RTStrFree(pszDesc);
     703    }
     704
     705    LogFlowFuncLeaveRC(rc);
     706    return rc;
     707}
     708
     709static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
     710{
     711    AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
     712    AssertPtrReturn(pStrmSt,           VERR_INVALID_POINTER);
     713    AssertReturn(u8Strm <= LAST_INDEX, VERR_INVALID_PARAMETER);
     714    AssertPtrReturn(pCfg,              VERR_INVALID_POINTER);
     715
     716    pStrmSt->u8Strm = u8Strm;
     717
     718    LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n",
     719                 pStrmSt->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
    536720
    537721    int rc;
    538 
    539     PAC97DRIVER pDrv;
    540     uint8_t uLUN = 0;
    541 
    542     if (freq)
    543     {
    544         PDMAUDIOSTREAMCFG streamCfg;
    545         RT_ZERO(streamCfg);
    546         streamCfg.uHz           = freq;
     722    switch (pStrmSt->u8Strm)
     723    {
     724        case PI_INDEX:
     725            rc = ichac97OpenIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE_IN, pCfg);
     726            break;
     727
     728        case MC_INDEX:
     729            rc = ichac97OpenIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);
     730            break;
     731
     732        case PO_INDEX:
     733            rc = ichac97OpenOut(pThis, "ac97.po", pCfg);
     734            break;
     735
     736        default:
     737            rc = VERR_NOT_SUPPORTED;
     738            break;
     739    }
     740
     741    LogFlowFuncLeaveRC(rc);
     742    return rc;
     743}
     744
     745static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm)
     746{
     747    int rc = VINF_SUCCESS;
     748
     749    PDMAUDIOSTREAMCFG streamCfg;
     750    RT_ZERO(streamCfg);
     751
     752    switch (u8Strm)
     753    {
     754        case PI_INDEX:
     755            streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_LR_ADC_Rate);
     756            break;
     757
     758        case MC_INDEX:
     759            streamCfg.uHz = ichac97MixerGet(pThis, AC97_MIC_ADC_Rate);
     760            break;
     761
     762        case PO_INDEX:
     763            streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_Front_DAC_Rate);
     764            break;
     765
     766        default:
     767            rc = VERR_NOT_SUPPORTED;
     768            break;
     769    }
     770
     771    if (RT_FAILURE(rc))
     772        return rc;
     773
     774    if (streamCfg.uHz)
     775    {
    547776        streamCfg.cChannels     = 2;
    548777        streamCfg.enmFormat     = AUD_FMT_S16;
    549778        streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    550779
    551         char *pszDesc;
    552 
    553         switch (index)
    554         {
    555             case PI_INDEX: /* Line input. */
    556             {
    557                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    558                 {
    559                     if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.pi", uLUN) <= 0)
    560                     {
    561                         rc = VERR_NO_MEMORY;
    562                         break;
    563                     }
    564 
    565                     rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector,
    566                                                        pszDesc, PDMAUDIORECSOURCE_LINE_IN, &streamCfg, &pDrv->LineIn.pStrmIn);
    567                     LogFlowFunc(("LUN#%RU8: Created line input with rc=%Rrc\n", uLUN, rc));
    568                     if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
    569                     {
    570                         AudioMixerRemoveStream(pThis->pSinkLineIn, pDrv->LineIn.phStrmIn);
    571                         rc = AudioMixerAddStreamIn(pThis->pSinkLineIn,
    572                                                    pDrv->pConnector, pDrv->LineIn.pStrmIn,
    573                                                    0 /* uFlags */,
    574                                                    &pDrv->LineIn.phStrmIn);
    575                     }
    576 
    577                     RTStrFree(pszDesc);
    578                     uLUN++;
    579                 }
    580                 break;
    581             }
    582 
    583             case PO_INDEX: /* Output. */
    584             {
    585                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    586                 {
    587                     if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.po", uLUN) <= 0)
    588                     {
    589                         rc = VERR_NO_MEMORY;
    590                         break;
    591                     }
    592 
    593                     rc = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, &streamCfg, &pDrv->Out.pStrmOut);
    594                     LogFlowFunc(("LUN#%RU8: Created output with rc=%Rrc\n", uLUN, rc));
    595                     if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
    596                     {
    597                         AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
    598                         rc = AudioMixerAddStreamOut(pThis->pSinkOutput,
    599                                                     pDrv->pConnector, pDrv->Out.pStrmOut,
    600                                                     0 /* uFlags */,
    601                                                     &pDrv->Out.phStrmOut);
    602                     }
    603 
    604                     RTStrFree(pszDesc);
    605                     uLUN++;
    606                 }
    607                 break;
    608             }
    609 
    610             case MC_INDEX: /* Mic in */
    611             {
    612                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    613                 {
    614                     if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] ac97.mc", uLUN) <= 0)
    615                     {
    616                         rc = VERR_NO_MEMORY;
    617                         break;
    618                     }
    619 
    620                     rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector,
    621                                                        pszDesc, PDMAUDIORECSOURCE_MIC, &streamCfg, &pDrv->MicIn.pStrmIn);
    622                     LogFlowFunc(("LUN#%RU8: Created mic input with rc=%Rrc\n", uLUN, rc));
    623                     if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
    624                     {
    625                         AudioMixerRemoveStream(pThis->pSinkMicIn, pDrv->MicIn.phStrmIn);
    626                         rc = AudioMixerAddStreamIn(pThis->pSinkMicIn,
    627                                                    pDrv->pConnector, pDrv->MicIn.pStrmIn,
    628                                                    0 /* uFlags */,
    629                                                    &pDrv->MicIn.phStrmIn);
    630                     }
    631 
    632                     RTStrFree(pszDesc);
    633                     uLUN++;
    634                 }
    635                 break;
    636             }
    637 
    638             default:
    639                 AssertMsgFailed(("Unsupported index %d\n", index));
    640                 rc = VERR_NOT_SUPPORTED;
    641                 break;
    642         }
    643     }
    644     else
    645     {
    646         switch (index)
    647         {
    648             case PI_INDEX:
    649             {
    650                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    651                 {
    652                     pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pDrv->LineIn.pStrmIn);
    653                     AudioMixerRemoveStream(pThis->pSinkLineIn, pDrv->LineIn.phStrmIn);
    654 
    655                     pDrv->LineIn.pStrmIn  = NULL;
    656                     pDrv->LineIn.phStrmIn = NULL;
    657                 }
    658 
    659                 LogFlowFunc(("Closed line input\n"));
    660                 break;
    661             }
    662 
    663             case PO_INDEX:
    664             {
    665                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    666                 {
    667                     pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
    668                     AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
    669 
    670                     pDrv->Out.pStrmOut  = NULL;
    671                     pDrv->Out.phStrmOut = NULL;
    672                 }
    673 
    674                 LogFlowFunc(("Closed output\n"));
    675                 break;
    676             }
    677 
    678             case MC_INDEX:
    679             {
    680                 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    681                 {
    682                     pDrv->pConnector->pfnDestroyIn(pDrv->pConnector, pDrv->MicIn.pStrmIn);
    683                     AudioMixerRemoveStream(pThis->pSinkMicIn, pDrv->MicIn.phStrmIn);
    684 
    685                     pDrv->MicIn.pStrmIn  = NULL;
    686                     pDrv->MicIn.phStrmIn = NULL;
    687                 }
    688 
    689                 LogFlowFunc(("Closed microphone input\n"));
    690                 break;
    691             }
    692 
    693             default:
    694                 AssertMsgFailed(("Unsupported index %d\n", index));
    695                 break;
    696         }
    697 
    698         rc = VINF_SUCCESS;
    699     }
    700 
    701     AudioMixerInvalidate(pThis->pMixer);
    702 
    703     LogFlowFuncLeaveRC(rc);
    704 }
    705 
    706 /** @todo r=andy D'oh, pretty bad argument handling -- fix this! */
    707 static void ichac97ResetStreams(PAC97STATE pThis, uint8_t active[LAST_INDEX])
    708 {
    709     uint16_t uFreq = ichac97MixerLoad(pThis, AC97_PCM_LR_ADC_Rate);
    710     bool fEnable = RT_BOOL(active[PI_INDEX]);
    711     LogFlowFunc(("Input ADC uFreq=%RU16, fEnabled=%RTbool\n", uFreq, fEnable));
    712 
    713     ichac97OpenStream(pThis, PI_INDEX, uFreq);
    714 
    715     PAC97DRIVER pDrv;
    716     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    717         pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, fEnable);
    718 
    719     uFreq = ichac97MixerLoad(pThis, AC97_PCM_Front_DAC_Rate);
    720     fEnable = RT_BOOL(active[PO_INDEX]);
    721     LogFlowFunc(("Output DAC uFreq=%RU16, fEnabled=%RTbool\n", uFreq, fEnable));
    722 
    723     ichac97OpenStream(pThis, PO_INDEX, uFreq);
    724 
    725     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    726         pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, fEnable);
    727 
    728     uFreq = ichac97MixerLoad(pThis, AC97_MIC_ADC_Rate);
    729     fEnable = RT_BOOL(active[MC_INDEX]);
    730     LogFlowFunc(("Mic ADC uFreq=%RU16, fEnabled=%RTbool\n", uFreq, fEnable));
    731 
    732     ichac97OpenStream(pThis, MC_INDEX, uFreq);
    733 
    734     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    735         pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, fEnable);
    736 }
    737 
    738 static void ichac97SetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL mt, uint32_t val)
     780        return ichac97StreamInitEx(pThis, pStrmSt, u8Strm, &streamCfg);
     781    }
     782
     783    /* If no frequency is given, disable the stream. */
     784    return ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
     785}
     786
     787static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrmSt)
     788{
     789    return ichac97StreamInit(pThis, pStrmSt, pStrmSt->u8Strm);
     790}
     791
     792static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrmSt)
     793{
     794    AssertPtrReturnVoid(pThis);
     795    AssertPtrReturnVoid(pStrmSt);
     796
     797    LogFlowFunc(("uStrm=%RU8\n", pStrmSt->u8Strm));
     798}
     799
     800static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL mt, uint32_t val)
    739801{
    740802    int mute = (val >> MUTE_SHIFT) & 1;
     
    757819    LogFunc(("mt=%ld, val=%RX32, mute=%RTbool\n", mt, val, RT_BOOL(mute)));
    758820
     821    int rc;
     822
    759823#ifdef SOFT_VOLUME
    760824    if (pThis->pMixer) /* Device can be in reset state, so no mixer available. */
     
    764828        {
    765829            case PDMAUDIOMIXERCTL_VOLUME:
    766                 AudioMixerSetMasterVolume(pThis->pMixer, &vol);
     830                rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
    767831                break;
    768832
    769833            case PDMAUDIOMIXERCTL_PCM:
    770                 AudioMixerSetSinkVolume(pThis->pSinkOutput, &vol);
     834                rc = AudioMixerSetSinkVolume(pThis->pSinkOutput, &vol);
    771835                break;
    772836
    773837            case PDMAUDIOMIXERCTL_MIC_IN:
    774                 AudioMixerSetSinkVolume(pThis->pSinkMicIn, &vol);
     838                rc = AudioMixerSetSinkVolume(pThis->pSinkMicIn, &vol);
    775839                break;
    776840
    777841            case PDMAUDIOMIXERCTL_LINE_IN:
    778                 AudioMixerSetSinkVolume(pThis->pSinkLineIn, &vol);
     842                rc = AudioMixerSetSinkVolume(pThis->pSinkLineIn, &vol);
    779843                break;
    780844
    781845            default:
     846                rc = VERR_NOT_SUPPORTED;
    782847                break;
    783848        }
    784849    }
     850
     851    if (RT_FAILURE(rc))
     852        return rc;
     853#else
     854    rc = VINF_SUCCESS;
    785855#endif /* SOFT_VOLUME */
    786856
     
    801871        val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
    802872
    803     ichac97MixerStore(pThis, index, val);
     873    ichac97MixerSet(pThis, index, val);
     874
     875    return rc;
    804876}
    805877
     
    849921    rs = ichac97RecSourceToIndex(ars);
    850922    ls = ichac97RecSourceToIndex(als);
    851     ichac97MixerStore(pThis, AC97_Record_Select, rs | (ls << 8));
     923    ichac97MixerSet(pThis, AC97_Record_Select, rs | (ls << 8));
    852924}
    853925
     
    860932    RT_ZERO(pThis->mixer_data);
    861933
    862     /*
    863      * Tear down mixer and streams.
    864      */
    865     if (pThis->pMixer)
    866     {
    867         AudioMixerDestroy(pThis->pMixer);
    868         pThis->pMixer = NULL;
    869     }
    870 
    871     pThis->pSinkLineIn = NULL;
    872     pThis->pSinkMicIn  = NULL;
    873     pThis->pSinkOutput = NULL;
    874 
    875     PAC97DRIVER pDrv;
    876     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    877     {
    878         pDrv->pConnector->pfnDestroyIn (pDrv->pConnector, pDrv->LineIn.pStrmIn);
    879         RT_ZERO(pDrv->LineIn);
    880 
    881         pDrv->pConnector->pfnDestroyIn (pDrv->pConnector, pDrv->MicIn.pStrmIn);
    882         RT_ZERO(pDrv->MicIn);
    883 
    884         pDrv->pConnector->pfnDestroyOut(pDrv->pConnector, pDrv->Out.pStrmOut);
    885         RT_ZERO(pDrv->Out);
    886     }
    887 
    888     /*
    889      * (Re-)Create the mixer. The streams will be created on demand later.
    890      */
    891     int rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
    892     if (RT_FAILURE(rc))
    893         return rc;
    894 
    895     do
    896     {
    897         /* Set a default audio format for our mixer. */
    898         PDMAUDIOSTREAMCFG streamCfg;
    899         streamCfg.uHz           = 44100;
    900         streamCfg.cChannels     = 2;
    901         streamCfg.enmFormat     = AUD_FMT_S16;
    902         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    903 
    904         rc = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
    905         if (RT_FAILURE(rc))
    906             break;
    907 
    908         /* Add all required audio sinks. */
    909         rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
    910         if (RT_FAILURE(rc))
    911             break;
    912 
    913         rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
    914         if (RT_FAILURE(rc))
    915             break;
    916 
    917         rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
    918         if (RT_FAILURE(rc))
    919             break;
    920 
    921     } while (0);
    922 
    923934    /* Note: Make sure to reset all registers first before bailing out on error. */
    924935
    925     ichac97MixerStore(pThis, AC97_Reset                   , 0x0000); /* 6940 */
    926     ichac97MixerStore(pThis, AC97_Master_Volume_Mono_Mute , 0x8000);
    927     ichac97MixerStore(pThis, AC97_PC_BEEP_Volume_Mute     , 0x0000);
    928 
    929     ichac97MixerStore(pThis, AC97_Phone_Volume_Mute       , 0x8008);
    930     ichac97MixerStore(pThis, AC97_Mic_Volume_Mute         , 0x8008);
    931     ichac97MixerStore(pThis, AC97_CD_Volume_Mute          , 0x8808);
    932     ichac97MixerStore(pThis, AC97_Aux_Volume_Mute         , 0x8808);
    933     ichac97MixerStore(pThis, AC97_Record_Gain_Mic_Mute    , 0x8000);
    934     ichac97MixerStore(pThis, AC97_General_Purpose         , 0x0000);
    935     ichac97MixerStore(pThis, AC97_3D_Control              , 0x0000);
    936     ichac97MixerStore(pThis, AC97_Powerdown_Ctrl_Stat     , 0x000f);
    937 
    938     ichac97MixerStore(pThis, AC97_Extended_Audio_ID       , 0x0809);
    939     ichac97MixerStore(pThis, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
    940     ichac97MixerStore(pThis, AC97_PCM_Front_DAC_Rate      , 0xbb80);
    941     ichac97MixerStore(pThis, AC97_PCM_Surround_DAC_Rate   , 0xbb80);
    942     ichac97MixerStore(pThis, AC97_PCM_LFE_DAC_Rate        , 0xbb80);
    943     ichac97MixerStore(pThis, AC97_PCM_LR_ADC_Rate         , 0xbb80);
    944     ichac97MixerStore(pThis, AC97_MIC_ADC_Rate            , 0xbb80);
     936    ichac97MixerSet(pThis, AC97_Reset                   , 0x0000); /* 6940 */
     937    ichac97MixerSet(pThis, AC97_Master_Volume_Mono_Mute , 0x8000);
     938    ichac97MixerSet(pThis, AC97_PC_BEEP_Volume_Mute     , 0x0000);
     939
     940    ichac97MixerSet(pThis, AC97_Phone_Volume_Mute       , 0x8008);
     941    ichac97MixerSet(pThis, AC97_Mic_Volume_Mute         , 0x8008);
     942    ichac97MixerSet(pThis, AC97_CD_Volume_Mute          , 0x8808);
     943    ichac97MixerSet(pThis, AC97_Aux_Volume_Mute         , 0x8808);
     944    ichac97MixerSet(pThis, AC97_Record_Gain_Mic_Mute    , 0x8000);
     945    ichac97MixerSet(pThis, AC97_General_Purpose         , 0x0000);
     946    ichac97MixerSet(pThis, AC97_3D_Control              , 0x0000);
     947    ichac97MixerSet(pThis, AC97_Powerdown_Ctrl_Stat     , 0x000f);
     948
     949    ichac97MixerSet(pThis, AC97_Extended_Audio_ID       , 0x0809);
     950    ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
     951    ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate      , 0xbb80);
     952    ichac97MixerSet(pThis, AC97_PCM_Surround_DAC_Rate   , 0xbb80);
     953    ichac97MixerSet(pThis, AC97_PCM_LFE_DAC_Rate        , 0xbb80);
     954    ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate         , 0xbb80);
     955    ichac97MixerSet(pThis, AC97_MIC_ADC_Rate            , 0xbb80);
    945956
    946957    if (pThis->uCodecModel == Codec_AD1980)
    947958    {
    948959        /* Analog Devices 1980 (AD1980) */
    949         ichac97MixerStore(pThis, AC97_Reset                   , 0x0010);    /* Headphones. */
    950         ichac97MixerStore(pThis, AC97_Vendor_ID1              , 0x4144);
    951         ichac97MixerStore(pThis, AC97_Vendor_ID2              , 0x5370);
    952         ichac97MixerStore(pThis, AC97_Headphone_Volume_Mute   , 0x8000);
     960        ichac97MixerSet(pThis, AC97_Reset                   , 0x0010);    /* Headphones. */
     961        ichac97MixerSet(pThis, AC97_Vendor_ID1              , 0x4144);
     962        ichac97MixerSet(pThis, AC97_Vendor_ID2              , 0x5370);
     963        ichac97MixerSet(pThis, AC97_Headphone_Volume_Mute   , 0x8000);
    953964    }
    954965    else if (pThis->uCodecModel == Codec_AD1981B)
    955966    {
    956967        /* Analog Devices 1981B (AD1981B) */
    957         ichac97MixerStore(pThis, AC97_Vendor_ID1              , 0x4144);
    958         ichac97MixerStore(pThis, AC97_Vendor_ID2              , 0x5374);
     968        ichac97MixerSet(pThis, AC97_Vendor_ID1              , 0x4144);
     969        ichac97MixerSet(pThis, AC97_Vendor_ID2              , 0x5374);
    959970    }
    960971    else
    961972    {
    962973        /* Sigmatel 9700 (STAC9700) */
    963         ichac97MixerStore(pThis, AC97_Vendor_ID1              , 0x8384);
    964         ichac97MixerStore(pThis, AC97_Vendor_ID2              , 0x7600); /* 7608 */
     974        ichac97MixerSet(pThis, AC97_Vendor_ID1              , 0x8384);
     975        ichac97MixerSet(pThis, AC97_Vendor_ID2              , 0x7600); /* 7608 */
    965976    }
    966977    ichac97RecordSelect(pThis, 0);
    967978
    968     ichac97SetVolume(pThis, AC97_Master_Volume_Mute,  PDMAUDIOMIXERCTL_VOLUME,  0x8000);
    969     ichac97SetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_PCM,     0x8808);
    970     ichac97SetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808);
    971 
    972     /* Reset all streams. */
    973     uint8_t active[LAST_INDEX] = { 0 };
    974     ichac97ResetStreams(pThis, active);
    975 
    976     return rc;
     979    ichac97MixerSetVolume(pThis, AC97_Master_Volume_Mute,  PDMAUDIOMIXERCTL_VOLUME,  0x8000);
     980    ichac97MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_PCM,     0x8808);
     981    ichac97MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808);
     982
     983    return VINF_SUCCESS;
    977984}
    978985
     
    981988 *
    982989 * @return  IPRT status code.
    983  * @return  int
    984990 * @param   pThis
    985  * @param   pReg
     991 * @param   pStrmSt
    986992 * @param   cbMax
    987993 * @param   pcbWritten
    988994 */
    989 static int ichac97WriteAudio(PAC97STATE pThis, PAC97BMREG pReg, uint32_t cbMax, uint32_t *pcbWritten)
    990 {
    991     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    992     AssertPtrReturn(pReg, VERR_INVALID_POINTER);
    993     AssertReturn(cbMax, VERR_INVALID_PARAMETER);
    994     AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);
     995static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbWritten)
     996{
     997    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
     998    AssertPtrReturn(pStrmSt,    VERR_INVALID_POINTER);
     999    AssertReturn(cbMax,         VERR_INVALID_PARAMETER);
     1000    /* pcbWritten is optional. */
    9951001
    9961002    PPDMDEVINS  pDevIns = ICHAC97STATE_2_DEVINS(pThis);
    997 
    998     uint32_t    addr           = pReg->bd.addr;
     1003    PAC97BMREGS pRegs   = &pStrmSt->Regs;
     1004
     1005    uint32_t    addr           = pRegs->bd.addr;
    9991006    uint32_t    cbWrittenTotal = 0;
    10001007    uint32_t    cbToRead;
    10011008
    1002     uint32_t cbToWrite = RT_MIN((uint32_t)(pReg->picb << 1), cbMax);
     1009    uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax);
    10031010    if (!cbToWrite)
    10041011    {
    1005         *pcbWritten = 0;
     1012        if (pcbWritten)
     1013            *pcbWritten = 0;
    10061014        return VINF_EOF;
    10071015    }
     
    10091017    int rc = VINF_SUCCESS;
    10101018
    1011     LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pReg, cbMax, cbToWrite));
     1019    LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite));
    10121020
    10131021    while (cbToWrite)
     
    10371045    }
    10381046
    1039     pReg->bd.addr = addr;
     1047    pRegs->bd.addr = addr;
    10401048
    10411049    if (RT_SUCCESS(rc))
     
    10521060        }
    10531061
    1054         *pcbWritten = cbWrittenTotal;
     1062        if (pcbWritten)
     1063            *pcbWritten = cbWrittenTotal;
    10551064    }
    10561065
     
    10781087    while (cbElapsed)
    10791088    {
    1080         uint32_t cbWrittenMin = UINT32_MAX;
    1081 
    10821089        uint32_t cbToWrite = RT_MIN(cbElapsed, (uint32_t)sizeof(pThis->silence));
    1083         while (cbToWrite)
    1084         {
    1085             PAC97DRIVER pDrv;
    1086             uint32_t cbWritten;
    1087             RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     1090        uint32_t cbWrittenToStream;
     1091        int rc2;
     1092
     1093        PAC97DRIVER pDrv;
     1094        RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     1095        {
     1096            if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
    10881097            {
    1089                 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    1090                                                      pThis->silence, cbToWrite, &cbWritten);
    1091                 if (RT_FAILURE(rc2))
    1092                     continue;
    1093 
    1094                 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten);
     1098                rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
     1099                                                 pThis->silence, cbToWrite, &cbWrittenToStream);
     1100                if (RT_SUCCESS(rc2))
     1101                {
     1102                    if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
     1103                        LogFlowFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, expect lags\n",
     1104                                     pDrv->uLUN, cbWrittenToStream, cbToWrite));
     1105                }
    10951106            }
    1096 
    1097             if (!cbWrittenMin)
    1098                 return;
    1099 
    1100             Assert(cbToWrite >= cbWrittenMin);
    1101             cbToWrite -= cbWrittenMin;
    1102             Assert(cbElapsed >= cbWrittenMin);
    1103             cbElapsed -= cbWrittenMin;
    1104         }
    1105     }
    1106 }
    1107 
    1108 static int ichac97ReadAudio(PAC97STATE pThis, PAC97BMREG pReg, uint32_t cbMax, uint32_t *pcbRead)
    1109 {
    1110     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1111     AssertPtrReturn(pReg, VERR_INVALID_POINTER);
    1112     AssertReturn(cbMax, VERR_INVALID_PARAMETER);
    1113     AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
     1107            else /* Stream disabled, not fatal. */
     1108            {
     1109                cbWrittenToStream = 0;
     1110                rc2 = VERR_NOT_AVAILABLE;
     1111                /* Keep going. */
     1112            }
     1113        }
     1114
     1115        /* Always report all data as being written;
     1116         * backends who were not able to catch up have to deal with it themselves. */
     1117        Assert(cbElapsed >= cbToWrite);
     1118        cbElapsed -= cbToWrite;
     1119    }
     1120}
     1121
     1122static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbRead)
     1123{
     1124    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1125    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1126    AssertReturn(cbMax,      VERR_INVALID_PARAMETER);
     1127    /* pcbRead is optional. */
    11141128
    11151129    PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
     1130    PAC97BMREGS pRegs  = &pStrmSt->Regs;
     1131
     1132    /* Select audio sink to process. */
     1133    AssertMsg(pStrmSt->u8Strm != PO_INDEX, ("Can't read from output\n"));
     1134    PAUDMIXSINK pSink = pStrmSt->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
     1135    AssertPtr(pSink);
     1136
     1137    uint32_t cbRead   = 0;
     1138
     1139    uint32_t cbMixBuf = cbMax;
     1140    uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1), cbMixBuf);
     1141
     1142    if (!cbToRead)
     1143    {
     1144        if (pcbRead)
     1145            *pcbRead = 0;
     1146        return VINF_EOF;
     1147    }
    11161148
    11171149    int rc;
    1118 
    1119     /* Select audio sink to process. */
    1120     PAUDMIXSINK pSink = (pReg - pThis->bm_regs) == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
    1121     AssertPtr(pSink);
    1122 
    1123     uint32_t cbRead = 0;
    1124 
    1125     uint32_t cbMixBuf = cbMax;
    1126     uint32_t cbToRead = RT_MIN((uint32_t)(pReg->picb << 1), cbMixBuf);
    1127 
    1128     if (!cbToRead)
    1129     {
    1130         *pcbRead = 0;
    1131         return VINF_EOF;
    1132     }
    11331150
    11341151    uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbMixBuf);
     
    11391156            && cbRead)
    11401157        {
    1141             PDMDevHlpPCIPhysWrite(pDevIns, pReg->bd.addr, pvMixBuf, cbRead);
    1142             pReg->bd.addr += cbRead;
     1158            PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, pvMixBuf, cbRead);
     1159            pRegs->bd.addr += cbRead;
    11431160        }
    11441161
     
    11501167    if (RT_SUCCESS(rc))
    11511168    {
    1152         Assert(cbRead);
    1153         *pcbRead = cbRead;
     1169        if (pcbRead)
     1170            *pcbRead = cbRead;
    11541171    }
    11551172
     
    11731190    PAC97DRIVER pDrv;
    11741191
    1175     uint32_t cbIn, cbOut, cSamplesLive;
     1192    uint32_t cbIn, cbOut;
    11761193
    11771194    uint64_t uTicksNow     = PDMDevHlpTMTimeVirtGet(pDevIns);
     
    11811198    pThis->uTimerTS = uTicksNow;
    11821199
     1200    LogFlowFunc(("pDevIns=%p\n", pDevIns));
     1201
    11831202    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    11841203    {
     
    11861205        rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
    11871206                                              &cbIn, &cbOut, NULL /* cSamplesLive */);
     1207        LogFlowFunc(("rc1=%Rrc\n", rc));
    11881208        if (RT_SUCCESS(rc))
    11891209            rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
    11901210
     1211        LogFlowFunc(("rc2=%Rrc\n", rc));
     1212
    11911213        uint32_t cSamplesMin  = (int)((2 * uTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + uTicksPerSec) / uTicksPerSec / 2);
    11921214        uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
     1215
     1216        LogFlowFunc(("rc3=%Rrc\n", rc));
    11931217
    11941218        LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbOut=%RU32, cSamplesMin=%RU32, cbSamplesMin=%RU32\n",
     
    12351259#endif
    12361260
    1237 static int ichac97TransferAudio(PAC97STATE pThis, int index, uint32_t cbElapsed)
    1238 {
    1239     LogFlowFunc(("pThis=%p, index=%d, cbElapsed=%RU32\n", pThis, index, cbElapsed));
    1240 
    1241     PAC97BMREG pReg = &pThis->bm_regs[index];
    1242     if (pReg->sr & SR_DCH) /* Controller halted? */
    1243     {
    1244         if (pReg->cr & CR_RPBM)
    1245         {
    1246             switch (index)
     1261static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed)
     1262{
     1263    LogFlowFunc(("pThis=%p, enmSrc=%RU32, cbElapsed=%RU32\n", pThis, enmSrc, cbElapsed));
     1264
     1265    PAC97STREAM pStrmSt;
     1266    switch (enmSrc)
     1267    {
     1268        case PI_INDEX: pStrmSt = &pThis->StrmStLineIn; break;
     1269        case MC_INDEX: pStrmSt = &pThis->StrmStMicIn;  break;
     1270        case PO_INDEX: pStrmSt = &pThis->StrmStOut;    break;
     1271        default:
     1272        {
     1273            AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
     1274            return VERR_NOT_SUPPORTED;
     1275        }
     1276    }
     1277
     1278    PAC97BMREGS pRegs = &pStrmSt->Regs;
     1279
     1280    if (pRegs->sr & SR_DCH) /* Controller halted? */
     1281    {
     1282        if (pRegs->cr & CR_RPBM)
     1283        {
     1284            switch (enmSrc)
    12471285            {
    12481286                case PO_INDEX:
     
    12631301    while (cbElapsed >> 1)
    12641302    {
    1265         if (!pReg->bd_valid)
     1303        if (!pRegs->bd_valid)
    12661304        {
    12671305            LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n"));
    1268             ichac97FetchBufDesc(pThis, pReg);
    1269         }
    1270 
    1271         if (!pReg->picb) /* Got a new buffer descriptor, that is, the position is 0? */
     1306            ichac97StreamFetchBDLE(pThis, pStrmSt);
     1307        }
     1308
     1309        if (!pRegs->picb) /* Got a new buffer descriptor, that is, the position is 0? */
    12721310        {
    12731311            LogFlowFunc(("Fresh buffer descriptor %RU8 is empty, addr=%#x, len=%#x, skipping\n",
    1274                          pReg->civ, pReg->bd.addr, pReg->bd.ctl_len));
    1275             if (pReg->civ == pReg->lvi)
     1312                         pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len));
     1313            if (pRegs->civ == pRegs->lvi)
    12761314            {
    1277                 pReg->sr |= SR_DCH; /* CELV? */
     1315                pRegs->sr |= SR_DCH; /* CELV? */
    12781316                pThis->bup_flag = 0;
    12791317
     
    12821320            }
    12831321
    1284             pReg->sr &= ~SR_CELV;
    1285             pReg->civ = pReg->piv;
    1286             pReg->piv = (pReg->piv + 1) % 32;
    1287 
    1288             ichac97FetchBufDesc(pThis, pReg);
     1322            pRegs->sr &= ~SR_CELV;
     1323            pRegs->civ = pRegs->piv;
     1324            pRegs->piv = (pRegs->piv + 1) % 32;
     1325
     1326            ichac97StreamFetchBDLE(pThis, pStrmSt);
    12891327            continue;
    12901328        }
    12911329
    12921330        uint32_t cbTransferred;
    1293         switch (index)
     1331        switch (enmSrc)
    12941332        {
    12951333            case PO_INDEX:
    12961334            {
    1297                 rc = ichac97WriteAudio(pThis, pReg, cbElapsed, &cbTransferred);
     1335                rc = ichac97WriteAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
    12981336                if (   RT_SUCCESS(rc)
    12991337                    && cbTransferred)
     
    13031341                    cbElapsed      -= cbTransferred;
    13041342                    Assert((cbTransferred & 1) == 0);    /* Else the following shift won't work */
    1305                     pReg->picb     -= (cbTransferred >> 1);
     1343                    pRegs->picb    -= (cbTransferred >> 1);
    13061344                }
    13071345                break;
     
    13111349            case MC_INDEX:
    13121350            {
    1313                 rc = ichac97ReadAudio(pThis, pReg, cbElapsed, &cbTransferred);
     1351                rc = ichac97ReadAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
    13141352                if (   RT_SUCCESS(rc)
    13151353                    && cbTransferred)
     
    13181356                    cbElapsed  -= cbTransferred;
    13191357                    Assert((cbTransferred & 1) == 0);    /* Else the following shift won't work */
    1320                     pReg->picb -= (cbTransferred >> 1);
     1358                    pRegs->picb -= (cbTransferred >> 1);
    13211359                }
    13221360                break;
     
    13241362
    13251363            default:
    1326                 AssertMsgFailed(("Index %ld not supported\n", index));
     1364                AssertMsgFailed(("Source %RU32 not supported\n", enmSrc));
    13271365                rc = VERR_NOT_SUPPORTED;
    13281366                break;
    13291367        }
    13301368
    1331         LogFlowFunc(("pReg->picb=%#x, cbWrittenTotal=%RU32\n", pReg->picb, cbWrittenTotal));
    1332 
    1333         if (!pReg->picb)
    1334         {
    1335             uint32_t new_sr = pReg->sr & ~SR_CELV;
    1336 
    1337             if (pReg->bd.ctl_len & BD_IOC)
     1369        LogFlowFunc(("pReg->picb=%#x, cbWrittenTotal=%RU32\n", pRegs->picb, cbWrittenTotal));
     1370
     1371        if (!pRegs->picb)
     1372        {
     1373            uint32_t new_sr = pRegs->sr & ~SR_CELV;
     1374
     1375            if (pRegs->bd.ctl_len & BD_IOC)
    13381376            {
    13391377                new_sr |= SR_BCIS;
    13401378            }
    13411379
    1342             if (pReg->civ == pReg->lvi)
     1380            if (pRegs->civ == pRegs->lvi)
    13431381            {
    1344                 LogFlowFunc(("Underrun civ (%RU8) == lvi (%RU8)\n", pReg->civ, pReg->lvi));
     1382                LogFlowFunc(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi));
    13451383                new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
    1346                 pThis->bup_flag = (pReg->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
     1384                pThis->bup_flag = (pRegs->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
    13471385
    13481386                rc = VINF_EOF;
     
    13501388            else
    13511389            {
    1352                 pReg->civ = pReg->piv;
    1353                 pReg->piv = (pReg->piv + 1) % 32;
    1354                 ichac97FetchBufDesc(pThis, pReg);
     1390                pRegs->civ = pRegs->piv;
     1391                pRegs->piv = (pRegs->piv + 1) % 32;
     1392                ichac97StreamFetchBDLE(pThis, pStrmSt);
    13551393            }
    13561394
    1357             ichac97UpdateStatus(pThis, pReg, new_sr);
     1395            ichac97StreamUpdateStatus(pThis, pStrmSt, new_sr);
    13581396        }
    13591397
     
    13721410 * @callback_method_impl{FNIOMIOPORTIN}
    13731411 */
    1374 static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
    1375 {
    1376     PAC97STATE pThis = (PAC97STATE)pvUser;
    1377 
    1378     switch (cb)
     1412static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
     1413                                               uint32_t *pu32Val, unsigned cbVal)
     1414{
     1415    PAC97STATE pThis    = (PAC97STATE)pvUser;
     1416
     1417    /* Get the index of the NABMBAR port. */
     1418    const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
     1419
     1420    PAC97STREAM pStrmSt     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
     1421    PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
     1422
     1423    switch (cbVal)
    13791424    {
    13801425        case 1:
    13811426        {
    1382             PAC97BMREG pReg = NULL;
    1383             uint32_t index = Port - pThis->IOPortBase[1];
    1384             *pu32 = ~0U;
    1385 
    1386             switch (index)
     1427            switch (uPortIdx)
    13871428            {
    13881429                case CAS:
    13891430                    /* Codec Access Semaphore Register */
    13901431                    LogFlowFunc(("CAS %d\n", pThis->cas));
    1391                     *pu32 = pThis->cas;
     1432                    *pu32Val = pThis->cas;
    13921433                    pThis->cas = 1;
    13931434                    break;
     
    13961437                case MC_CIV:
    13971438                    /* Current Index Value Register */
    1398                     pReg = &pThis->bm_regs[GET_BM(index)];
    1399                     *pu32 = pReg->civ;
    1400                     LogFlowFunc(("CIV[%d] -> %#x\n", GET_BM(index), *pu32));
     1439                    *pu32Val = pRegs->civ;
     1440                    LogFlowFunc(("CIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14011441                    break;
    14021442                case PI_LVI:
     
    14041444                case MC_LVI:
    14051445                    /* Last Valid Index Register */
    1406                     pReg = &pThis->bm_regs[GET_BM(index)];
    1407                     *pu32 = pReg->lvi;
    1408                     LogFlowFunc(("LVI[%d] -> %#x\n", GET_BM(index), *pu32));
     1446                    *pu32Val = pRegs->lvi;
     1447                    LogFlowFunc(("LVI[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14091448                    break;
    14101449                case PI_PIV:
     
    14121451                case MC_PIV:
    14131452                    /* Prefetched Index Value Register */
    1414                     pReg = &pThis->bm_regs[GET_BM(index)];
    1415                     *pu32 = pReg->piv;
    1416                     LogFlowFunc(("PIV[%d] -> %#x\n", GET_BM(index), *pu32));
     1453                    *pu32Val = pRegs->piv;
     1454                    LogFlowFunc(("PIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14171455                    break;
    14181456                case PI_CR:
     
    14201458                case MC_CR:
    14211459                    /* Control Register */
    1422                     pReg = &pThis->bm_regs[GET_BM(index)];
    1423                     *pu32 = pReg->cr;
    1424                     LogFlowFunc(("CR[%d] -> %#x\n", GET_BM(index), *pu32));
     1460                    *pu32Val = pRegs->cr;
     1461                    LogFlowFunc(("CR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14251462                    break;
    14261463                case PI_SR:
     
    14281465                case MC_SR:
    14291466                    /* Status Register (lower part) */
    1430                     pReg = &pThis->bm_regs[GET_BM(index)];
    1431                     *pu32 = pReg->sr & 0xff;
    1432                     LogFlowFunc(("SRb[%d] -> %#x\n", GET_BM(index), *pu32));
     1467                    *pu32Val = pRegs->sr & 0xff; /** @todo r=andy Use RT_LO_U8. */
     1468                    LogFlowFunc(("SRb[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14331469                    break;
    14341470                default:
    1435                     LogFlowFunc(("U nabm readb %#x -> %#x\n", Port, *pu32));
     1471                    *pu32Val = UINT32_MAX;
     1472                    LogFlowFunc(("U nabm readb %#x -> %#x\n", Port, *pu32Val));
    14361473                    break;
    14371474            }
     
    14411478        case 2:
    14421479        {
    1443             PAC97BMREG pReg = NULL;
    1444             uint32_t index = Port - pThis->IOPortBase[1];
    1445             *pu32 = ~0U;
    1446 
    1447             switch (index)
     1480            switch (uPortIdx)
    14481481            {
    14491482                case PI_SR:
     
    14511484                case MC_SR:
    14521485                    /* Status Register */
    1453                     pReg = &pThis->bm_regs[GET_BM(index)];
    1454                     *pu32 = pReg->sr;
    1455                     LogFlowFunc(("SR[%d] -> %#x\n", GET_BM(index), *pu32));
     1486                    *pu32Val = pRegs->sr;
     1487                    LogFlowFunc(("SR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14561488                    break;
    14571489                case PI_PICB:
     
    14591491                case MC_PICB:
    14601492                    /* Position in Current Buffer Register */
    1461                     pReg = &pThis->bm_regs[GET_BM(index)];
    1462                     *pu32 = pReg->picb;
    1463                     LogFlowFunc(("PICB[%d] -> %#x\n", GET_BM(index), *pu32));
     1493                    *pu32Val = pRegs->picb;
     1494                    LogFlowFunc(("PICB[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14641495                    break;
    14651496                default:
    1466                     LogFlowFunc(("U nabm readw %#x -> %#x\n", Port, *pu32));
     1497                    *pu32Val = UINT32_MAX;
     1498                    LogFlowFunc(("U nabm readw %#x -> %#x\n", Port, *pu32Val));
    14671499                    break;
    14681500            }
     
    14721504        case 4:
    14731505        {
    1474             PAC97BMREG pReg = NULL;
    1475             uint32_t index = Port - pThis->IOPortBase[1];
    1476             *pu32 = ~0U;
    1477 
    1478             switch (index)
     1506            switch (uPortIdx)
    14791507            {
    14801508                case PI_BDBAR:
     
    14821510                case MC_BDBAR:
    14831511                    /* Buffer Descriptor Base Address Register */
    1484                     pReg = &pThis->bm_regs[GET_BM(index)];
    1485                     *pu32 = pReg->bdbar;
    1486                     LogFlowFunc(("BMADDR[%d] -> %#x\n", GET_BM(index), *pu32));
     1512                    *pu32Val = pRegs->bdbar;
     1513                    LogFlowFunc(("BMADDR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    14871514                    break;
    14881515                case PI_CIV:
     
    14921519                     *                Last Valid Index Register +
    14931520                     *                Status Register */
    1494                     pReg = &pThis->bm_regs[GET_BM(index)];
    1495                     *pu32 = pReg->civ | (pReg->lvi << 8) | (pReg->sr << 16);
    1496                     LogFlowFunc(("CIV LVI SR[%d] -> %#x, %#x, %#x\n", GET_BM(index), pReg->civ, pReg->lvi, pReg->sr));
     1521                    *pu32Val = pRegs->civ | (pRegs->lvi << 8) | (pRegs->sr << 16); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
     1522                    LogFlowFunc(("CIV LVI SR[%d] -> %#x, %#x, %#x\n",
     1523                                 AC97_PORT2IDX(uPortIdx), pRegs->civ, pRegs->lvi, pRegs->sr));
    14971524                    break;
    14981525                case PI_PICB:
     
    15021529                     *                Prefetched Index Value Register +
    15031530                     *                Control Register */
    1504                     pReg = &pThis->bm_regs[GET_BM(index)];
    1505                     *pu32 = pReg->picb | (pReg->piv << 16) | (pReg->cr << 24);
    1506                     LogFlowFunc(("PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM(index), *pu32, pReg->picb, pReg->piv, pReg->cr));
     1531                    *pu32Val = pRegs->picb | (pRegs->piv << 16) | (pRegs->cr << 24); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
     1532                    LogFlowFunc(("PICB PIV CR[%d] -> %#x %#x %#x %#x\n",
     1533                                 AC97_PORT2IDX(uPortIdx), *pu32Val, pRegs->picb, pRegs->piv, pRegs->cr));
    15071534                    break;
    15081535                case GLOB_CNT:
    15091536                    /* Global Control */
    1510                     *pu32 = pThis->glob_cnt;
    1511                     LogFlowFunc(("glob_cnt -> %#x\n", *pu32));
     1537                    *pu32Val = pThis->glob_cnt;
     1538                    LogFlowFunc(("glob_cnt -> %#x\n", *pu32Val));
    15121539                    break;
    15131540                case GLOB_STA:
    15141541                    /* Global Status */
    1515                     *pu32 = pThis->glob_sta | GS_S0CR;
    1516                     LogFlowFunc(("glob_sta -> %#x\n", *pu32));
     1542                    *pu32Val = pThis->glob_sta | GS_S0CR;
     1543                    LogFlowFunc(("glob_sta -> %#x\n", *pu32Val));
    15171544                    break;
    15181545                default:
    1519                     LogFlowFunc(("U nabm readl %#x -> %#x\n", Port, *pu32));
     1546                    *pu32Val = UINT32_MAX;
     1547                    LogFlowFunc(("U nabm readl %#x -> %#x\n", Port, *pu32Val));
    15201548                    break;
    15211549            }
     
    15321560 * @callback_method_impl{FNIOMIOPORTOUT}
    15331561 */
    1534 static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
    1535 {
    1536     PAC97STATE pThis = (PAC97STATE)pvUser;
    1537 
    1538     switch (cb)
     1562static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
     1563                                                uint32_t u32Val, unsigned cbVal)
     1564{
     1565    PAC97STATE  pThis   = (PAC97STATE)pvUser;
     1566
     1567    /* Get the index of the NABMBAR register. */
     1568    const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
     1569
     1570    PAC97STREAM pStrmSt     = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
     1571    PAC97BMREGS pRegs       = pStrmSt ? &pStrmSt->Regs : NULL;
     1572
     1573    switch (cbVal)
    15391574    {
    15401575        case 1:
    15411576        {
    1542             PAC97BMREG pReg = NULL;
    1543             uint32_t index = Port - pThis->IOPortBase[1];
    1544             switch (index)
     1577            switch (uPortIdx)
    15451578            {
    15461579                case PI_LVI:
     
    15481581                case MC_LVI:
    15491582                    /* Last Valid Index */
    1550                     pReg = &pThis->bm_regs[GET_BM(index)];
    1551                     if ((pReg->cr & CR_RPBM) && (pReg->sr & SR_DCH))
     1583                    if ((pRegs->cr & CR_RPBM) && (pRegs->sr & SR_DCH))
    15521584                    {
    1553                         pReg->sr &= ~(SR_DCH | SR_CELV);
    1554                         pReg->civ = pReg->piv;
    1555                         pReg->piv = (pReg->piv + 1) % 32;
    1556                         ichac97FetchBufDesc(pThis, pReg);
     1585                        pRegs->sr &= ~(SR_DCH | SR_CELV);
     1586                        pRegs->civ = pRegs->piv;
     1587                        pRegs->piv = (pRegs->piv + 1) % 32;
     1588
     1589                        ichac97StreamFetchBDLE(pThis, pStrmSt);
    15571590                    }
    1558                     pReg->lvi = u32 % 32;
    1559                     LogFlowFunc(("LVI[%d] <- %#x\n", GET_BM(index), u32));
     1591                    pRegs->lvi = u32Val % 32;
     1592                    LogFlowFunc(("LVI[%d] <- %#x\n", AC97_PORT2IDX(uPortIdx), u32Val));
    15601593                    break;
    15611594                case PI_CR:
    15621595                case PO_CR:
    15631596                case MC_CR:
     1597                {
    15641598                    /* Control Register */
    1565                     pReg = &pThis->bm_regs[GET_BM(index)];
    1566                     if (u32 & CR_RR)
    1567                         ichac97ResetBMRegs(pThis, pReg);
     1599                    if (u32Val & CR_RR) /* Busmaster reset */
     1600                    {
     1601                        ichac97StreamResetBMRegs(pThis, pStrmSt);
     1602                    }
    15681603                    else
    15691604                    {
    1570                         pReg->cr = u32 & CR_VALID_MASK;
    1571                         if (!(pReg->cr & CR_RPBM))
     1605                        pRegs->cr = u32Val & CR_VALID_MASK;
     1606                        if (!(pRegs->cr & CR_RPBM))
    15721607                        {
    1573                             ichac97StreamSetActive(pThis, pReg - pThis->bm_regs, 0);
    1574                             pReg->sr |= SR_DCH;
     1608                            ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
     1609                            pRegs->sr |= SR_DCH;
    15751610                        }
    15761611                        else
    15771612                        {
    1578                             pReg->civ = pReg->piv;
    1579                             pReg->piv = (pReg->piv + 1) % 32;
    1580                             ichac97FetchBufDesc(pThis, pReg);
    1581                             pReg->sr &= ~SR_DCH;
    1582                             ichac97StreamSetActive(pThis, pReg - pThis->bm_regs, 1);
     1613                            pRegs->civ = pRegs->piv;
     1614                            pRegs->piv = (pRegs->piv + 1) % 32;
     1615
     1616                            ichac97StreamFetchBDLE(pThis, pStrmSt);
     1617
     1618                            pRegs->sr &= ~SR_DCH;
     1619                            ichac97StreamSetActive(pThis, pStrmSt, true /* fActive */);
    15831620                        }
    15841621                    }
    1585                     LogFlowFunc(("CR[%d] <- %#x (cr %#x)\n", GET_BM(index), u32, pReg->cr));
    1586                     break;
     1622                    LogFlowFunc(("CR[%d] <- %#x (cr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->cr));
     1623                    break;
     1624                }
    15871625                case PI_SR:
    15881626                case PO_SR:
    15891627                case MC_SR:
    15901628                    /* Status Register */
    1591                     pReg = &pThis->bm_regs[GET_BM(index)];
    1592                     pReg->sr |= u32 & ~(SR_RO_MASK | SR_WCLEAR_MASK);
    1593                     ichac97UpdateStatus(pThis, pReg, pReg->sr & ~(u32 & SR_WCLEAR_MASK));
    1594                     LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", GET_BM(index), u32, pReg->sr));
     1629                    pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
     1630                    ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
     1631                    LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
    15951632                    break;
    15961633                default:
    1597                     LogFlowFunc(("U nabm writeb %#x <- %#x\n", Port, u32));
     1634                    LogFlowFunc(("U nabm writeb %#x <- %#x\n", Port, u32Val));
    15981635                    break;
    15991636            }
     
    16031640        case 2:
    16041641        {
    1605             PAC97BMREG pReg = NULL;
    1606             uint32_t index = Port - pThis->IOPortBase[1];
    1607             switch (index)
     1642            switch (uPortIdx)
    16081643            {
    16091644                case PI_SR:
     
    16111646                case MC_SR:
    16121647                    /* Status Register */
    1613                     pReg = &pThis->bm_regs[GET_BM(index)];
    1614                     pReg->sr |= u32 & ~(SR_RO_MASK | SR_WCLEAR_MASK);
    1615                     ichac97UpdateStatus(pThis, pReg, pReg->sr & ~(u32 & SR_WCLEAR_MASK));
    1616                     LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", GET_BM(index), u32, pReg->sr));
     1648                    pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
     1649                    ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
     1650                    LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
    16171651                    break;
    16181652                default:
    1619                     LogFlowFunc(("U nabm writew %#x <- %#x\n", Port, u32));
     1653                    LogFlowFunc(("U nabm writew %#x <- %#x\n", Port, u32Val));
    16201654                    break;
    16211655            }
     
    16251659        case 4:
    16261660        {
    1627             PAC97BMREG pReg = NULL;
    1628             uint32_t index = Port - pThis->IOPortBase[1];
    1629             switch (index)
     1661            switch (uPortIdx)
    16301662            {
    16311663                case PI_BDBAR:
     
    16331665                case MC_BDBAR:
    16341666                    /* Buffer Descriptor list Base Address Register */
    1635                     pReg = &pThis->bm_regs[GET_BM(index)];
    1636                     pReg->bdbar = u32 & ~3;
    1637                     LogFlowFunc(("BDBAR[%d] <- %#x (bdbar %#x)\n", GET_BM(index), u32, pReg->bdbar));
     1667                    pRegs->bdbar = u32Val & ~3;
     1668                    LogFlowFunc(("BDBAR[%d] <- %#x (bdbar %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->bdbar));
    16381669                    break;
    16391670                case GLOB_CNT:
    16401671                    /* Global Control */
    1641                     if (u32 & GC_WR)
     1672                    if (u32Val & GC_WR)
    16421673                        ichac97WarmReset(pThis);
    1643                     if (u32 & GC_CR)
     1674                    if (u32Val & GC_CR)
    16441675                        ichac97ColdReset(pThis);
    1645                     if (!(u32 & (GC_WR | GC_CR)))
    1646                         pThis->glob_cnt = u32 & GC_VALID_MASK;
    1647                     LogFlowFunc(("glob_cnt <- %#x (glob_cnt %#x)\n", u32, pThis->glob_cnt));
     1676                    if (!(u32Val & (GC_WR | GC_CR)))
     1677                        pThis->glob_cnt = u32Val & GC_VALID_MASK;
     1678                    LogFlowFunc(("glob_cnt <- %#x (glob_cnt %#x)\n", u32Val, pThis->glob_cnt));
    16481679                    break;
    16491680                case GLOB_STA:
    16501681                    /* Global Status */
    1651                     pThis->glob_sta &= ~(u32 & GS_WCLEAR_MASK);
    1652                     pThis->glob_sta |= (u32 & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
    1653                     LogFlowFunc(("glob_sta <- %#x (glob_sta %#x)\n", u32, pThis->glob_sta));
     1682                    pThis->glob_sta &= ~(u32Val & GS_WCLEAR_MASK);
     1683                    pThis->glob_sta |= (u32Val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
     1684                    LogFlowFunc(("glob_sta <- %#x (glob_sta %#x)\n", u32Val, pThis->glob_sta));
    16541685                    break;
    16551686                default:
    1656                     LogFlowFunc(("U nabm writel %#x <- %#x\n", Port, u32));
     1687                    LogFlowFunc(("U nabm writel %#x <- %#x\n", Port, u32Val));
    16571688                    break;
    16581689            }
     
    16611692
    16621693        default:
    1663             AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
     1694            AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
    16641695            break;
    16651696    }
     
    16701701 * @callback_method_impl{FNIOMIOPORTIN}
    16711702 */
    1672 static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     1703static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32Val, unsigned cbVal)
    16731704{
    16741705    PAC97STATE pThis = (PAC97STATE)pvUser;
    16751706
    1676     switch (cb)
     1707    switch (cbVal)
    16771708    {
    16781709        case 1:
     
    16801711            LogFlowFunc(("U nam readb %#x\n", Port));
    16811712            pThis->cas = 0;
    1682             *pu32 = ~0U;
     1713            *pu32Val = UINT32_MAX;
    16831714            break;
    16841715        }
     
    16871718        {
    16881719            uint32_t index = Port - pThis->IOPortBase[0];
    1689             *pu32 = ~0U;
     1720            *pu32Val = UINT32_MAX;
    16901721            pThis->cas = 0;
    16911722            switch (index)
    16921723            {
    16931724                default:
    1694                     *pu32 = ichac97MixerLoad(pThis, index);
    1695                     LogFlowFunc(("nam readw %#x -> %#x\n", Port, *pu32));
     1725                    *pu32Val = ichac97MixerGet(pThis, index);
     1726                    LogFlowFunc(("nam readw %#x -> %#x\n", Port, *pu32Val));
    16961727                    break;
    16971728            }
     
    17031734            LogFlowFunc(("U nam readl %#x\n", Port));
    17041735            pThis->cas = 0;
    1705             *pu32 = ~0U;
     1736            *pu32Val = UINT32_MAX;
    17061737            break;
    17071738        }
     
    17171748 */
    17181749static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
    1719                                                void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
     1750                                               void *pvUser, RTIOPORT Port, uint32_t u32Val, unsigned cbVal)
    17201751{
    17211752    PAC97STATE pThis = (PAC97STATE)pvUser;
    17221753
    1723     switch (cb)
     1754    switch (cbVal)
    17241755    {
    17251756        case 1:
    17261757        {
    1727             LogFlowFunc(("U nam writeb %#x <- %#x\n", Port, u32));
     1758            LogFlowFunc(("U nam writeb %#x <- %#x\n", Port, u32Val));
    17281759            pThis->cas = 0;
    17291760            break;
     
    17371768            {
    17381769                case AC97_Reset:
    1739                     ichac97MixerReset(pThis);
     1770                    ichac97Reset(pThis->CTX_SUFF(pDevIns));
    17401771                    break;
    17411772                case AC97_Powerdown_Ctrl_Stat:
    1742                     u32 &= ~0xf;
    1743                     u32 |= ichac97MixerLoad(pThis, index) & 0xf;
    1744                     ichac97MixerStore(pThis, index, u32);
     1773                    u32Val &= ~0xf;
     1774                    u32Val |= ichac97MixerGet(pThis, index) & 0xf;
     1775                    ichac97MixerSet(pThis, index, u32Val);
    17451776                    break;
    17461777                case AC97_Master_Volume_Mute:
    17471778                    if (pThis->uCodecModel == Codec_AD1980)
    1748                         if (ichac97MixerLoad(pThis, AC97_AD_Misc) & AD_MISC_LOSEL)
     1779                        if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_LOSEL)
    17491780                            break;  /* Register controls surround (rear), do nothing. */
    1750                     ichac97SetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32);
     1781                    ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val);
    17511782                    break;
    17521783                case AC97_Headphone_Volume_Mute:
    17531784                    if (pThis->uCodecModel == Codec_AD1980)
    1754                         if (ichac97MixerLoad(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
     1785                        if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
    17551786                            /* Register controls PCM (front) outputs. */
    1756                             ichac97SetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32);
     1787                            ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val);
    17571788                    break;
    17581789                case AC97_PCM_Out_Volume_Mute:
    1759                     ichac97SetVolume(pThis, index, PDMAUDIOMIXERCTL_PCM, u32);
     1790                    ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_PCM, u32Val);
    17601791                    break;
    17611792                case AC97_Line_In_Volume_Mute:
    1762                     ichac97SetVolume(pThis, index, PDMAUDIOMIXERCTL_LINE_IN, u32);
     1793                    ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
    17631794                    break;
    17641795                case AC97_Record_Select:
    1765                     ichac97RecordSelect(pThis, u32);
     1796                    ichac97RecordSelect(pThis, u32Val);
    17661797                    break;
    17671798                case AC97_Vendor_ID1:
    17681799                case AC97_Vendor_ID2:
    1769                     LogFlowFunc(("Attempt to write vendor ID to %#x\n", u32));
     1800                    LogFlowFunc(("Attempt to write vendor ID to %#x\n", u32Val));
    17701801                    break;
    17711802                case AC97_Extended_Audio_ID:
    1772                     LogFlowFunc(("Attempt to write extended audio ID to %#x\n", u32));
     1803                    LogFlowFunc(("Attempt to write extended audio ID to %#x\n", u32Val));
    17731804                    break;
    17741805                case AC97_Extended_Audio_Ctrl_Stat:
    1775                     if (!(u32 & EACS_VRA))
     1806                    if (!(u32Val & EACS_VRA))
    17761807                    {
    1777                         ichac97MixerStore(pThis, AC97_PCM_Front_DAC_Rate, 0xbb80);
    1778                         ichac97MixerStore(pThis, AC97_PCM_LR_ADC_Rate,    0xbb80);
    1779                         ichac97OpenStream(pThis, PI_INDEX, 48000);
    1780                         ichac97OpenStream(pThis, PO_INDEX, 48000);
     1808                        ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate, 48000);
     1809                        ichac97StreamReInit(pThis, &pThis->StrmStOut);
     1810
     1811                        ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate,    48000);
     1812                        ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
    17811813                    }
    1782                     if (!(u32 & EACS_VRM))
     1814                    if (!(u32Val & EACS_VRM))
    17831815                    {
    1784                         ichac97MixerStore(pThis, AC97_MIC_ADC_Rate, 0xbb80);
    1785                         ichac97OpenStream(pThis, MC_INDEX, 48000);
     1816                        ichac97MixerSet(pThis, AC97_MIC_ADC_Rate,       48000);
     1817                        ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
    17861818                    }
    1787                     LogFlowFunc(("Setting extended audio control to %#x\n", u32));
    1788                     ichac97MixerStore(pThis, AC97_Extended_Audio_Ctrl_Stat, u32);
     1819                    LogFlowFunc(("Setting extended audio control to %#x\n", u32Val));
     1820                    ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, u32Val);
    17891821                    break;
    17901822                case AC97_PCM_Front_DAC_Rate:
    1791                     if (ichac97MixerLoad(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
     1823                    if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
    17921824                    {
    1793                         ichac97MixerStore(pThis, index, u32);
    1794                         LogFlowFunc(("Set front DAC rate to %d\n", u32));
    1795                         ichac97OpenStream(pThis, PO_INDEX, u32);
     1825                        ichac97MixerSet(pThis, index, u32Val);
     1826                        LogFlowFunc(("Set front DAC rate to %RU32\n", u32Val));
     1827                        ichac97StreamReInit(pThis, &pThis->StrmStOut);
    17961828                    }
    17971829                    else
    1798                         LogFlowFunc(("Attempt to set front DAC rate to %d, but VRA is not set\n", u32));
     1830                        LogFlowFunc(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
    17991831                    break;
    18001832                case AC97_MIC_ADC_Rate:
    1801                     if (ichac97MixerLoad(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM)
     1833                    if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM)
    18021834                    {
    1803                         ichac97MixerStore(pThis, index, u32);
    1804                         LogFlowFunc(("Set MIC ADC rate to %d\n", u32));
    1805                         ichac97OpenStream(pThis, MC_INDEX, u32);
     1835                        ichac97MixerSet(pThis, index, u32Val);
     1836                        LogFlowFunc(("Set MIC ADC rate to %RU32\n", u32Val));
     1837                        ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
    18061838                    }
    18071839                    else
    1808                         LogFlowFunc(("Attempt to set MIC ADC rate to %d, but VRM is not set\n", u32));
     1840                        LogFlowFunc(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
    18091841                    break;
    18101842                case AC97_PCM_LR_ADC_Rate:
    1811                     if (ichac97MixerLoad(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
     1843                    if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
    18121844                    {
    1813                         ichac97MixerStore(pThis, index, u32);
    1814                         LogFlowFunc(("Set front LR ADC rate to %d\n", u32));
    1815                         ichac97OpenStream(pThis, PI_INDEX, u32);
     1845                        ichac97MixerSet(pThis, index, u32Val);
     1846                        LogFlowFunc(("Set front LR ADC rate to %RU32\n", u32Val));
     1847                        ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
    18161848                    }
    18171849                    else
    1818                         LogFlowFunc(("Attempt to set LR ADC rate to %d, but VRA is not set\n", u32));
     1850                        LogFlowFunc(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
    18191851                    break;
    18201852                default:
    1821                     LogFlowFunc(("U nam writew %#x <- %#x\n", Port, u32));
    1822                     ichac97MixerStore(pThis, index, u32);
     1853                    LogFlowFunc(("U nam writew %#x <- %#x\n", Port, u32Val));
     1854                    ichac97MixerSet(pThis, index, u32Val);
    18231855                    break;
    18241856            }
     
    18281860        case 4:
    18291861        {
    1830             LogFlowFunc(("U nam writel %#x <- %#x\n", Port, u32));
     1862            LogFlowFunc(("U nam writel %#x <- %#x\n", Port, u32Val));
    18311863            pThis->cas = 0;
    18321864            break;
     
    18341866
    18351867        default:
    1836             AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
     1868            AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
    18371869            break;
    18381870    }
     
    18491881{
    18501882    PPDMDEVINS  pDevIns = pPciDev->pDevIns;
    1851     PAC97STATE  pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);
    1852     RTIOPORT    Port = (RTIOPORT)GCPhysAddress;
    1853     int         rc;
     1883    PAC97STATE  pThis   = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);
     1884    RTIOPORT    Port    = (RTIOPORT)GCPhysAddress;
    18541885
    18551886    Assert(enmType == PCI_ADDRESS_SPACE_IO);
    18561887    Assert(cb >= 0x20);
    18571888
     1889    if (iRegion < 0 || iRegion > 1) /* We support 2 regions max. at the moment. */
     1890        return VERR_INVALID_PARAMETER;
     1891
     1892    int rc;
    18581893    if (iRegion == 0)
    18591894        rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, pThis,
     
    18711906}
    18721907
     1908DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID)
     1909{
     1910    switch (uID)
     1911    {
     1912        case PI_INDEX: return &pThis->StrmStLineIn;
     1913        case MC_INDEX: return &pThis->StrmStMicIn;
     1914        case PO_INDEX: return &pThis->StrmStOut;
     1915        default:       break;
     1916    }
     1917
     1918    return NULL;
     1919}
     1920
    18731921#ifdef IN_RING3
     1922static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
     1923{
     1924    PAC97BMREGS pRegs = &pStrmSt->Regs;
     1925
     1926    SSMR3PutU32(pSSM, pRegs->bdbar);
     1927    SSMR3PutU8( pSSM, pRegs->civ);
     1928    SSMR3PutU8( pSSM, pRegs->lvi);
     1929    SSMR3PutU16(pSSM, pRegs->sr);
     1930    SSMR3PutU16(pSSM, pRegs->picb);
     1931    SSMR3PutU8( pSSM, pRegs->piv);
     1932    SSMR3PutU8( pSSM, pRegs->cr);
     1933    SSMR3PutS32(pSSM, pRegs->bd_valid);
     1934    SSMR3PutU32(pSSM, pRegs->bd.addr);
     1935    SSMR3PutU32(pSSM, pRegs->bd.ctl_len);
     1936
     1937    return VINF_SUCCESS;
     1938}
     1939
    18741940/**
    18751941 * @callback_method_impl{FNSSMDEVSAVEEXEC}
     
    18771943static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    18781944{
    1879     PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
     1945    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
    18801946
    18811947    SSMR3PutU32(pSSM, pThis->glob_cnt);
     
    18831949    SSMR3PutU32(pSSM, pThis->cas);
    18841950
    1885     for (unsigned i = 0; i < RT_ELEMENTS(pThis->bm_regs); i++)
    1886     {
    1887         PAC97BMREG pReg = &pThis->bm_regs[i];
    1888         SSMR3PutU32(pSSM, pReg->bdbar);
    1889         SSMR3PutU8( pSSM, pReg->civ);
    1890         SSMR3PutU8( pSSM, pReg->lvi);
    1891         SSMR3PutU16(pSSM, pReg->sr);
    1892         SSMR3PutU16(pSSM, pReg->picb);
    1893         SSMR3PutU8( pSSM, pReg->piv);
    1894         SSMR3PutU8( pSSM, pReg->cr);
    1895         SSMR3PutS32(pSSM, pReg->bd_valid);
    1896         SSMR3PutU32(pSSM, pReg->bd.addr);
    1897         SSMR3PutU32(pSSM, pReg->bd.ctl_len);
    1898     }
     1951    /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
     1952    /* Note: The order the streams are saved here is critical, so don't touch. */
     1953    int rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStLineIn);
     1954    AssertRC(rc2);
     1955    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStOut);
     1956    AssertRC(rc2);
     1957    rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStMicIn);
     1958    AssertRC(rc2);
     1959
    18991960    SSMR3PutMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
    19001961
     
    19161977}
    19171978
     1979static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
     1980{
     1981    PAC97BMREGS pRegs = &pStrmSt->Regs;
     1982
     1983    SSMR3GetU32(pSSM, &pRegs->bdbar);
     1984    SSMR3GetU8( pSSM, &pRegs->civ);
     1985    SSMR3GetU8( pSSM, &pRegs->lvi);
     1986    SSMR3GetU16(pSSM, &pRegs->sr);
     1987    SSMR3GetU16(pSSM, &pRegs->picb);
     1988    SSMR3GetU8( pSSM, &pRegs->piv);
     1989    SSMR3GetU8( pSSM, &pRegs->cr);
     1990    SSMR3GetS32(pSSM, &pRegs->bd_valid);
     1991    SSMR3GetU32(pSSM, &pRegs->bd.addr);
     1992    SSMR3GetU32(pSSM, &pRegs->bd.ctl_len);
     1993
     1994    return VINF_SUCCESS;
     1995}
    19181996
    19191997/**
     
    19222000static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    19232001{
    1924     PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
    1925 
    1926     AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
     2002    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
     2003
     2004    AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%RU32\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
    19272005    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    19282006
     
    19312009    SSMR3GetU32(pSSM, &pThis->cas);
    19322010
    1933     for (unsigned i = 0; i < RT_ELEMENTS(pThis->bm_regs); i++)
    1934     {
    1935         PAC97BMREG pReg = &pThis->bm_regs[i];
    1936         SSMR3GetU32(pSSM, &pReg->bdbar);
    1937         SSMR3GetU8( pSSM, &pReg->civ);
    1938         SSMR3GetU8( pSSM, &pReg->lvi);
    1939         SSMR3GetU16(pSSM, &pReg->sr);
    1940         SSMR3GetU16(pSSM, &pReg->picb);
    1941         SSMR3GetU8( pSSM, &pReg->piv);
    1942         SSMR3GetU8( pSSM, &pReg->cr);
    1943         SSMR3GetS32(pSSM, &pReg->bd_valid);
    1944         SSMR3GetU32(pSSM, &pReg->bd.addr);
    1945         SSMR3GetU32(pSSM, &pReg->bd.ctl_len);
    1946     }
     2011    /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
     2012    /* Note: The order the streams are loaded here is critical, so don't touch. */
     2013    int rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStLineIn);
     2014    AssertRC(rc2);
     2015    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStOut);
     2016    AssertRC(rc2);
     2017    rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStMicIn);
     2018    AssertRC(rc2);
    19472019
    19482020    SSMR3GetMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
    1949     uint8_t active[LAST_INDEX];
    1950     SSMR3GetMem(pSSM, active, sizeof(active));
    1951 
    1952     ichac97RecordSelect(pThis, ichac97MixerLoad(pThis, AC97_Record_Select));
    1953 # define V_(a, b) ichac97SetVolume(pThis, a, b, ichac97MixerLoad(pThis, a))
     2021
     2022    /** @todo r=andy Stream IDs are hardcoded to certain streams. */
     2023    uint8_t uaStrmsActive[LAST_INDEX];
     2024    SSMR3GetMem(pSSM, uaStrmsActive, sizeof(uaStrmsActive));
     2025
     2026    ichac97RecordSelect(pThis, ichac97MixerGet(pThis, AC97_Record_Select));
     2027# define V_(a, b) ichac97MixerSetVolume(pThis, a, b, ichac97MixerGet(pThis, a))
    19542028    V_(AC97_Master_Volume_Mute,  PDMAUDIOMIXERCTL_VOLUME);
    19552029    V_(AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_PCM);
     
    19572031# undef V_
    19582032    if (pThis->uCodecModel == Codec_AD1980)
    1959         if (ichac97MixerLoad(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
    1960             ichac97SetVolume(pThis, AC97_Headphone_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME,
    1961                              ichac97MixerLoad(pThis, AC97_Headphone_Volume_Mute));
    1962 
    1963     ichac97ResetStreams(pThis, active);
     2033        if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
     2034            ichac97MixerSetVolume(pThis, AC97_Headphone_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME,
     2035                             ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
     2036
     2037    int rc;
     2038    rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
     2039    AssertRC(rc);
     2040    rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
     2041    AssertRC(rc);
     2042    rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
     2043    AssertRC(rc);
     2044
     2045    /** @todo r=andy Stream IDs are hardcoded to certain streams. */
     2046    rc = ichac97StreamSetActive(pThis, &pThis->StrmStLineIn, RT_BOOL(uaStrmsActive[PI_INDEX]));
     2047    AssertRC(rc);
     2048    rc = ichac97StreamSetActive(pThis, &pThis->StrmStMicIn,  RT_BOOL(uaStrmsActive[MC_INDEX]));
     2049    AssertRC(rc);
     2050    rc = ichac97StreamSetActive(pThis, &pThis->StrmStOut,    RT_BOOL(uaStrmsActive[PO_INDEX]));
     2051    AssertRC(rc);
    19642052
    19652053    pThis->bup_flag = 0;
     
    19892077 *          make sense to me so we'll do it.
    19902078 */
    1991 static DECLCALLBACK(void) ac97Reset(PPDMDEVINS pDevIns)
    1992 {
    1993     PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
     2079static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns)
     2080{
     2081    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
     2082
     2083    LogFlowFuncEnter();
    19942084
    19952085    /*
    19962086     * Reset the device state (will need pDrv later).
    19972087     */
    1998     ichac97ResetBMRegs(pThis, &pThis->bm_regs[0]);
    1999     ichac97ResetBMRegs(pThis, &pThis->bm_regs[1]);
    2000     ichac97ResetBMRegs(pThis, &pThis->bm_regs[2]);
     2088    ichac97StreamResetBMRegs(pThis, &pThis->StrmStLineIn);
     2089    ichac97StreamResetBMRegs(pThis, &pThis->StrmStMicIn);
     2090    ichac97StreamResetBMRegs(pThis, &pThis->StrmStOut);
    20012091
    20022092    /*
     
    20062096     */
    20072097    ichac97MixerReset(pThis);
     2098
     2099    /*
     2100     * Stop any audio currently playing.
     2101     */
     2102    PAC97DRIVER pDrv;
     2103    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     2104    {
     2105        pDrv->pConnector->pfnEnableIn(pDrv->pConnector,  pDrv->LineIn.pStrmIn, false /* Disable */);
     2106        /* Ignore rc. */
     2107        pDrv->pConnector->pfnEnableIn(pDrv->pConnector,  pDrv->MicIn.pStrmIn,  false /* Disable */);
     2108        /* Ditto. */
     2109        pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut,   false /* Disable */);
     2110        /* Ditto. */
     2111    }
     2112
     2113    /*
     2114     * Reset all streams.
     2115     */
     2116    ichac97StreamReset(pThis, &pThis->StrmStLineIn);
     2117    ichac97StreamReset(pThis, &pThis->StrmStMicIn);
     2118    ichac97StreamReset(pThis, &pThis->StrmStOut);
     2119
     2120    LogRel(("AC97: Reset\n"));
    20082121}
    20092122
     
    21692282     * Initialize data (most of it anyway).
    21702283     */
    2171     pThis->pDevIns                  = pDevIns;
     2284    pThis->pDevInsR3                = pDevIns;
    21722285    /* IBase */
    21732286    pThis->IBase.pfnQueryInterface  = ichac97QueryInterface;
     
    22112324     */
    22122325    rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
    2213     if (RT_FAILURE (rc))
     2326    if (RT_FAILURE(rc))
    22142327        return rc;
    22152328
    22162329    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 256, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
    2217     if (RT_FAILURE (rc))
     2330    if (RT_FAILURE(rc))
    22182331        return rc;
    22192332
    22202333    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 64, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
    2221     if (RT_FAILURE (rc))
     2334    if (RT_FAILURE(rc))
    22222335        return rc;
    22232336
    22242337    rc = PDMDevHlpSSMRegister(pDevIns, AC97_SSM_VERSION, sizeof(*pThis), ichac97SaveExec, ichac97LoadExec);
    2225     if (RT_FAILURE (rc))
     2338    if (RT_FAILURE(rc))
    22262339        return rc;
    22272340
     
    22462359    LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
    22472360
    2248     ac97Reset(pDevIns);
    2249 
    2250     PAC97DRIVER pDrv;
    2251     uLUN = 0;
    2252     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    2253     {
    2254         if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->LineIn.pStrmIn))
    2255             LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU32!\n", uLUN));
    2256         if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut))
    2257             LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU32!\n", uLUN));
    2258         if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->MicIn.pStrmIn))
    2259             LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", uLUN));
    2260 
    2261         uLUN++;
    2262     }
    2263 
    2264     RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    2265     {
    2266         /*
    2267          * Only primary drivers are critical for the VM to run. Everything else
    2268          * might not worth showing an own error message box in the GUI.
    2269          */
    2270         if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
    2271             continue;
    2272 
    2273         PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    2274         AssertPtr(pCon);
    2275         if (   !pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn)
    2276             && !pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn)
    2277             && !pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
    2278         {
    2279             LogRel(("AC97: Falling back to NULL driver (no sound audible)\n"));
    2280 
    2281             ac97Reset(pDevIns);
    2282 
    2283             /* Was not able initialize *any* stream.
    2284              * Select the NULL audio driver instead. */
    2285             pCon->pfnInitNull(pCon);
    2286 
    2287             PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    2288                 N_("No audio devices could be opened. Selecting the NULL audio backend "
    2289                    "with the consequence that no sound is audible"));
    2290         }
    2291         else if (   !pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn)
    2292                  || !pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn)
    2293                  || !pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
    2294         {
    2295             char   szMissingStreams[255];
    2296             size_t len = 0;
     2361    if (RT_SUCCESS(rc))
     2362    {
     2363        rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
     2364        if (RT_SUCCESS(rc))
     2365        {
     2366            /* Set a default audio format for our mixer. */
     2367            PDMAUDIOSTREAMCFG streamCfg;
     2368            streamCfg.uHz           = 44100;
     2369            streamCfg.cChannels     = 2;
     2370            streamCfg.enmFormat     = AUD_FMT_S16;
     2371            streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     2372
     2373            rc = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
     2374            AssertRC(rc);
     2375
     2376            /* Add all required audio sinks. */
     2377            rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
     2378            AssertRC(rc);
     2379
     2380            rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
     2381            AssertRC(rc);
     2382
     2383            rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
     2384            AssertRC(rc);
     2385        }
     2386    }
     2387
     2388    ichac97Reset(pDevIns);
     2389
     2390    if (RT_SUCCESS(rc))
     2391    {
     2392        rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
     2393        if (RT_FAILURE(rc))
     2394            return rc;
     2395        rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn,  MC_INDEX);
     2396        if (RT_FAILURE(rc))
     2397            return rc;
     2398        rc = ichac97StreamInit(pThis, &pThis->StrmStOut,    PO_INDEX);
     2399        if (RT_FAILURE(rc))
     2400            return rc;
     2401
     2402        PAC97DRIVER pDrv;
     2403        RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
     2404        {
     2405            /*
     2406             * Only primary drivers are critical for the VM to run. Everything else
     2407             * might not worth showing an own error message box in the GUI.
     2408             */
     2409            if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
     2410                continue;
     2411
     2412            PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
     2413            AssertPtr(pCon);
     2414
     2415            uint8_t cFailed = 0;
    22972416            if (!pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn))
    2298                 len = RTStrPrintf(szMissingStreams,
    2299                                   sizeof(szMissingStreams), "PCM Input");
     2417                cFailed++;
     2418            if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn))
     2419                cFailed++;
    23002420            if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
    2301                 len += RTStrPrintf(szMissingStreams + len,
    2302                                    sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
    2303             if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn))
    2304                 len += RTStrPrintf(szMissingStreams + len,
    2305                                    sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
    2306 
    2307             PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
    2308                 N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
    2309                 "output or depending on audio input may hang. Make sure your host audio device "
    2310                 "is working properly. Check the logfile for error messages of the audio "
    2311                 "subsystem"), szMissingStreams);
     2421                cFailed++;
     2422
     2423            if (cFailed == 3)
     2424            {
     2425                LogRel(("AC97: Falling back to NULL driver (no sound audible)\n"));
     2426
     2427                ichac97Reset(pDevIns);
     2428
     2429                /* Was not able initialize *any* stream.
     2430                 * Select the NULL audio driver instead. */
     2431                pCon->pfnInitNull(pCon);
     2432
     2433                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     2434                    N_("No audio devices could be opened. Selecting the NULL audio backend "
     2435                       "with the consequence that no sound is audible"));
     2436            }
     2437            else if (cFailed)
     2438            {
     2439                if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->LineIn.pStrmIn))
     2440                    LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU32!\n",       pDrv->uLUN));
     2441                if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->MicIn.pStrmIn))
     2442                    LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", pDrv->uLUN));
     2443                if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut))
     2444                    LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU32!\n",           pDrv->uLUN));
     2445
     2446                char   szMissingStreams[255];
     2447                size_t len = 0;
     2448                if (!pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn))
     2449                    len = RTStrPrintf(szMissingStreams,
     2450                                      sizeof(szMissingStreams), "PCM Input");
     2451                if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
     2452                    len += RTStrPrintf(szMissingStreams + len,
     2453                                       sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
     2454                if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn))
     2455                    len += RTStrPrintf(szMissingStreams + len,
     2456                                       sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
     2457
     2458                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     2459                    N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
     2460                    "output or depending on audio input may hang. Make sure your host audio device "
     2461                    "is working properly. Check the logfile for error messages of the audio "
     2462                    "subsystem"), szMissingStreams);
     2463            }
    23122464        }
    23132465    }
     
    23852537# endif
    23862538
    2387     return VINF_SUCCESS;
     2539    LogFlowFuncLeaveRC(rc);
     2540    return rc;
    23882541}
    23892542
     
    24222575    NULL,
    24232576    /* pfnReset */
    2424     ac97Reset,
     2577    ichac97Reset,
    24252578    /* pfnSuspend */
    24262579    NULL,
Note: See TracChangeset for help on using the changeset viewer.

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