VirtualBox

Changeset 64572 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 4, 2016 12:54:38 PM (8 years ago)
Author:
vboxsync
Message:

Audio/HDA: Rewritten large parts of the interrupt delivery and DMA handling to improve audio data delivery.

We now update the interrupt status when needed, and not when the status is read by the guest -- this created all kinds of funny side effects. Also, split out the DMA transfers to an own routine for easier debugging and made sure we transfer the correct sizes according to FIFOS boundaries.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

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

    r64404 r64572  
    179179#define HDA_REG_STATESTS            7 /* 0x0E */
    180180#define HDA_RMX_STATESTS            7
    181 #define HDA_STATES_SCSF             0x7
     181#define HDA_STATESTS_SCSF_MASK      0x7 /* State Change Status Flags (6.2.8). */
    182182
    183183#define HDA_REG_GSTS                8 /* 0x10-0x11*/
     
    477477 * Other values not listed are not supported.
    478478 */
     479/** Maximum FIFO size (in bytes). */
     480#define HDA_FIFO_MAX                256
     481
    479482#define HDA_SDIFIFO_120B            0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
    480483#define HDA_SDIFIFO_160B            0x9F /* 20-, 24-bit Input Streams Streams */
     
    566569     *  Used to check if we need fill up the FIFO again. */
    567570    uint32_t     cbBelowFIFOW;
    568     /** The buffer descriptor's internal DMA buffer. */
    569     uint8_t      au8FIFO[HDA_SDOFIFO_256B + 1];
    570571    /** Current offset in DMA buffer (in bytes).*/
    571572    uint32_t     u32BufOff;
     
    603604    /** Number of audio channels in this stream. */
    604605    uint8_t                           cChannels;
    605     /** Array audio channels. */
     606    /** Array of audio channels. */
    606607    R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels;
     608    /** Circular buffer holding for holding audio data for this mapping. */
    607609    R3PTRTYPE(PRTCIRCBUF)             pCircBuf;
    608610} HDASTREAMMAPPING, *PHDASTREAMMAPPING;
     
    616618     *  maximum (cBDLE) is reached. */
    617619    uint16_t                uCurBDLE;
    618     /** Stop indicator. */
    619     volatile bool           fDoStop;
    620     /** Flag indicating whether this stream is in an
    621      *  active (operative) state or not. */
    622     volatile bool           fActive;
    623620    /** Flag indicating whether this stream currently is
    624621     *  in reset mode and therefore not acccessible by the guest. */
    625622    volatile bool           fInReset;
    626623    /** Unused, padding. */
    627     bool                    fPadding;
     624    uint32_t                Padding0;
    628625    /** Critical section to serialize access. */
    629626    RTCRITSECT              CritSect;
    630     /** Event signalling that the stream's state has been changed. */
    631     RTSEMEVENT              hStateChangedEvent;
    632627    /** This stream's data mapping. */
    633628    HDASTREAMMAPPING        Mapping;
    634629    /** Current BDLE (Buffer Descriptor List Entry). */
    635630    HDABDLE                 BDLE;
     631    /** Circular buffer (FIFO) for holding DMA'ed data. */
     632    R3PTRTYPE(PRTCIRCBUF)   pCircBuf;
    636633} HDASTREAMSTATE, *PHDASTREAMSTATE;
    637634
     
    659656
    660657/**
    661  * Structure for keeping a HDA stream state.
     658 * Structure for keeping a HDA stream (SDI / SDO).
     659 *
     660 * Note: This HDA stream has nothing to do with a regular audio stream handled
     661 * by the audio connector or the audio mixer. This HDA stream is a serial data in/out
     662 * stream (SDI/SDO) defined in hardware and can contain multiple audio streams
     663 * in one single SDI/SDO (interleaving streams).
     664 *
     665 * How a specific SDI/SDO is mapped to our internal audio streams relies on the
     666 * stream channel mappings.
    662667 *
    663668 * Contains only register values which do *not* change until a
     
    678683    /** FIFO Size (FIFOS).
    679684     *  Maximum number of bytes that may have been DMA'd into
    680      *  memory but not yet transmitted on the link.
    681      *
    682      *  Must be a power of two. */
     685     *  memory but not yet transmitted on the link. */
    683686    uint16_t                 u16FIFOS;
     687    /** FIFO Watermark. */
     688    uint16_t                 u16FIFOW;
    684689    /** Last Valid Index (SDnLVI). */
    685690    uint16_t                 u16LVI;
    686     uint16_t                 Padding1[3];
     691    uint16_t                 Padding1[2];
    687692    /** Pointer to HDA sink this stream is attached to. */
    688693    R3PTRTYPE(PHDAMIXERSINK) pMixSink;
     
    827832     * Used to calculate the time actually elapsed between two timer callbacks. */
    828833    uint64_t                           uTimerTS;
     834    uint64_t                           uTimerMS;
    829835#endif
    830836#ifdef VBOX_WITH_STATISTICS
     
    892898 */
    893899static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    894 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    895900static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    896901static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
    897 //static int hdaRegReadSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value); - unused
    898 //static int hdaRegWriteSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);  - unused
    899 //static int hdaRegWriteINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - implementation not found.
    900902static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    901903static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
     
    905907static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    906908static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
     909static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    907910static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    908911static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
     
    917920static int       hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    918921static int       hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    919 //static int       hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - unused
    920 //static int       hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value); - unused
     922static int       hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
     923static int       hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    921924static int       hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
    922925static int       hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
     
    945948/** @} */
    946949
     950/** @name Stream functions.
     951 * @{
     952 */
    947953#ifdef IN_RING3
    948 static void hdaStreamDestroy(PHDASTREAM pStream);
    949 static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive);
    950 //static int hdaStreamStart(PHDASTREAM pStream); - unused
    951 static int hdaStreamStop(PHDASTREAM pStream);
    952 /*static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout); - currently unused */
    953 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed);
    954 #endif
    955 
     954static void          hdaStreamDestroy(PHDASTREAM pStream);
     955static int           hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t cbToProcess, uint32_t *pcbProcessed);
     956static int           hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive);
     957static int           hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream);
     958DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);
     959#endif /* IN_RING3 */
     960/** @} */
     961
     962/** @name Stream mapping functions.
     963 * @{
     964 */
    956965#ifdef IN_RING3
    957 static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg);
    958 static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping);
    959 static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping);
    960 #endif
    961 
     966static int           hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg);
     967static void          hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping);
     968static void          hdaStreamMapReset(PHDASTREAMMAPPING pMapping);
     969#endif /* IN_RING3 */
     970/** @} */
     971
     972/** @name HDA device functions.
     973 * @{
     974 */
     975#ifdef IN_RING3
     976static void          hdaDoTransfers(PHDASTATE pThis);
     977#endif /* IN_RING3 */
     978static int           hdaProcessInterrupt(PHDASTATE pThis);
     979/** @} */
     980
     981/** @name BDLE (Buffer Descriptor List Entry) functions.
     982 * @{
     983 */
    962984#ifdef IN_RING3
    963985static int           hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
    964 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);
    965986# ifdef LOG_ENABLED
    966987static void          hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
    967988# endif
    968 #endif
    969 static int           hdaProcessInterrupt(PHDASTATE pThis);
    970 
    971 /*
    972  * Timer routines.
     989#endif /* IN_RING3 */
     990/** @} */
     991
     992/** @name Timer functions.
     993 * @{
    973994 */
    974995#if !defined(VBOX_WITH_AUDIO_HDA_CALLBACKS) && defined(IN_RING3)
    975 static void hdaTimerMaybeStart(PHDASTATE pThis);
    976 static void hdaTimerMaybeStop(PHDASTATE pThis);
    977 #endif
     996static void          hdaTimerMaybeStart(PHDASTATE pThis);
     997static void          hdaTimerMaybeStop(PHDASTATE pThis);
     998#endif
     999/** @} */
    9781000
    9791001
     
    10011023    { offset,        0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , HDA_REG_IDX_STRM(name, CTL)  , #name " Stream Descriptor Control" }, \
    10021024    /* Offset 0x83 (SD0) */ \
    1003     { offset + 0x3,  0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8  , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS)  , #name " Status" }, \
     1025    { offset + 0x3,  0x00001, 0x0000003C, 0x0000001C, hdaRegReadU8  , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS)  , #name " Status" }, \
    10041026    /* Offset 0x84 (SD0) */ \
    10051027    { offset + 0x4,  0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadLPIB, hdaRegWriteU32   , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
     
    10091031    { offset + 0xC,  0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16, hdaRegWriteSDLVI  , HDA_REG_IDX_STRM(name, LVI)  , #name " Last Valid Index" }, \
    10101032    /* Reserved: FIFO Watermark. ** @todo Document this! */ \
    1011     { offset + 0xE,  0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteU16,    HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
     1033    { offset + 0xE,  0x00002, 0x00000007, 0x00000007, hdaRegReadU16, hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
    10121034    /* Offset 0x90 (SD0) */ \
    1013     { offset + 0x10, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16, hdaRegWriteU16,    HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
     1035    { offset + 0x10, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16, hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
    10141036    /* Offset 0x92 (SD0) */ \
    10151037    { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16, hdaRegWriteSDFMT  , HDA_REG_IDX_STRM(name, FMT)  , #name " Stream Format" }, \
     
    10611083    { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16        , HDA_REG_IDX(OUTSTRMPAY)   }, /* Output Stream Payload Capability */
    10621084    { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimpl     , HDA_REG_IDX(INSTRMPAY)    }, /* Input Stream Payload Capability */
    1063     { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32          , hdaRegWriteU32        , HDA_REG_IDX(INTCTL)       }, /* Interrupt Control */
    1064     { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS       , hdaRegWriteUnimpl     , HDA_REG_IDX(INTSTS)       }, /* Interrupt Status */
     1085    { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32          , hdaRegWriteINTCTL     , HDA_REG_IDX(INTCTL)       }, /* Interrupt Control */
     1086    { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadU32          , hdaRegWriteUnimpl     , HDA_REG_IDX(INTSTS)       }, /* Interrupt Status */
    10651087    { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK       , hdaRegWriteUnimpl     , HDA_REG_IDX_LOCAL(WALCLK) }, /* Wall Clock Counter */
    10661088    { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32          , hdaRegWriteU32        , HDA_REG_IDX(SSYNC)        }, /* Stream Synchronization */
     
    11331155    SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
    11341156    SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
    1135     SSMFIELD_ENTRY(HDABDLESTATE, au8FIFO),
     1157    SSMFIELD_ENTRY_OLD(FIFO, 256),
    11361158    SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
    11371159    SSMFIELD_ENTRY_TERM()
     
    11431165    SSMFIELD_ENTRY_OLD(cBDLE, 2),
    11441166    SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
    1145     SSMFIELD_ENTRY(HDASTREAMSTATE, fDoStop),
    1146     SSMFIELD_ENTRY(HDASTREAMSTATE, fActive),
     1167    SSMFIELD_ENTRY_OLD(fDoStop, 1),
     1168    SSMFIELD_ENTRY_OLD(fActive, 1),
    11471169    SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
    11481170    SSMFIELD_ENTRY_TERM()
     
    11571179    UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff)
    11581180};
    1159 
    1160 #ifdef IN_RING3
    1161 
    1162 DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
    1163 {
    1164     AssertPtrReturn(pThis,   0);
    1165     AssertPtrReturn(pStream, 0);
    1166 
    1167     Assert(u32LPIB <= pStream->u32CBL);
    1168 
    1169     LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
    1170                  pStream->u8SD, u32LPIB, pThis->fDMAPosition));
    1171 
    1172     /* Update LPIB in any case. */
    1173     HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
    1174 
    1175     /* Do we need to tell the current DMA position? */
    1176     if (pThis->fDMAPosition)
    1177     {
    1178         int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
    1179                                         (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)),
    1180                                         (void *)&u32LPIB, sizeof(uint32_t));
    1181         AssertRC(rc2);
    1182     }
    1183 
    1184     return u32LPIB;
    1185 }
    11861181
    11871182
     
    12181213
    12191214
    1220 # if defined(IN_RING3) && (defined(DEBUG) || defined(VBOX_HDA_WITH_FIFO))
    12211215/**
    12221216 * Retrieves the number of bytes of a FIFOW register.
     
    12381232    return cb;
    12391233}
    1240 #endif
     1234
     1235
     1236#ifdef IN_RING3
     1237DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
     1238{
     1239    AssertPtrReturn(pThis,   0);
     1240    AssertPtrReturn(pStream, 0);
     1241
     1242    AssertMsg(u32LPIB <= pStream->u32CBL,
     1243              ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));
     1244
     1245    u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
     1246
     1247    LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
     1248                 pStream->u8SD, u32LPIB, pThis->fDMAPosition));
     1249
     1250    /* Update LPIB in any case. */
     1251    HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
     1252
     1253    /* Do we need to tell the current DMA position? */
     1254    if (pThis->fDMAPosition)
     1255    {
     1256        int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
     1257                                        (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)),
     1258                                        (void *)&u32LPIB, sizeof(uint32_t));
     1259        AssertRC(rc2);
     1260    }
     1261
     1262    return u32LPIB;
     1263}
    12411264
    12421265
     
    12461269 * @return  IPRT status code.
    12471270 */
    1248 DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream)
     1271DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream, bool *pfWrapAround)
    12491272{
    12501273    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     
    12611284# endif
    12621285
    1263     PHDABDLE pBDLE = &pStream->State.BDLE;
     1286    PHDABDLE pBDLE       = &pStream->State.BDLE;
     1287    bool     fWrapAround = false;
     1288
     1289    AssertMsg(pBDLE->State.u32BufOff == pBDLE->u32BufSize, ("BDLE not finished yet: %R[bdle]\n", pBDLE));
    12641290
    12651291    /*
     
    12711297    {
    12721298        pStream->State.uCurBDLE = 0;
    1273 
    1274         hdaStreamUpdateLPIB(pThis, pStream, 0);
     1299        fWrapAround = true;
    12751300    }
    12761301
     
    12791304    /* Fetch the next BDLE entry. */
    12801305    int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
    1281 
    1282     LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",
    1283                  pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));
     1306    if (RT_SUCCESS(rc))
     1307    {
     1308        LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",
     1309                     pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));
     1310
     1311        if (pfWrapAround)
     1312            *pfWrapAround = fWrapAround;
     1313    }
     1314
    12841315    return rc;
    12851316}
    12861317
     1318
     1319/**
     1320 * Returns the HDA stream of specified stream descriptor number.
     1321 *
     1322 * @return  Pointer to HDA stream, or NULL if none found.
     1323 */
     1324DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD)
     1325{
     1326    AssertPtrReturn(pThis, NULL);
     1327    AssertReturn(uSD <= HDA_MAX_STREAMS, NULL);
     1328
     1329    if (uSD >= HDA_MAX_STREAMS)
     1330        return NULL;
     1331
     1332    return &pThis->aStreams[uSD];
     1333}
     1334
     1335
     1336/**
     1337 * Returns the HDA stream of specified HDA sink.
     1338 *
     1339 * @return  Pointer to HDA stream, or NULL if none found.
     1340 */
     1341DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink)
     1342{
     1343    AssertPtrReturn(pThis, NULL);
     1344    AssertPtrReturn(pSink, NULL);
     1345
     1346    /** @todo Do something with the channel mapping here? */
     1347    return hdaStreamFromSD(pThis, pSink->uSD);
     1348}
     1349
     1350/**
     1351 * Retrieves the minimum number of bytes accumulated/free in the
     1352 * FIFO before the controller will start a fetch/eviction of data.
     1353 *
     1354 * Uses SDFIFOW (FIFO Watermark Register).
     1355 *
     1356 * @return Number of bytes accumulated/free in the FIFO.
     1357 */
     1358DECLINLINE(uint8_t) hdaStreamGetFIFOW(PHDASTATE pThis, PHDASTREAM pStream)
     1359{
     1360    AssertPtrReturn(pThis, 0);
     1361    AssertPtrReturn(pStream, 0);
     1362
     1363# ifdef VBOX_HDA_WITH_FIFO
     1364    return hdaSDFIFOWToBytes(HDA_STREAM_REG(pThis, FIFOW, pStream->u8SD));
     1365# else
     1366    return 0;
     1367# endif
     1368}
     1369
     1370#endif /* IN_RING3 */
    12871371
    12881372/**
     
    13081392}
    13091393
    1310 
    1311 /**
    1312  * Returns the HDA stream of specified stream descriptor number.
    1313  *
    1314  * @return  Pointer to HDA stream, or NULL if none found.
    1315  */
    1316 DECLINLINE(PHDASTREAM) hdaStreamFromSD(PHDASTATE pThis, uint8_t uSD)
    1317 {
    1318     AssertPtrReturn(pThis, NULL);
    1319     AssertReturn(uSD <= HDA_MAX_STREAMS, NULL);
    1320 
    1321     if (uSD >= HDA_MAX_STREAMS)
    1322         return NULL;
    1323 
    1324     return &pThis->aStreams[uSD];
    1325 }
    1326 
    1327 
    1328 /**
    1329  * Returns the HDA stream of specified HDA sink.
    1330  *
    1331  * @return  Pointer to HDA stream, or NULL if none found.
    1332  */
    1333 DECLINLINE(PHDASTREAM) hdaGetStreamFromSink(PHDASTATE pThis, PHDAMIXERSINK pSink)
    1334 {
    1335     AssertPtrReturn(pThis, NULL);
    1336     AssertPtrReturn(pSink, NULL);
    1337 
    1338     /** @todo Do something with the channel mapping here? */
    1339     return hdaStreamFromSD(pThis, pSink->uSD);
    1340 }
    1341 
    1342 /**
    1343  * Retrieves the minimum number of bytes accumulated/free in the
    1344  * FIFO before the controller will start a fetch/eviction of data.
    1345  *
    1346  * Uses SDFIFOW (FIFO Watermark Register).
    1347  *
    1348  * @return Number of bytes accumulated/free in the FIFO.
    1349  */
    1350 DECLINLINE(uint8_t) hdaStreamGetFIFOW(PHDASTATE pThis, PHDASTREAM pStream)
    1351 {
    1352     AssertPtrReturn(pThis, 0);
    1353     AssertPtrReturn(pStream, 0);
    1354 
    1355 # ifdef VBOX_HDA_WITH_FIFO
    1356     return hdaSDFIFOWToBytes(HDA_STREAM_REG(pThis, FIFOW, pStream->u8SD));
    1357 # else
    1358     return 0;
    1359 # endif
    1360 }
    1361 
    1362 #endif /* IN_RING3 */
     1394static void hdaUpdateINTSTS(PHDASTATE pThis)
     1395{
     1396    uint32_t intSts = 0;
     1397
     1398    if (/* Response Overrun Interrupt Status (ROIS) */
     1399           HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
     1400        /* Response Interrupt */
     1401        || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
     1402        /* SDIN State Change Status Flags (SCSF) */
     1403        || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
     1404    {
     1405        intSts |= RT_BIT(30); /* Touch Controller Interrupt Status (CIS). */
     1406    }
     1407
     1408#define HDA_MARK_STREAM(x)                                                  \
     1409        if (   (INTCTL_SX(pThis, x))                                        \
     1410            && (   (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))   \
     1411                || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))   \
     1412                || (SDSTS(pThis, x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)) \
     1413               )                                                            \
     1414           )                                                                \
     1415    {                                                                       \
     1416        Log3Func(("[SD%RU8] Marked\n", x));                                 \
     1417        intSts |= RT_BIT(x);                                                \
     1418    }
     1419
     1420    HDA_MARK_STREAM(0);
     1421    HDA_MARK_STREAM(1);
     1422    HDA_MARK_STREAM(2);
     1423    HDA_MARK_STREAM(3);
     1424    HDA_MARK_STREAM(4);
     1425    HDA_MARK_STREAM(5);
     1426    HDA_MARK_STREAM(6);
     1427    HDA_MARK_STREAM(7);
     1428
     1429#undef HDA_MARK_STREAM
     1430
     1431    if (intSts)
     1432        intSts |= RT_BIT(31); /* Touch Global Interrupt Status (GIS). */
     1433
     1434    HDA_REG(pThis, INTSTS) = intSts;
     1435
     1436    Log3Func(("INTSTS=%x\n", intSts));
     1437}
    13631438
    13641439static int hdaProcessInterrupt(PHDASTATE pThis)
    13651440{
    1366 #define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \
    1367         (   INTCTL_SX((pThis), num) \
    1368          && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
     1441    hdaUpdateINTSTS(pThis);
    13691442
    13701443    int iLevel = 0;
    13711444
    1372     /** @todo Optimize IRQ handling. */
    1373 
    1374     if (/* Controller Interrupt Enable (CIE). */
    1375           HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE)
    1376        && (   HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
    1377            || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
    1378            || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))))
    1379     {
     1445    /* Global Interrupt Status (GIS) touched? */
     1446    if (HDA_REG_FLAG_VALUE(pThis, INTSTS, GIS))
    13801447        iLevel = 1;
    1381     }
    1382 
    1383     if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
    1384         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 1)
    1385         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 2)
    1386         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 3)
    1387         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4)
    1388         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 5)
    1389         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 6)
    1390         || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 7))
    1391     {
    1392         iLevel = 1;
    1393     }
    1394 
     1448
     1449    Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel));
     1450
     1451    /* Global Interrupt Enable (GIE) set? */
    13951452    if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
    1396     {
    1397         Log3Func(("Level=%d\n", iLevel));
    1398         PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , iLevel);
    1399     }
    1400 
    1401 #undef IS_INTERRUPT_OCCURED_AND_ENABLED
     1453        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel);
    14021454
    14031455    return VINF_SUCCESS;
     
    16381690    AssertReturn(uSD <= HDA_MAX_STREAMS, VERR_INVALID_PARAMETER);
    16391691
    1640     int rc = RTSemEventCreate(&pStream->State.hStateChangedEvent);
    1641     if (RT_SUCCESS(rc))
    1642         rc = RTCritSectInit(&pStream->State.CritSect);
    1643 
     1692    int rc = RTCritSectInit(&pStream->State.CritSect);
    16441693    if (RT_SUCCESS(rc))
    16451694    {
     
    16471696        pStream->pMixSink       = NULL;
    16481697
    1649         pStream->State.fActive  = false;
    16501698        pStream->State.fInReset = false;
    1651         pStream->State.fDoStop  = false;
    1652     }
     1699    }
     1700
     1701    if (RT_SUCCESS(rc))
     1702        rc = RTCircBufCreate(&pStream->State.pCircBuf, HDA_FIFO_MAX);
    16531703
    16541704    LogFlowFunc(("uSD=%RU8\n", uSD));
     
    16621712    LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
    16631713
    1664     int rc2 = hdaStreamStop(pStream);
     1714    hdaStreamMapDestroy(&pStream->State.Mapping);
     1715
     1716    int rc2 = RTCritSectDelete(&pStream->State.CritSect);
    16651717    AssertRC(rc2);
    16661718
    1667     hdaStreamMapDestroy(&pStream->State.Mapping);
    1668 
    1669     rc2 = RTCritSectDelete(&pStream->State.CritSect);
    1670     AssertRC(rc2);
    1671 
    1672     if (pStream->State.hStateChangedEvent != NIL_RTSEMEVENT)
    1673     {
    1674         rc2 = RTSemEventDestroy(pStream->State.hStateChangedEvent);
    1675         AssertRC(rc2);
    1676         pStream->State.hStateChangedEvent = NIL_RTSEMEVENT;
     1719    if (pStream->State.pCircBuf)
     1720    {
     1721        RTCircBufDestroy(pStream->State.pCircBuf);
     1722        pStream->State.pCircBuf = NULL;
    16771723    }
    16781724
     
    17391785    RT_ZERO(pStream->State.BDLE);
    17401786    pStream->State.uCurBDLE = 0;
     1787
     1788    if (pStream->State.pCircBuf)
     1789        RTCircBufReset(pStream->State.pCircBuf);
     1790#if 0
     1791    RT_ZERO(pStream->State.abFIFO);
     1792    pStream->State.cbFIFOUsed = 0;
     1793    pStream->State.cbFIFOOff  = 0;
     1794#endif
    17411795
    17421796    /*
     
    17471801     * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
    17481802    HDA_STREAM_REG(pThis, CTL,   uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    1749     /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39. */
    1750     HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B;
     1803    /*
     1804     * ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39.
     1805     * BUT: Windows guests seem to read the FIFOS but define a DMA region which does not fit to that FIFO size
     1806     *      (e.g. 1792 bytes DMA region vs. 192 bytes FIFOS).
     1807     *      This will lead to crackling and corrupted sound -- so define a 256 bytes FIOS for output streams here per default.
     1808     */
     1809    HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_256B;
    17511810    /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
    17521811    HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
     
    17631822    AssertRC(rc2);
    17641823
    1765     /* Report that we're done resetting this stream. */
    1766     HDA_STREAM_REG(pThis, CTL,   uSD) = 0;
    1767 
    17681824    /* Exit reset state. */
    17691825    ASMAtomicXchgBool(&pStream->State.fInReset, false);
    17701826}
    17711827
    1772 # if 0 /* unused */
    1773 static bool hdaStreamIsActive(PHDASTATE pThis, PHDASTREAM pStream)
    1774 {
    1775     AssertPtrReturn(pThis,   false);
    1776     AssertPtrReturn(pStream, false);
    1777 
    1778     bool fActive = pStream->State.fActive;
    1779 
    1780     LogFlowFunc(("SD=%RU8, fActive=%RTbool\n", pStream->u8SD, fActive));
    1781     return fActive;
    1782 }
    1783 # endif
    1784 
    17851828static int hdaStreamSetActive(PHDASTATE pThis, PHDASTREAM pStream, bool fActive)
    17861829{
     
    17891832
    17901833    LogFlowFunc(("[SD%RU8]: fActive=%RTbool, pMixSink=%p\n", pStream->u8SD, fActive, pStream->pMixSink));
    1791 
    1792     if (pStream->State.fActive == fActive) /* No change required? */
    1793     {
    1794         LogFlowFunc(("[SD%RU8]: No change\n", pStream->u8SD));
    1795         return VINF_SUCCESS;
    1796     }
    17971834
    17981835    int rc = VINF_SUCCESS;
     
    18151852        return rc;
    18161853    }
    1817 
    1818     pStream->State.fActive = fActive;
    18191854
    18201855    /* Second, see if we need to start or stop the timer. */
     
    18521887        AssertRC(rc2);
    18531888    }
    1854 }
    1855 
    1856 # if 0 /** @todo hdaStreamStart is unused */
    1857 static int hdaStreamStart(PHDASTREAM pStream)
    1858 {
    1859     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1860 
    1861     ASMAtomicXchgBool(&pStream->State.fDoStop, false);
    1862     ASMAtomicXchgBool(&pStream->State.fActive, true);
    1863 
    1864     LogFlowFuncLeave();
    1865     return VINF_SUCCESS;
    1866 }
    1867 # endif /* unused */
    1868 
    1869 static int hdaStreamStop(PHDASTREAM pStream)
    1870 {
    1871     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1872 
    1873     /* Already in stopped state? */
    1874     bool fActive = ASMAtomicReadBool(&pStream->State.fActive);
    1875     if (!fActive)
    1876         return VINF_SUCCESS;
    1877 
    1878 # if 0 /** @todo Does not work (yet), as EMT deadlocks then. */
    1879     /*
    1880      * Wait for the stream to stop.
    1881      */
    1882     ASMAtomicXchgBool(&pStream->State.fDoStop, true);
    1883 
    1884     int rc = hdaStreamWaitForStateChange(pStream, 60 * 1000 /* ms timeout */);
    1885     fActive = ASMAtomicReadBool(&pStream->State.fActive);
    1886     if (   /* Waiting failed? */
    1887            RT_FAILURE(rc)
    1888            /* Stream is still active? */
    1889         || fActive)
    1890     {
    1891         AssertRC(rc);
    1892         LogRel(("HDA: Warning: Unable to stop stream %RU8 (state: %s), rc=%Rrc\n",
    1893                 pStream->u8Strm, fActive ? "active" : "stopped", rc));
    1894     }
    1895 # else
    1896     int rc = VINF_SUCCESS;
    1897 # endif
    1898 
    1899     LogFlowFuncLeaveRC(rc);
    1900     return rc;
    19011889}
    19021890
     
    21472135static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    21482136{
    2149     uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
    2150 
    2151     uint32_t v = pThis->au32Regs[iRegMem];
    2152     uint32_t nv = u32Value & HDA_STATES_SCSF;
    2153     pThis->au32Regs[iRegMem] &= ~(v & nv); /* write of 1 clears corresponding bit */
    2154     return VINF_SUCCESS;
    2155 }
    2156 
    2157 static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    2158 {
    2159     RT_NOREF_PV(iReg);
    2160 
    2161     uint32_t v = 0;
    2162     if (   HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
    2163         || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
    2164         || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI)
    2165         || HDA_REG(pThis, STATESTS))
    2166     {
    2167         v |= RT_BIT(30); /* Touch CIS. */
    2168     }
    2169 
    2170 #define HDA_MARK_STREAM(x)                                             \
    2171     if (/* Descriptor Error */                                         \
    2172            (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))    \
    2173         /* FIFO Error */                                               \
    2174         || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))    \
    2175         /* Buffer Completion Interrupt Status */                       \
    2176         || (SDSTS((pThis), x) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))) \
    2177     {                                                                  \
    2178         Log3Func(("[SD%RU8] BCIS: Marked\n", x));                      \
    2179         v |= RT_BIT(x);                                                \
    2180     }
    2181 
    2182     HDA_MARK_STREAM(0);
    2183     HDA_MARK_STREAM(1);
    2184     HDA_MARK_STREAM(2);
    2185     HDA_MARK_STREAM(3);
    2186     HDA_MARK_STREAM(4);
    2187     HDA_MARK_STREAM(5);
    2188     HDA_MARK_STREAM(6);
    2189     HDA_MARK_STREAM(7);
    2190 
    2191 #undef HDA_MARK_STREAM
    2192 
    2193     /* "OR" bit of all interrupt status bits. */
    2194     v |= v ? RT_BIT(31) : 0;
    2195 
    2196     *pu32Value = v;
    2197     return VINF_SUCCESS;
     2137    uint32_t v  = HDA_REG_IND(pThis, iReg);
     2138    uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK;
     2139
     2140    HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
     2141
     2142    return hdaProcessInterrupt(pThis);
     2143}
     2144
     2145static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     2146{
     2147    RT_NOREF(iReg);
     2148
     2149    HDA_REG(pThis, INTCTL) = u32Value;
     2150
     2151    return hdaProcessInterrupt(pThis);
    21982152}
    21992153
     
    22212175    return VINF_SUCCESS;
    22222176}
    2223 
    2224 #if 0 /** @todo hdaRegReadSSYNC &  hdaRegWriteSSYNC are unused */
    2225 
    2226 static int hdaRegReadSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
    2227 {
    2228     RT_NOREF_PV(iReg);
    2229 
    2230     /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
    2231     *pu32Value = HDA_REG(pThis, SSYNC);
    2232     LogFlowFunc(("%RU32\n", *pu32Value));
    2233     return VINF_SUCCESS;
    2234 }
    2235 
    2236 static int hdaRegWriteSSYNC(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    2237 {
    2238     LogFlowFunc(("%RU32\n", u32Value));
    2239     return hdaRegWriteU32(pThis, iReg, u32Value);
    2240 }
    2241 
    2242 #endif /* unused */
    22432177
    22442178static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
     
    23402274{
    23412275#ifdef IN_RING3
     2276    /*
     2277     * Some guests write too much (that is, 32-bit with the top 8 bit being junk)
     2278     * instead of 24-bit required for SDCTL. So just mask this here to be safe.
     2279     */
     2280    u32Value = (u32Value & 0x00ffffff);
     2281
    23422282    bool fRun      = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
    23432283    bool fInRun    = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
     
    23462286    bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
    23472287
     2288    /* Get the stream descriptor. */
     2289    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
     2290
     2291    LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
     2292             uSD, fRun, fInRun, fReset, fInReset, u32Value));
     2293
    23482294    if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
    23492295        return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    2350 
    2351     /* Get the stream descriptor. */
    2352     uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
    23532296
    23542297    /*
     
    23822325    AssertRC(rc2);
    23832326
    2384     LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
    2385              uSD, fRun, fInRun, fReset, fInReset, u32Value));
    2386 
    23872327    if (fInReset)
    23882328    {
     
    24012341
    24022342        LogFunc(("[SD%RU8]: Guest initiated enter to stream reset\n", pStream->u8SD));
     2343
    24032344        hdaStreamReset(pThis, pStream);
    24042345    }
     
    24222363            }
    24232364        }
    2424 
    2425         if (!fInRun && !fRun)
    2426             hdaStreamInit(pThis, pStream, pStream->u8SD);
    2427     }
     2365    }
     2366
     2367    rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
     2368    AssertRC(rc2);
    24282369
    24292370    /* Make sure to handle interrupts here as well. */
    24302371    hdaProcessInterrupt(pThis);
    2431 
    2432     rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
    2433     AssertRC(rc2);
    24342372
    24352373    hdaRegWriteSDUnlock(pStream);
     
    24432381static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    24442382{
    2445     uint32_t v  = HDA_REG_IND(pThis, iReg);
    2446              /* Clear (zero) FIFOE and DESE bits when writing 1 to it. */
    2447              v &= ~(u32Value & v);
    2448 
    2449     HDA_REG_IND(pThis, iReg) = v;
     2383    uint32_t v = HDA_REG_IND(pThis, iReg);
     2384
     2385    /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */
     2386    HDA_REG_IND(pThis, iReg) &= ~(u32Value & v);
     2387
     2388    LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg)));
    24502389
    24512390    hdaProcessInterrupt(pThis);
    2452     return VINF_SUCCESS;
     2391    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
    24532392}
    24542393
     
    24592398        return VINF_SUCCESS;
    24602399
    2461     PHDASTREAM pStream = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, LVI, iReg));
     2400    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
     2401
     2402    PHDASTREAM pStream = hdaStreamFromSD(pThis, uSD);
    24622403    if (!pStream)
    24632404    {
    2464         LogFunc(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", HDA_SD_NUM_FROM_REG(pThis, CTL, iReg), u32Value));
     2405        AssertMsgFailed(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", uSD, u32Value));
    24652406        return hdaRegWriteU16(pThis, iReg, u32Value);
    24662407    }
    24672408
    24682409    int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value);
    2469     AssertRC(rc2);
    2470 
    2471     /** @todo Validate LVI. */
    2472     pStream->u16LVI = u32Value;
    2473 
    2474     /* Reset BDLE state. */
    2475     RT_ZERO(pStream->State.BDLE);
    2476     pStream->State.uCurBDLE = 0;
    2477 
    2478     rc2 = hdaRegWriteU16(pThis, iReg, u32Value);
    2479     AssertRC(rc2);
    2480 
    2481     LogFlowFunc(("[SD%RU8]: LVI=%RU32\n", pStream->u8SD, u32Value));
    2482     hdaRegWriteSDUnlock(pStream);
     2410    if (RT_SUCCESS(rc2))
     2411    {
     2412        /** @todo Validate LVI. */
     2413        pStream->u16LVI = u32Value;
     2414        LogFunc(("[SD%RU8]: Updating LVI to %RU32\n", uSD, pStream->u16LVI));
     2415
     2416        /* Reset BDLE state. */
     2417        RT_ZERO(pStream->State.BDLE);
     2418        pStream->State.uCurBDLE = 0;
     2419
     2420        rc2 = hdaRegWriteU16(pThis, iReg, u32Value);
     2421        AssertRC(rc2);
     2422
     2423        hdaRegWriteSDUnlock(pStream);
     2424    }
     2425    else
     2426        LogRel(("HDA: Warning: Guest tried to write LVI to running stream #%RU8, ignoring\n", uSD));
    24832427
    24842428    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     
    24902434}
    24912435
    2492 #if 0 /** @todo hdaRegWriteSDFIFOW & hdaRegWriteSDFIFOS are unused */
    24932436static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    24942437{
    2495     uint8_t  uSD      = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
    2496     /** @todo Only allow updating FIFOS if RUN bit is 0? */
    2497     uint32_t u32FIFOW = 0;
     2438#ifdef IN_RING3
     2439    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
    24982440
    24992441    if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_IN) /* FIFOW for input streams only. */
    25002442    {
    2501         LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to stream #%RU8, ignoring\n", uSD));
     2443        LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", uSD));
    25022444        return VINF_SUCCESS;
    25032445    }
    25042446
    2505     switch (u32Value)
    2506     {
    2507         case HDA_SDFIFOW_8B:
    2508         case HDA_SDFIFOW_16B:
    2509         case HDA_SDFIFOW_32B:
    2510             u32FIFOW = u32Value;
    2511             break;
    2512         default:
    2513             LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
    2514                     u32Value, uSD));
    2515             u32FIFOW = HDA_SDFIFOW_32B;
    2516             break;
    2517     }
    2518 
    2519     if (u32FIFOW)
    2520     {
    2521         LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, hdaSDFIFOSToBytes(u32FIFOW)));
    2522         /** @todo Update internal stream state with new FIFOS. */
    2523 
    2524         return hdaRegWriteU16(pThis, iReg, u32FIFOW);
    2525     }
    2526 
    2527     return VINF_SUCCESS; /* Never reached. */
     2447    PHDASTREAM pStream = hdaStreamFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg));
     2448    if (!pStream)
     2449    {
     2450        AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOW on non-attached stream (0x%x)\n", uSD, u32Value));
     2451        return hdaRegWriteU16(pThis, iReg, u32Value);
     2452    }
     2453
     2454    int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value);
     2455    if (RT_SUCCESS(rc2))
     2456    {
     2457        uint32_t u32FIFOW = 0;
     2458
     2459        switch (u32Value)
     2460        {
     2461            case HDA_SDFIFOW_8B:
     2462            case HDA_SDFIFOW_16B:
     2463            case HDA_SDFIFOW_32B:
     2464                u32FIFOW = u32Value;
     2465                break;
     2466            default:
     2467                LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
     2468                        u32Value, uSD));
     2469                AssertFailed();
     2470                u32FIFOW = HDA_SDFIFOW_32B;
     2471                break;
     2472        }
     2473
     2474        if (u32FIFOW)
     2475        {
     2476            pStream->u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW);
     2477            LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, pStream->u16FIFOW));
     2478
     2479            rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOW);
     2480            AssertRC(rc2);
     2481        }
     2482
     2483        hdaRegWriteSDUnlock(pStream);
     2484    }
     2485    else
     2486        LogRel(("HDA: Warning: Guest tried to write FIFOW to running stream #%RU8, ignoring\n", uSD));
     2487
     2488    return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     2489#else  /* !IN_RING3 */
     2490    RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
     2491    return VINF_IOM_R3_MMIO_WRITE;
     2492#endif /* IN_RING3 */
    25282493}
    25292494
    25302495/**
    2531  * @note This method could be called for changing value on Output Streams
    2532  *       only (ICH6 datasheet 18.2.39).
     2496 * @note This method could be called for changing value on Output Streams only (ICH6 datasheet 18.2.39).
    25332497 */
    25342498static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
    25352499{
    2536     uint8_t  uSD      = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
    2537     /** @todo Only allow updating FIFOS if RUN bit is 0? */
    2538     uint32_t u32FIFOS = 0;
     2500#ifdef IN_RING3
     2501    uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
    25392502
    25402503    if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_OUT) /* FIFOS for output streams only. */
    25412504    {
    2542         LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to stream #%RU8, ignoring\n", uSD));
     2505        LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to input stream #%RU8, ignoring\n", uSD));
    25432506        return VINF_SUCCESS;
    25442507    }
    25452508
    2546     switch(u32Value)
    2547     {
    2548         case HDA_SDOFIFO_16B:
    2549         case HDA_SDOFIFO_32B:
    2550         case HDA_SDOFIFO_64B:
    2551         case HDA_SDOFIFO_128B:
    2552         case HDA_SDOFIFO_192B:
    2553             u32FIFOS = u32Value;
    2554             break;
    2555 
    2556         case HDA_SDOFIFO_256B: /** @todo r=andy Investigate this. */
    2557             LogFunc(("256-bit is unsupported, HDA is switched into 192-bit mode\n"));
    2558             /* Fall through is intentional. */
    2559         default:
    2560             LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
    2561                     u32Value, uSD));
    2562             u32FIFOS = HDA_SDOFIFO_192B;
    2563             break;
    2564     }
    2565 
    2566     if (u32FIFOS)
    2567     {
    2568         LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n",
    2569                  HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg), hdaSDFIFOSToBytes(u32FIFOS)));
    2570         /** @todo Update internal stream state with new FIFOS. */
    2571 
    2572         return hdaRegWriteU16(pThis, iReg, u32FIFOS);
    2573     }
    2574 
    2575     return VINF_SUCCESS;
    2576 }
    2577 
    2578 #endif /* unused */
     2509    PHDASTREAM pStream = hdaStreamFromSD(pThis, uSD);
     2510    if (!pStream)
     2511    {
     2512        AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOS on non-attached stream (0x%x)\n", uSD, u32Value));
     2513        return hdaRegWriteU16(pThis, iReg, u32Value);
     2514    }
     2515
     2516    int rc2 = hdaRegWriteSDLock(pThis, pStream, iReg, u32Value);
     2517    if (RT_SUCCESS(rc2))
     2518    {
     2519        uint32_t u32FIFOS = 0;
     2520
     2521        switch(u32Value)
     2522        {
     2523            case HDA_SDOFIFO_16B:
     2524            case HDA_SDOFIFO_32B:
     2525            case HDA_SDOFIFO_64B:
     2526            case HDA_SDOFIFO_128B:
     2527            case HDA_SDOFIFO_192B:
     2528            case HDA_SDOFIFO_256B:
     2529                u32FIFOS = u32Value;
     2530                break;
     2531
     2532            default:
     2533                LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
     2534                        u32Value, uSD));
     2535                AssertFailed();
     2536                u32FIFOS = HDA_SDOFIFO_192B;
     2537                break;
     2538        }
     2539
     2540        if (u32FIFOS)
     2541        {
     2542            pStream->u16FIFOS = hdaSDFIFOSToBytes(u32FIFOS);
     2543            LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", uSD, pStream->u16FIFOS));
     2544
     2545            rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOS);
     2546            AssertRC(rc2);
     2547        }
     2548
     2549        hdaRegWriteSDUnlock(pStream);
     2550    }
     2551    else
     2552        LogRel(("HDA: Warning: Guest tried to write FIFOS to running stream #%RU8, ignoring\n", uSD));
     2553
     2554     return VINF_SUCCESS; /* Always return success to the MMIO handler. */
     2555#else  /* !IN_RING3 */
     2556    RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
     2557    return VINF_IOM_R3_MMIO_WRITE;
     2558#endif /* IN_RING3 */
     2559}
    25792560
    25802561#ifdef IN_RING3
     
    32423223    AssertPtrReturn(pThis,   0);
    32433224    AssertPtrReturn(pStream, 0);
    3244 
    3245     if (!cbMax)
    3246         return 0;
     3225    AssertReturn   (cbMax,   0);
    32473226
    32483227    PHDABDLE pBDLE = &pStream->State.BDLE;
     
    32513230    Assert(u32LPIB <= pStream->u32CBL);
    32523231
    3253     uint32_t cbFree = pStream->u32CBL - u32LPIB;
    3254     if (cbFree)
    3255     {
    3256         /* Limit to the available free space of the current BDLE. */
    3257         cbFree = RT_MIN(cbFree, pBDLE->u32BufSize - pBDLE->State.u32BufOff);
    3258 
    3259         /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
    3260         cbFree = RT_MIN(cbFree, uint32_t(pStream->u16FIFOS));
    3261 
    3262         /* Make sure we only transfer as many bytes as requested. */
    3263         cbFree = RT_MIN(cbFree, cbMax);
    3264 
    3265         if (pBDLE->State.cbBelowFIFOW)
     3232    uint32_t cbData = pStream->u32CBL - u32LPIB;
     3233    AssertMsg(cbData, ("No CBL space left (%RU32/%RU32): %R[bdle]\n", pStream->u32CBL, u32LPIB, pBDLE));
     3234
     3235    /* Limit to the available free space of the current BDLE. */
     3236    cbData = RT_MIN(cbData, pBDLE->u32BufSize - pBDLE->State.u32BufOff);
     3237    AssertMsg(cbData, ("No BDLE space left (%RU32/%RU32): %R[bdle]\n", pBDLE->State.u32BufOff, pBDLE->u32BufSize, pBDLE));
     3238
     3239    /* Make sure we only transfer as many bytes as requested. */
     3240    cbData = RT_MIN(cbData, cbMax);
     3241
     3242    if (pBDLE->State.cbBelowFIFOW)
     3243    {
     3244        /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?
     3245         * No need to read data from DMA then. */
     3246        if (cbData > pBDLE->State.cbBelowFIFOW)
    32663247        {
    3267             /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?
    3268              * No need to read data from DMA then. */
    3269             if (cbFree > pBDLE->State.cbBelowFIFOW)
    3270             {
    3271                 /* Subtract the amount of bytes that still would fit in the stream's FIFO
    3272                  * and therefore do not need to be processed by DMA. */
    3273                 cbFree -= pBDLE->State.cbBelowFIFOW;
    3274             }
     3248            /* Subtract the amount of bytes that still would fit in the stream's FIFO
     3249             * and therefore do not need to be processed by DMA. */
     3250            cbData -= pBDLE->State.cbBelowFIFOW;
    32753251        }
    32763252    }
    32773253
    3278     LogFlowFunc(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbFree=%RU32, %R[bdle]\n", pStream->u8SD,
    3279                  pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS, cbFree, pBDLE));
    3280     return cbFree;
     3254    AssertMsg((cbData % 2 == 0), ("Transfer size invalid: %RU32\n", cbData));
     3255
     3256    Log3Func(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbData=%RU32, %R[bdle]\n", pStream->u8SD,
     3257              pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS,
     3258              cbData, pBDLE));
     3259
     3260    return cbData;
    32813261}
    32823262
     
    32873267    if (!cbData || !cbProcessed)
    32883268        return;
     3269
     3270    Assert(pBDLE->u32BufSize >= cbProcessed);
    32893271
    32903272    /* Fewer than cbBelowFIFOW bytes were copied.
     
    33093291    /* We always increment the position of DMA buffer counter because we're always reading
    33103292     * into an intermediate buffer. */
    3311     pBDLE->State.u32BufOff += cbData;
    3312     Assert(pBDLE->State.u32BufOff <= pBDLE->u32BufSize);
     3293    Assert(pBDLE->u32BufSize >= (pBDLE->State.u32BufOff + cbProcessed));
     3294    pBDLE->State.u32BufOff += cbProcessed;
    33133295
    33143296    LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE));
     
    34543436    AssertPtrReturnVoid(pStream);
    34553437
    3456     LogFlowFunc(("[SD%RU8]: cbInc=%RU32\n", pStream->u8SD, cbInc));
    3457 
    3458     //Assert(cbInc <= pStream->u16FIFOS);
    3459 
    34603438    if (!cbInc) /* Nothing to do? Bail out early. */
    34613439        return;
    3462 
    3463     PHDABDLE pBDLE = &pStream->State.BDLE;
    34643440
    34653441    /*
     
    34683444     * (ICH6 datasheet 18.2.38).
    34693445     */
     3446    PHDABDLE pBDLE = &pStream->State.BDLE;
    34703447    if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */
    34713448    {
    3472         uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    3473 
    3474         AssertMsg(((u32LPIB + cbInc) <= pStream->u32CBL),
    3475                   ("[SD%RU8] Increment (%RU32) exceeds CBL (%RU32): LPIB (%RU32)\n",
    3476                    pStream->u8SD, cbInc, pStream->u32CBL, u32LPIB));
    3477 
    3478         u32LPIB = RT_MIN(u32LPIB + cbInc, pStream->u32CBL);
    3479 
    3480         LogFlowFunc(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
    3481                      pStream->u8SD,
    3482                      HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc,
    3483                      pStream->u32CBL));
     3449        uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc;
     3450
     3451        Log3Func(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
     3452                  pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), u32LPIB, pStream->u32CBL));
    34843453
    34853454        hdaStreamUpdateLPIB(pThis, pStream, u32LPIB);
     
    34873456}
    34883457
    3489 static bool hdaStreamTransferIsComplete(PHDASTATE pThis, PHDASTREAM pStream, bool *pfInterrupt)
    3490 {
    3491     AssertPtrReturn(pThis,   true);
    3492     AssertPtrReturn(pStream, true);
     3458static bool hdaBDLEIsComplete(PHDABDLE pBDLE, bool *pfInterrupt)
     3459{
     3460    AssertPtrReturn(pBDLE, true);
    34933461
    34943462    bool fInterrupt  = false;
    34953463    bool fIsComplete = false;
    3496 
    3497     PHDABDLE       pBDLE   = &pStream->State.BDLE;
    3498 #ifdef LOG_ENABLED
    3499     const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
    3500 #endif
    35013464
    35023465    /* Check if the current BDLE entry is complete (full). */
     
    35113474           )
    35123475        {
    3513             LogFlowFunc(("[SD%RU8]: %R[bdle] => COMPLETE\n",  pStream->u8SD, pBDLE));
    3514 
    3515             /*
    3516              * If the ICE (IOCE, "Interrupt On Completion Enable") bit of the SDCTL register is set
    3517              * we need to generate an interrupt.
    3518              */
    3519             if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    3520                 fInterrupt = true;
     3476            fInterrupt = true;
    35213477        }
    35223478
     
    35273483        *pfInterrupt = fInterrupt;
    35283484
    3529     LogFlowFunc(("[SD%RU8]: u32LPIB=%RU32, CBL=%RU32, fIsComplete=%RTbool, fInterrupt=%RTbool, %R[bdle]\n",
    3530                  pStream->u8SD, u32LPIB, pStream->u32CBL, fIsComplete, fInterrupt, pBDLE));
     3485    LogFlowFunc(("%R[bdle] fIsComplete=%RTbool, fInterrupt=%RTbool\n", pBDLE, fIsComplete, fInterrupt));
    35313486
    35323487    return fIsComplete;
    35333488}
    35343489
     3490#if 0
    35353491/**
    35363492 * hdaReadAudio - copies samples from audio backend to DMA.
     
    35843540#ifdef HDA_DEBUG_DUMP_PCM_DATA
    35853541        RTFILE fh;
    3586         RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio-hda.pcm",
     3542        RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaReadAudio.pcm",
    35873543                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    35883544        RTFileWrite(fh, pBDLE->State.au8FIFO, cbRead, NULL);
     
    36563612#ifdef HDA_DEBUG_DUMP_PCM_DATA
    36573613        RTFILE fh;
    3658         RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio-hda.pcm",
     3614        RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm",
    36593615                   RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    36603616        RTFileWrite(fh, pvBuf, cbBuf, NULL);
     
    37143670            AssertRC(rc2);
    37153671#endif
     3672
    37163673            /*
    37173674             * Write data to according mixer sinks.
     
    37213678            AssertRC(rc2);
    37223679#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    3723             rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE,      AUDMIXOP_COPY, pvDataCenterLFE, cbDataCenterLFE,
     3680            rc2 = AudioMixerSinkWrite(pThis->SinkCenterLFE,      AUDMIXOP_COPY, pvDataCenterLFE, (uint32_t)cbDataCenterLFE,
    37243681                                      NULL /* pcbWritten */);
    37253682            AssertRC(rc2);
    3726             rc2 = AudioMixerSinkWrite(pThis->SinkRear,           AUDMIXOP_COPY, pvDataRear,      cbDataRear,
     3683            rc2 = AudioMixerSinkWrite(pThis->SinkRear,           AUDMIXOP_COPY, pvDataRear,      (uint32_t)cbDataRear,
    37273684                                      NULL /* pcbWritten */);
    37283685            AssertRC(rc2);
     
    37453702        else
    37463703        {
     3704            AssertFailed();
     3705
    37473706            Assert(pBDLE->State.u32BufOff + cbWritten <= pBDLE->u32BufSize);
    37483707            pBDLE->State.u32BufOff    += cbWritten;
     
    37563715    }
    37573716
    3758     //Assert(cbWritten <= pStream->u16FIFOS);
     3717    Assert(cbWritten <= pStream->u16FIFOS);
    37593718
    37603719    if (RT_SUCCESS(rc))
     
    37693728    return rc;
    37703729}
     3730#endif
    37713731
    37723732/**
     
    41294089static void hdaTimerMaybeStart(PHDASTATE pThis)
    41304090{
    4131     if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
     4091    if (pThis->cStreamsActive == 0) /* Only start the timer if there at least is one active streams. */
    41324092        return;
    41334093
     
    41374097    LogFlowFuncEnter();
    41384098
    4139     LogFlowFunc(("Starting timer\n"));
     4099    LogRel2(("HDA: Starting transfers\n"));
    41404100
    41414101    /* Set timer flag. */
     
    41454105    pThis->uTimerTS = TMTimerGet(pThis->pTimer);
    41464106
    4147     /* Fire off timer. */
    4148     TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
     4107    /* Start transfers. */
     4108    hdaDoTransfers(pThis);
    41494109}
    41504110
     
    41574117        return;
    41584118
    4159     LogFlowFunc(("Stopping timer\n"));
     4119    LogRel2(("HDA: Stopping transfers\n"));
    41604120
    41614121    /* Set timer flag. */
     
    41634123}
    41644124
    4165 static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    4166 {
    4167     RT_NOREF(pDevIns);
    4168     PHDASTATE pThis = (PHDASTATE)pvUser;
    4169     Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE));
    4170     AssertPtr(pThis);
     4125static void hdaDoTransfers(PHDASTATE pThis)
     4126{
     4127    AssertPtrReturnVoid(pThis);
    41714128
    41724129    STAM_PROFILE_START(&pThis->StatTimer, a);
    41734130
    4174     uint64_t cTicksNow = TMTimerGet(pTimer);
    4175 
    4176     LogFlowFuncEnter();
     4131    uint64_t cTicksNow = TMTimerGet(pThis->pTimer);
     4132
     4133    Log4Func(("Timer enter\n"));
    41774134
    41784135    /* Update current time timestamp. */
     
    41834140    bool fKickTimer = false;
    41844141
    4185     PHDASTREAM pStreamLineIn  = hdaGetStreamFromSink(pThis, &pThis->SinkLineIn);
     4142    PHDASTREAM pStreamLineIn  = hdaSinkGetStream(pThis, &pThis->SinkLineIn);
    41864143#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    4187     PHDASTREAM pStreamMicIn   = hdaGetStreamFromSink(pThis, &pThis->SinkMicIn);
    4188 #endif
    4189     PHDASTREAM pStreamFront   = hdaGetStreamFromSink(pThis, &pThis->SinkFront);
     4144    PHDASTREAM pStreamMicIn   = hdaSinkGetStream(pThis, &pThis->SinkMicIn);
     4145#endif
     4146    PHDASTREAM pStreamFront   = hdaSinkGetStream(pThis, &pThis->SinkFront);
    41904147#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    41914148    /** @todo See note below. */
    41924149#endif
    41934150
    4194     uint32_t cbToProcess;
    4195     int rc = AudioMixerSinkUpdate(pThis->SinkLineIn.pMixSink);
    4196     if (RT_SUCCESS(rc))
    4197     {
    4198         cbToProcess = AudioMixerSinkGetReadable(pThis->SinkLineIn.pMixSink);
    4199         if (cbToProcess)
    4200         {
    4201             rc = hdaTransfer(pThis, pStreamLineIn, cbToProcess, NULL /* pcbProcessed */);
    4202             fKickTimer |= RT_SUCCESS(rc);
    4203         }
    4204     }
    4205 
     4151    hdaStreamUpdate(pThis, pStreamLineIn);
    42064152#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    4207     rc = AudioMixerSinkUpdate(pThis->SinkMicIn.pMixSink);
    4208     if (RT_SUCCESS(rc))
    4209     {
    4210         cbToProcess = AudioMixerSinkGetReadable(pThis->SinkMicIn.pMixSink);
    4211         if (cbToProcess)
    4212         {
    4213             rc = hdaTransfer(pThis, pStreamMicIn, cbToProcess, NULL /* pcbProcessed */);
    4214             fKickTimer |= RT_SUCCESS(rc);
    4215         }
    4216     }
    4217 #endif
     4153    hdaStreamUpdate(pThis, pStreamMicIn);
     4154#endif
     4155    hdaStreamUpdate(pThis, pStreamFront);
     4156
    42184157
    42194158#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    4220     rc = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink);
    4221     if (RT_SUCCESS(rc))
    4222     {
    4223 
    4224     }
    4225 
    4226     rc = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink);
    4227     if (RT_SUCCESS(rc))
    4228     {
    4229 
    4230     }
    4231     /** @todo Check for stream interleaving and only call hdaTransfer() if required! */
     4159    rc2 = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink);
     4160    AssertRC(rc2);
     4161
     4162    rc2 = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink);
     4163    AssertRC(rc2);
     4164    /** @todo Check for stream interleaving and only call hdaStreamDoDMA() if required! */
    42324165
    42334166    /*
     
    42374170     */
    42384171#endif
    4239     rc = AudioMixerSinkUpdate(pThis->SinkFront.pMixSink);
    4240     if (RT_SUCCESS(rc))
    4241     {
    4242         cbToProcess = AudioMixerSinkGetWritable(pThis->SinkFront.pMixSink);
    4243         if (cbToProcess)
    4244         {
    4245             rc = hdaTransfer(pThis, pStreamFront, cbToProcess, NULL /* pcbProcessed */);
    4246             fKickTimer |= RT_SUCCESS(rc);
    4247         }
    4248     }
     4172
     4173    /* Do we need to kick the timer again? */
     4174    if (   AudioMixerSinkIsActive(pThis->SinkFront.pMixSink)
     4175#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     4176        || AudioMixerSinkIsActive(pThis->SinkCenterLFE.pMixSink)
     4177        || AudioMixerSinkIsActive(pThis->SinkRear.pMixSink)
     4178#endif
     4179        || AudioMixerSinkIsActive(pThis->SinkLineIn.pMixSink)
     4180#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
     4181        || AudioMixerSinkIsActive(pThis->SinkMicIn.pMixSink)
     4182#endif
     4183        )
     4184    {
     4185        fKickTimer = true;
     4186    }
     4187
     4188    pThis->uTimerMS = RTTimeMilliTS();
    42494189
    42504190    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     
    42574197    }
    42584198
    4259     LogFlowFuncLeave();
    4260 
    42614199    STAM_PROFILE_STOP(&pThis->StatTimer, a);
     4200}
     4201
     4202static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     4203{
     4204    RT_NOREF(pDevIns, pTimer);
     4205
     4206    PHDASTATE pThis = (PHDASTATE)pvUser;
     4207    Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE));
     4208    AssertPtr(pThis);
     4209
     4210    hdaDoTransfers(pThis);
    42624211}
    42634212
     
    42784227    AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_INPUT), VERR_INVALID_PARAMETER);
    42794228
    4280     return hdaTransfer(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
     4229    return hdaStreamDoDMA(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
    42814230}
    42824231
     
    42974246    PHDASTATE pThis = pCtx->pThis;
    42984247
    4299     int rc = hdaTransfer(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
     4248    int rc = hdaStreamDoDMA(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
    43004249    if (   RT_SUCCESS(rc)
    43014250        && pData->cbOutWritten)
     
    43124261#endif /* VBOX_WITH_AUDIO_HDA_CALLBACKS */
    43134262
    4314 static int hdaTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
    4315 {
    4316     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    4317     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     4263#ifdef DEBUG_andy
     4264# define HDA_DEBUG_DMA
     4265#endif
     4266
     4267/**
     4268 * Does a single DMA transfer for a specific HDA stream (SDI/SDO).
     4269 * This either can be a read or write operation, depending on the HDA stream.
     4270 *
     4271 * @returns IPRT status code.
     4272 * @param   pThis               HDA state.
     4273 * @param   pStream             HDA stream to do the DMA transfer for.
     4274 * @param   pvBuf               Pointer to buffer data to write data to / read data from.
     4275 * @param   cbBuf               Size of buffer (in bytes).
     4276 * @param   cbToProcess         Size (in bytes) to transfer (read/write).
     4277 * @param   pcbProcessed        Size (in bytes) transferred (read/written). Optional.
     4278 */
     4279static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf,
     4280                          uint32_t cbToProcess, uint32_t *pcbProcessed)
     4281{
     4282    AssertPtrReturn(pThis,             VERR_INVALID_POINTER);
     4283    AssertPtrReturn(pStream,           VERR_INVALID_POINTER);
     4284    AssertPtrReturn(pvBuf,             VERR_INVALID_POINTER);
     4285    AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER);
    43184286    /* pcbProcessed is optional. */
    43194287
    43204288    if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
    43214289    {
    4322         LogFlowFunc(("HDA in reset mode, skipping\n"));
    4323 
    43244290        if (pcbProcessed)
    43254291            *pcbProcessed = 0;
     
    43284294
    43294295    bool fProceed = true;
    4330     int rc = RTCritSectEnter(&pStream->State.CritSect);
    4331     if (RT_FAILURE(rc))
    4332         return rc;
    4333 
    4334     Log3Func(("[SD%RU8] fActive=%RTbool, cbToProcess=%RU32\n", pStream->u8SD, pStream->State.fActive, cbToProcess));
    4335 
    4336     /* Stop request received? */
    4337     if (   !pStream->State.fActive
    4338         || pStream->State.fDoStop)
    4339     {
    4340         pStream->State.fActive = false;
    4341 
    4342         rc = RTSemEventSignal(pStream->State.hStateChangedEvent);
    4343         AssertRC(rc);
    4344 
     4296
     4297    Log3Func(("[SD%RU8] %R[sdsts] cbToProcess=%RU32\n",
     4298              pStream->u8SD, HDA_STREAM_REG(pThis, STS, pStream->u8SD), cbToProcess));
     4299
     4300    /* Is the stream not in a running state currently? */
     4301    if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
    43454302        fProceed = false;
    4346     }
    4347     /* Is the stream not in a running state currently? */
    4348     else if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)))
     4303    /* Is the BCIS (Buffer Completion Interrupt Status) flag set? Then we have to wait and skip. */
     4304    else if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
    43494305        fProceed = false;
    4350     /* Nothing to process? */
    4351     else if (!cbToProcess)
    4352         fProceed = false;
    4353 
    4354     if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
    4355     {
    4356         Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    4357         fProceed = false;
    4358     }
    43594306
    43604307    if (!fProceed)
    43614308    {
    4362         Log3Func(("[SD%RU8]: Skipping\n", pStream->u8SD));
    4363 
    4364         rc = RTCritSectLeave(&pStream->State.CritSect);
    4365         AssertRC(rc);
    4366 
     4309#ifdef HDA_DEBUG_DMA
     4310        Log3Func(("DMA: Skip\n"));
     4311#endif
    43674312        if (pcbProcessed)
    43684313            *pcbProcessed = 0;
    43694314        return VINF_SUCCESS;
    43704315    }
     4316
     4317    int rc = VINF_SUCCESS;
     4318
     4319#ifdef HDA_DEBUG_DMA
     4320    Log3Func(("DMA: Start\n"));
     4321#endif
    43714322
    43724323    /* Sanity checks. */
     
    43794330    Assert(HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) <= pStream->u32CBL);
    43804331
    4381     bool fInterrupt = false;
    4382 
    4383 #ifdef DEBUG_andy
    4384 //# define DEBUG_SIMPLE
    4385 #endif
    4386 
    4387 #ifdef DEBUG_SIMPLE
    4388     uint8_t u8FIFO[_16K+1];
    4389     size_t u8FIFOff = 0;
    4390 #endif
    4391 
    4392     uint32_t cbLeft           = cbToProcess;
     4332    bool fSendInterrupt = false;
     4333
     4334    /* Only do one FIFO size at a time. */
     4335    uint32_t cbLeft           = RT_MIN(pStream->u16FIFOS, RT_MIN(cbToProcess, cbBuf));
    43934336    uint32_t cbTotal          = 0;
    43944337    uint32_t cbChunk          = 0;
    43954338    uint32_t cbChunkProcessed = 0;
    43964339
    4397     /* Set the FIFORDY bit on the stream while doing the transfer. */
    4398     HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    4399 
    4400     while (cbLeft)
    4401     {
    4402         /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
    4403         if (hdaStreamNeedsNextBDLE(pThis, pStream))
    4404         {
    4405             rc = hdaStreamGetNextBDLE(pThis, pStream);
    4406             if (RT_FAILURE(rc))
    4407                 break;
    4408         }
    4409 
     4340#ifdef HDA_DEBUG_DMA
     4341    LogFunc(("DMA: cbToProcess=%RU32, cbLeft=%RU32\n", cbToProcess, cbLeft));
     4342#endif
     4343
     4344    /* Get the maximum number of BDL entries. */
     4345    uint16_t cBDLE = pStream->u16LVI + 1;
     4346
     4347    while (   cbLeft
     4348           && cBDLE--)
     4349    {
    44104350        cbChunk          = hdaStreamGetTransferSize(pThis, pStream, cbLeft);
    44114351        cbChunkProcessed = 0;
    44124352
    4413         if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN)
    4414             rc = hdaReadAudio(pThis, pStream, cbChunk, &cbChunkProcessed);
    4415         else
     4353        PHDABDLE pBDLE = &pStream->State.BDLE;
     4354
     4355        if (cbChunk)
    44164356        {
    4417 #ifndef DEBUG_SIMPLE
    4418             rc = hdaWriteAudio(pThis, pStream, cbChunk, &cbChunkProcessed);
    4419 #else
    4420             void    *pvBuf = u8FIFO + u8FIFOff;
    4421             int32_t cbBuf  = cbChunk;
    4422 
    4423             PHDABDLE pBDLE = &pStream->State.BDLE;
    4424 
    4425             if (cbBuf)
    4426                 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
    4427                                        pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
    4428                                        pvBuf, cbBuf);
    4429 
    4430             cbChunkProcessed = cbChunk;
    4431 
    4432             hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);
    4433 
    4434             u8FIFOff += cbChunkProcessed;
    4435             Assert((u8FIFOff & 1) == 0);
    4436             Assert(u8FIFOff <= sizeof(u8FIFO));
     4357            if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
     4358            {
     4359                PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
     4360                                  pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
     4361                                  (uint8_t *)pvBuf + cbTotal, cbChunk);
     4362            }
     4363            else /* Input (SDI). */
     4364            {
     4365                PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns),
     4366                                   pBDLE->u64BufAdr + pBDLE->State.u32BufOff,
     4367                                   (uint8_t *)pvBuf + cbTotal, cbChunk);
     4368            }
     4369
     4370#ifdef HDA_DEBUG_DUMP_PCM_DATA
     4371            RTFILE fh;
     4372            RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaDMA.pcm",
     4373                       RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     4374            RTFileWrite(fh, (uint8_t *)pvBuf + cbTotal, cbChunk, NULL);
     4375            RTFileClose(fh);
    44374376#endif
    44384377        }
    44394378
    4440         if (RT_FAILURE(rc))
    4441             break;
    4442 
    4443         hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);
     4379        cbChunkProcessed = cbChunk;
     4380
     4381        hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);
     4382
     4383        LogFunc(("DMA: Entry %RU32 Pos %RU32/%RU32 Chunk %RU32\n",
     4384                 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->u32BufSize, cbChunk));
    44444385
    44454386        Assert(cbLeft >= cbChunkProcessed);
    44464387        cbLeft  -= cbChunkProcessed;
    44474388        cbTotal += cbChunkProcessed;
    4448 
    4449         if (rc == VINF_EOF)
     4389        Assert(cbTotal <= cbToProcess);
     4390
     4391        hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);
     4392
     4393#ifdef HDA_DEBUG_DMA
     4394        LogFunc(("DMA: LPIB %RU32 Pos %RU32 Left %RU32\n", HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbTotal, cbLeft));
     4395#endif
     4396        bool fNeedsInterrupt = false;
     4397        bool fBDLEIsComplete = hdaBDLEIsComplete(pBDLE, &fNeedsInterrupt);
     4398
     4399        if (fNeedsInterrupt)
     4400            fSendInterrupt = true;
     4401
     4402        if (fBDLEIsComplete)
     4403        {
     4404            /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
     4405            if (hdaStreamNeedsNextBDLE(pThis, pStream))
     4406            {
     4407                bool fWrapAround;
     4408                rc = hdaStreamGetNextBDLE(pThis, pStream, &fWrapAround);
     4409                if (   RT_SUCCESS(rc)
     4410                    && fWrapAround)
     4411                {
     4412                    hdaStreamUpdateLPIB(pThis, pStream, 0);
     4413                }
     4414            }
     4415        }
     4416
     4417        if (RT_FAILURE(rc))
    44504418            break;
    4451 
    4452         if (hdaStreamTransferIsComplete(pThis, pStream, &fInterrupt))
    4453             break;
    4454     }
    4455 
    4456     /* Remove the FIFORDY bit again. */
    4457     HDA_STREAM_REG(pThis, STS, pStream->u8SD) &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    4458 
    4459     LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8SD, cbTotal, cbToProcess, rc));
    4460 
    4461 #ifdef DEBUG_SIMPLE
    4462 # ifdef HDA_DEBUG_DUMP_PCM_DATA
    4463         RTFILE fh;
    4464         RTFileOpen(&fh, HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaWriteAudio.pcm",
    4465                    RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    4466         RTFileWrite(fh, u8FIFO, u8FIFOff, NULL);
    4467         RTFileClose(fh);
    4468 # endif
    4469 
    4470      AudioMixerSinkWrite(pThis->SinkFront.pMixSink, AUDMIXOP_COPY, u8FIFO, u8FIFOff,
    4471                          NULL /* pcbWritten */);
    4472 #endif /* DEBUG_SIMPLE */
    4473 
    4474     if (fInterrupt)
    4475     {
     4419    }
     4420
     4421    Log3Func(("[SD%RU8]: cbLeft=%RU32, rc=%Rrc\n", pStream->u8SD, cbLeft, rc));
     4422
     4423    if (fSendInterrupt)
     4424    {
     4425#ifdef HDA_DEBUG_DMA
     4426        Log3Func(("DMA: Interrupt\n"));
     4427#endif
    44764428        /**
    44774429         * Set the BCIS (Buffer Completion Interrupt Status) flag as the
     
    44854437         */
    44864438        HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
    4487         Log3Func(("[SD%RU8]: BCIS: Set\n", pStream->u8SD));
     4439        Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
    44884440
    44894441        hdaProcessInterrupt(pThis);
     
    44964448    }
    44974449
    4498     int rc2 = RTCritSectLeave(&pStream->State.CritSect);
    4499     if (RT_SUCCESS(rc))
    4500         rc = rc2;
     4450#ifdef HDA_DEBUG_DMA
     4451    Log3Func(("DMA: End\n"));
     4452#endif
     4453
     4454    return rc;
     4455}
     4456
     4457/**
     4458 * Updates a HDA stream according to its usage.
     4459 *
     4460 * For an SDO (output) stream this means reading DMA data from the device to
     4461 * the connected audio sink(s).
     4462 *
     4463 * For an SDI (input) stream this is reading audio data from the connected
     4464 * audio sink(s) and writing it as DMA data to the device.
     4465 *
     4466 * @returns IPRT status code.
     4467 * @param   pThis               HDA state.
     4468 * @param   pStream             HDA stream to update.
     4469 */
     4470static int hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream)
     4471{
     4472    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     4473    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     4474
     4475    PHDAMIXERSINK pSink  = pStream->pMixSink;
     4476    if (!pSink)
     4477        return VINF_SUCCESS;
     4478
     4479    PAUDMIXSINK pMixSink = pSink->pMixSink;
     4480    AssertPtr(pSink);
     4481
     4482    if (AudioMixerSinkIsActive(pMixSink) == false)
     4483        return VINF_SUCCESS;
     4484
     4485    PRTCIRCBUF pCircBuf  = pStream->State.pCircBuf;
     4486    AssertPtr(pCircBuf);
     4487
     4488    void *pvSrc, *pvDst;
     4489    size_t cbSrc, cbDst;
     4490
     4491    int rc = VINF_SUCCESS;
     4492
     4493    uint32_t cbToProcess = _16K; /** @todo Tweak this. Later. */
     4494
     4495    while (cbToProcess >= pStream->u16FIFOS)
     4496    {
     4497        uint32_t cbProcessed;
     4498        int rc2;
     4499
     4500        if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
     4501        {
     4502            if (RTCircBufUsed(pCircBuf) == 0)
     4503            {
     4504                Assert(pStream->u16FIFOS);
     4505                RTCircBufAcquireWriteBlock(pCircBuf, pStream->u16FIFOS, &pvDst, &cbDst);
     4506
     4507                /* Do one DMA transfer with FIFOS size at a time. */
     4508                rc2 = hdaStreamDoDMA(pThis, pStream, pvDst, cbDst, cbDst /* cbToProcess */, &cbProcessed);
     4509                AssertRC(rc2);
     4510
     4511                RTCircBufReleaseWriteBlock(pCircBuf, cbProcessed);
     4512
     4513                if (!cbProcessed)
     4514                    break;
     4515            }
     4516
     4517            if (RTCircBufUsed(pCircBuf))
     4518            {
     4519                RTCircBufAcquireReadBlock(pCircBuf, RTCircBufUsed(pCircBuf), &pvSrc, &cbSrc);
     4520                Assert(cbDst);
     4521
     4522                rc2 = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, cbSrc, &cbProcessed);
     4523                AssertRC(rc2);
     4524
     4525                RTCircBufReleaseReadBlock(pCircBuf, cbSrc);
     4526            }
     4527        }
     4528        else /* Input (SDI). */
     4529        {
     4530            Assert(pStream->u16FIFOS);
     4531            if (RTCircBufUsed(pCircBuf))
     4532            {
     4533                RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc);
     4534
     4535                /* Do one DMA transfer with FIFOS size at a time. */
     4536                rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, cbSrc, cbSrc /* cbToProcess */, &cbProcessed);
     4537                AssertRC(rc2);
     4538
     4539                RTCircBufReleaseReadBlock(pCircBuf, cbSrc);
     4540
     4541                if (!cbProcessed)
     4542                    break;
     4543            }
     4544
     4545            if (RTCircBufUsed(pCircBuf) < pStream->u16FIFOS)
     4546            {
     4547                RTCircBufAcquireWriteBlock(pCircBuf, pStream->u16FIFOS, &pvDst, &cbDst);
     4548                Assert(cbDst);
     4549
     4550                rc2 = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, cbDst, &cbProcessed);
     4551                AssertRC(rc2);
     4552
     4553                RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
     4554            }
     4555        }
     4556
     4557        rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
     4558        AssertRC(rc2);
     4559
     4560        cbToProcess -= RT_MIN(cbToProcess, cbProcessed);
     4561    }
    45014562
    45024563    return rc;
     
    49865047    rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */   \
    49875048    AssertRCReturn(rc, rc);                                             \
    4988     rc = SSMR3GetMem(pSSM, &x.State.au8FIFO, sizeof(x.State.au8FIFO));  \
     5049    rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256);   /* FIFO */           \
    49895050    AssertRCReturn(rc, rc);                                             \
    49905051    rc = SSMR3Skip(pSSM, sizeof(uint32_t));        /* End marker */     \
     
    50975158                            rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */
    50985159                            AssertRC(rc);
    5099                             rc = SSMR3GetMem(pSSM,
    5100                                              &pStrm->State.BDLE.State.au8FIFO,
    5101                                              sizeof(pStrm->State.BDLE.State.au8FIFO));     /* au8FIFO */
     5160                            rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256);                   /* FIFO, deprecated */
    51025161                            AssertRC(rc);
    51035162                            rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.u32BufOff);    /* u32BufOff */
     
    51095168                        {
    51105169                            rc = SSMR3Skip(pSSM,   sizeof(uint32_t)      /* cbBelowFIFOW */
    5111                                                  + sizeof(uint8_t) * 256 /* au8FIFO */
     5170                                                 + sizeof(uint8_t) * 256 /* FIFO, deprecated */
    51125171                                                 + sizeof(uint32_t)      /* u32BufOff */
    51135172                                                 + sizeof(uint32_t));    /* End marker */
     
    55085567     */
    55095568    if (pThis->SinkFront.pMixSink)
    5510         AudioMixerSinkCtl(pThis->SinkFront.pMixSink,     AUDMIXSINKCMD_DISABLE);
     5569        AudioMixerSinkReset(pThis->SinkFront.pMixSink);
    55115570# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
    55125571    if (pThis->SinkMicIn.pMixSink)
    5513         AudioMixerSinkCtl(pThis->SinkMicIn.pMixSink,     AUDMIXSINKCMD_DISABLE);
     5572        AudioMixerSinkReset(pThis->SinkMicIn.pMixSink);
    55145573# endif
    55155574    if (pThis->SinkLineIn.pMixSink)
    5516         AudioMixerSinkCtl(pThis->SinkLineIn.pMixSink,    AUDMIXSINKCMD_DISABLE);
     5575        AudioMixerSinkReset(pThis->SinkLineIn.pMixSink);
    55175576# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    55185577    if (pThis->SinkCenterLFE.pMixSink)
    5519         AudioMixerSinkCtl(pThis->SinkCenterLFE.pMixSink, AUDMIXSINKCMD_DISABLE);
     5578        AudioMixerSinkReset(pThis->SinkCenterLFE.pMixSink);
    55205579    if (pThis->SinkRear.pMixSink)
    5521         AudioMixerSinkCtl(pThis->SinkRear.pMixSink,      AUDMIXSINKCMD_DISABLE);
     5580        AudioMixerSinkReset(pThis->SinkRear.pMixSink);
    55225581# endif
    55235582
     
    58375896#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
    58385897    uint16_t uTimerHz;
    5839     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
     5898    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */);
    58405899    if (RT_FAILURE(rc))
    58415900        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    62636322    if (RT_SUCCESS(rc))
    62646323    {
    6265         /* Start the emulation timer. */
     6324        /* Create the emulation timer. */
    62666325        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis,
    62676326                                    TMTIMER_FLAGS_NO_CRIT_SECT, "DevHDA", &pThis->pTimer);
     
    62736332            pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
    62746333            LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
    6275 
    6276             hdaTimerMaybeStart(pThis);
    62776334        }
    62786335    }
     
    63226379    }
    63236380# endif
     6381
     6382#ifdef HDA_DEBUG_DUMP_PCM_DATA
     6383    RTFileDelete(HDA_DEBUG_DUMP_PCM_DATA_PATH "hdaDMA.pcm");
     6384#endif
    63246385
    63256386    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r64419 r64572  
    19081908    GEN_CHECK_OFF(HDABDLESTATE, u32BDLIndex);
    19091909    GEN_CHECK_OFF(HDABDLESTATE, cbBelowFIFOW);
    1910     GEN_CHECK_OFF(HDABDLESTATE, au8FIFO);
    19111910    GEN_CHECK_OFF(HDABDLESTATE, u32BufOff);
    19121911
     
    19191918    GEN_CHECK_SIZE(HDASTREAMSTATE);
    19201919    GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE);
     1920    GEN_CHECK_OFF(HDASTREAMSTATE, fInReset);
     1921    GEN_CHECK_OFF(HDASTREAMSTATE, CritSect);
     1922    GEN_CHECK_OFF(HDASTREAMSTATE, Mapping);
    19211923    GEN_CHECK_OFF(HDASTREAMSTATE, BDLE);
     1924    GEN_CHECK_OFF(HDASTREAMSTATE, pCircBuf);
    19221925
    19231926    GEN_CHECK_SIZE(HDASTREAM);
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