VirtualBox

Changeset 89753 in vbox


Ignore:
Timestamp:
Jun 16, 2021 10:54:04 PM (3 years ago)
Author:
vboxsync
Message:

DevIchAc97: Don't allow enabling a stream that's already enabled. bugref:9890

File:
1 edited

Legend:

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

    r89752 r89753  
    17191719    pRegs->picb     = 0;
    17201720    pRegs->piv      = 0; /* Note! Because this is also zero, we will actually start transferring with BDLE00. */
    1721     pRegs->cr       = pRegs->cr & AC97_CR_DONT_CLEAR_MASK;
     1721    pRegs->cr      &= AC97_CR_DONT_CLEAR_MASK;
    17221722    pRegs->bd_valid = 0;
    17231723
     
    27022702                     */
    27032703                    case AC97_NABM_OFF_CR:
     2704                    {
    27042705#ifdef IN_RING3
    27052706                        DEVAC97_LOCK(pDevIns, pThis);
    27062707
    2707                         Log3Func(("[SD%RU8] CR <- %#x (cr %#x)\n", pStream->u8SD, u32, pRegs->cr));
    2708                         if (u32 & AC97_CR_RR) /* Busmaster reset. */
     2708                        uint32_t const fCrChanged = pRegs->cr ^ u32;
     2709                        Log3Func(("[SD%RU8] CR <- %#x (was %#x; changed %#x)\n", pStream->u8SD, u32, pRegs->cr, fCrChanged));
     2710
     2711                        /*
     2712                         * Busmaster reset.
     2713                         */
     2714                        if (u32 & AC97_CR_RR)
    27092715                        {
    2710                             Log3Func(("[SD%RU8] Reset\n", pStream->u8SD));
    2711 
    2712                             /* Make sure that Run/Pause Bus Master bit (RPBM) is cleared (0). */
    2713                             Assert((pRegs->cr & AC97_CR_RPBM) == 0);
    2714                             if (pRegs->cr & AC97_CR_RPBM)
    2715                                 ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream, pStreamCC, false /* fEnable */);
     2716                            LogFunc(("[SD%RU8] Reset\n", pStream->u8SD));
     2717
     2718                            /* Make sure that Run/Pause Bus Master bit (RPBM) is cleared (0).
     2719                               3.2.7 in 302349-003 says RPBM be must be clear when resetting
     2720                               and that behavior is undefined if it's set. */
     2721                            ASSERT_GUEST_STMT((pRegs->cr & AC97_CR_RPBM) == 0,
     2722                                              ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream,
     2723                                                                    pStreamCC, false /* fEnable */));
    27162724
    27172725                            ichac97R3StreamReset(pThis, pStream, pStreamCC);
    27182726
    27192727                            ichac97StreamUpdateSR(pDevIns, pThis, pStream, AC97_SR_DCH); /** @todo Do we need to do that? */
     2728
     2729                            DEVAC97_UNLOCK(pDevIns, pThis);
     2730                            break;
     2731                        }
     2732
     2733                        /*
     2734                         * Write the new value to the register and if RPBM didn't change we're done.
     2735                         */
     2736                        pRegs->cr = u32 & AC97_CR_VALID_MASK;
     2737
     2738                        if (!(fCrChanged & AC97_CR_RPBM))
     2739                            DEVAC97_UNLOCK(pDevIns, pThis); /* Probably not so likely, but avoid one extra intentation level. */
     2740                        /*
     2741                         * Pause busmaster.
     2742                         */
     2743                        else if (!(pRegs->cr & AC97_CR_RPBM))
     2744                        {
     2745                            LogFunc(("[SD%RU8] Pause busmaster (disable stream) SR=%#x -> %#x\n",
     2746                                     pStream->u8SD, pRegs->sr, pRegs->sr | AC97_SR_DCH));
     2747                            ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream, pStreamCC, false /* fEnable */);
     2748                            pRegs->sr |= AC97_SR_DCH;
    27202749
    27212750                            DEVAC97_UNLOCK(pDevIns, pThis);
    27222751                        }
     2752                        /*
     2753                         * Run busmaster.
     2754                         */
    27232755                        else
    27242756                        {
    2725                             pRegs->cr = u32 & AC97_CR_VALID_MASK;
    2726 
    2727                             if (!(pRegs->cr & AC97_CR_RPBM))
    2728                             {
    2729                                 Log3Func(("[SD%RU8] Disable\n", pStream->u8SD));
    2730 
    2731                                 ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream, pStreamCC, false /* fEnable */);
    2732 
    2733                                 pRegs->sr |= AC97_SR_DCH;
    2734 
    2735                                 DEVAC97_UNLOCK(pDevIns, pThis);
    2736                             }
    2737                             else
    2738                             {
    2739                                 /** @todo r=bird: How do we prevent the guest from triggering enable more
    2740                                  *        than once?  Only take action if the RBMP bit changed. Duh^3 */
    2741                                 Log3Func(("[SD%RU8] Enable\n", pStream->u8SD));
    2742 
    2743                                 pRegs->sr &= ~AC97_SR_DCH;
    2744 
    2745                                 if (ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC))
    2746                                     ichac97StreamUpdateSR(pDevIns, pThis, pStream, pRegs->sr | AC97_SR_BCIS);
     2757                            LogFunc(("[SD%RU8] Run busmaster (enable stream) SR=%#x -> %#x\n",
     2758                                     pStream->u8SD, pRegs->sr, pRegs->sr & ~AC97_SR_DCH));
     2759                            pRegs->sr &= ~AC97_SR_DCH;
     2760
     2761                            if (ichac97R3StreamFetchNextBdle(pDevIns, pStream, pStreamCC))
     2762                                ichac97StreamUpdateSR(pDevIns, pThis, pStream, pRegs->sr | AC97_SR_BCIS);
    27472763# ifdef LOG_ENABLED
    2748                                 if (LogIsFlowEnabled())
    2749                                     ichac97R3DbgPrintBdl(pDevIns, pThis, pStream, DBGFR3InfoLogHlp(), "ichac97IoPortNabmWrite: ");
     2764                            if (LogIsFlowEnabled())
     2765                                ichac97R3DbgPrintBdl(pDevIns, pThis, pStream, DBGFR3InfoLogHlp(), "ichac97IoPortNabmWrite: ");
    27502766# endif
    2751                                 ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream, pStreamCC, true /* fEnable */);
    2752 
    2753                                 /*
    2754                                  * Arm the DMA timer.  Must drop the AC'97 device lock first as it would
    2755                                  * create a lock order violation with the virtual sync time lock otherwise.
    2756                                  */
    2757                                 /** @todo is ichac97R3StreamTransferUpdate called here? */
    2758                                 uint64_t const cTicksToDeadline = pStreamCC->State.cTransferTicks;
    2759 
    2760                                 DEVAC97_UNLOCK(pDevIns, pThis);
    2761 
    2762                                 /** @todo take down the start time here.  */
    2763                                 int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/);
    2764                                 AssertRC(rc2);
    2765                             }
     2767                            ichac97R3StreamEnable(pDevIns, pThis, pThisCC, pStream, pStreamCC, true /* fEnable */);
     2768
     2769                            /*
     2770                             * Arm the DMA timer.  Must drop the AC'97 device lock first as it would
     2771                             * create a lock order violation with the virtual sync time lock otherwise.
     2772                             */
     2773                            /** @todo is ichac97R3StreamTransferUpdate called here? */
     2774                            uint64_t const cTicksToDeadline = pStreamCC->State.cTransferTicks;
     2775
     2776                            DEVAC97_UNLOCK(pDevIns, pThis);
     2777
     2778                            /** @todo for output streams we could probably service this a little bit
     2779                             *        earlier if we push it, just to reduce the lag...  For HDA we do a
     2780                             *        DMA run immediately after the stream is enabled. */
     2781                            /** @todo take down the start time here.  */
     2782                            int rc2 = PDMDevHlpTimerSetRelative(pDevIns, pStream->hTimer, cTicksToDeadline, NULL /*pu64Now*/);
     2783                            AssertRC(rc2);
    27662784                        }
    27672785#else /* !IN_RING3 */
     
    27692787#endif
    27702788                        break;
     2789                    }
    27712790
    27722791                    /*
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