VirtualBox

Changeset 63862 in vbox


Ignore:
Timestamp:
Sep 16, 2016 9:47:12 AM (8 years ago)
Author:
vboxsync
Message:

Audio/DevIchAc97.cpp: Better separated initialization/destruction and opening/closing the AC'97 streams, added some critical sections, minor logging adjustments.

File:
1 edited

Legend:

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

    r63819 r63862  
    8484#define AC97_CR_DONT_CLEAR_MASK (AC97_CR_IOCE | AC97_CR_FEIE | AC97_CR_LVBIE)
    8585
    86 #define AC97_GC_WR    4              /* rw */
    87 #define AC97_GC_CR    2              /* rw */
     86#define AC97_GC_WR    4                 /* rw    Warm reset. */
     87#define AC97_GC_CR    2                 /* rw    Cold reset. */
    8888#define AC97_GC_VALID_MASK (RT_BIT(6) - 1)
    8989
     
    282282
    283283/**
    284  * Internal state of an AC97 stream.
     284 * Internal state of an AC'97 stream.
    285285 */
    286286typedef struct AC97STREAMSTATE
     
    296296
    297297/**
    298  * Structure for keeping an AC97 stream state.
    299  *
    300  * Contains only register values which do *not* change until a
    301  * stream reset occurs.
     298 * Structure for keeping an AC'97 stream state.
    302299 */
    303300typedef struct AC97STREAM
     
    305302    /** Stream number (SDn). */
    306303    uint8_t         u8Strm;
     304    /** Criticial section for this stream. */
     305    RTCRITSECT      CritSect;
    307306    /** Bus master registers of this stream. */
    308307    AC97BMREGS      Regs;
     
    378377    /** The timer for pumping data thru the attached LUN drivers. */
    379378    PTMTIMERR3              pTimer;
     379    /** Criticial section for timer. */
     380    RTCRITSECT              csTimer;
    380381# if HC_ARCH_BITS == 32
    381382    uint32_t                Padding0;
     
    401402    R3PTRTYPE(PAUDIOMIXER)  pMixer;
    402403    /** Audio sink for PCM output. */
    403     R3PTRTYPE(PAUDMIXSINK)  pSinkOutput;
     404    R3PTRTYPE(PAUDMIXSINK)  pSinkOut;
    404405    /** Audio sink for line input. */
    405406    R3PTRTYPE(PAUDMIXSINK)  pSinkLineIn;
     
    429430#endif
    430431DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
    431 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm);
     432static int ichac97StreamInit(PAC97STREAM pStream, uint8_t u8Strm);
     433static void ichac97StreamDestroy(PAC97STREAM pStream);
     434static int ichac97StreamOpen(PAC97STATE pThis, PAC97STREAM pStream);
     435static int ichac97StreamReOpen(PAC97STATE pThis, PAC97STREAM pStream);
     436static void ichac97StreamClose(PAC97STREAM pStream);
    432437static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
    433438#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
     
    455460    {
    456461        case AC97SOUNDSOURCE_PI_INDEX: return pThis->pSinkLineIn; break;
    457         case AC97SOUNDSOURCE_PO_INDEX: return pThis->pSinkOutput; break;
     462        case AC97SOUNDSOURCE_PO_INDEX: return pThis->pSinkOut;    break;
    458463        case AC97SOUNDSOURCE_MC_INDEX: return pThis->pSinkMicIn;  break;
    459464        default:       break;
     
    540545}
    541546
    542 static bool ichac97StreamIsActive(PAC97STATE pThis, PAC97STREAM pStream)
     547/**
     548 * Returns whether an AC'97 stream is enabled or not.
     549 *
     550 * @returns IPRT status code.
     551 * @param   pThis               AC'97 device state.
     552 * @param   pStream             Stream to return status for.
     553 */
     554static bool ichac97StreamIsEnabled(PAC97STATE pThis, PAC97STREAM pStream)
    543555{
    544556    AssertPtrReturn(pThis,   false);
     
    546558
    547559    PAUDMIXSINK pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
    548     bool fActive = RT_BOOL(AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING);
    549 
    550     LogFlowFunc(("[SD%RU8] fActive=%RTbool\n", pStream->u8Strm, fActive));
    551     return fActive;
    552 }
    553 
    554 static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStream, bool fActive)
     560    bool fIsEnabled = RT_BOOL(AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING);
     561
     562    LogFunc(("[SD%RU8] fIsEnabled=%RTbool\n", pStream->u8Strm, fIsEnabled));
     563    return fIsEnabled;
     564}
     565
     566static int ichac97StreamEnable(PAC97STATE pThis, PAC97STREAM pStream, bool fEnable)
    555567{
    556568    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    557569    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    558570
    559     /* Check the stream's status register if a state change actually is required. */
    560     const bool fIsActive = !RT_BOOL(pStream->Regs.sr & AC97_SR_DCH);
    561 
    562     LogFunc(("[SD%RU8] fActive=%RTbool, fIsActive=%RTbool, cStreamsActive=%RU8\n",
    563              pStream->u8Strm, fActive, fIsActive, pThis->cStreamsActive));
    564 
    565     if (fIsActive == fActive) /* Is a change required? */
    566         return VINF_SUCCESS;
    567 
    568     if (!fActive)
    569     {
    570         if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
    571             pThis->cStreamsActive--;
     571    PAUDMIXSINK pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
     572    AssertPtr(pSink);
     573
     574    const bool fIsEnabled = AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING;
     575
     576    LogFunc(("[SD%RU8] fEnable=%RTbool, fIsEnabled=%RTbool, DCH=%RTbool, cStreamsActive=%RU8\n",
     577             pStream->u8Strm, fEnable, fIsEnabled, RT_BOOL(pStream->Regs.sr & AC97_SR_DCH), pThis->cStreamsActive));
     578
     579    int rc = VINF_SUCCESS;
     580
     581    if (fEnable != fIsEnabled)
     582    {
     583        rc = ichac97StreamReOpen(pThis, pStream);
     584        if (RT_SUCCESS(rc))
     585            rc = AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
     586                                   fEnable ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     587        if (RT_SUCCESS(rc))
     588        {
     589            if (!fEnable)
     590            {
     591                if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
     592                    pThis->cStreamsActive--;
    572593
    573594#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
    574         ichac97TimerMaybeStop(pThis);
     595                ichac97TimerMaybeStop(pThis);
    575596#endif
    576     }
    577     else
    578     {
    579         pThis->cStreamsActive++;
     597            }
     598            else
     599            {
     600                pThis->cStreamsActive++;
    580601#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
    581         ichac97TimerMaybeStart(pThis);
     602                ichac97TimerMaybeStart(pThis);
    582603#endif
    583     }
    584 
    585     return AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
    586                              fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     604            }
     605        }
     606    }
     607
     608    LogFunc(("Returning %Rrc\n", rc));
     609    return rc;
    587610}
    588611
     
    592615    AssertPtrReturnVoid(pStream);
    593616
    594     LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
     617    LogFunc(("[SD%RU8]\n", pStream->u8Strm));
    595618
    596619    PAC97BMREGS pRegs = &pStream->Regs;
     
    600623    pRegs->lvi      = 0;
    601624
    602     ichac97StreamSetActive(pThis, pStream, false /* fActive */);
     625    ichac97StreamEnable(pThis, pStream, false /* fActive */);
    603626
    604627    ichac97StreamUpdateSR(pThis, pStream, AC97_SR_DCH); /** @todo Do we need to do that? */
     
    612635}
    613636
     637static int ichac97StreamInit(PAC97STREAM pStream, uint8_t u8Strm)
     638{
     639    AssertPtrReturn(pStream, VERR_INVALID_PARAMETER);
     640
     641    LogFunc(("[SD%RU8] pStream=%p\n", u8Strm, pStream));
     642
     643    int rc = VINF_SUCCESS;
     644
     645    pStream->u8Strm         = u8Strm;
     646    pStream->State.cbFIFOW  = _4K; /** @todo Make FIFOW size configurable. */
     647    pStream->State.offFIFOW = 0;
     648    pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW);
     649    if (pStream->State.au8FIFOW)
     650    {
     651        rc = RTCritSectInit(&pStream->CritSect);
     652    }
     653    else
     654        rc = VERR_NO_MEMORY;
     655
     656    return rc;
     657}
     658
    614659static void ichac97StreamDestroy(PAC97STREAM pStream)
    615660{
     
    625670    pStream->State.cbFIFOW  = 0;
    626671    pStream->State.offFIFOW = 0;
    627 }
    628 
    629 #if 0 /* unused */
    630 static void ichac97StreamsDestroy(PAC97STATE pThis)
     672
     673    if (RTCritSectIsInitialized(&pStream->CritSect))
     674        RTCritSectDelete(&pStream->CritSect);
     675}
     676
     677static int ichac97StreamsInit(PAC97STATE pThis)
    631678{
    632679    LogFlowFuncEnter();
    633680
    634     ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_LINE);
    635     ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_MIC);
    636     ichac97DestroyOut(pThis);
    637 
    638     ichac97StreamDestroy(&pThis->StreamLineIn);
    639     ichac97StreamDestroy(&pThis->StreamMicIn);
    640     ichac97StreamDestroy(&pThis->StreamOut);
    641 }
    642 #endif
    643 
    644 static int ichac97StreamsInit(PAC97STATE pThis)
    645 {
    646     LogFlowFuncEnter();
    647 
    648     ichac97StreamInit(pThis, &pThis->StreamLineIn, AC97SOUNDSOURCE_PI_INDEX);
    649     ichac97StreamInit(pThis, &pThis->StreamMicIn,  AC97SOUNDSOURCE_MC_INDEX);
    650     ichac97StreamInit(pThis, &pThis->StreamOut,    AC97SOUNDSOURCE_PO_INDEX);
     681    ichac97StreamInit(&pThis->StreamLineIn, AC97SOUNDSOURCE_PI_INDEX);
     682    ichac97StreamInit(&pThis->StreamMicIn,  AC97SOUNDSOURCE_MC_INDEX);
     683    ichac97StreamInit(&pThis->StreamOut,    AC97SOUNDSOURCE_PO_INDEX);
    651684
    652685    return VINF_SUCCESS;
     
    810843    AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    811844
     845    LogFunc(("%s\n", pszName));
     846
    812847    /* Update the sink's format. */
    813848    PDMAUDIOPCMPROPS PCMProps;
    814849    int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps);
    815850    if (RT_SUCCESS(rc))
    816         rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps);
     851        rc = AudioMixerSinkSetFormat(pThis->pSinkOut, &PCMProps);
    817852
    818853    if (RT_FAILURE(rc))
     
    829864        }
    830865
    831         AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     866        AudioMixerSinkRemoveStream(pThis->pSinkOut, pDrv->Out.pMixStrm);
    832867
    833868        AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
    834869        pDrv->Out.pMixStrm = NULL;
    835870
    836         int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOutput, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
     871        int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOut, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
    837872        if (RT_SUCCESS(rc2))
    838873        {
    839             rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     874            rc2 = AudioMixerSinkAddStream(pThis->pSinkOut, pDrv->Out.pMixStrm);
    840875            LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
    841876        }
     
    849884}
    850885
    851 static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
     886/**
     887 * Opens an AC'97 stream, extended version.
     888 *
     889 * @returns IPRT status code.
     890 * @param   pThis               AC'97 device state.
     891 * @param   pStream             Stream to initialize.
     892 * @param   pCfg                Audio stream configuration to initialize the stream with.
     893 */
     894static int ichac97StreamOpenEx(PAC97STATE pThis, PAC97STREAM pStream, PPDMAUDIOSTREAMCFG pCfg)
    852895{
    853896    AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
    854897    AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
    855     AssertReturn(u8Strm <= AC97SOUNDSOURCE_LAST_INDEX, VERR_INVALID_PARAMETER);
    856898    AssertPtrReturn(pCfg,              VERR_INVALID_POINTER);
    857899
    858     pStream->u8Strm = u8Strm;
    859 
    860     LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n",
    861                  pStream->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
     900    LogFunc(("[SD%RU8] pCfg=%p\n", pStream->u8Strm, pCfg));
    862901
    863902    int rc;
     
    877916
    878917        default:
    879             rc = VERR_NOT_SUPPORTED;
     918            AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
    880919            break;
    881920    }
     
    888927}
    889928
    890 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm)
     929/**
     930 * Opens an AC'97 stream.
     931 * This will open an AC'97 stream with 2 (stereo) channels, 16-bit samples and
     932 * the last set sample rate in the AC'97 mixer for this stream.
     933 *
     934 * @returns IPRT status code.
     935 * @param   pThis               AC'97 device state.
     936 * @param   pStream             Stream to initialize.
     937 */
     938static int ichac97StreamOpen(PAC97STATE pThis, PAC97STREAM pStream)
    891939{
    892940    int rc = VINF_SUCCESS;
     941
     942    LogFunc(("[SD%RU8]\n", pStream->u8Strm));
    893943
    894944    PDMAUDIOSTREAMCFG streamCfg;
    895945    RT_ZERO(streamCfg);
    896946
    897     switch (u8Strm)
     947    switch (pStream->u8Strm)
    898948    {
    899949        case AC97SOUNDSOURCE_PI_INDEX:
     
    922972    if (RT_SUCCESS(rc))
    923973    {
    924         pStream->State.cbFIFOW  = _4K; /** @todo Make FIFOW size configurable. */
    925         pStream->State.offFIFOW = 0;
    926         pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW);
    927         if (!pStream->State.au8FIFOW)
    928             rc = VERR_NO_MEMORY;
    929     }
    930 
    931     if (RT_SUCCESS(rc))
    932     {
    933974        if (streamCfg.uHz)
    934975        {
    935             streamCfg.cChannels     = 2; /** @todo Handle mono channels? */
     976            streamCfg.cChannels     = 2;
    936977            streamCfg.enmFormat     = PDMAUDIOFMT_S16;
    937978            streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    938979
    939             rc = ichac97StreamInitEx(pThis, pStream, u8Strm, &streamCfg);
     980            rc = ichac97StreamOpenEx(pThis, pStream, &streamCfg);
    940981        }
    941982        else
    942         {
    943             /* If no frequency is given, disable the stream. */
    944             rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */);
    945         }
    946     }
    947 
    948     LogFlowFunc(("[SD%RU8] rc=%Rrc\n", u8Strm, rc));
     983            rc = VERR_INVALID_PARAMETER;
     984    }
     985
     986    LogFlowFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8Strm, rc));
    949987    return rc;
    950988}
    951989
    952 static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrm)
    953 {
    954     return ichac97StreamInit(pThis, pStrm, pStrm->u8Strm);
     990static void ichac97StreamClose(PAC97STREAM pStream)
     991{
     992    LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
     993}
     994
     995/**
     996 * Re-opens an AC'97 stream on the backend side with the current AC'97 mixer
     997 * settings for this stream.
     998 *
     999 * @returns IPRT status code.
     1000 * @param   pThis               AC'97 device state.
     1001 * @param   pStream             Stream to re-open.
     1002 */
     1003static int ichac97StreamReOpen(PAC97STATE pThis, PAC97STREAM pStream)
     1004{
     1005    LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
     1006
     1007    ichac97StreamClose(pStream);
     1008
     1009    return ichac97StreamOpen(pThis, pStream);
    9551010}
    9561011
     
    10331088                break;
    10341089            case PDMAUDIOMIXERCTL_FRONT:
    1035                 rc = AudioMixerSinkSetVolume(pThis->pSinkOutput, &Vol);
     1090                rc = AudioMixerSinkSetVolume(pThis->pSinkOut,    &Vol);
    10361091                break;
    10371092
     
    12261281         * Write data to the mixer sink.
    12271282         */
    1228         rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, pu8FIFOW, cbToRead, &cbWritten);
     1283        rc = AudioMixerSinkWrite(pThis->pSinkOut, AUDMIXOP_COPY, pu8FIFOW, cbToRead, &cbWritten);
    12291284        if (RT_FAILURE(rc))
    12301285            break;
     
    12901345        uint32_t cbWrittenToStream;
    12911346
    1292         int rc2 = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY,
     1347        int rc2 = AudioMixerSinkWrite(pThis->pSinkOut, AUDMIXOP_COPY,
    12931348                                      pThis->silence, cbToWrite, &cbWrittenToStream);
    12941349        if (RT_SUCCESS(rc2))
     
    13551410
    13561411#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
     1412#if 0
     1413static int ichac97TimerStart(PAC97STATE pThis)
     1414{
     1415    /*int rc = RTCritSectEnter(&pThis->csTimer);
     1416    if (RT_SUCCESS(rc))*/
     1417    {
     1418        AssertPtr(pThis->pTimer);
     1419
     1420        const bool fIsActive = TMTimerIsActive(pThis->pTimer);
     1421
     1422        LogFunc(("cStreamsActive=%RU8, fIsActive=%RTbool\n", pThis->cStreamsActive, fIsActive));
     1423
     1424        if (!fIsActive) /* Timer not started yet? */
     1425        {
     1426            LogFunc(("Starting timer\n"));
     1427            LogRel3(("AC97: Starting timer\n"));
     1428
     1429            /* Update current time timestamp. */
     1430            pThis->uTimerTS = TMTimerGet(pThis->pTimer);
     1431
     1432            /* Fire off timer. */
     1433            TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     1434        }
     1435
     1436        /*int rc2 = RTCritSectLeave(&pThis->csTimer);
     1437        if (RT_SUCCESS(rc))
     1438            rc = rc2;*/
     1439    }
     1440
     1441    return 0;
     1442}
     1443#endif
     1444
    13571445static void ichac97TimerMaybeStart(PAC97STATE pThis)
    13581446{
     
    13751463
    13761464    /* Fire off timer. */
    1377     TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     1465    TMTimerSet(pThis->pTimer, 0 /* u64Expire */);
    13781466}
    13791467
     
    14021490    AssertPtr(pThis);
    14031491
    1404     STAM_PROFILE_START(&pThis->StatTimer, a);
    1405 
    1406     uint64_t cTicksNow     = TMTimerGet(pTimer);
    1407 
    1408     LogFlowFuncEnter();
    1409 
    1410     /* Update current time timestamp. */
    1411     pThis->uTimerTS = cTicksNow;
    1412 
    1413     /* Flag indicating whether to kick the timer again for a
    1414      * new data processing round. */
    1415     bool fKickTimer = false;
    1416 
    1417     uint32_t cbToProcess;
    1418 
    1419     int rc = AudioMixerSinkUpdate(pThis->pSinkLineIn);
     1492    int rc = RTCritSectEnter(&pThis->csTimer);
    14201493    if (RT_SUCCESS(rc))
    14211494    {
    1422         cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkLineIn);
    1423         if (cbToProcess)
    1424             rc = ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbToProcess, NULL /* pcbProcessed */);
    1425 
    1426         fKickTimer |= !!(AudioMixerSinkGetStatus(pThis->pSinkLineIn) & AUDMIXSINK_STS_DIRTY);
    1427     }
    1428 
    1429     rc = AudioMixerSinkUpdate(pThis->pSinkMicIn);
    1430     if (RT_SUCCESS(rc))
    1431     {
    1432         cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkMicIn);
    1433         if (cbToProcess)
    1434             rc = ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbToProcess, NULL /* pcbProcessed */);
    1435 
    1436         fKickTimer |= !!(AudioMixerSinkGetStatus(pThis->pSinkMicIn) & AUDMIXSINK_STS_DIRTY);
    1437     }
    1438 
    1439     rc = AudioMixerSinkUpdate(pThis->pSinkOutput);
    1440     if (RT_SUCCESS(rc))
    1441     {
    1442         cbToProcess = AudioMixerSinkGetWritable(pThis->pSinkOutput);
    1443         if (cbToProcess)
    1444             rc = ichac97TransferAudio(pThis, &pThis->StreamOut, cbToProcess, NULL /* pcbProcessed */);
    1445 
    1446         fKickTimer |= !!(AudioMixerSinkGetStatus(pThis->pSinkOutput) & AUDMIXSINK_STS_DIRTY);
    1447     }
    1448 
    1449     if (   ASMAtomicReadBool(&pThis->fTimerActive)
    1450         || fKickTimer)
    1451     {
    1452         /* Kick the timer again. */
    1453         uint64_t cTicks = pThis->cTimerTicks;
    1454         /** @todo adjust cTicks down by now much cbOutMin represents. */
    1455         TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
    1456     }
    1457 
    1458     STAM_PROFILE_STOP(&pThis->StatTimer, a);
     1495        STAM_PROFILE_START(&pThis->StatTimer, a);
     1496
     1497        uint64_t cTicksNow = TMTimerGet(pTimer);
     1498
     1499        /* Update current time timestamp. */
     1500        pThis->uTimerTS = cTicksNow;
     1501
     1502        /* Flag indicating whether to kick the timer again for the next DMA transfer or sink processing. */
     1503        bool fDoNextTransfer = false;
     1504
     1505        uint32_t cbToProcess;
     1506
     1507        rc = AudioMixerSinkUpdate(pThis->pSinkLineIn);
     1508        if (RT_SUCCESS(rc))
     1509        {
     1510            cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkLineIn);
     1511            if (cbToProcess)
     1512                rc = ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbToProcess, NULL /* pcbProcessed */);
     1513
     1514            if (AudioMixerSinkGetStatus(pThis->pSinkLineIn) & AUDMIXSINK_STS_DIRTY)
     1515                fDoNextTransfer = true;
     1516        }
     1517
     1518        rc = AudioMixerSinkUpdate(pThis->pSinkMicIn);
     1519        if (RT_SUCCESS(rc))
     1520        {
     1521            cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkMicIn);
     1522            if (cbToProcess)
     1523                rc = ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbToProcess, NULL /* pcbProcessed */);
     1524
     1525            if (AudioMixerSinkGetStatus(pThis->pSinkMicIn) & AUDMIXSINK_STS_DIRTY)
     1526                fDoNextTransfer = true;
     1527        }
     1528
     1529        rc = AudioMixerSinkUpdate(pThis->pSinkOut);
     1530        if (RT_SUCCESS(rc))
     1531        {
     1532            cbToProcess = AudioMixerSinkGetWritable(pThis->pSinkOut);
     1533            if (cbToProcess)
     1534                rc = ichac97TransferAudio(pThis, &pThis->StreamOut, cbToProcess, NULL /* pcbProcessed */);
     1535
     1536            if (AudioMixerSinkGetStatus(pThis->pSinkOut) & AUDMIXSINK_STS_DIRTY)
     1537                fDoNextTransfer = true;
     1538        }
     1539
     1540        if (fDoNextTransfer)
     1541        {
     1542            /* Kick the timer again. */
     1543            uint64_t cTicks = pThis->cTimerTicks;
     1544            /** @todo adjust cTicks down by now much cbOutMin represents. */
     1545            TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
     1546        }
     1547        else
     1548        {
     1549            LogFunc(("Stopping timer\n"));
     1550            LogRel3(("AC97: Stopping timer\n"));
     1551        }
     1552
     1553        STAM_PROFILE_STOP(&pThis->StatTimer, a);
     1554
     1555        int rc2 = RTCritSectLeave(&pThis->csTimer);
     1556        if (RT_SUCCESS(rc))
     1557            rc2 = rc;
     1558    }
    14591559}
    14601560#endif /* !VBOX_WITH_AUDIO_AC97_CALLBACKS */
     
    14661566    /* pcbProcessed is optional. */
    14671567
    1468     Log3Func(("[SD%RU8] cbToProcess=%RU32\n", pStream->u8Strm, cbToProcess));
     1568    int rc = RTCritSectEnter(&pStream->CritSect);
     1569    if (RT_FAILURE(rc))
     1570        return rc;
     1571
     1572    LogFunc(("[SD%RU8] cbToProcess=%RU32\n", pStream->u8Strm, cbToProcess));
    14691573
    14701574    PAC97BMREGS pRegs = &pStream->Regs;
     
    14871591        if (pcbProcessed)
    14881592            *pcbProcessed = 0;
     1593
     1594        Log3Func(("[SD%RU8] Halted\n", pStream->u8Strm));
     1595
     1596        rc = RTCritSectLeave(&pStream->CritSect);
     1597        AssertRC(rc);
     1598
    14891599        return VINF_SUCCESS;
    14901600    }
     
    14941604    {
    14951605        Log3Func(("[SD%RU8] BCIS set\n", pStream->u8Strm));
     1606
    14961607        if (pcbProcessed)
    14971608            *pcbProcessed = 0;
     1609
     1610        rc = RTCritSectLeave(&pStream->CritSect);
     1611        AssertRC(rc);
     1612
    14981613        return VINF_SUCCESS;
    14991614    }
    1500 
    1501     int rc = VINF_SUCCESS;
    15021615
    15031616    uint32_t cbLeft  = RT_MIN((uint32_t)(pRegs->picb << 1), cbToProcess);
     
    16191732    }
    16201733
     1734    int rc2 = RTCritSectLeave(&pStream->CritSect);
     1735    AssertRC(rc2);
     1736
    16211737    if (RT_SUCCESS(rc))
    16221738    {
     
    16411757
    16421758    PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
    1643     PAC97BMREGS pRegs   = pStream ? &pStream->Regs : NULL;
     1759    PAC97BMREGS pRegs   = NULL;
     1760
     1761    if (pStream)
     1762    {
     1763        pRegs = &pStream->Regs;
     1764
     1765        int rc2 = RTCritSectEnter(&pStream->CritSect);
     1766        AssertRC(rc2);
     1767    }
     1768
     1769    int rc = VINF_SUCCESS;
    16441770
    16451771    switch (cbVal)
     
    16871813                case MC_SR:
    16881814                    /* Status Register (lower part) */
    1689                     *pu32Val = pRegs->sr & 0xff; /** @todo r=andy Use RT_LO_U8. */
     1815                    *pu32Val = RT_LO_U8(pRegs->sr);
    16901816                    Log3Func(("SRb[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
    16911817                    break;
     
    17741900
    17751901        default:
    1776             return VERR_IOM_IOPORT_UNUSED;
    1777     }
    1778     return VINF_SUCCESS;
     1902        {
     1903            AssertFailed();
     1904            rc = VERR_IOM_IOPORT_UNUSED;
     1905        }
     1906    }
     1907
     1908    if (pStream)
     1909    {
     1910        int rc2 = RTCritSectLeave(&pStream->CritSect);
     1911        AssertRC(rc2);
     1912    }
     1913
     1914    return rc;
    17791915}
    17801916
     
    17921928
    17931929    PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
    1794     PAC97BMREGS pRegs   = pStream ? &pStream->Regs : NULL;
     1930    PAC97BMREGS pRegs   = NULL;
     1931
     1932    PAUDMIXSINK pSink   = NULL;
     1933
     1934    if (pStream)
     1935    {
     1936        pRegs = &pStream->Regs;
     1937        pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
     1938        AssertPtr(pSink);
     1939
     1940        int rc2 = RTCritSectEnter(&pStream->CritSect);
     1941        AssertRC(rc2);
     1942    }
    17951943
    17961944    switch (cbVal)
     
    18001948            switch (uPortIdx)
    18011949            {
     1950                /*
     1951                 * Last Valid Index.
     1952                 */
    18021953                case PI_LVI:
    18031954                case PO_LVI:
    18041955                case MC_LVI:
    1805                     /* Last Valid Index */
    1806                     if ((pRegs->cr & AC97_CR_RPBM) && (pRegs->sr & AC97_SR_DCH))
     1956                {
     1957                    if (   (pRegs->cr & AC97_CR_RPBM)
     1958                        && (pRegs->sr & AC97_SR_DCH))
    18071959                    {
    18081960                        pRegs->sr &= ~(AC97_SR_DCH | AC97_SR_CELV);
     
    18131965                    }
    18141966                    pRegs->lvi = u32Val % 32;
    1815                     Log3Func(("LVI[%d] <- %#x\n", AC97_PORT2IDX(uPortIdx), u32Val));
    1816                     break;
     1967                    Log3Func(("[SD%RU8] LVI <- %#x\n", pStream->u8Strm, u32Val));
     1968                    break;
     1969                }
     1970
     1971                /*
     1972                 * Control Registers.
     1973                 */
    18171974                case PI_CR:
    18181975                case PO_CR:
    18191976                case MC_CR:
    18201977                {
    1821                     /* Control Register */
    18221978                    if (u32Val & AC97_CR_RR) /* Busmaster reset */
    18231979                    {
     
    18291985                        if (!(pRegs->cr & AC97_CR_RPBM))
    18301986                        {
    1831                             ichac97StreamSetActive(pThis, pStream, false /* fActive */);
     1987                            ichac97StreamEnable(pThis, pStream, false /* fActive */);
    18321988
    18331989                            pRegs->sr |= AC97_SR_DCH;
     
    18381994                            pRegs->piv = (pRegs->piv + 1) % 32;
    18391995
     1996                            pRegs->sr &= ~AC97_SR_DCH;
     1997
     1998                            /* Fetch the initial BDLE descriptor. */
    18401999                            ichac97StreamFetchBDLE(pThis, pStream);
    1841                             ichac97StreamSetActive(pThis, pStream, true /* fActive */);
    1842 
    1843                             pRegs->sr &= ~AC97_SR_DCH;
     2000
     2001                            ichac97StreamEnable(pThis, pStream, true /* fActive */);
    18442002                        }
    18452003                    }
    1846                     Log3Func(("CR[%d] <- %#x (cr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->cr));
     2004                    Log3Func(("[SD%RU8] CR <- %#x (cr %#x)\n", pStream->u8Strm, u32Val, pRegs->cr));
    18472005                    break;
    18482006                }
     2007
     2008                /*
     2009                 * Status Registers.
     2010                 */
    18492011                case PI_SR:
    18502012                case PO_SR:
    18512013                case MC_SR:
    1852                     /* Status Register */
     2014                {
    18532015                    pRegs->sr |= u32Val & ~(AC97_SR_RO_MASK | AC97_SR_WCLEAR_MASK);
    18542016                    ichac97StreamUpdateSR(pThis, pStream, pRegs->sr & ~(u32Val & AC97_SR_WCLEAR_MASK));
    1855                     Log3Func(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
    1856                     break;
     2017                    Log3Func(("[SD%RU8] SR <- %#x (sr %#x)\n", pStream->u8Strm, u32Val, pRegs->sr));
     2018                    break;
     2019                }
     2020
    18572021                default:
    1858                     LogFunc(("U nabm writeb %#x <- %#x\n", Port, u32Val));
     2022                    LogFunc(("Unimplemented: %#x <- %#x (Byte)\n", Port, u32Val));
    18592023                    break;
    18602024            }
     
    18722036                    pRegs->sr |= u32Val & ~(AC97_SR_RO_MASK | AC97_SR_WCLEAR_MASK);
    18732037                    ichac97StreamUpdateSR(pThis, pStream, pRegs->sr & ~(u32Val & AC97_SR_WCLEAR_MASK));
    1874                     Log3Func(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
     2038                    Log3Func(("[SD%RU8] SR <- %#x (sr %#x)\n", pStream->u8Strm, u32Val, pRegs->sr));
    18752039                    break;
    18762040                default:
    1877                     LogFunc(("U nabm writew %#x <- %#x\n", Port, u32Val));
     2041                    LogFunc(("Unimplemented: %#x <- %#x (Word)\n", Port, u32Val));
    18782042                    break;
    18792043            }
     
    18902054                    /* Buffer Descriptor list Base Address Register */
    18912055                    pRegs->bdbar = u32Val & ~3;
    1892                     Log3Func(("BDBAR[%d] <- %#x (bdbar %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->bdbar));
     2056                    Log3Func(("[SD%RU8] BDBAR <- %#x (bdbar %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->bdbar));
    18932057                    break;
    18942058                case AC97_GLOB_CNT:
     
    19092073                    break;
    19102074                default:
    1911                     LogFunc(("U nabm writel %#x <- %#x\n", Port, u32Val));
     2075                    LogFunc(("Unimplemented: %#x <- %#x (DWord)\n", Port, u32Val));
    19122076                    break;
    19132077            }
     
    19192083            break;
    19202084    }
     2085
     2086    if (pStream)
     2087    {
     2088        int rc2 = RTCritSectLeave(&pStream->CritSect);
     2089        AssertRC(rc2);
     2090    }
     2091
    19212092    return VINF_SUCCESS;
    19222093}
     
    19292100    RT_NOREF(pDevIns);
    19302101    PAC97STATE pThis = (PAC97STATE)pvUser;
     2102
     2103    int rc = VINF_SUCCESS;
    19312104
    19322105    switch (cbVal)
     
    19662139        {
    19672140            AssertFailed();
    1968             return VERR_IOM_IOPORT_UNUSED;
    1969         }
    1970     }
    1971     return VINF_SUCCESS;
     2141            rc = VERR_IOM_IOPORT_UNUSED;
     2142        }
     2143    }
     2144
     2145    return rc;
    19722146}
    19732147
     
    20412215                    {
    20422216                        ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate, 48000);
    2043                         ichac97StreamReInit(pThis, &pThis->StreamOut);
     2217                        ichac97StreamReOpen(pThis, &pThis->StreamOut);
    20442218
    20452219                        ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate,    48000);
    2046                         ichac97StreamReInit(pThis, &pThis->StreamLineIn);
     2220                        ichac97StreamReOpen(pThis, &pThis->StreamLineIn);
    20472221                    }
    20482222                    if (!(u32Val & AC97_EACS_VRM))
    20492223                    {
    20502224                        ichac97MixerSet(pThis, AC97_MIC_ADC_Rate,       48000);
    2051                         ichac97StreamReInit(pThis, &pThis->StreamMicIn);
     2225                        ichac97StreamReOpen(pThis, &pThis->StreamMicIn);
    20522226                    }
    20532227                    LogFunc(("Setting extended audio control to %#x\n", u32Val));
     
    20592233                        ichac97MixerSet(pThis, index, u32Val);
    20602234                        LogFunc(("Set front DAC rate to %RU32\n", u32Val));
    2061                         ichac97StreamReInit(pThis, &pThis->StreamOut);
     2235                        ichac97StreamReOpen(pThis, &pThis->StreamOut);
    20622236                    }
    20632237                    else
     
    20692243                        ichac97MixerSet(pThis, index, u32Val);
    20702244                        LogFunc(("Set MIC ADC rate to %RU32\n", u32Val));
    2071                         ichac97StreamReInit(pThis, &pThis->StreamMicIn);
     2245                        ichac97StreamReOpen(pThis, &pThis->StreamMicIn);
    20722246                    }
    20732247                    else
     
    20792253                        ichac97MixerSet(pThis, index, u32Val);
    20802254                        LogFunc(("Set front LR ADC rate to %RU32\n", u32Val));
    2081                         ichac97StreamReInit(pThis, &pThis->StreamLineIn);
     2255                        ichac97StreamReOpen(pThis, &pThis->StreamLineIn);
    20822256                    }
    20832257                    else
     
    21482322        case AC97SOUNDSOURCE_MC_INDEX: return &pThis->StreamMicIn;
    21492323        case AC97SOUNDSOURCE_PO_INDEX: return &pThis->StreamOut;
    2150         default:       break;
     2324        default:                       break;
    21512325    }
    21522326
     
    22002374    uint8_t active[AC97SOUNDSOURCE_LAST_INDEX];
    22012375
    2202     active[AC97SOUNDSOURCE_PI_INDEX] = ichac97StreamIsActive(pThis, &pThis->StreamLineIn) ? 1 : 0;
    2203     active[AC97SOUNDSOURCE_PO_INDEX] = ichac97StreamIsActive(pThis, &pThis->StreamOut)    ? 1 : 0;
    2204     active[AC97SOUNDSOURCE_MC_INDEX] = ichac97StreamIsActive(pThis, &pThis->StreamMicIn)  ? 1 : 0;
     2376    active[AC97SOUNDSOURCE_PI_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamLineIn) ? 1 : 0;
     2377    active[AC97SOUNDSOURCE_PO_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamOut)    ? 1 : 0;
     2378    active[AC97SOUNDSOURCE_MC_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamMicIn)  ? 1 : 0;
    22052379
    22062380    SSMR3PutMem(pSSM, active, sizeof(active));
     
    22722446                             ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
    22732447
    2274     int rc = ichac97StreamsInit(pThis);
    2275     if (RT_SUCCESS(rc))
     2448    rc2 = ichac97StreamsInit(pThis);
     2449    if (RT_SUCCESS(rc2))
    22762450    {
    22772451        /** @todo r=andy Stream IDs are hardcoded to certain streams. */
    2278         rc = ichac97StreamSetActive(pThis, &pThis->StreamLineIn,    RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PI_INDEX]));
    2279         if (RT_SUCCESS(rc))
    2280             rc = ichac97StreamSetActive(pThis, &pThis->StreamMicIn, RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_MC_INDEX]));
    2281         if (RT_SUCCESS(rc))
    2282             rc = ichac97StreamSetActive(pThis, &pThis->StreamOut,   RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PO_INDEX]));
     2452        rc2 = ichac97StreamEnable(pThis, &pThis->StreamLineIn,    RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PI_INDEX]));
     2453        if (RT_SUCCESS(rc2))
     2454            rc2 = ichac97StreamEnable(pThis, &pThis->StreamMicIn, RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_MC_INDEX]));
     2455        if (RT_SUCCESS(rc2))
     2456            rc2 = ichac97StreamEnable(pThis, &pThis->StreamOut,   RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PO_INDEX]));
    22832457    }
    22842458
     
    22862460    pThis->last_samp = 0;
    22872461
    2288     LogFlowFuncLeaveRC(rc);
    2289     return rc;
     2462    return VINF_SUCCESS;
    22902463}
    22912464
     
    23552528
    23562529    /*
    2357      * Stop any audio currently playing and/or recording.
    2358      */
    2359     AudioMixerSinkCtl(pThis->pSinkOutput, AUDMIXSINKCMD_DISABLE);
    2360     AudioMixerSinkCtl(pThis->pSinkMicIn,  AUDMIXSINKCMD_DISABLE);
    2361     AudioMixerSinkCtl(pThis->pSinkLineIn, AUDMIXSINKCMD_DISABLE);
    2362 
    2363     /*
    23642530     * Reset all streams.
    23652531     */
     
    23952561    Assert(RTListIsEmpty(&pThis->lstDrv));
    23962562
    2397     LogFlowFuncLeave();
    2398     return VINF_SUCCESS;
     2563    int rc;
     2564#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
     2565    rc = RTCritSectDelete(&pThis->csTimer);
     2566#else
     2567    rc = VINF_SUCCESS;
     2568#endif
     2569
     2570    LogFlowFuncLeaveRC(rc);
     2571    return rc;
    23992572}
    24002573
     
    27122885        {
    27132886            /* Add all required audio sinks. */
    2714             int rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
     2887            int rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOut);
    27152888            AssertRC(rc2);
    27162889
     
    27312904    if (RT_SUCCESS(rc))
    27322905    {
    2733         /* Start the emulation timer. */
    2734         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis,
    2735                                     TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer);
    2736         AssertRCReturn(rc, rc);
    2737 
     2906        rc = RTCritSectInit(&pThis->csTimer);
    27382907        if (RT_SUCCESS(rc))
    27392908        {
    2740             pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
    2741             pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
    2742             LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
    2743 
    2744             ichac97TimerMaybeStart(pThis);
     2909            /* Start the emulation timer. */
     2910            rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis,
     2911                                        TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer);
     2912            AssertRCReturn(rc, rc);
     2913
     2914            if (RT_SUCCESS(rc))
     2915            {
     2916                pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
     2917                pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
     2918                LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
     2919            }
    27452920        }
    27462921    }
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