VirtualBox

Changeset 82229 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Nov 26, 2019 10:50:31 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
135044
Message:

DevSB16: Converted timers. bugref:9218

File:
1 edited

Legend:

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

    r82228 r82229  
    193193    uint8_t                        cStreamsActive;
    194194    /** The timer for pumping data thru the attached LUN drivers. */
    195     PTMTIMERR3                     pTimerIO;
     195    TMTIMERHANDLE                  hTimerIO;
    196196    /** Flag indicating whether the timer is active or not. */
    197197    bool                           fTimerActive;
    198198    uint8_t                        u8Padding1[7];
    199199    /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
    200     uint64_t                       cTimerTicksIO;
     200    uint64_t                       cTicksTimerIOInterval;
    201201    /** Timestamp of the last timer callback (sb16TimerIO).
    202202     * 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;
    205206    /** The base interface for LUN\#0. */
    206207    PDMIBASE                       IBase;
     
    217218*   Internal Functions                                                                                                           *
    218219*********************************************************************************************************************************/
    219 static int sb16CheckAndReOpenOut(PSB16STATE pThis);
    220 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);
     220static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis);
     221static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);
    221222static void sb16CloseOut(PSB16STATE pThis);
    222 static void sb16TimerMaybeStart(PSB16STATE pThis);
     223static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis);
    223224static void sb16TimerMaybeStop(PSB16STATE pThis);
    224225
     
    286287}
    287288
    288 static void sb16Control(PSB16STATE pThis, int hold)
     289static void sb16Control(PPDMDEVINS pDevIns, PSB16STATE pThis, int hold)
    289290{
    290291    int dma = pThis->use_hdma ? pThis->hdma : pThis->dma;
     
    309310    {
    310311        pThis->cStreamsActive++;
    311         sb16TimerMaybeStart(pThis);
     312        sb16TimerMaybeStart(pDevIns, pThis);
    312313        PDMDevHlpDMASchedule(pThis->pDevInsR3);
    313314    }
     
    323324 * @callback_method_impl{PFNTMTIMERDEV}
    324325 */
    325 static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis)
    326 {
    327     RT_NOREF(pDevIns, pTimer);
    328     PSB16STATE pThis = (PSB16STATE)pvThis;
     326static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     327{
     328    PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);
     329    RT_NOREF(pvUser, pTimer);
     330
    329331    pThis->can_write = 1;
    330     PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
     332    PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1);
    331333}
    332334
     
    334336#define DMA8_HIGH 2
    335337
    336 static void continue_dma8(PSB16STATE pThis)
    337 {
    338     sb16CheckAndReOpenOut(pThis);
    339     sb16Control(pThis, 1);
    340 }
    341 
    342 static void dma_cmd8(PSB16STATE pThis, int mask, int dma_len)
     338static void continue_dma8(PPDMDEVINS pDevIns, PSB16STATE pThis)
     339{
     340    sb16CheckAndReOpenOut(pDevIns, pThis);
     341    sb16Control(pDevIns, pThis, 1);
     342}
     343
     344static void dma_cmd8(PPDMDEVINS pDevIns, PSB16STATE pThis, int mask, int dma_len)
    343345{
    344346    pThis->fmt        = PDMAUDIOFMT_U8;
     
    392394                 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed));
    393395
    394     continue_dma8(pThis);
     396    continue_dma8(pDevIns, pThis);
    395397    sb16SpeakerControl(pThis, 1);
    396398}
    397399
    398 static void dma_cmd(PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len)
     400static void dma_cmd(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len)
    399401{
    400402    pThis->use_hdma   = cmd < 0xc0;
     
    460462    }
    461463
    462     sb16CheckAndReOpenOut(pThis);
    463     sb16Control(pThis, 1);
     464    sb16CheckAndReOpenOut(pDevIns, pThis);
     465    sb16Control(pDevIns, pThis, 1);
    464466    sb16SpeakerControl(pThis, 1);
    465467}
     
    484486}
    485487
    486 static void sb16HandleCommand(PSB16STATE pThis, uint8_t cmd)
     488static void sb16HandleCommand(PPDMDEVINS pDevIns, PSB16STATE pThis, uint8_t cmd)
    487489{
    488490    LogFlowFunc(("command %#x\n", cmd));
     
    548550
    549551            case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
    550                 dma_cmd8(pThis, DMA8_AUTO, -1);
     552                dma_cmd8(pDevIns, pThis, DMA8_AUTO, -1);
    551553                break;
    552554
     
    624626            case 0x90:
    625627            case 0x91:
    626                 dma_cmd8(pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1);
     628                dma_cmd8(pDevIns, pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1);
    627629                break;
    628630
    629631            case 0xd0:              /* halt DMA operation. 8bit */
    630                 sb16Control(pThis, 0);
     632                sb16Control(pDevIns, pThis, 0);
    631633                break;
    632634
     
    642644                /* KQ6 (or maybe Sierras audblst.drv in general) resets
    643645                   the frequency between halt/continue */
    644                 continue_dma8(pThis);
     646                continue_dma8(pDevIns, pThis);
    645647                break;
    646648
    647649            case 0xd5:              /* halt DMA operation. 16bit */
    648                 sb16Control(pThis, 0);
     650                sb16Control(pDevIns, pThis, 0);
    649651                break;
    650652
    651653            case 0xd6:              /* continue DMA operation. 16bit */
    652                 sb16Control(pThis, 1);
     654                sb16Control(pDevIns, pThis, 1);
    653655                break;
    654656
     
    756758}
    757759
    758 static void complete(PSB16STATE pThis)
     760static void complete(PPDMDEVINS pDevIns, PSB16STATE pThis)
    759761{
    760762    int d0, d1, d2;
     
    773775        {
    774776            LogFlowFunc(("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", pThis->cmd, d0, d1, d2));
    775             dma_cmd(pThis, pThis->cmd, d0, d1 + (d2 << 8));
     777            dma_cmd(pDevIns, pThis, pThis->cmd, d0, d1 + (d2 << 8));
    776778        }
    777779    }
     
    832834
    833835        case 0x14:
    834             dma_cmd8(pThis, 0, dsp_get_lohi (pThis) + 1);
     836            dma_cmd8(pDevIns, pThis, 0, dsp_get_lohi (pThis) + 1);
    835837            break;
    836838
     
    863865        case 0x80:
    864866        {
    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);
    874874            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));
    877877            break;
    878878        }
     
    10331033}
    10341034
    1035 static void sb16CmdReset(PSB16STATE pThis)
    1036 {
    1037     PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
     1035static void sb16CmdReset(PPDMDEVINS pDevIns, PSB16STATE pThis)
     1036{
     1037    PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0);
    10381038    if (pThis->dma_auto)
    10391039    {
    1040         PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
    1041         PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
     1040        PDMDevHlpISASetIrq(pDevIns, pThis->irq, 1);
     1041        PDMDevHlpISASetIrq(pDevIns, pThis->irq, 0);
    10421042    }
    10431043
     
    10571057    sb16SpeakerControl(pThis, 0);
    10581058
    1059     sb16Control(pThis, 0);
     1059    sb16Control(pDevIns, pThis, 0);
    10601060    sb16CmdResetLegacy(pThis);
    10611061}
     
    10841084                            pThis->highspeed = 0;
    10851085                            PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
    1086                             sb16Control(pThis, 0);
     1086                            sb16Control(pDevIns, pThis, 0);
    10871087                        }
    10881088                        else
    1089                             sb16CmdReset(pThis);
     1089                            sb16CmdReset(pDevIns, pThis);
    10901090                    }
    10911091                    pThis->v2x6 = 0;
     
    11031103
    11041104                case 0xb8:              /* Panic */
    1105                     sb16CmdReset(pThis);
     1105                    sb16CmdReset(pDevIns, pThis);
    11061106                    break;
    11071107
    11081108                case 0x39:
    11091109                    dsp_out_data(pThis, 0x38);
    1110                     sb16CmdReset(pThis);
     1110                    sb16CmdReset(pDevIns, pThis);
    11111111                    pThis->v2x6 = 0x39;
    11121112                    break;
     
    11251125            if (0 == pThis->needed_bytes)
    11261126            {
    1127                 sb16HandleCommand(pThis, val);
     1127                sb16HandleCommand(pDevIns, pThis, val);
    11281128#if 0
    11291129                if (0 == pThis->needed_bytes) {
     
    11441144                    {
    11451145                        pThis->needed_bytes = 0;
    1146                         complete (pThis);
     1146                        complete(pDevIns, pThis);
    11471147#if 0
    11481148                        log_dsp (pThis);
     
    16201620        if (0 == pThis->dma_auto)
    16211621        {
    1622             sb16Control(pThis, 0);
     1622            sb16Control(pDevIns, pThis, 0);
    16231623            sb16SpeakerControl(pThis, 0);
    16241624        }
     
    16351635}
    16361636
    1637 static void sb16TimerMaybeStart(PSB16STATE pThis)
     1637static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis)
    16381638{
    16391639    LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
     
    16421642        return;
    16431643
    1644     if (!pThis->pTimerIO)
    1645         return;
    1646 
    16471644    /* Set timer flag. */
    1648     ASMAtomicXchgBool(&pThis->fTimerActive, true);
     1645    ASMAtomicWriteBool(&pThis->fTimerActive, true);
    16491646
    16501647    /* 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 */
    16571659static void sb16TimerMaybeStop(PSB16STATE pThis)
    16581660{
     
    16621664        return;
    16631665
    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);
    16691668}
    16701669
     
    16741673static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    16751674{
    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);
    16821679    bool     fIsPlaying    = false; /* Whether one or more streams are still playing. */
    16831680    bool     fDoTransfer   = false;
    16841681
    1685     pThis->uTimerTSIO = cTicksNow;
     1682    pThis->tsTimerIO = cTicksNow;
    16861683
    16871684    PSB16DRIVER pDrv;
     
    17371734    {
    17381735        /* Kick the timer again. */
    1739         uint64_t cTicks = pThis->cTimerTicksIO;
     1736        uint64_t cTicks = pThis->cTicksTimerIOInterval;
    17401737        /** @todo adjust cTicks down by now much cbOutMin represents. */
    1741         TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);
     1738        PDMDevHlpTimerSet(pDevIns, pThis->hTimerIO, cTicksNow + cTicks);
    17421739    }
    17431740}
     
    17481745static DECLCALLBACK(int) sb16LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    17491746{
     1747    PSB16STATE    pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);
     1748    PCPDMDEVHLPR3 pHlp  = pDevIns->pHlpR3;
    17501749    RT_NOREF(uPass);
    1751     PSB16STATE    pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE);
    1752     PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
    17531750
    17541751    pHlp->pfnSSMPutS32(pSSM, pThis->irqCfg);
     
    18311828 * Worker for sb16LoadExec.
    18321829 */
    1833 static int sb16Load(PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM, PSB16STATE pThis)
    1834 {
     1830static int sb16Load(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PSB16STATE pThis)
     1831{
     1832    PCPDMDEVHLPR3 pHlp  = pDevIns->pHlpR3;
     1833
    18351834    pHlp->pfnSSMGetS32(pSSM, &pThis->irq);
    18361835    pHlp->pfnSSMGetS32(pSSM, &pThis->dma);
     
    18891888    if (pThis->dma_running)
    18901889    {
    1891         sb16CheckAndReOpenOut(pThis);
    1892         sb16Control(pThis, 1);
     1890        sb16CheckAndReOpenOut(pDevIns, pThis);
     1891        sb16Control(pDevIns, pThis, 1);
    18931892        sb16SpeakerControl(pThis, pThis->speaker);
    18941893    }
     
    19451944        return VINF_SUCCESS;
    19461945
    1947     return sb16Load(pHlp, pSSM, pThis);
     1946    return sb16Load(pDevIns, pSSM, pThis);
    19481947}
    19491948
     
    20142013 * Checks if the output stream needs to be (re-)created and does so if needed.
    20152014 *
    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 */
     2019static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis)
    20202020{
    20212021    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    20452045            sb16CloseOut(pThis);
    20462046
    2047             rc = sb16OpenOut(pThis, &Cfg);
     2047            rc = sb16OpenOut(pDevIns, pThis, &Cfg);
    20482048            AssertRC(rc);
    20492049        }
     
    20562056}
    20572057
    2058 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg)
    2059 {
    2060     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    2061     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    2062 
     2058static 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...
    20632062    LogFlowFuncEnter();
    20642063
     
    20712070
    20722071    /* 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));
    20752076
    20762077    PSB16DRIVER pDrv;
     
    20932094static void sb16CloseOut(PSB16STATE pThis)
    20942095{
    2095     AssertPtrReturnVoid(pThis);
    2096 
     2096    AssertPtrReturnVoid(pThis); /// @todo r=bird: too much panaoia here!
    20972097    LogFlowFuncEnter();
    20982098
    20992099    PSB16DRIVER pDrv;
    21002100    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     2101    {
    21012102        sb16DestroyDrvStream(pThis, pDrv);
     2103    }
    21022104
    21032105    LogFlowFuncLeave();
     
    23022304    sb16MixerReset(pThis);
    23032305    sb16SpeakerControl(pThis, 0);
    2304     sb16Control(pThis, 0);
     2306    sb16Control(pDevIns, pThis, 0);
    23052307    sb16CmdResetLegacy(pThis);
    23062308}
     
    24052407    if (RT_FAILURE(rc))
    24062408        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."));
    24072413
    24082414    /*
     
    24182424     * Create timers.
    24192425     */
    2420     rc = PDMDevHlpTMTimerCreate(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);
    24222428    AssertRCReturn(rc, rc);
    2423     rc = PDMDevHlpTMTimerCreate(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);
    24252431    AssertRCReturn(rc, rc);
    2426     pThis->cTimerTicksIO = TMTimerGetFreq(pThis->pTimerIO) / uTimerHz;
    2427     pThis->uTimerTSIO    = TMTimerGet(pThis->pTimerIO);
    2428     LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicksIO, 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));
    24292435
    24302436    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette