Changeset 68712 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Sep 11, 2017 10:06:06 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r68499 r68712 392 392 /** R3 Pointer to the device instance. */ 393 393 PPDMDEVINSR3 pDevInsR3; 394 /** Critical section protecting the AC'97 state. */ 395 PDMCRITSECT CritSect; 394 396 /** Global Control (Bus Master Control Register). */ 395 397 uint32_t glob_cnt; … … 411 413 /** The timer for pumping data thru the attached LUN drivers. */ 412 414 PTMTIMERR3 pTimer; 413 /** Criticial section for timer. */414 RTCRITSECT csTimer;415 # if HC_ARCH_BITS == 32416 uint32_t Padding0;417 # endif418 415 /** Flag indicating whether the timer is active or not. */ 419 416 bool fTimerActive; … … 452 449 } AC97STATE, *PAC97STATE; 453 450 451 /** 452 * Acquires the AC'97 lock. 453 */ 454 #define DEVAC97_LOCK(a_pThis) \ 455 do { \ 456 int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \ 457 AssertRC(rcLock); \ 458 } while (0) 459 460 /** 461 * Acquires the AC'97 lock or returns. 462 */ 463 # define DEVAC97_LOCK_RETURN(a_pThis, a_rcBusy) \ 464 do { \ 465 int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, a_rcBusy); \ 466 if (rcLock != VINF_SUCCESS) \ 467 { \ 468 AssertRC(rcLock); \ 469 return rcLock; \ 470 } \ 471 } while (0) 472 473 /** 474 * Acquires the AC'97 lock or returns. 475 */ 476 # define DEVAC97_LOCK_RETURN_VOID(a_pThis) \ 477 do { \ 478 int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \ 479 if (rcLock != VINF_SUCCESS) \ 480 { \ 481 AssertRC(rcLock); \ 482 return; \ 483 } \ 484 } while (0) 485 486 /** 487 * Releases the AC'97 lock. 488 */ 489 #define DEVAC97_UNLOCK(a_pThis) \ 490 do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0) 491 492 /** 493 * Acquires the TM lock and AC'97 lock, returns on failure. 494 */ 495 #define DEVAC97_LOCK_BOTH_RETURN_VOID(a_pThis) \ 496 do { \ 497 int rcLock = TMTimerLock((a_pThis)->pTimer, VERR_IGNORED); \ 498 if (rcLock != VINF_SUCCESS) \ 499 { \ 500 AssertRC(rcLock); \ 501 return; \ 502 } \ 503 rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \ 504 if (rcLock != VINF_SUCCESS) \ 505 { \ 506 AssertRC(rcLock); \ 507 TMTimerUnlock((a_pThis)->pTimer); \ 508 return; \ 509 } \ 510 } while (0) 511 512 /** 513 * Acquires the TM lock and AC'97 lock, returns on failure. 514 */ 515 #define DEVAC97_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \ 516 do { \ 517 int rcLock = TMTimerLock((a_pThis)->pTimer, (a_rcBusy)); \ 518 if (rcLock != VINF_SUCCESS) \ 519 return rcLock; \ 520 rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \ 521 if (rcLock != VINF_SUCCESS) \ 522 { \ 523 AssertRC(rcLock); \ 524 TMTimerUnlock((a_pThis)->pTimer); \ 525 return rcLock; \ 526 } \ 527 } while (0) 528 529 /** 530 * Releases the AC'97 lock and TM lock. 531 */ 532 #define DEVAC97_UNLOCK_BOTH(a_pThis) \ 533 do { \ 534 PDMCritSectLeave(&(a_pThis)->CritSect); \ 535 TMTimerUnlock((a_pThis)->pTimer); \ 536 } while (0) 537 454 538 #ifdef VBOX_WITH_STATISTICS 455 539 AssertCompileMemberAlignment(AC97STATE, StatTimer, 8); … … 476 560 static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns); 477 561 #ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS 478 static void ichac97TimerMaybeStart(PAC97STATE pThis); 479 static void ichac97TimerMaybeStop(PAC97STATE pThis); 562 static int ichac97TimerStart(PAC97STATE pThis); 563 static int ichac97TimerMaybeStart(PAC97STATE pThis); 564 static int ichac97TimerStop(PAC97STATE pThis); 565 static int ichac97TimerMaybeStop(PAC97STATE pThis); 480 566 static void ichac97TimerMain(PAC97STATE pThis); 481 567 static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser); … … 1213 1299 } 1214 1300 1215 /* How much (guest output) data is available at the moment for the HDAstream? */1301 /* How much (guest output) data is available at the moment for the AC'97 stream? */ 1216 1302 uint32_t cbUsed = ichac97StreamGetUsed(pStream); 1217 1303 … … 1991 2077 #ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS 1992 2078 /** 2079 * Starts the internal audio device timer. 2080 * 2081 * @return IPRT status code. 2082 * @param pThis AC'97 state. 2083 */ 2084 static int ichac97TimerStart(PAC97STATE pThis) 2085 { 2086 LogFlowFuncEnter(); 2087 2088 DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE); 2089 2090 AssertPtr(pThis->pTimer); 2091 2092 if (!pThis->fTimerActive) 2093 { 2094 LogRel2(("AC97: Starting transfers\n")); 2095 2096 pThis->fTimerActive = true; 2097 2098 /* Start transfers. */ 2099 ichac97TimerMain(pThis); 2100 } 2101 2102 DEVAC97_UNLOCK_BOTH(pThis); 2103 2104 return VINF_SUCCESS; 2105 } 2106 2107 /** 1993 2108 * Starts the internal audio device timer (if not started yet). 1994 2109 * 2110 * @return IPRT status code. 1995 2111 * @param pThis AC'97 state. 1996 2112 */ 1997 static voidichac97TimerMaybeStart(PAC97STATE pThis)2113 static int ichac97TimerMaybeStart(PAC97STATE pThis) 1998 2114 { 1999 2115 LogFlowFuncEnter(); 2000 2116 2001 2117 if (!pThis->pTimer) 2002 return ;2118 return VERR_WRONG_ORDER; 2003 2119 2004 2120 pThis->cStreamsActive++; … … 2006 2122 /* Only start the timer at the first active stream. */ 2007 2123 if (pThis->cStreamsActive == 1) 2008 { 2009 LogRel2(("AC97: Starting transfers\n")); 2010 2011 /* Set timer flag. */ 2012 ASMAtomicXchgBool(&pThis->fTimerActive, true); 2013 2014 /* Update current time timestamp. */ 2015 pThis->uTimerTS = TMTimerGet(pThis->pTimer); 2016 2017 /* Start transfers. */ 2018 ichac97TimerMain(pThis); 2019 } 2124 return ichac97TimerStart(pThis); 2125 2126 return VINF_SUCCESS; 2020 2127 } 2021 2128 … … 2023 2130 * Stops the internal audio device timer. 2024 2131 * 2132 * @return IPRT status code. 2025 2133 * @param pThis AC'97 state. 2026 2134 */ 2027 static voidichac97TimerStop(PAC97STATE pThis)2135 static int ichac97TimerStop(PAC97STATE pThis) 2028 2136 { 2029 2137 LogFlowFuncEnter(); 2030 2138 2031 /* Set timer flag. */ 2032 ASMAtomicXchgBool(&pThis->fTimerActive, false); 2139 if (!pThis->pTimer) /* Only can happen on device construction time, so no locking needed here. */ 2140 return VINF_SUCCESS; 2141 2142 DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE); 2143 2144 if (pThis->fTimerActive) 2145 { 2146 LogRel2(("AC97: Stopping transfers ...\n")); 2147 2148 pThis->fTimerActive = false; 2149 2150 TMTimerStop(pThis->pTimer); 2151 } 2152 2153 DEVAC97_UNLOCK_BOTH(pThis); 2154 2155 return VINF_SUCCESS; 2033 2156 } 2034 2157 … … 2038 2161 * stopped. 2039 2162 * 2163 * @return IPRT status code. 2040 2164 * @param pThis AC'97 state. 2041 2165 */ 2042 static voidichac97TimerMaybeStop(PAC97STATE pThis)2166 static int ichac97TimerMaybeStop(PAC97STATE pThis) 2043 2167 { 2044 2168 LogFlowFuncEnter(); 2045 2169 2046 2170 if (!pThis->pTimer) 2047 return ;2171 return VERR_WRONG_ORDER; 2048 2172 2049 2173 if (pThis->cStreamsActive) /* Function can be called mupltiple times. */ … … 2052 2176 2053 2177 if (pThis->cStreamsActive == 0) 2054 ichac97TimerStop(pThis); 2055 } 2178 return ichac97TimerStop(pThis); 2179 } 2180 2181 return VINF_SUCCESS; 2056 2182 } 2057 2183 … … 2059 2185 * Main routine for the device timer. 2060 2186 * 2061 * @returns IPRT status code.2062 2187 * @param pThis AC'97 state. 2063 2188 */ … … 2065 2190 { 2066 2191 STAM_PROFILE_START(&pThis->StatTimer, a); 2192 2193 DEVAC97_LOCK_BOTH_RETURN_VOID(pThis); 2067 2194 2068 2195 uint64_t cTicksNow = TMTimerGet(pThis->pTimer); … … 2093 2220 } 2094 2221 else 2095 LogRel2(("AC97: Stopping transfers\n")); 2222 LogRel2(("AC97: Stopped transfers\n")); 2223 2224 DEVAC97_UNLOCK_BOTH(pThis); 2096 2225 2097 2226 STAM_PROFILE_STOP(&pThis->StatTimer, a); … … 2136 2265 * 2137 2266 * For an SDO (output) stream this means reading DMA data from the device to 2138 * the HDAstream's internal FIFO buffer.2139 * 2140 * For an SDI (input) stream this is reading audio data from the HDAstream's2267 * the AC'97 stream's internal FIFO buffer. 2268 * 2269 * For an SDI (input) stream this is reading audio data from the AC'97 stream's 2141 2270 * internal FIFO buffer and writing it as DMA data to the device. 2142 2271 * … … 2369 2498 { 2370 2499 RT_NOREF(pDevIns); 2500 2371 2501 PAC97STATE pThis = (PAC97STATE)pvUser; 2502 2503 DEVAC97_LOCK(pThis); 2372 2504 2373 2505 /* Get the index of the NABMBAR port. */ … … 2519 2651 } 2520 2652 2653 DEVAC97_UNLOCK(pThis); 2654 2521 2655 return rc; 2522 2656 } … … 2538 2672 { 2539 2673 RT_NOREF(pDevIns); 2540 PAC97STATE pThis = (PAC97STATE)pvUser; 2674 2675 PAC97STATE pThis = (PAC97STATE)pvUser; 2676 2677 DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE); 2541 2678 2542 2679 /* Get the index of the NABMBAR register. */ … … 2705 2842 } 2706 2843 2844 DEVAC97_UNLOCK_BOTH(pThis); 2845 2707 2846 return VINF_SUCCESS; 2708 2847 } … … 2727 2866 PAC97STATE pThis = (PAC97STATE)pvUser; 2728 2867 2868 DEVAC97_LOCK(pThis); 2869 2729 2870 int rc = VINF_SUCCESS; 2730 2871 … … 2769 2910 } 2770 2911 } 2912 2913 DEVAC97_UNLOCK(pThis); 2771 2914 2772 2915 return rc; … … 2790 2933 RT_NOREF(pDevIns); 2791 2934 PAC97STATE pThis = (PAC97STATE)pvUser; 2935 2936 DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE); 2792 2937 2793 2938 uint32_t uPortIdx = uPort - pThis->IOPortBase[0]; … … 2931 3076 } 2932 3077 3078 DEVAC97_UNLOCK_BOTH(pThis); 3079 2933 3080 return VINF_SUCCESS; 2934 3081 } … … 2942 3089 { 2943 3090 RT_NOREF(cb, enmType); 2944 PAC97STATE pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);2945 RTIOPORT Port = (RTIOPORT)GCPhysAddress;2946 3091 2947 3092 Assert(enmType == PCI_ADDRESS_SPACE_IO); … … 2950 3095 if (iRegion > 1) /* We support 2 regions max. at the moment. */ 2951 3096 return VERR_INVALID_PARAMETER; 3097 3098 PAC97STATE pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev); 3099 RTIOPORT Port = (RTIOPORT)GCPhysAddress; 2952 3100 2953 3101 int rc; … … 3196 3344 AudioMixerSinkReset(pThis->pSinkMicIn); 3197 3345 AudioMixerSinkReset(pThis->pSinkOut); 3346 3347 # ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS 3348 /* 3349 * Stop the timer, if any. 3350 */ 3351 ichac97TimerStop(pThis); 3352 3353 pThis->cStreamsActive = 0; 3354 # endif 3198 3355 } 3199 3356 … … 3218 3375 Assert(RTListIsEmpty(&pThis->lstDrv)); 3219 3376 3220 int rc; 3221 #ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS 3222 rc = RTCritSectDelete(&pThis->csTimer); 3223 #else 3224 rc = VINF_SUCCESS; 3225 #endif 3226 3227 LogFlowFuncLeaveRC(rc); 3228 return rc; 3377 return VINF_SUCCESS; 3229 3378 } 3230 3379 … … 3448 3597 3449 3598 /* 3599 * Use an own critical section for the device instead of the default 3600 * one provided by PDM. This allows fine-grained locking in combination 3601 * with TM when timer-specific stuff is being called in e.g. the MMIO handlers. 3602 */ 3603 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "AC'97"); 3604 AssertRCReturn(rc, rc); 3605 3606 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 3607 AssertRCReturn(rc, rc); 3608 3609 /* 3450 3610 * Initialize data (most of it anyway). 3451 3611 */ … … 3454 3614 pThis->IBase.pfnQueryInterface = ichac97QueryInterface; 3455 3615 3456 /* PCI Device (the assertions will be removed later)*/3616 /* PCI Device */ 3457 3617 PCIDevSetVendorId (&pThis->PciDev, 0x8086); /* 00 ro - intel. */ Assert(pThis->PciDev.abConfig[0x00] == 0x86); Assert(pThis->PciDev.abConfig[0x01] == 0x80); 3458 3618 PCIDevSetDeviceId (&pThis->PciDev, 0x2415); /* 02 ro - 82801 / 82801aa(?). */ Assert(pThis->PciDev.abConfig[0x02] == 0x15); Assert(pThis->PciDev.abConfig[0x03] == 0x24); … … 3669 3829 if (RT_SUCCESS(rc)) 3670 3830 { 3671 rc = RTCritSectInit(&pThis->csTimer); 3672 if (RT_SUCCESS(rc)) 3673 { 3674 /* Create the emulation timer. */ 3675 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis, 3676 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer); 3677 AssertRCReturn(rc, rc); 3678 3679 if (RT_SUCCESS(rc)) 3680 { 3681 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz; 3682 pThis->uTimerTS = TMTimerGet(pThis->pTimer); 3683 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz)); 3684 } 3685 } 3831 /* Create the emulation timer. 3832 * 3833 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's AC'97 driver 3834 * relies on exact (virtual) DMA timing and uses DMA Position Buffers 3835 * instead of the LPIB registers. 3836 */ 3837 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, ichac97Timer, pThis, 3838 TMTIMER_FLAGS_NO_CRIT_SECT, "AC'97 Timer", &pThis->pTimer); 3839 AssertRCReturn(rc, rc); 3840 3841 /* Use our own critcal section for the device timer. 3842 * That way we can control more fine-grained when to lock what. */ 3843 rc = TMR3TimerSetCritSect(pThis->pTimer, &pThis->CritSect); 3844 AssertRCReturn(rc, rc); 3845 3846 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz; 3847 pThis->uTimerTS = TMTimerGet(pThis->pTimer); 3848 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz)); 3686 3849 } 3687 3850 #else /* !VBOX_WITH_AUDIO_AC97_CALLBACKS */
Note:
See TracChangeset
for help on using the changeset viewer.