VirtualBox

Changeset 59160 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 16, 2015 6:26:04 PM (9 years ago)
Author:
vboxsync
Message:

Audio/HDA: Try to fix stream initialization / reset handling for >= 2 VCPUs.

File:
1 edited

Legend:

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

    r59102 r59160  
    3636#ifdef IN_RING3
    3737# include <iprt/mem.h>
     38# include <iprt/semaphore.h>
    3839# include <iprt/string.h>
    3940# include <iprt/uuid.h>
     
    577578    uint16_t            uCurBDLE;
    578579    uint32_t            Padding;
     580    /** Stop indicator. */
     581    volatile bool       fDoStop;
     582    /** Flag indicating whether this stream is in an
     583     *  active (operative) state or not. */
     584    volatile bool       fActive;
     585    /** Flag indicating whether this stream currently is
     586     *  in reset mode and therefore not acccessible by the guest. */
     587    volatile bool       fInReset;
     588    /** Event signalling that the stream's state has been changed. */
     589    RTSEMEVENT          hStateChangedEvent;
    579590    /** Array of BDLEs. */
    580591    R3PTRTYPE(PHDABDLE) paBDLE;
     
    834845static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
    835846
     847#ifdef IN_RING3
     848static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm);
    836849static void hdaStreamDestroy(PHDASTREAM pStrmSt);
    837 
    838 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbMax, uint32_t *pcbProcessed);
     850static int hdaStreamStart(PHDASTREAM pStrmSt);
     851static int hdaStreamStop(PHDASTREAM pStrmSt);
     852static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout);
     853static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed);
     854#endif
    839855
    840856#ifdef IN_RING3
     
    10651081        default:
    10661082        {
    1067             cb = 0;
    1068             AssertMsgFailed(("Wrong FIFO value\n"));
     1083            cb = 0; /* Can happen on stream reset. */
    10691084            break;
    10701085        }
     
    11531168
    11541169#ifdef DEBUG
    1155     LogFlowFunc(("uOldBDLE=%RU16, uCurBDLE=%RU16, cBDLE=%RU32, %R[bdle]\n",
    1156                  uOldBDLE, pStrmSt->State.uCurBDLE, pStrmSt->State.cBDLE, pBDLE));
     1170    LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, cBDLE=%RU32, %R[bdle]\n",
     1171                 pStrmSt->u8Strm, uOldBDLE, pStrmSt->State.uCurBDLE, pStrmSt->State.cBDLE, pBDLE));
    11571172#endif
    11581173    return pBDLE;
     
    14491464}
    14501465
     1466static int hdaStreamCreate(PHDASTREAM pStrmSt)
     1467{
     1468    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1469
     1470    int rc = RTSemEventCreate(&pStrmSt->State.hStateChangedEvent);
     1471    AssertRC(rc);
     1472
     1473    pStrmSt->State.fActive  = false;
     1474    pStrmSt->State.fInReset = false;
     1475    pStrmSt->State.fDoStop  = false;
     1476
     1477    LogFlowFuncLeaveRC(rc);
     1478    return rc;
     1479}
     1480
    14511481static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm)
    14521482{
    1453     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1483    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    14541484    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
    14551485
     
    14611491    pStrmSt->u16FIFOS   = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, u8Strm));
    14621492
    1463     hdaStreamDestroy(pStrmSt);
    1464 
    14651493    int rc = VINF_SUCCESS;
    14661494
     1495    if (pStrmSt->State.paBDLE)
     1496    {
     1497        Assert(pStrmSt->State.cBDLE);
     1498        RTMemFree(pStrmSt->State.paBDLE);
     1499        pStrmSt->State.paBDLE = NULL;
     1500    }
     1501
     1502    pStrmSt->State.cBDLE = 0;
     1503
    14671504    if (pStrmSt->u16LVI) /* Any BDLEs to fetch? */
    14681505    {
     1506        AssertMsg(pStrmSt->u64BaseDMA, ("No base DMA address set for stream %RU8\n", u8Strm));
     1507
    14691508        uint32_t cbBDLE = 0;
    14701509
     
    14881527            {
    14891528                if (pStrmSt->u32CBL != cbBDLE)
     1529                {
     1530                    AssertMsgFailed(("CBL (%RU32) does not match BDL entries (%RU32)\n", pStrmSt->u32CBL, cbBDLE));
    14901531                    LogRel(("HDA: Warning: CBL (%RU32) does not match BDL entries (%RU32); expect sound hickups\n",
    14911532                            pStrmSt->u32CBL, cbBDLE));
     1533                }
    14921534
    14931535                HDA_STREAM_REG(pThis, STS, pStrmSt->u8Strm) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     
    15081550    AssertPtrReturnVoid(pStrmSt);
    15091551
     1552    LogFlowFuncEnter();
     1553
     1554    int rc2 = hdaStreamStop(pStrmSt);
     1555    AssertRC(rc2);
     1556
     1557    if (pStrmSt->State.hStateChangedEvent != NIL_RTSEMEVENT)
     1558    {
     1559        rc2 = RTSemEventDestroy(pStrmSt->State.hStateChangedEvent);
     1560        AssertRC(rc2);
     1561    }
     1562
     1563    /*
     1564     * Destroy.
     1565     */
    15101566    if (pStrmSt->State.paBDLE)
    15111567    {
     
    15161572
    15171573    pStrmSt->State.cBDLE = 0;
    1518 }
    1519 #endif
     1574
     1575    LogFlowFuncLeave();
     1576}
    15201577
    15211578static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm)
     
    15261583
    15271584    /*
    1528      * Initialize stream state.
     1585     * Stop the stream and wait until our internal processing is done.
    15291586     */
    1530     RT_BZERO(pStrmSt, sizeof(HDASTREAM));
     1587    int rc2 = hdaStreamStop(pStrmSt);
     1588    if (RT_FAILURE(rc2))
     1589    {
     1590        AssertReleaseMsgFailed(("HDA: Unable to stop stream %RU8, rc=%Rrc\n", pStrmSt->u8Strm, rc2));
     1591        return;
     1592    }
    15311593
    15321594    /*
    1533      * Initialize registers.
     1595     * Set reset state.
     1596     */
     1597    Assert(ASMAtomicReadBool(&pStrmSt->State.fInReset) == false); /* No nested calls. */
     1598    ASMAtomicXchgBool(&pStrmSt->State.fInReset, true);
     1599
     1600    /*
     1601     * First, initialize the internal stream state.
     1602     */
     1603    rc2 = hdaStreamInit(pThis, pStrmSt, u8Strm);
     1604    AssertRC(rc2);
     1605
     1606    /*
     1607     * Second, initialize registers.
    15341608     */
    15351609    HDA_STREAM_REG(pThis, STS,   u8Strm) = 0;
     
    15491623    HDA_STREAM_REG(pThis, BDPL,  u8Strm) = 0;
    15501624
    1551     LogFunc(("[SD%RU8] Reset\n", u8Strm));
    1552 }
     1625    LogFunc(("[SD%RU8]: Reset\n", u8Strm));
     1626
     1627    /* Exit reset mode. */
     1628    ASMAtomicXchgBool(&pStrmSt->State.fInReset, false);
     1629
     1630    /*
     1631     * Start stream again.
     1632     */
     1633    rc2 = hdaStreamStart(pStrmSt);
     1634    AssertRC(rc2);
     1635}
     1636
     1637static int hdaStreamStart(PHDASTREAM pStrmSt)
     1638{
     1639    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1640
     1641    ASMAtomicXchgBool(&pStrmSt->State.fDoStop, false);
     1642    ASMAtomicXchgBool(&pStrmSt->State.fActive, true);
     1643
     1644    LogFlowFuncLeave();
     1645    return VINF_SUCCESS;
     1646}
     1647
     1648static int hdaStreamStop(PHDASTREAM pStrmSt)
     1649{
     1650    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1651
     1652    /* Already in stopped state? */
     1653    bool fActive = ASMAtomicReadBool(&pStrmSt->State.fActive);
     1654    if (!fActive)
     1655        return VINF_SUCCESS;
     1656
     1657#if 0 /** @todo Does not work (yet), as EMT deadlocks then. */
     1658    /*
     1659     * Wait for the stream to stop.
     1660     */
     1661    ASMAtomicXchgBool(&pStrmSt->State.fDoStop, true);
     1662
     1663    int rc = hdaStreamWaitForStateChange(pStrmSt, 60 * 1000 /* ms timeout */);
     1664    fActive = ASMAtomicReadBool(&pStrmSt->State.fActive);
     1665    if (   /* Waiting failed? */
     1666           RT_FAILURE(rc)
     1667           /* Stream is still active? */
     1668        || fActive)
     1669    {
     1670        AssertRC(rc);
     1671        LogRel(("HDA: Warning: Unable to stop stream %RU8 (state: %s), rc=%Rrc\n",
     1672                pStrmSt->u8Strm, fActive ? "active" : "stopped", rc));
     1673    }
     1674#else
     1675    int rc = VINF_SUCCESS;
     1676#endif
     1677
     1678    LogFlowFuncLeaveRC(rc);
     1679    return rc;
     1680}
     1681
     1682static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout)
     1683{
     1684    AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
     1685
     1686    LogFlowFunc(("[SD%RU8]: msTimeout=%RU32\n", pStrmSt->u8Strm, msTimeout));
     1687    return RTSemEventWait(pStrmSt->State.hStateChangedEvent, msTimeout);
     1688}
     1689#endif /* IN_RING3 */
    15531690
    15541691/* Register access handlers. */
     
    16261763    if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
    16271764    {
    1628         /* Exit reset state. */
     1765        /* Set the CRST bit to indicate that we're leaving reset mode. */
    16291766        HDA_REG(pThis, GCTL) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
    1630         pThis->fInReset = false;
     1767
     1768        if (pThis->fInReset)
     1769        {
     1770            LogFunc(("Leaving reset\n"));
     1771            pThis->fInReset = false;
     1772        }
    16311773    }
    16321774    else
     
    16371779            || HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA))
    16381780        {
    1639             LogFunc(("HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
     1781            LogFunc(("Entering reset with DMA(RIRB:%s, CORB:%s)\n",
    16401782                     HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) ? "on" : "off",
    16411783                     HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA) ? "on" : "off"));
    16421784        }
    1643         hdaReset(pThis->CTX_SUFF(pDevIns));
     1785
     1786        /* Clear the CRST bit to indicate that we're in reset mode. */
    16441787        HDA_REG(pThis, GCTL) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
    16451788        pThis->fInReset = true;
     1789
     1790        /* As the CRST bit now is set, we now can proceed resetting stuff. */
     1791        hdaReset(pThis->CTX_SUFF(pDevIns));
    16461792#else
    16471793        return VINF_IOM_R3_MMIO_WRITE;
     
    18261972    }
    18271973
    1828     LogFunc(("[SD%RU8]: %R[sdctl]\n", u8Strm, u32Value));
     1974    LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
     1975             u8Strm, fRun, fInRun, fReset, fInReset, u32Value));
    18291976
    18301977    if (fInReset)
     
    18552002        {
    18562003            Assert(!fReset && !fInReset);
     2004            LogFunc(("[SD%RU8]: fRun=%RTbool\n", u8Strm, fRun));
    18572005
    18582006            PHDADRIVER pDrv;
     
    28893037    PHDADRIVER pDrv;
    28903038
    2891     uint32_t cbIn, cbOut, cSamplesLive;
     3039    uint32_t cbIn, cbOut;
    28923040
    28933041    uint64_t uTicksNow     = PDMDevHlpTMTimeVirtGet(pDevIns);
     
    29393087        cbOutMin = 0;
    29403088
    2941     /*
    2942      * Playback.
    2943      */
    2944     if (cbOutMin)
    2945     {
    2946         Assert(cbOutMin != UINT32_MAX);
    2947         hdaTransfer(pThis, PO_INDEX, cbOutMin /* cbMax */, NULL /* pcbProcessed */); /** @todo Add rc! */
    2948     }
    2949 
    2950     /*
    2951      * Recording.
    2952      */
    2953     if (cbInMax)
    2954         hdaTransfer(pThis, PI_INDEX, cbInMax /* cbMax */, NULL /* pcbProcessed */); /** @todo Add rc! */
    2955 
     3089    /* Do the actual device transfers. */
     3090    hdaTransfer(pThis, PO_INDEX, cbOutMin /* cbToProcess */, NULL /* pcbProcessed */);
     3091    hdaTransfer(pThis, PI_INDEX, cbInMax  /* cbToProcess */, NULL /* pcbProcessed */);
     3092
     3093    /* Kick the timer again. */
    29563094    TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
    29573095
     
    30093147#endif /* VBOX_WITH_AUDIO_CALLBACKS */
    30103148
    3011 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbMax, uint32_t *pcbProcessed)
     3149static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed)
    30123150{
    30133151    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    30143152    /* pcbProcessed is optional. */
    30153153
    3016     LogFlowFunc(("enmSrc=%RU32, cbMax=%RU32\n", enmSrc, cbMax));
    3017 
    3018     PHDASTREAM pStrmSt;
    3019     switch (enmSrc)
    3020     {
    3021         case PI_INDEX:
    3022         {
    3023             pStrmSt = &pThis->StrmStLineIn;
    3024             break;
    3025         }
    3026 
    3027 #ifdef VBOX_WITH_HDA_MIC_IN
    3028         case MC_INDEX:
    3029         {
    3030             pStrmSt = &pThis->StrmStMicIn;
    3031             break;
    3032         }
    3033 #endif
    3034         case PO_INDEX:
    3035         {
    3036             pStrmSt = &pThis->StrmStOut;
    3037             break;
    3038         }
    3039 
    3040         default:
    3041         {
    3042             AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
    3043             return VERR_NOT_SUPPORTED;
    3044         }
    3045     }
    3046 
    3047     if (pStrmSt->State.cBDLE == 0) /* No buffers available? */
    3048     {
    3049         LogFlowFunc(("[SD%RU8] No buffers available\n", pStrmSt->u8Strm));
     3154    LogFlowFunc(("enmSrc=%RU32, cbToProcess=%RU32\n", enmSrc, cbToProcess));
     3155
     3156    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
     3157    {
     3158        LogFlowFunc(("In reset mode, skipping\n"));
    30503159
    30513160        if (pcbProcessed)
     
    30533162        return VINF_SUCCESS;
    30543163    }
    3055     AssertPtr(pStrmSt->State.paBDLE);
    3056 
    3057     /* Is this stream running? */
    3058     const bool fIsRunning = RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStrmSt->u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
    3059     if (!fIsRunning)
    3060     {
    3061         LogFlowFunc(("[SD%RU8]: Stream not running\n", pStrmSt->u8Strm));
    3062 
     3164
     3165    PHDASTREAM pStrmSt;
     3166    switch (enmSrc)
     3167    {
     3168        case PI_INDEX:
     3169        {
     3170            pStrmSt = &pThis->StrmStLineIn;
     3171            break;
     3172        }
     3173
     3174#ifdef VBOX_WITH_HDA_MIC_IN
     3175        case MC_INDEX:
     3176        {
     3177            pStrmSt = &pThis->StrmStMicIn;
     3178            break;
     3179        }
     3180#endif
     3181        case PO_INDEX:
     3182        {
     3183            pStrmSt = &pThis->StrmStOut;
     3184            break;
     3185        }
     3186
     3187        default:
     3188        {
     3189            AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
     3190            return VERR_NOT_SUPPORTED;
     3191        }
     3192    }
     3193
     3194    int  rc       = VINF_SUCCESS;
     3195    bool fProceed = true;
     3196
     3197    /* Stop request received? */
     3198    if (ASMAtomicReadBool(&pStrmSt->State.fDoStop))
     3199    {
     3200        pStrmSt->State.fActive = false;
     3201
     3202        rc = RTSemEventSignal(pStrmSt->State.hStateChangedEvent);
     3203        AssertRC(rc);
     3204
     3205        fProceed = false;
     3206    }
     3207    /* Is the stream not in a running state currently? */
     3208    else if (!(HDA_STREAM_REG(pThis, CTL, pStrmSt->u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
     3209        fProceed = false;
     3210    /* There must be BDLEs defined in order to have a working stream. */
     3211    else if (pStrmSt->State.cBDLE == 0)
     3212        fProceed = false;
     3213    /* Nothing to process? */
     3214    else if (!cbToProcess)
     3215        fProceed = false;
     3216
     3217    if (!fProceed)
     3218    {
    30633219        if (pcbProcessed)
    30643220            *pcbProcessed = 0;
     
    30663222    }
    30673223
     3224    /* Sanity checks. */
    30683225    Assert(pStrmSt->u8Strm <= 7); /** @todo Use a define for MAX_STREAMS! */
    30693226    Assert(pStrmSt->u64BaseDMA);
    30703227    Assert(pStrmSt->u32CBL);
    30713228
    3072     int      rc               = VINF_SUCCESS;
    3073     uint32_t cbToProcess      = cbMax;
     3229    /* State sanity checks. */
     3230    AssertPtr(pStrmSt->State.paBDLE);
     3231    Assert(ASMAtomicReadBool(&pStrmSt->State.fInReset) == false);
     3232
    30743233    uint32_t cbProcessedTotal = 0;
    30753234    bool     fIsComplete      = false;
     
    39714130    pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
    39724131
     4132    /*
     4133     * Stop the timer, if any.
     4134     */
     4135    int rc2;
     4136    if (pThis->pTimer)
     4137    {
     4138        rc2 = TMTimerStop(pThis->pTimer);
     4139        AssertRC(rc2);
     4140    }
     4141
    39734142    for (uint8_t u8Strm = 0; u8Strm < 8; u8Strm++) /** @todo Use a define here. */
    39744143    {
     
    39944163    /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
    39954164    HDA_REG(pThis, STATESTS) = 0x1;
     4165
     4166    /*
     4167     * Start timer again, if any.
     4168     */
     4169    if (pThis->pTimer)
     4170    {
     4171        rc2 = TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks);
     4172        AssertRC(rc2);
     4173    }
    39964174
    39974175    LogRel(("HDA: Reset\n"));
     
    43444522        PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
    43454523        PCIDevSetSubSystemId(      &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
     4524    }
     4525
     4526    if (RT_SUCCESS(rc))
     4527    {
     4528        rc = hdaStreamCreate(&pThis->StrmStLineIn);
     4529        AssertRC(rc);
     4530#ifdef VBOX_WITH_HDA_MIC_IN
     4531        rc = hdaStreamCreate(&pThis->StrmStMicIn);
     4532        AssertRC(rc);
     4533#endif
     4534        rc = hdaStreamCreate(&pThis->StrmStOut);
     4535        AssertRC(rc);
    43464536    }
    43474537
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