Changeset 82230 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Nov 26, 2019 11:52:11 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135045
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r82229 r82230 83 83 * Structures and Typedefs * 84 84 *********************************************************************************************************************************/ 85 /** Pointer to the SB16 state. */ 86 typedef struct SB16STATE *PSB16STATE; 87 85 88 /** 86 89 * Structure defining a (host backend) driver stream. … … 96 99 97 100 /** 98 * Struct for maintaining a host backend driver. 99 */ 100 typedef struct SB16STATE *PSB16STATE; 101 * Struct for tracking a host backend driver, i.e. our per-LUN data. 102 */ 101 103 typedef struct SB16DRIVER 102 104 { 103 105 /** Node for storing this driver in our device driver list of SB16STATE. */ 104 RTLISTNODER3 106 RTLISTNODER3 Node; 105 107 /** Pointer to SB16 controller (state). */ 106 R3PTRTYPE(PSB16STATE) pSB16State; 108 R3PTRTYPE(PSB16STATE) pSB16State; 109 /** Pointer to attached driver base interface. */ 110 R3PTRTYPE(PPDMIBASE) pDrvBase; 111 /** Audio connector interface to the underlying host backend. */ 112 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 113 /** Stream for output. */ 114 SB16DRIVERSTREAM Out; 107 115 /** Driver flags. */ 108 PDMAUDIODRVFLAGS 116 PDMAUDIODRVFLAGS fFlags; 109 117 /** LUN # to which this driver has been assigned. */ 110 uint8_t 118 uint8_t uLUN; 111 119 /** Whether this driver is in an attached state or not. */ 112 bool fAttached; 113 uint8_t Padding[2]; 114 /** Pointer to attached driver base interface. */ 115 R3PTRTYPE(PPDMIBASE) pDrvBase; 116 /** Audio connector interface to the underlying host backend. */ 117 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector; 118 /** Stream for output. */ 119 SB16DRIVERSTREAM Out; 120 } SB16DRIVER, *PSB16DRIVER; 120 bool fAttached; 121 /** The LUN description. */ 122 char szDesc[2+48]; 123 } SB16DRIVER; 124 /** Pointer to the per-LUN data. */ 125 typedef SB16DRIVER *PSB16DRIVER; 121 126 122 127 /** … … 127 132 /** The stream's current configuration. */ 128 133 PDMAUDIOSTREAMCFG Cfg; 129 } SB16STREAM, *PSB16STREAM; 130 134 } SB16STREAM; 135 /** Pointer to a SB16 stream */ 136 typedef SB16STREAM *PSB16STREAM; 137 138 /** 139 * The SB16 state. 140 */ 131 141 typedef struct SB16STATE 132 142 { … … 164 174 int use_hdma; 165 175 int highspeed; 166 int can_write; /** @todo Value never gets 0?*/176 int can_write; /** @todo Value never gets set to 0! */ 167 177 168 178 int v2x6; … … 171 181 uint8_t csp_value; 172 182 uint8_t csp_mode; 183 uint8_t csp_index; 173 184 uint8_t csp_regs[256]; 174 uint8_t csp_index;175 185 uint8_t csp_reg83[4]; 176 186 int csp_reg83r; … … 190 200 191 201 RTLISTANCHOR lstDrv; 192 /** Number of active (running) SDn streams. */193 uint8_t cStreamsActive;194 /** The timer for pumping data thru the attached LUN drivers. */195 TMTIMERHANDLE hTimerIO;196 /** Flag indicating whether the timer is active or not. */197 bool fTimerActive;198 uint8_t u8Padding1[7];199 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */200 uint64_t cTicksTimerIOInterval;201 /** Timestamp of the last timer callback (sb16TimerIO).202 * Used to calculate the time actually elapsed between two timer callbacks. */203 uint64_t tsTimerIO;204 202 /** IRQ timer */ 205 203 TMTIMERHANDLE hTimerIRQ; … … 209 207 SB16STREAM Out; 210 208 209 /** The timer for pumping data thru the attached LUN drivers. */ 210 TMTIMERHANDLE hTimerIO; 211 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */ 212 uint64_t cTicksTimerIOInterval; 213 /** Timestamp of the last timer callback (sb16TimerIO). 214 * Used to calculate the time actually elapsed between two timer callbacks. */ 215 uint64_t tsTimerIO; 216 /** Number of active (running) SDn streams. */ 217 uint8_t cStreamsActive; 218 /** Flag indicating whether the timer is active or not. */ 219 bool volatile fTimerActive; 220 uint8_t u8Padding1[5]; 221 211 222 /* mixer state */ 212 223 uint8_t mixer_nreg; 213 224 uint8_t mixer_regs[256]; 214 } SB16STATE , *PSB16STATE;225 } SB16STATE; 215 226 216 227 … … 387 398 388 399 if (pThis->block_size & pThis->align) 389 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n", 390 pThis->block_size, pThis->align + 1)); 400 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n", pThis->block_size, pThis->align + 1)); 391 401 392 402 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n", … … 480 490 return pThis->in2_data[--pThis->in_index]; 481 491 } 482 else { 483 LogFlowFunc(("buffer underflow\n")); 484 return 0; 485 } 492 LogFlowFunc(("buffer underflow\n")); 493 return 0; 486 494 } 487 495 … … 739 747 740 748 warn: 741 LogFlowFunc(("warning: command %#x,%d is not truly understood yet\n", 742 cmd, pThis->needed_bytes)); 749 LogFlowFunc(("warning: command %#x,%d is not truly understood yet\n", cmd, pThis->needed_bytes)); 743 750 goto exit; 744 751 } … … 761 768 { 762 769 int d0, d1, d2; 763 LogFlowFunc(("complete command %#x, in_index %d, needed_bytes %d\n", 764 pThis->cmd, pThis->in_index, pThis->needed_bytes)); 770 LogFlowFunc(("complete command %#x, in_index %d, needed_bytes %d\n", pThis->cmd, pThis->in_index, pThis->needed_bytes)); 765 771 766 772 if (pThis->cmd > 0xaf && pThis->cmd < 0xd0) … … 792 798 pThis->csp_param = dsp_get_data (pThis); 793 799 pThis->csp_value = dsp_get_data (pThis); 794 LogFlowFunc(("CSP command 0x05: param=%#x value=%#x\n", 795 pThis->csp_param, 796 pThis->csp_value)); 800 LogFlowFunc(("CSP command 0x05: param=%#x value=%#x\n", pThis->csp_param, pThis->csp_value)); 797 801 break; 798 802 … … 818 822 if (d0 == 0x83) 819 823 { 820 LogFlowFunc(("0x83[%d] -> %#x\n", 821 pThis->csp_reg83w, 822 pThis->csp_reg83[pThis->csp_reg83w % 4])); 823 dsp_out_data (pThis, pThis->csp_reg83[pThis->csp_reg83w % 4]); 824 LogFlowFunc(("0x83[%d] -> %#x\n", pThis->csp_reg83w, pThis->csp_reg83[pThis->csp_reg83w % 4])); 825 dsp_out_data(pThis, pThis->csp_reg83[pThis->csp_reg83w % 4]); 824 826 pThis->csp_reg83w += 1; 825 827 } … … 997 999 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 998 1000 { 999 if (!pDrv->Out.pStream) 1000 continue; 1001 1002 int rc2 = pDrv->pConnector->pfnStreamSetVolume(pDrv->pConnector, pDrv->Out.pStream, &VolCombined); 1003 AssertRC(rc2); 1001 PPDMAUDIOSTREAM pStream = pDrv->Out.pStream; 1002 if (pStream) 1003 { 1004 int rc2 = pDrv->pConnector->pfnStreamSetVolume(pDrv->pConnector, pStream, &VolCombined); 1005 AssertRC(rc2); 1006 } 1004 1007 } 1005 1008 } … … 1027 1030 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBytes, pCfg->Props.cChannels); 1028 1031 1029 AssertCompile(sizeof(pCfg->szName) > sizeof("Output"));1030 strcpy(pCfg->szName, "Output");1032 AssertCompile(sizeof(pCfg->szName) >= sizeof("Output")); 1033 memcpy(pCfg->szName, "Output", sizeof("Output")); 1031 1034 1032 1035 sb16CloseOut(pThis); … … 1282 1285 } 1283 1286 1284 uint32_t popcount(uint32_t u) /** @todo r=andy WTF? */ 1287 #ifndef VBOX 1288 static uint32_t popcount(uint32_t u) 1285 1289 { 1286 1290 u = ((u&0x55555555) + ((u>>1)&0x55555555)); … … 1291 1295 return u; 1292 1296 } 1293 1294 uint32_t lsbindex(uint32_t u) 1295 { 1297 #endif 1298 1299 static uint32_t lsbindex(uint32_t u) 1300 { 1301 #ifdef VBOX 1302 return u ? ASMBitFirstSetU32(u) - 1 : 32; 1303 #else 1296 1304 return popcount((u & -(int32_t)u) - 1); 1305 #endif 1297 1306 } 1298 1307 … … 1505 1514 static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos, uint32_t dma_len, int len) 1506 1515 { 1507 uint8_t tmpbuf[_4K]; /** @todo Have a buffer on the heap. */1516 uint8_t abBuf[_4K]; /** @todo Have a buffer on the heap. */ 1508 1517 uint32_t cbToWrite = len; 1509 1518 uint32_t cbWrittenTotal = 0; … … 1512 1521 { 1513 1522 uint32_t cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite); 1514 if (cbToRead > sizeof( tmpbuf))1515 cbToRead = sizeof( tmpbuf);1523 if (cbToRead > sizeof(abBuf)) 1524 cbToRead = sizeof(abBuf); 1516 1525 1517 1526 uint32_t cbRead = 0; 1518 int rc2 = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, tmpbuf, dma_pos, cbToRead, &cbRead);1527 int rc2 = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, abBuf, dma_pos, cbToRead, &cbRead); 1519 1528 AssertMsgRC(rc2, (" from DMA failed: %Rrc\n", rc2)); 1520 1529 … … 1525 1534 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "sb16WriteAudio.pcm", 1526 1535 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1527 RTFileWrite(fh, tmpbuf, cbRead, NULL);1536 RTFileWrite(fh, abBuf, cbRead, NULL); 1528 1537 RTFileClose(fh); 1529 1538 } … … 1539 1548 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1540 1549 { 1541 if (!pDrv->Out.pStream) 1542 continue; 1543 1544 if (!DrvAudioHlpStreamStatusCanWrite(pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pDrv->Out.pStream))) 1545 continue; 1546 1547 uint32_t cbWrittenToStream = 0; 1548 rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, tmpbuf, cbRead, &cbWrittenToStream); 1549 1550 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWrittenToStream=%RU32\n", pDrv->uLUN, rc2, cbWrittenToStream)); 1550 if ( pDrv->Out.pStream 1551 && DrvAudioHlpStreamStatusCanWrite(pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pDrv->Out.pStream))) 1552 { 1553 uint32_t cbWrittenToStream = 0; 1554 rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, abBuf, cbRead, &cbWrittenToStream); 1555 1556 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWrittenToStream=%RU32\n", pDrv->uLUN, rc2, cbWrittenToStream)); 1557 } 1551 1558 } 1552 1559 … … 1555 1562 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32\n", 1556 1563 cbToRead, cbToWrite, cbWritten, cbToWrite - cbWrittenTotal)); 1564 1565 if (!cbWritten) 1566 break; 1557 1567 1558 1568 Assert(cbToWrite >= cbWritten); … … 1560 1570 dma_pos = (dma_pos + cbWritten) % dma_len; 1561 1571 cbWrittenTotal += cbWritten; 1562 1563 if (!cbWritten)1564 break;1565 1572 } 1566 1573 … … 1626 1633 1627 1634 Log3Func(("pos %d/%d free %5d till %5d copy %5d written %5d block_size %5d\n", 1628 dma_pos, dma_len, free, pThis->left_till_irq, copy, written, 1629 pThis->block_size)); 1635 dma_pos, dma_len, free, pThis->left_till_irq, copy, written, pThis->block_size)); 1630 1636 1631 1637 while (pThis->left_till_irq <= 0) … … 1685 1691 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1686 1692 { 1687 PPDMAUDIOSTREAM pStream = pDrv->Out.pStream; 1688 if (!pStream) 1689 continue; 1690 1691 PPDMIAUDIOCONNECTOR pConn = pDrv->pConnector; 1692 if (!pConn) 1693 continue; 1694 1695 int rc2 = pConn->pfnStreamIterate(pConn, pStream); 1696 if (RT_SUCCESS(rc2)) 1693 PPDMAUDIOSTREAM const pStream = pDrv->Out.pStream; 1694 PPDMIAUDIOCONNECTOR const pConn = pDrv->pConnector; 1695 if (pStream && pConn) 1697 1696 { 1698 rc2 = pConn->pfnStreamPlay(pConn, pStream, NULL /* cPlayed */);1699 if (RT_ FAILURE(rc2))1697 int rc2 = pConn->pfnStreamIterate(pConn, pStream); 1698 if (RT_SUCCESS(rc2)) 1700 1699 { 1701 LogFlowFunc(("%s: Failed playing stream, rc=%Rrc\n", pStream->szName, rc2)); 1702 continue; 1700 rc2 = pConn->pfnStreamPlay(pConn, pStream, NULL /* cPlayed */); 1701 if (RT_FAILURE(rc2)) 1702 { 1703 LogFlowFunc(("%s: Failed playing stream, rc=%Rrc\n", pStream->szName, rc2)); 1704 continue; 1705 } 1706 1707 /* Only do the next DMA transfer if we're able to write the remaining data block. */ 1708 fDoTransfer = pConn->pfnStreamGetWritable(pConn, pStream) > (unsigned)pThis->left_till_irq; 1703 1709 } 1704 1710 1705 /* Only do the next DMA transfer if we're able to write the remaining data block. */ 1706 fDoTransfer = pConn->pfnStreamGetWritable(pConn, pStream) > (unsigned)pThis->left_till_irq; 1711 PDMAUDIOSTREAMSTS strmSts = pConn->pfnStreamGetStatus(pConn, pStream); 1712 fIsPlaying |= ( (strmSts & PDMAUDIOSTREAMSTS_FLAG_ENABLED) 1713 || (strmSts & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)); 1707 1714 } 1708 1709 PDMAUDIOSTREAMSTS strmSts = pConn->pfnStreamGetStatus(pConn, pStream);1710 fIsPlaying |= ( (strmSts & PDMAUDIOSTREAMSTS_FLAG_ENABLED)1711 || (strmSts & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE));1712 1715 } 1713 1716 1714 1717 bool fTimerActive = ASMAtomicReadBool(&pThis->fTimerActive); 1715 bool fKickTimer = fTimerActive || fIsPlaying; 1716 1718 bool fArmTimer = fTimerActive || fIsPlaying; 1717 1719 LogFlowFunc(("fTimerActive=%RTbool, fIsPlaying=%RTbool\n", fTimerActive, fIsPlaying)); 1718 1720 … … 1720 1722 { 1721 1723 /* Schedule the next transfer. */ 1722 PDMDevHlpDMASchedule(p This->pDevInsR3);1723 1724 /* Kickthe timer at least one more time. */1725 f KickTimer = true;1724 PDMDevHlpDMASchedule(pDevIns); 1725 1726 /* Arm the timer at least one more time. */ 1727 fArmTimer = true; 1726 1728 } 1727 1729 … … 1731 1733 /** @todo Implement recording. */ 1732 1734 1733 if (f KickTimer)1734 { 1735 /* Kickthe timer again. */1735 if (fArmTimer) 1736 { 1737 /* Arm the timer again. */ 1736 1738 uint64_t cTicks = pThis->cTicksTimerIOInterval; 1737 1739 /** @todo adjust cTicks down by now much cbOutMin represents. */ … … 1914 1916 { 1915 1917 int32_t irq; 1916 pHlp->pfnSSMGetS32 1918 pHlp->pfnSSMGetS32(pSSM, &irq); 1917 1919 int32_t dma; 1918 pHlp->pfnSSMGetS32 1920 pHlp->pfnSSMGetS32(pSSM, &dma); 1919 1921 int32_t hdma; 1920 pHlp->pfnSSMGetS32 1922 pHlp->pfnSSMGetS32(pSSM, &hdma); 1921 1923 int32_t port; 1922 pHlp->pfnSSMGetS32 1924 pHlp->pfnSSMGetS32(pSSM, &port); 1923 1925 int32_t ver; 1924 int rc = pHlp->pfnSSMGetS32 1926 int rc = pHlp->pfnSSMGetS32(pSSM, &ver); 1925 1927 AssertRCReturn (rc, rc); 1926 1928 … … 1932 1934 { 1933 1935 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, 1934 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"),1935 irq, pThis->irqCfg,1936 dma, pThis->dmaCfg,1937 hdma, pThis->hdmaCfg,1938 port, pThis->portCfg,1939 ver, pThis->verCfg);1936 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"), 1937 irq, pThis->irqCfg, 1938 dma, pThis->dmaCfg, 1939 hdma, pThis->hdmaCfg, 1940 port, pThis->portCfg, 1941 ver, pThis->verCfg); 1940 1942 } 1941 1943 } … … 1951 1953 * 1952 1954 * @returns IPRT status code. 1953 * @param pThis SB16 state.1954 1955 * @param pCfg Stream configuration to use. 1955 1956 * @param pDrv Driver stream to create PDM stream for. 1956 1957 */ 1957 static int sb16CreateDrvStream(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv) 1958 { 1959 RT_NOREF(pThis); 1960 1958 static int sb16CreateDrvStream(PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv) 1959 { 1961 1960 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER); 1962 1961 Assert(DrvAudioHlpStreamCfgIsValid(pCfg)); … … 1993 1992 static void sb16DestroyDrvStream(PSB16STATE pThis, PSB16DRIVER pDrv) 1994 1993 { 1995 AssertPtr ReturnVoid(pThis);1996 AssertPtr ReturnVoid(pDrv);1994 AssertPtr(pThis); 1995 AssertPtr(pDrv); 1997 1996 1998 1997 if (pDrv->Out.pStream) … … 2019 2018 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis) 2020 2019 { 2021 AssertPtr Return(pThis, VERR_INVALID_POINTER);2020 AssertPtr(pThis); 2022 2021 2023 2022 int rc = VINF_SUCCESS; … … 2058 2057 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2059 2058 { 2060 AssertPtrReturn(pThis, VERR_INVALID_POINTER); /// @todo r=bird: Too paranoiad here.2061 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); /// @todo r=bird: This is certifiable, only caller sends us a stack object...2062 2059 LogFlowFuncEnter(); 2060 AssertPtr(pThis); 2061 AssertPtr(pCfg); 2063 2062 2064 2063 if (!DrvAudioHlpStreamCfgIsValid(pCfg)) … … 2066 2065 2067 2066 int rc = DrvAudioHlpStreamCfgCopy(&pThis->Out.Cfg, pCfg); 2068 if (RT_ FAILURE(rc))2069 return rc;2070 2071 /* Set scheduling hint (if available). */2072 if (pThis->cTicksTimerIOInterval)2073 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */2074 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO)2075 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2076 2077 PSB16DRIVER pDrv;2078 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)2079 {2080 int rc2 = sb16CreateDrvStream(pThis, &pThis->Out.Cfg, pDrv);2081 if (RT_FAILURE(rc2))2082 LogFunc(("Attaching stream failed with %Rrc\n", rc2)); 2083 2084 /* Do not pass failure to rc here, as there might be drivers which aren't2085 * configured / ready yet. */2086 } 2087 2088 sb16UpdateVolume(pThis);2067 if (RT_SUCCESS(rc)) 2068 { 2069 /* Set scheduling hint (if available). */ 2070 if (pThis->cTicksTimerIOInterval) 2071 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */ 2072 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 2073 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2074 2075 PSB16DRIVER pDrv; 2076 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2077 { 2078 int rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv); 2079 if (RT_FAILURE(rc2)) 2080 LogFunc(("Attaching stream failed with %Rrc\n", rc2)); 2081 2082 /* Do not pass failure to rc here, as there might be drivers which aren't 2083 * configured / ready yet. */ 2084 } 2085 2086 sb16UpdateVolume(pThis); 2087 } 2089 2088 2090 2089 LogFlowFuncLeaveRC(rc); … … 2094 2093 static void sb16CloseOut(PSB16STATE pThis) 2095 2094 { 2096 AssertPtrReturnVoid(pThis); /// @todo r=bird: too much panaoia here!2097 2095 LogFlowFuncEnter(); 2096 AssertPtr(pThis); 2098 2097 2099 2098 PSB16DRIVER pDrv; … … 2140 2139 * Attach driver. 2141 2140 */ 2142 char *pszDesc;2143 if (RTStrAPrintf(&pszDesc, "Audio driver port (SB16) for LUN #%u", uLUN) <= 0)2144 AssertLogRelFailedReturn(VERR_NO_MEMORY);2141 PSB16DRIVER pDrv = (PSB16DRIVER)RTMemAllocZ(sizeof(SB16DRIVER)); 2142 AssertReturn(pDrv, VERR_NO_MEMORY); 2143 RTStrPrintf(pDrv->szDesc, sizeof(pDrv->szDesc), "Audio driver port (SB16) for LUN #%u", uLUN); 2145 2144 2146 2145 PPDMIBASE pDrvBase; 2147 int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, uLUN, 2148 &pThis->IBase, &pDrvBase, pszDesc); 2146 int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, uLUN, &pThis->IBase, &pDrvBase, pDrv->szDesc); 2149 2147 if (RT_SUCCESS(rc)) 2150 2148 { 2151 PSB16DRIVER pDrv = (PSB16DRIVER)RTMemAllocZ(sizeof(SB16DRIVER)); 2152 if (pDrv) 2149 pDrv->pDrvBase = pDrvBase; 2150 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR); 2151 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", uLUN, rc)); 2152 pDrv->pSB16State = pThis; 2153 pDrv->uLUN = uLUN; 2154 2155 /* 2156 * For now we always set the driver at LUN 0 as our primary 2157 * host backend. This might change in the future. 2158 */ 2159 if (pDrv->uLUN == 0) 2160 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY; 2161 2162 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags)); 2163 2164 /* Attach to driver list if not attached yet. */ 2165 if (!pDrv->fAttached) 2153 2166 { 2154 pDrv->pDrvBase = pDrvBase; 2155 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR); 2156 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", uLUN, rc)); 2157 pDrv->pSB16State = pThis; 2158 pDrv->uLUN = uLUN; 2159 2160 /* 2161 * For now we always set the driver at LUN 0 as our primary 2162 * host backend. This might change in the future. 2163 */ 2164 if (pDrv->uLUN == 0) 2165 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY; 2166 2167 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags)); 2168 2169 /* Attach to driver list if not attached yet. */ 2170 if (!pDrv->fAttached) 2171 { 2172 RTListAppend(&pThis->lstDrv, &pDrv->Node); 2173 pDrv->fAttached = true; 2174 } 2175 2176 if (ppDrv) 2177 *ppDrv = pDrv; 2167 RTListAppend(&pThis->lstDrv, &pDrv->Node); 2168 pDrv->fAttached = true; 2178 2169 } 2179 else 2180 rc = VERR_NO_MEMORY; 2181 } 2182 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 2183 LogFunc(("No attached driver for LUN #%u\n", uLUN)); 2184 2185 if (RT_FAILURE(rc)) 2186 { 2187 /* Only free this string on failure; 2188 * must remain valid for the live of the driver instance. */ 2189 RTStrFree(pszDesc); 2170 2171 if (ppDrv) 2172 *ppDrv = pDrv; 2173 } 2174 else 2175 { 2176 if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 2177 LogFunc(("No attached driver for LUN #%u\n", uLUN)); 2178 RTMemFree(pDrv); 2190 2179 } 2191 2180 … … 2229 2218 int rc2 = sb16AttachInternal(pThis, iLUN, fFlags, &pDrv); 2230 2219 if (RT_SUCCESS(rc2)) 2231 rc2 = sb16CreateDrvStream( pThis,&pThis->Out.Cfg, pDrv);2220 rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv); 2232 2221 2233 2222 return VINF_SUCCESS; … … 2321 2310 PSB16DRIVER pDrv; 2322 2311 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2312 { 2323 2313 sb16DestroyDrvStream(pThis, pDrv); 2314 } 2324 2315 } 2325 2316
Note:
See TracChangeset
for help on using the changeset viewer.