Changeset 59160 in vbox for trunk/src/VBox
- Timestamp:
- Dec 16, 2015 6:26:04 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r59102 r59160 36 36 #ifdef IN_RING3 37 37 # include <iprt/mem.h> 38 # include <iprt/semaphore.h> 38 39 # include <iprt/string.h> 39 40 # include <iprt/uuid.h> … … 577 578 uint16_t uCurBDLE; 578 579 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; 579 590 /** Array of BDLEs. */ 580 591 R3PTRTYPE(PHDABDLE) paBDLE; … … 834 845 static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value); 835 846 847 #ifdef IN_RING3 848 static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm); 836 849 static void hdaStreamDestroy(PHDASTREAM pStrmSt); 837 838 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbMax, uint32_t *pcbProcessed); 850 static int hdaStreamStart(PHDASTREAM pStrmSt); 851 static int hdaStreamStop(PHDASTREAM pStrmSt); 852 static int hdaStreamWaitForStateChange(PHDASTREAM pStrmSt, RTMSINTERVAL msTimeout); 853 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed); 854 #endif 839 855 840 856 #ifdef IN_RING3 … … 1065 1081 default: 1066 1082 { 1067 cb = 0; 1068 AssertMsgFailed(("Wrong FIFO value\n")); 1083 cb = 0; /* Can happen on stream reset. */ 1069 1084 break; 1070 1085 } … … 1153 1168 1154 1169 #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)); 1157 1172 #endif 1158 1173 return pBDLE; … … 1449 1464 } 1450 1465 1466 static 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 1451 1481 static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm) 1452 1482 { 1453 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1483 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1454 1484 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER); 1455 1485 … … 1461 1491 pStrmSt->u16FIFOS = hdaSDFIFOSToBytes(HDA_STREAM_REG(pThis, FIFOS, u8Strm)); 1462 1492 1463 hdaStreamDestroy(pStrmSt);1464 1465 1493 int rc = VINF_SUCCESS; 1466 1494 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 1467 1504 if (pStrmSt->u16LVI) /* Any BDLEs to fetch? */ 1468 1505 { 1506 AssertMsg(pStrmSt->u64BaseDMA, ("No base DMA address set for stream %RU8\n", u8Strm)); 1507 1469 1508 uint32_t cbBDLE = 0; 1470 1509 … … 1488 1527 { 1489 1528 if (pStrmSt->u32CBL != cbBDLE) 1529 { 1530 AssertMsgFailed(("CBL (%RU32) does not match BDL entries (%RU32)\n", pStrmSt->u32CBL, cbBDLE)); 1490 1531 LogRel(("HDA: Warning: CBL (%RU32) does not match BDL entries (%RU32); expect sound hickups\n", 1491 1532 pStrmSt->u32CBL, cbBDLE)); 1533 } 1492 1534 1493 1535 HDA_STREAM_REG(pThis, STS, pStrmSt->u8Strm) |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS); … … 1508 1550 AssertPtrReturnVoid(pStrmSt); 1509 1551 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 */ 1510 1566 if (pStrmSt->State.paBDLE) 1511 1567 { … … 1516 1572 1517 1573 pStrmSt->State.cBDLE = 0; 1518 } 1519 #endif 1574 1575 LogFlowFuncLeave(); 1576 } 1520 1577 1521 1578 static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStrmSt, uint8_t u8Strm) … … 1526 1583 1527 1584 /* 1528 * Initialize stream state.1585 * Stop the stream and wait until our internal processing is done. 1529 1586 */ 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 } 1531 1593 1532 1594 /* 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. 1534 1608 */ 1535 1609 HDA_STREAM_REG(pThis, STS, u8Strm) = 0; … … 1549 1623 HDA_STREAM_REG(pThis, BDPL, u8Strm) = 0; 1550 1624 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 1637 static 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 1648 static 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 1682 static 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 */ 1553 1690 1554 1691 /* Register access handlers. */ … … 1626 1763 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST)) 1627 1764 { 1628 /* Exit reset state. */1765 /* Set the CRST bit to indicate that we're leaving reset mode. */ 1629 1766 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 } 1631 1773 } 1632 1774 else … … 1637 1779 || HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA)) 1638 1780 { 1639 LogFunc((" HDA enters inreset with DMA(RIRB:%s, CORB:%s)\n",1781 LogFunc(("Entering reset with DMA(RIRB:%s, CORB:%s)\n", 1640 1782 HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) ? "on" : "off", 1641 1783 HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA) ? "on" : "off")); 1642 1784 } 1643 hdaReset(pThis->CTX_SUFF(pDevIns)); 1785 1786 /* Clear the CRST bit to indicate that we're in reset mode. */ 1644 1787 HDA_REG(pThis, GCTL) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST); 1645 1788 pThis->fInReset = true; 1789 1790 /* As the CRST bit now is set, we now can proceed resetting stuff. */ 1791 hdaReset(pThis->CTX_SUFF(pDevIns)); 1646 1792 #else 1647 1793 return VINF_IOM_R3_MMIO_WRITE; … … 1826 1972 } 1827 1973 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)); 1829 1976 1830 1977 if (fInReset) … … 1855 2002 { 1856 2003 Assert(!fReset && !fInReset); 2004 LogFunc(("[SD%RU8]: fRun=%RTbool\n", u8Strm, fRun)); 1857 2005 1858 2006 PHDADRIVER pDrv; … … 2889 3037 PHDADRIVER pDrv; 2890 3038 2891 uint32_t cbIn, cbOut , cSamplesLive;3039 uint32_t cbIn, cbOut; 2892 3040 2893 3041 uint64_t uTicksNow = PDMDevHlpTMTimeVirtGet(pDevIns); … … 2939 3087 cbOutMin = 0; 2940 3088 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. */ 2956 3094 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTimerTicks); 2957 3095 … … 3009 3147 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ 3010 3148 3011 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cb Max, uint32_t *pcbProcessed)3149 static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbToProcess, uint32_t *pcbProcessed) 3012 3150 { 3013 3151 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3014 3152 /* pcbProcessed is optional. */ 3015 3153 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")); 3050 3159 3051 3160 if (pcbProcessed) … … 3053 3162 return VINF_SUCCESS; 3054 3163 } 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 { 3063 3219 if (pcbProcessed) 3064 3220 *pcbProcessed = 0; … … 3066 3222 } 3067 3223 3224 /* Sanity checks. */ 3068 3225 Assert(pStrmSt->u8Strm <= 7); /** @todo Use a define for MAX_STREAMS! */ 3069 3226 Assert(pStrmSt->u64BaseDMA); 3070 3227 Assert(pStrmSt->u32CBL); 3071 3228 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 3074 3233 uint32_t cbProcessedTotal = 0; 3075 3234 bool fIsComplete = false; … … 3971 4130 pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns); 3972 4131 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 3973 4142 for (uint8_t u8Strm = 0; u8Strm < 8; u8Strm++) /** @todo Use a define here. */ 3974 4143 { … … 3994 4163 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */ 3995 4164 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 } 3996 4174 3997 4175 LogRel(("HDA: Reset\n")); … … 4344 4522 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */ 4345 4523 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); 4346 4536 } 4347 4537
Note:
See TracChangeset
for help on using the changeset viewer.