Changeset 82229 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Nov 26, 2019 10:50:31 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135044
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r82228 r82229 193 193 uint8_t cStreamsActive; 194 194 /** The timer for pumping data thru the attached LUN drivers. */ 195 PTMTIMERR3 pTimerIO;195 TMTIMERHANDLE hTimerIO; 196 196 /** Flag indicating whether the timer is active or not. */ 197 197 bool fTimerActive; 198 198 uint8_t u8Padding1[7]; 199 199 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */ 200 uint64_t cTi merTicksIO;200 uint64_t cTicksTimerIOInterval; 201 201 /** Timestamp of the last timer callback (sb16TimerIO). 202 202 * Used to calculate the time actually elapsed between two timer callbacks. */ 203 uint64_t uTimerTSIO; 204 PTMTIMER pTimerIRQ; 203 uint64_t tsTimerIO; 204 /** IRQ timer */ 205 TMTIMERHANDLE hTimerIRQ; 205 206 /** The base interface for LUN\#0. */ 206 207 PDMIBASE IBase; … … 217 218 * Internal Functions * 218 219 *********************************************************************************************************************************/ 219 static int sb16CheckAndReOpenOut(P SB16STATE pThis);220 static int sb16OpenOut(P SB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);220 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis); 221 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg); 221 222 static void sb16CloseOut(PSB16STATE pThis); 222 static void sb16TimerMaybeStart(P SB16STATE pThis);223 static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis); 223 224 static void sb16TimerMaybeStop(PSB16STATE pThis); 224 225 … … 286 287 } 287 288 288 static void sb16Control(P SB16STATE pThis, int hold)289 static void sb16Control(PPDMDEVINS pDevIns, PSB16STATE pThis, int hold) 289 290 { 290 291 int dma = pThis->use_hdma ? pThis->hdma : pThis->dma; … … 309 310 { 310 311 pThis->cStreamsActive++; 311 sb16TimerMaybeStart(p This);312 sb16TimerMaybeStart(pDevIns, pThis); 312 313 PDMDevHlpDMASchedule(pThis->pDevInsR3); 313 314 } … … 323 324 * @callback_method_impl{PFNTMTIMERDEV} 324 325 */ 325 static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis) 326 { 327 RT_NOREF(pDevIns, pTimer); 328 PSB16STATE pThis = (PSB16STATE)pvThis; 326 static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 327 { 328 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 329 RT_NOREF(pvUser, pTimer); 330 329 331 pThis->can_write = 1; 330 PDMDevHlpISASetIrq(p This->pDevInsR3, pThis->irq, 1);332 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1); 331 333 } 332 334 … … 334 336 #define DMA8_HIGH 2 335 337 336 static void continue_dma8(P SB16STATE pThis)337 { 338 sb16CheckAndReOpenOut(p This);339 sb16Control(p This, 1);340 } 341 342 static void dma_cmd8(P SB16STATE pThis, int mask, int dma_len)338 static void continue_dma8(PPDMDEVINS pDevIns, PSB16STATE pThis) 339 { 340 sb16CheckAndReOpenOut(pDevIns, pThis); 341 sb16Control(pDevIns, pThis, 1); 342 } 343 344 static void dma_cmd8(PPDMDEVINS pDevIns, PSB16STATE pThis, int mask, int dma_len) 343 345 { 344 346 pThis->fmt = PDMAUDIOFMT_U8; … … 392 394 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed)); 393 395 394 continue_dma8(p This);396 continue_dma8(pDevIns, pThis); 395 397 sb16SpeakerControl(pThis, 1); 396 398 } 397 399 398 static void dma_cmd(P SB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len)400 static void dma_cmd(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len) 399 401 { 400 402 pThis->use_hdma = cmd < 0xc0; … … 460 462 } 461 463 462 sb16CheckAndReOpenOut(p This);463 sb16Control(p This, 1);464 sb16CheckAndReOpenOut(pDevIns, pThis); 465 sb16Control(pDevIns, pThis, 1); 464 466 sb16SpeakerControl(pThis, 1); 465 467 } … … 484 486 } 485 487 486 static void sb16HandleCommand(P SB16STATE pThis, uint8_t cmd)488 static void sb16HandleCommand(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd) 487 489 { 488 490 LogFlowFunc(("command %#x\n", cmd)); … … 548 550 549 551 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ 550 dma_cmd8(p This, DMA8_AUTO, -1);552 dma_cmd8(pDevIns, pThis, DMA8_AUTO, -1); 551 553 break; 552 554 … … 624 626 case 0x90: 625 627 case 0x91: 626 dma_cmd8(p This, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1);628 dma_cmd8(pDevIns, pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1); 627 629 break; 628 630 629 631 case 0xd0: /* halt DMA operation. 8bit */ 630 sb16Control(p This, 0);632 sb16Control(pDevIns, pThis, 0); 631 633 break; 632 634 … … 642 644 /* KQ6 (or maybe Sierras audblst.drv in general) resets 643 645 the frequency between halt/continue */ 644 continue_dma8(p This);646 continue_dma8(pDevIns, pThis); 645 647 break; 646 648 647 649 case 0xd5: /* halt DMA operation. 16bit */ 648 sb16Control(p This, 0);650 sb16Control(pDevIns, pThis, 0); 649 651 break; 650 652 651 653 case 0xd6: /* continue DMA operation. 16bit */ 652 sb16Control(p This, 1);654 sb16Control(pDevIns, pThis, 1); 653 655 break; 654 656 … … 756 758 } 757 759 758 static void complete(P SB16STATE pThis)760 static void complete(PPDMDEVINS pDevIns, PSB16STATE pThis) 759 761 { 760 762 int d0, d1, d2; … … 773 775 { 774 776 LogFlowFunc(("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", pThis->cmd, d0, d1, d2)); 775 dma_cmd(p This, pThis->cmd, d0, d1 + (d2 << 8));777 dma_cmd(pDevIns, pThis, pThis->cmd, d0, d1 + (d2 << 8)); 776 778 } 777 779 } … … 832 834 833 835 case 0x14: 834 dma_cmd8(p This, 0, dsp_get_lohi (pThis) + 1);836 dma_cmd8(pDevIns, pThis, 0, dsp_get_lohi (pThis) + 1); 835 837 break; 836 838 … … 863 865 case 0x80: 864 866 { 865 int freq, samples, bytes; 866 uint64_t ticks; 867 868 freq = pThis->freq > 0 ? pThis->freq : 11025; 869 samples = dsp_get_lohi (pThis) + 1; 870 bytes = samples << pThis->fmt_stereo << ((pThis->fmt_bits == 16) ? 1 : 0); 871 ticks = (bytes * TMTimerGetFreq(pThis->pTimerIRQ)) / freq; 872 if (ticks < TMTimerGetFreq(pThis->pTimerIRQ) / 1024) 873 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1); 867 uint32_t const freq = pThis->freq > 0 ? pThis->freq : 11025; 868 uint32_t const samples = dsp_get_lohi(pThis) + 1; 869 uint32_t const bytes = samples << pThis->fmt_stereo << (pThis->fmt_bits == 16 ? 1 : 0); 870 uint64_t const uTimerHz = PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIRQ); 871 uint64_t const cTicks = (bytes * uTimerHz) / freq; 872 if (cTicks < uTimerHz / 1024) 873 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1); 874 874 else 875 TMTimerSet(pThis->pTimerIRQ, TMTimerGet(pThis->pTimerIRQ) + ticks);876 LogFlowFunc(("mix silence: %d samples, %d bytes, %RU64 ticks\n", samples, bytes, ticks));875 PDMDevHlpTimerSetRelative(pDevIns, pThis->hTimerIRQ, cTicks, NULL); 876 LogFlowFunc(("mix silence: %d samples, %d bytes, %RU64 ticks\n", samples, bytes, cTicks)); 877 877 break; 878 878 } … … 1033 1033 } 1034 1034 1035 static void sb16CmdReset(P SB16STATE pThis)1036 { 1037 PDMDevHlpISASetIrq(p This->pDevInsR3, pThis->irq, 0);1035 static void sb16CmdReset(PPDMDEVINS pDevIns, PSB16STATE pThis) 1036 { 1037 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0); 1038 1038 if (pThis->dma_auto) 1039 1039 { 1040 PDMDevHlpISASetIrq(p This->pDevInsR3, pThis->irq, 1);1041 PDMDevHlpISASetIrq(p This->pDevInsR3, pThis->irq, 0);1040 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1); 1041 PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0); 1042 1042 } 1043 1043 … … 1057 1057 sb16SpeakerControl(pThis, 0); 1058 1058 1059 sb16Control(p This, 0);1059 sb16Control(pDevIns, pThis, 0); 1060 1060 sb16CmdResetLegacy(pThis); 1061 1061 } … … 1084 1084 pThis->highspeed = 0; 1085 1085 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0); 1086 sb16Control(p This, 0);1086 sb16Control(pDevIns, pThis, 0); 1087 1087 } 1088 1088 else 1089 sb16CmdReset(p This);1089 sb16CmdReset(pDevIns, pThis); 1090 1090 } 1091 1091 pThis->v2x6 = 0; … … 1103 1103 1104 1104 case 0xb8: /* Panic */ 1105 sb16CmdReset(p This);1105 sb16CmdReset(pDevIns, pThis); 1106 1106 break; 1107 1107 1108 1108 case 0x39: 1109 1109 dsp_out_data(pThis, 0x38); 1110 sb16CmdReset(p This);1110 sb16CmdReset(pDevIns, pThis); 1111 1111 pThis->v2x6 = 0x39; 1112 1112 break; … … 1125 1125 if (0 == pThis->needed_bytes) 1126 1126 { 1127 sb16HandleCommand(p This, val);1127 sb16HandleCommand(pDevIns, pThis, val); 1128 1128 #if 0 1129 1129 if (0 == pThis->needed_bytes) { … … 1144 1144 { 1145 1145 pThis->needed_bytes = 0; 1146 complete (pThis);1146 complete(pDevIns, pThis); 1147 1147 #if 0 1148 1148 log_dsp (pThis); … … 1620 1620 if (0 == pThis->dma_auto) 1621 1621 { 1622 sb16Control(p This, 0);1622 sb16Control(pDevIns, pThis, 0); 1623 1623 sb16SpeakerControl(pThis, 0); 1624 1624 } … … 1635 1635 } 1636 1636 1637 static void sb16TimerMaybeStart(P SB16STATE pThis)1637 static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis) 1638 1638 { 1639 1639 LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive)); … … 1642 1642 return; 1643 1643 1644 if (!pThis->pTimerIO)1645 return;1646 1647 1644 /* Set timer flag. */ 1648 ASMAtomic XchgBool(&pThis->fTimerActive, true);1645 ASMAtomicWriteBool(&pThis->fTimerActive, true); 1649 1646 1650 1647 /* Update current time timestamp. */ 1651 pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO); 1652 1653 /* Fire off timer. */ 1654 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->cTimerTicksIO); 1655 } 1656 1648 uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pThis->hTimerIO); 1649 pThis->tsTimerIO = tsNow; 1650 1651 /* Arm the timer. */ 1652 PDMDevHlpTimerSet(pDevIns, pThis->hTimerIO, tsNow + pThis->cTicksTimerIOInterval); 1653 } 1654 1655 /** 1656 * This clears fTimerActive if no streams are active, so that the timer won't be 1657 * rearmed then next time it fires. 1658 */ 1657 1659 static void sb16TimerMaybeStop(PSB16STATE pThis) 1658 1660 { … … 1662 1664 return; 1663 1665 1664 if (!pThis->pTimerIO) 1665 return; 1666 1667 /* Set timer flag. */ 1668 ASMAtomicXchgBool(&pThis->fTimerActive, false); 1666 /* Clear the timer flag. */ 1667 ASMAtomicWriteBool(&pThis->fTimerActive, false); 1669 1668 } 1670 1669 … … 1674 1673 static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1675 1674 { 1676 RT_NOREF(pDevIns); 1677 PSB16STATE pThis = (PSB16STATE)pvUser; 1678 Assert(pThis == PDMDEVINS_2_DATA(pDevIns, PSB16STATE)); 1679 AssertPtr(pThis); 1680 1681 uint64_t cTicksNow = TMTimerGet(pTimer); 1675 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1676 RT_NOREF(pTimer, pvUser); 1677 1678 uint64_t cTicksNow = PDMDevHlpTimerGet(pDevIns, pThis->hTimerIO); 1682 1679 bool fIsPlaying = false; /* Whether one or more streams are still playing. */ 1683 1680 bool fDoTransfer = false; 1684 1681 1685 pThis-> uTimerTSIO = cTicksNow;1682 pThis->tsTimerIO = cTicksNow; 1686 1683 1687 1684 PSB16DRIVER pDrv; … … 1737 1734 { 1738 1735 /* Kick the timer again. */ 1739 uint64_t cTicks = pThis->cTi merTicksIO;1736 uint64_t cTicks = pThis->cTicksTimerIOInterval; 1740 1737 /** @todo adjust cTicks down by now much cbOutMin represents. */ 1741 TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);1738 PDMDevHlpTimerSet(pDevIns, pThis->hTimerIO, cTicksNow + cTicks); 1742 1739 } 1743 1740 } … … 1748 1745 static DECLCALLBACK(int) sb16LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1749 1746 { 1747 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1748 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 1750 1749 RT_NOREF(uPass); 1751 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);1752 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;1753 1750 1754 1751 pHlp->pfnSSMPutS32(pSSM, pThis->irqCfg); … … 1831 1828 * Worker for sb16LoadExec. 1832 1829 */ 1833 static int sb16Load(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PSB16STATE pThis) 1834 { 1830 static int sb16Load(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PSB16STATE pThis) 1831 { 1832 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 1833 1835 1834 pHlp->pfnSSMGetS32(pSSM, &pThis->irq); 1836 1835 pHlp->pfnSSMGetS32(pSSM, &pThis->dma); … … 1889 1888 if (pThis->dma_running) 1890 1889 { 1891 sb16CheckAndReOpenOut(p This);1892 sb16Control(p This, 1);1890 sb16CheckAndReOpenOut(pDevIns, pThis); 1891 sb16Control(pDevIns, pThis, 1); 1893 1892 sb16SpeakerControl(pThis, pThis->speaker); 1894 1893 } … … 1945 1944 return VINF_SUCCESS; 1946 1945 1947 return sb16Load(p Hlp, pSSM, pThis);1946 return sb16Load(pDevIns, pSSM, pThis); 1948 1947 } 1949 1948 … … 2014 2013 * Checks if the output stream needs to be (re-)created and does so if needed. 2015 2014 * 2016 * @return VBox status code. 2017 * @param pThis SB16 state. 2018 */ 2019 static int sb16CheckAndReOpenOut(PSB16STATE pThis) 2015 * @return VBox status code. 2016 * @param pDevIns The device instance. 2017 * @param pThis SB16 state. 2018 */ 2019 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis) 2020 2020 { 2021 2021 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 2045 2045 sb16CloseOut(pThis); 2046 2046 2047 rc = sb16OpenOut(p This, &Cfg);2047 rc = sb16OpenOut(pDevIns, pThis, &Cfg); 2048 2048 AssertRC(rc); 2049 2049 } … … 2056 2056 } 2057 2057 2058 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2059 { 2060 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2061 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2062 2058 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2059 { 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... 2063 2062 LogFlowFuncEnter(); 2064 2063 … … 2071 2070 2072 2071 /* Set scheduling hint (if available). */ 2073 if (pThis->cTimerTicksIO) 2074 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */ / (TMTimerGetFreq(pThis->pTimerIO) / pThis->cTimerTicksIO); 2072 if (pThis->cTicksTimerIOInterval) 2073 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */ 2074 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 2075 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2075 2076 2076 2077 PSB16DRIVER pDrv; … … 2093 2094 static void sb16CloseOut(PSB16STATE pThis) 2094 2095 { 2095 AssertPtrReturnVoid(pThis); 2096 2096 AssertPtrReturnVoid(pThis); /// @todo r=bird: too much panaoia here! 2097 2097 LogFlowFuncEnter(); 2098 2098 2099 2099 PSB16DRIVER pDrv; 2100 2100 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2101 { 2101 2102 sb16DestroyDrvStream(pThis, pDrv); 2103 } 2102 2104 2103 2105 LogFlowFuncLeave(); … … 2302 2304 sb16MixerReset(pThis); 2303 2305 sb16SpeakerControl(pThis, 0); 2304 sb16Control(p This, 0);2306 sb16Control(pDevIns, pThis, 0); 2305 2307 sb16CmdResetLegacy(pThis); 2306 2308 } … … 2405 2407 if (RT_FAILURE(rc)) 2406 2408 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: failed to read Hertz (Hz) rate as unsigned integer")); 2409 if (uTimerHz == 0) 2410 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: TimerHz is zero")); 2411 if (uTimerHz > 2048) 2412 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Max TimerHz value is 2048.")); 2407 2413 2408 2414 /* … … 2418 2424 * Create timers. 2419 2425 */ 2420 rc = PDMDevHlpT MTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIRQ, pThis,2421 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IRQ timer", &pThis->pTimerIRQ);2426 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIRQ, pThis, 2427 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IRQ timer", &pThis->hTimerIRQ); 2422 2428 AssertRCReturn(rc, rc); 2423 rc = PDMDevHlpT MTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis,2424 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->pTimerIO);2429 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis, 2430 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->hTimerIO); 2425 2431 AssertRCReturn(rc, rc); 2426 pThis->cTi merTicksIO = TMTimerGetFreq(pThis->pTimerIO) / uTimerHz;2427 pThis-> uTimerTSIO = TMTimerGet(pThis->pTimerIO);2428 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTi merTicksIO, uTimerHz));2432 pThis->cTicksTimerIOInterval = PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) / uTimerHz; 2433 pThis->tsTimerIO = PDMDevHlpTimerGet(pDevIns, pThis->hTimerIO); 2434 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTicksTimerIOInterval, uTimerHz)); 2429 2435 2430 2436 /*
Note:
See TracChangeset
for help on using the changeset viewer.