VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevIchAc97.cpp@ 64393

Last change on this file since 64393 was 64393, checked in by vboxsync, 8 years ago

PDMPCIDEV: s/config/abConfig/ everywhere, removing the legacy alias.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 106.7 KB
Line 
1/* $Id: DevIchAc97.cpp 64393 2016-10-24 14:42:05Z vboxsync $ */
2/** @file
3 * DevIchAc97 - VBox ICH AC97 Audio Controller.
4 */
5
6/*
7 * Copyright (C) 2006-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_AC97
23#include <VBox/log.h>
24#include <VBox/vmm/pdmdev.h>
25#include <VBox/vmm/pdmaudioifs.h>
26
27#include <iprt/assert.h>
28#ifdef IN_RING3
29# ifdef DEBUG
30# include <iprt/file.h>
31# endif
32# include <iprt/mem.h>
33# include <iprt/string.h>
34# include <iprt/uuid.h>
35#endif
36
37#include "VBoxDD.h"
38
39#include "AudioMixBuffer.h"
40#include "AudioMixer.h"
41#include "DrvAudio.h"
42
43
44/*********************************************************************************************************************************
45* Defined Constants And Macros *
46*********************************************************************************************************************************/
47
48#if 0
49/*
50 * AC97_DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
51 * to a file on the host. Be sure to adjust AC97_DEBUG_DUMP_PCM_DATA_PATH
52 * to your needs before using this!
53 */
54# define AC97_DEBUG_DUMP_PCM_DATA
55# ifdef RT_OS_WINDOWS
56# define AC97_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
57# else
58# define AC97_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
59# endif
60#endif
61
62/** Current saved state version. */
63#define AC97_SSM_VERSION 1
64
65/** Timer frequency (in Hz) */
66#define AC97_TIMER_HZ 200
67
68#define AC97_SR_FIFOE RT_BIT(4) /* rwc, FIFO error. */
69#define AC97_SR_BCIS RT_BIT(3) /* rwc, Buffer completion interrupt status. */
70#define AC97_SR_LVBCI RT_BIT(2) /* rwc, Last valid buffer completion interrupt. */
71#define AC97_SR_CELV RT_BIT(1) /* ro, Current equals last valid. */
72#define AC97_SR_DCH RT_BIT(0) /* ro, Controller halted. */
73#define AC97_SR_VALID_MASK (RT_BIT(5) - 1)
74#define AC97_SR_WCLEAR_MASK (AC97_SR_FIFOE | AC97_SR_BCIS | AC97_SR_LVBCI)
75#define AC97_SR_RO_MASK (AC97_SR_DCH | AC97_SR_CELV)
76#define AC97_SR_INT_MASK (AC97_SR_FIFOE | AC97_SR_BCIS | AC97_SR_LVBCI)
77
78#define AC97_CR_IOCE RT_BIT(4) /* rw, Interrupt On Completion Enable. */
79#define AC97_CR_FEIE RT_BIT(3) /* rw FIFO Error Interrupt Enable. */
80#define AC97_CR_LVBIE RT_BIT(2) /* rw Last Valid Buffer Interrupt Enable. */
81#define AC97_CR_RR RT_BIT(1) /* rw Reset Registers. */
82#define AC97_CR_RPBM RT_BIT(0) /* rw Run/Pause Bus Master. */
83#define AC97_CR_VALID_MASK (RT_BIT(5) - 1)
84#define AC97_CR_DONT_CLEAR_MASK (AC97_CR_IOCE | AC97_CR_FEIE | AC97_CR_LVBIE)
85
86#define AC97_GC_WR 4 /* rw Warm reset. */
87#define AC97_GC_CR 2 /* rw Cold reset. */
88#define AC97_GC_VALID_MASK (RT_BIT(6) - 1)
89
90#define AC97_GS_MD3 RT_BIT(17) /* rw */
91#define AC97_GS_AD3 RT_BIT(16) /* rw */
92#define AC97_GS_RCS RT_BIT(15) /* rwc */
93#define AC97_GS_B3S12 RT_BIT(14) /* ro */
94#define AC97_GS_B2S12 RT_BIT(13) /* ro */
95#define AC97_GS_B1S12 RT_BIT(12) /* ro */
96#define AC97_GS_S1R1 RT_BIT(11) /* rwc */
97#define AC97_GS_S0R1 RT_BIT(10) /* rwc */
98#define AC97_GS_S1CR RT_BIT(9) /* ro */
99#define AC97_GS_S0CR RT_BIT(8) /* ro */
100#define AC97_GS_MINT RT_BIT(7) /* ro */
101#define AC97_GS_POINT RT_BIT(6) /* ro */
102#define AC97_GS_PIINT RT_BIT(5) /* ro */
103#define AC97_GS_RSRVD (RT_BIT(4)|RT_BIT(3))
104#define AC97_GS_MOINT RT_BIT(2) /* ro */
105#define AC97_GS_MIINT RT_BIT(1) /* ro */
106#define AC97_GS_GSCI RT_BIT(0) /* rwc */
107#define AC97_GS_RO_MASK (AC97_GS_B3S12 | \
108 AC97_GS_B2S12 | \
109 AC97_GS_B1S12 | \
110 AC97_GS_S1CR | \
111 AC97_GS_S0CR | \
112 AC97_GS_MINT | \
113 AC97_GS_POINT | \
114 AC97_GS_PIINT | \
115 AC97_GS_RSRVD | \
116 AC97_GS_MOINT | \
117 AC97_GS_MIINT)
118#define AC97_GS_VALID_MASK (RT_BIT(18) - 1)
119#define AC97_GS_WCLEAR_MASK (AC97_GS_RCS|AC97_GS_S1R1|AC97_GS_S0R1|AC97_GS_GSCI)
120
121/** @name Buffer Descriptor (BD).
122 * @{ */
123#define AC97_BD_IOC RT_BIT(31) /**< Interrupt on Completion. */
124#define AC97_BD_BUP RT_BIT(30) /**< Buffer Underrun Policy. */
125
126#define AC97_BD_MAX_LEN_MASK 0xFFFE
127/** @} */
128
129/** @name Extended Audio Status and Control Register (EACS).
130 * @{ */
131#define AC97_EACS_VRA 1 /**< Variable Rate Audio (4.2.1.1). */
132#define AC97_EACS_VRM 8 /**< Variable Rate Mic Audio (4.2.1.1). */
133/** @} */
134
135/** @name Baseline Audio Register Set (BARS).
136 * @{ */
137#define AC97_BARS_VOL_MASK 0x1f /**< Volume mask for the Baseline Audio Register Set (5.7.2). */
138#define AC97_BARS_VOL_STEPS 31 /**< Volume steps for the Baseline Audio Register Set (5.7.2). */
139#define AC97_BARS_VOL_MUTE_SHIFT 15 /**< Mute bit shift for the Baseline Audio Register Set (5.7.2). */
140/** @} */
141
142/* AC'97 uses 1.5dB steps, we use 0.375dB steps: 1 AC'97 step equals 4 PDM steps. */
143#define AC97_DB_FACTOR 4
144
145#define AC97_REC_MASK 7
146enum
147{
148 AC97_REC_MIC = 0,
149 AC97_REC_CD,
150 AC97_REC_VIDEO,
151 AC97_REC_AUX,
152 AC97_REC_LINE_IN,
153 AC97_REC_STEREO_MIX,
154 AC97_REC_MONO_MIX,
155 AC97_REC_PHONE
156};
157
158enum
159{
160 AC97_Reset = 0x00,
161 AC97_Master_Volume_Mute = 0x02,
162 AC97_Headphone_Volume_Mute = 0x04, /** Also known as AUX, see table 16, section 5.7. */
163 AC97_Master_Volume_Mono_Mute = 0x06,
164 AC97_Master_Tone_RL = 0x08,
165 AC97_PC_BEEP_Volume_Mute = 0x0A,
166 AC97_Phone_Volume_Mute = 0x0C,
167 AC97_Mic_Volume_Mute = 0x0E,
168 AC97_Line_In_Volume_Mute = 0x10,
169 AC97_CD_Volume_Mute = 0x12,
170 AC97_Video_Volume_Mute = 0x14,
171 AC97_Aux_Volume_Mute = 0x16,
172 AC97_PCM_Out_Volume_Mute = 0x18,
173 AC97_Record_Select = 0x1A,
174 AC97_Record_Gain_Mute = 0x1C,
175 AC97_Record_Gain_Mic_Mute = 0x1E,
176 AC97_General_Purpose = 0x20,
177 AC97_3D_Control = 0x22,
178 AC97_AC_97_RESERVED = 0x24,
179 AC97_Powerdown_Ctrl_Stat = 0x26,
180 AC97_Extended_Audio_ID = 0x28,
181 AC97_Extended_Audio_Ctrl_Stat = 0x2A,
182 AC97_PCM_Front_DAC_Rate = 0x2C,
183 AC97_PCM_Surround_DAC_Rate = 0x2E,
184 AC97_PCM_LFE_DAC_Rate = 0x30,
185 AC97_PCM_LR_ADC_Rate = 0x32,
186 AC97_MIC_ADC_Rate = 0x34,
187 AC97_6Ch_Vol_C_LFE_Mute = 0x36,
188 AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
189 AC97_Vendor_Reserved = 0x58,
190 AC97_AD_Misc = 0x76,
191 AC97_Vendor_ID1 = 0x7c,
192 AC97_Vendor_ID2 = 0x7e
193};
194
195/* Codec models. */
196typedef enum
197{
198 AC97_CODEC_STAC9700 = 0, /* SigmaTel STAC9700 */
199 AC97_CODEC_AD1980, /* Analog Devices AD1980 */
200 AC97_CODEC_AD1981B /* Analog Devices AD1981B */
201} AC97CODEC;
202
203/* Analog Devices miscellaneous regiter bits used in AD1980. */
204#define AC97_AD_MISC_LOSEL RT_BIT(5) /* Surround (rear) goes to line out outputs. */
205#define AC97_AD_MISC_HPSEL RT_BIT(10) /* PCM (front) goes to headphone outputs. */
206
207#define ICHAC97STATE_2_DEVINS(a_pAC97) ((a_pAC97)->pDevInsR3)
208
209enum
210{
211 BUP_SET = RT_BIT(0),
212 BUP_LAST = RT_BIT(1)
213};
214
215/** Emits registers for a specific (Native Audio Bus Master BAR) NABMBAR. */
216#define AC97_NABMBAR_REGS(prefix, off) \
217 enum { \
218 prefix ## _BDBAR = off, /* Buffer Descriptor Base Address */ \
219 prefix ## _CIV = off + 4, /* Current Index Value */ \
220 prefix ## _LVI = off + 5, /* Last Valid Index */ \
221 prefix ## _SR = off + 6, /* Status Register */ \
222 prefix ## _PICB = off + 8, /* Position in Current Buffer */ \
223 prefix ## _PIV = off + 10, /* Prefetched Index Value */ \
224 prefix ## _CR = off + 11 /* Control Register */ \
225 }
226
227#ifndef VBOX_DEVICE_STRUCT_TESTCASE
228typedef enum
229{
230 AC97SOUNDSOURCE_PI_INDEX = 0, /** PCM in */
231 AC97SOUNDSOURCE_PO_INDEX, /** PCM out */
232 AC97SOUNDSOURCE_MC_INDEX, /** Mic in */
233 AC97SOUNDSOURCE_LAST_INDEX
234} AC97SOUNDSOURCE;
235
236AC97_NABMBAR_REGS(PI, AC97SOUNDSOURCE_PI_INDEX * 16);
237AC97_NABMBAR_REGS(PO, AC97SOUNDSOURCE_PO_INDEX * 16);
238AC97_NABMBAR_REGS(MC, AC97SOUNDSOURCE_MC_INDEX * 16);
239#endif
240
241enum
242{
243 /** NABMBAR: Global Control Register. */
244 AC97_GLOB_CNT = 0x2c,
245 /** NABMBAR Global Status. */
246 AC97_GLOB_STA = 0x30,
247 /** Codec Access Semaphore Register. */
248 AC97_CAS = 0x34
249};
250
251#define AC97_PORT2IDX(a_idx) ( ((a_idx) >> 4) & 3 )
252
253
254/*********************************************************************************************************************************
255* Structures and Typedefs *
256*********************************************************************************************************************************/
257
258/**
259 * Buffer Descriptor List Entry (BDLE).
260 */
261typedef struct AC97BDLE
262{
263 uint32_t addr;
264 uint32_t ctl_len;
265} AC97BDLE, *PAC97BDLE;
266
267/**
268 * Bus master register set for an audio stream.
269 */
270typedef struct AC97BMREGS
271{
272 uint32_t bdbar; /** rw 0, Buffer Descriptor List: BAR (Base Address Register). */
273 uint8_t civ; /** ro 0, Current index value. */
274 uint8_t lvi; /** rw 0, Last valid index. */
275 uint16_t sr; /** rw 1, Status register. */
276 uint16_t picb; /** ro 0, Position in current buffer (in samples). */
277 uint8_t piv; /** ro 0, Prefetched index value. */
278 uint8_t cr; /** rw 0, Control register. */
279 int bd_valid; /** Whether current BDLE is initialized or not. */
280 AC97BDLE bd; /** Current Buffer Descriptor List Entry (BDLE). */
281} AC97BMREGS, *PAC97BMREGS;
282
283/**
284 * Internal state of an AC'97 stream.
285 */
286typedef struct AC97STREAMSTATE
287{
288 /** Temporary FIFO write buffer. */
289 R3PTRTYPE(uint8_t *) au8FIFOW;
290 /** Size of the temporary FIFO write buffer. */
291 uint32_t cbFIFOW;
292 /** Current write offset in FIFO write buffer. */
293 uint32_t offFIFOW;
294 uint8_t Padding;
295} AC97STREAMSTATE, *PAC97STREAMSTATE;
296
297/**
298 * Structure for keeping an AC'97 stream state.
299 */
300typedef struct AC97STREAM
301{
302 /** Stream number (SDn). */
303 uint8_t u8Strm;
304 /** Criticial section for this stream. */
305 RTCRITSECT CritSect;
306 /** Bus master registers of this stream. */
307 AC97BMREGS Regs;
308 /** Internal state of this stream. */
309 AC97STREAMSTATE State;
310} AC97STREAM, *PAC97STREAM;
311
312typedef struct AC97INPUTSTREAM
313{
314 /** Mixer handle for input stream. */
315 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
316} AC97INPUTSTREAM, *PAC97INPUTSTREAM;
317
318typedef struct AC97OUTPUTSTREAM
319{
320 /** Mixer handle for output stream. */
321 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
322} AC97OUTPUTSTREAM, *PAC97OUTPUTSTREAM;
323
324/**
325 * Struct for maintaining a host backend driver.
326 */
327typedef struct AC97STATE *PAC97STATE;
328typedef struct AC97DRIVER
329{
330 /** Node for storing this driver in our device driver list of AC97STATE. */
331 RTLISTNODER3 Node;
332 /** Pointer to AC97 controller (state). */
333 R3PTRTYPE(PAC97STATE) pAC97State;
334 /** Driver flags. */
335 PDMAUDIODRVFLAGS Flags;
336 uint32_t PaddingFlags;
337 /** LUN # to which this driver has been assigned. */
338 uint8_t uLUN;
339 /** Whether this driver is in an attached state or not. */
340 bool fAttached;
341 uint8_t Padding[4];
342 /** Pointer to attached driver base interface. */
343 R3PTRTYPE(PPDMIBASE) pDrvBase;
344 /** Audio connector interface to the underlying host backend. */
345 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
346 /** Stream for line input. */
347 AC97INPUTSTREAM LineIn;
348 /** Stream for mic input. */
349 AC97INPUTSTREAM MicIn;
350 /** Stream for output. */
351 AC97OUTPUTSTREAM Out;
352} AC97DRIVER, *PAC97DRIVER;
353
354typedef struct AC97STATE
355{
356 /** The PCI device state. */
357 PDMPCIDEV PciDev;
358 /** R3 Pointer to the device instance. */
359 PPDMDEVINSR3 pDevInsR3;
360 /** Global Control (Bus Master Control Register). */
361 uint32_t glob_cnt;
362 /** Global Status (Bus Master Control Register). */
363 uint32_t glob_sta;
364 /** Codec Access Semaphore Register (Bus Master Control Register). */
365 uint32_t cas;
366 uint32_t last_samp;
367 uint8_t mixer_data[256];
368 /** Stream state for line-in. */
369 AC97STREAM StreamLineIn;
370 /** Stream state for microphone-in. */
371 AC97STREAM StreamMicIn;
372 /** Stream state for output. */
373 AC97STREAM StreamOut;
374 /** Number of active (running) SDn streams. */
375 uint8_t cStreamsActive;
376#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
377 /** The timer for pumping data thru the attached LUN drivers. */
378 PTMTIMERR3 pTimer;
379 /** Criticial section for timer. */
380 RTCRITSECT csTimer;
381# if HC_ARCH_BITS == 32
382 uint32_t Padding0;
383# endif
384 /** Flag indicating whether the timer is active or not. */
385 bool fTimerActive;
386 uint8_t u8Padding1[7];
387 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
388 uint64_t cTimerTicks;
389 /** Timestamp of the last timer callback (ac97Timer).
390 * Used to calculate the time actually elapsed between two timer callbacks. */
391 uint64_t uTimerTS;
392#endif
393#ifdef VBOX_WITH_STATISTICS
394 uint8_t Padding1;
395 STAMPROFILE StatTimer;
396 STAMCOUNTER StatBytesRead;
397 STAMCOUNTER StatBytesWritten;
398#endif
399 /** List of associated LUN drivers (AC97DRIVER). */
400 RTLISTANCHOR lstDrv;
401 /** The device's software mixer. */
402 R3PTRTYPE(PAUDIOMIXER) pMixer;
403 /** Audio sink for PCM output. */
404 R3PTRTYPE(PAUDMIXSINK) pSinkOut;
405 /** Audio sink for line input. */
406 R3PTRTYPE(PAUDMIXSINK) pSinkLineIn;
407 /** Audio sink for microphone input. */
408 R3PTRTYPE(PAUDMIXSINK) pSinkMicIn;
409 uint8_t silence[128];
410 int bup_flag;
411 /** The base interface for LUN\#0. */
412 PDMIBASE IBase;
413 /** Base port of the I/O space region. */
414 RTIOPORT IOPortBase[2];
415 /** Codec model. */
416 uint32_t uCodecModel;
417} AC97STATE, *PAC97STATE;
418
419#ifdef VBOX_WITH_STATISTICS
420AssertCompileMemberAlignment(AC97STATE, StatTimer, 8);
421AssertCompileMemberAlignment(AC97STATE, StatBytesRead, 8);
422AssertCompileMemberAlignment(AC97STATE, StatBytesWritten, 8);
423#endif
424
425#ifndef VBOX_DEVICE_STRUCT_TESTCASE
426
427static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource);
428static void ichac97DestroyOut(PAC97STATE pThis);
429DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
430static int ichac97StreamInit(PAC97STREAM pStream, uint8_t u8Strm);
431static void ichac97StreamDestroy(PAC97STREAM pStream);
432static int ichac97StreamOpen(PAC97STATE pThis, PAC97STREAM pStream);
433static int ichac97StreamReOpen(PAC97STATE pThis, PAC97STREAM pStream);
434static void ichac97StreamClose(PAC97STREAM pStream);
435static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
436#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
437static void ichac97TimerMaybeStart(PAC97STATE pThis);
438static void ichac97TimerMaybeStop(PAC97STATE pThis);
439static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
440#endif
441static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed);
442
443static void ichac97WarmReset(PAC97STATE pThis)
444{
445 NOREF(pThis);
446}
447
448static void ichac97ColdReset(PAC97STATE pThis)
449{
450 NOREF(pThis);
451}
452
453DECLINLINE(PAUDMIXSINK) ichac97IndexToSink(PAC97STATE pThis, uint8_t uIndex)
454{
455 AssertPtrReturn(pThis, NULL);
456
457 switch (uIndex)
458 {
459 case AC97SOUNDSOURCE_PI_INDEX: return pThis->pSinkLineIn; break;
460 case AC97SOUNDSOURCE_PO_INDEX: return pThis->pSinkOut; break;
461 case AC97SOUNDSOURCE_MC_INDEX: return pThis->pSinkMicIn; break;
462 default: break;
463 }
464
465 AssertMsgFailed(("Wrong index %RU8\n", uIndex));
466 return NULL;
467}
468
469/** Fetches the buffer descriptor at _CIV. */
470static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStream)
471{
472 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
473 PAC97BMREGS pRegs = &pStream->Regs;
474
475 uint32_t u32[2];
476
477 PDMDevHlpPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * 8, &u32[0], sizeof(u32));
478 pRegs->bd_valid = 1;
479#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
480# error Please adapt the code (audio buffers are little endian)!
481#else
482 pRegs->bd.addr = RT_H2LE_U32(u32[0] & ~3);
483 pRegs->bd.ctl_len = RT_H2LE_U32(u32[1]);
484#endif
485 pRegs->picb = pRegs->bd.ctl_len & AC97_BD_MAX_LEN_MASK;
486 LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
487 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16,
488 pRegs->bd.ctl_len & AC97_BD_MAX_LEN_MASK,
489 (pRegs->bd.ctl_len & AC97_BD_MAX_LEN_MASK) << 1)); /** @todo r=andy Assumes 16bit samples. */
490}
491
492/**
493 * Update the BM status register
494 */
495static void ichac97StreamUpdateSR(PAC97STATE pThis, PAC97STREAM pStream, uint32_t new_sr)
496{
497 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
498 PAC97BMREGS pRegs = &pStream->Regs;
499
500 bool fSignal = false;
501 int iIRQL = 0;
502
503 uint32_t new_mask = new_sr & AC97_SR_INT_MASK;
504 uint32_t old_mask = pRegs->sr & AC97_SR_INT_MASK;
505
506 static uint32_t const masks[] = { AC97_GS_PIINT, AC97_GS_POINT, AC97_GS_MINT };
507
508 if (new_mask ^ old_mask)
509 {
510 /** @todo Is IRQ deasserted when only one of status bits is cleared? */
511 if (!new_mask)
512 {
513 fSignal = true;
514 iIRQL = 0;
515 }
516 else if ((new_mask & AC97_SR_LVBCI) && (pRegs->cr & AC97_CR_LVBIE))
517 {
518 fSignal = true;
519 iIRQL = 1;
520 }
521 else if ((new_mask & AC97_SR_BCIS) && (pRegs->cr & AC97_CR_IOCE))
522 {
523 fSignal = true;
524 iIRQL = 1;
525 }
526 }
527
528 pRegs->sr = new_sr;
529
530 LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, IRQL=%d\n",
531 pRegs->sr & AC97_SR_BCIS, pRegs->sr & AC97_SR_LVBCI, pRegs->sr, fSignal, iIRQL));
532
533 if (fSignal)
534 {
535 if (iIRQL)
536 pThis->glob_sta |= masks[pStream->u8Strm];
537 else
538 pThis->glob_sta &= ~masks[pStream->u8Strm];
539
540 LogFlowFunc(("Setting IRQ level=%d\n", iIRQL));
541 PDMDevHlpPCISetIrq(pDevIns, 0, iIRQL);
542 }
543}
544
545/**
546 * Returns whether an AC'97 stream is enabled or not.
547 *
548 * @returns IPRT status code.
549 * @param pThis AC'97 device state.
550 * @param pStream Stream to return status for.
551 */
552static bool ichac97StreamIsEnabled(PAC97STATE pThis, PAC97STREAM pStream)
553{
554 AssertPtrReturn(pThis, false);
555 AssertPtrReturn(pStream, false);
556
557 PAUDMIXSINK pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
558 bool fIsEnabled = RT_BOOL(AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING);
559
560 LogFunc(("[SD%RU8] fIsEnabled=%RTbool\n", pStream->u8Strm, fIsEnabled));
561 return fIsEnabled;
562}
563
564static int ichac97StreamEnable(PAC97STATE pThis, PAC97STREAM pStream, bool fEnable)
565{
566 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
567 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
568
569 PAUDMIXSINK pSink = ichac97IndexToSink(pThis, pStream->u8Strm);
570 if (!pSink) /* No sink available (yet)? Bail out early. */
571 return VINF_SUCCESS;
572
573 const bool fIsEnabled = AudioMixerSinkGetStatus(pSink) & AUDMIXSINK_STS_RUNNING;
574
575 LogFunc(("[SD%RU8] fEnable=%RTbool, fIsEnabled=%RTbool, DCH=%RTbool, cStreamsActive=%RU8\n",
576 pStream->u8Strm, fEnable, fIsEnabled, RT_BOOL(pStream->Regs.sr & AC97_SR_DCH), pThis->cStreamsActive));
577
578 int rc = VINF_SUCCESS;
579
580 if (fEnable != fIsEnabled)
581 {
582 rc = ichac97StreamReOpen(pThis, pStream);
583 if (RT_SUCCESS(rc))
584 rc = AudioMixerSinkCtl(ichac97IndexToSink(pThis, pStream->u8Strm),
585 fEnable ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
586 if (RT_SUCCESS(rc))
587 {
588 if (!fEnable)
589 {
590 if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
591 pThis->cStreamsActive--;
592
593#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
594 ichac97TimerMaybeStop(pThis);
595#endif
596 }
597 else
598 {
599 pThis->cStreamsActive++;
600#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
601 ichac97TimerMaybeStart(pThis);
602#endif
603 }
604 }
605 }
606
607 LogFunc(("Returning %Rrc\n", rc));
608 return rc;
609}
610
611static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStream)
612{
613 AssertPtrReturnVoid(pThis);
614 AssertPtrReturnVoid(pStream);
615
616 LogFunc(("[SD%RU8]\n", pStream->u8Strm));
617
618 PAC97BMREGS pRegs = &pStream->Regs;
619
620 pRegs->bdbar = 0;
621 pRegs->civ = 0;
622 pRegs->lvi = 0;
623
624 ichac97StreamEnable(pThis, pStream, false /* fActive */);
625
626 ichac97StreamUpdateSR(pThis, pStream, AC97_SR_DCH); /** @todo Do we need to do that? */
627
628 pRegs->picb = 0;
629 pRegs->piv = 0;
630 pRegs->cr = pRegs->cr & AC97_CR_DONT_CLEAR_MASK;
631 pRegs->bd_valid = 0;
632
633 RT_ZERO(pThis->silence);
634}
635
636static int ichac97StreamInit(PAC97STREAM pStream, uint8_t u8Strm)
637{
638 AssertPtrReturn(pStream, VERR_INVALID_PARAMETER);
639
640 LogFunc(("[SD%RU8] pStream=%p\n", u8Strm, pStream));
641
642 int rc = VINF_SUCCESS;
643
644 pStream->u8Strm = u8Strm;
645 pStream->State.cbFIFOW = _4K; /** @todo Make FIFOW size configurable. */
646 pStream->State.offFIFOW = 0;
647 pStream->State.au8FIFOW = (uint8_t *)RTMemAllocZ(pStream->State.cbFIFOW);
648 if (pStream->State.au8FIFOW)
649 {
650 rc = RTCritSectInit(&pStream->CritSect);
651 }
652 else
653 rc = VERR_NO_MEMORY;
654
655 return rc;
656}
657
658static void ichac97StreamDestroy(PAC97STREAM pStream)
659{
660 LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
661
662 if (pStream->State.au8FIFOW)
663 {
664 Assert(pStream->State.cbFIFOW);
665 RTMemFree(pStream->State.au8FIFOW);
666 pStream->State.au8FIFOW = NULL;
667 }
668
669 pStream->State.cbFIFOW = 0;
670 pStream->State.offFIFOW = 0;
671
672 if (RTCritSectIsInitialized(&pStream->CritSect))
673 RTCritSectDelete(&pStream->CritSect);
674}
675
676static int ichac97StreamsCreate(PAC97STATE pThis)
677{
678 LogFlowFuncEnter();
679
680 /*
681 * Create all sinks and AC'97 streams.
682 */
683
684 /* Line-In. */
685 int rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
686 if (RT_SUCCESS(rc))
687 rc = ichac97StreamInit(&pThis->StreamLineIn, AC97SOUNDSOURCE_PI_INDEX);
688
689 /* Microphone-In. */
690 if (RT_SUCCESS(rc))
691 {
692 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
693 if (RT_SUCCESS(rc))
694 rc = ichac97StreamInit(&pThis->StreamMicIn, AC97SOUNDSOURCE_MC_INDEX);
695 }
696
697 /* Output. */
698 if (RT_SUCCESS(rc))
699 {
700 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOut);
701 if (RT_SUCCESS(rc))
702 rc = ichac97StreamInit(&pThis->StreamOut, AC97SOUNDSOURCE_PO_INDEX);
703 }
704
705 /*
706 * Open all streams with the current AC'97 mixer settings.
707 */
708 if (RT_SUCCESS(rc))
709 {
710 rc = ichac97StreamOpen (pThis, &pThis->StreamLineIn);
711 if (RT_SUCCESS(rc))
712 {
713 rc = ichac97StreamOpen (pThis, &pThis->StreamMicIn);
714 if (RT_SUCCESS(rc))
715 {
716 rc = ichac97StreamOpen(pThis, &pThis->StreamOut);
717 }
718 }
719 }
720
721 LogFlowFunc(("Returning %Rrc\n", rc));
722 return rc;
723}
724
725static void ichac97StreamsDestroy(PAC97STATE pThis)
726{
727 LogFlowFuncEnter();
728
729 ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_LINE);
730 ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_MIC);
731 ichac97DestroyOut(pThis);
732
733 ichac97StreamDestroy(&pThis->StreamLineIn);
734 ichac97StreamDestroy(&pThis->StreamMicIn);
735 ichac97StreamDestroy(&pThis->StreamOut);
736}
737
738static void ichac97MixerSet(PAC97STATE pThis, uint8_t uMixerIdx, uint16_t uVal)
739{
740 if (size_t(uMixerIdx + 2) > sizeof(pThis->mixer_data))
741 {
742 AssertMsgFailed(("Index %RU8 out of bounds(%zu)\n", uMixerIdx, sizeof(pThis->mixer_data)));
743 return;
744 }
745
746 pThis->mixer_data[uMixerIdx + 0] = RT_LO_U8(uVal);
747 pThis->mixer_data[uMixerIdx + 1] = RT_HI_U8(uVal);
748}
749
750static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t uMixerIdx)
751{
752 uint16_t uVal;
753
754 if (size_t(uMixerIdx + 2) > sizeof(pThis->mixer_data))
755 {
756 AssertMsgFailed(("Index %RU8 out of bounds (%zu)\n", uMixerIdx, sizeof(pThis->mixer_data)));
757 uVal = UINT16_MAX;
758 }
759 else
760 uVal = RT_MAKE_U16(pThis->mixer_data[uMixerIdx + 0], pThis->mixer_data[uMixerIdx + 1]);
761
762 return uVal;
763}
764
765static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
766{
767 AssertPtrReturnVoid(pThis);
768
769 LogFlowFuncEnter();
770
771 switch (enmRecSource)
772 {
773 case PDMAUDIORECSOURCE_MIC:
774 AudioMixerSinkDestroy(pThis->pSinkMicIn);
775 pThis->pSinkMicIn = NULL;
776 break;
777
778 case PDMAUDIORECSOURCE_LINE:
779 AudioMixerSinkDestroy(pThis->pSinkLineIn);
780 pThis->pSinkLineIn = NULL;
781 break;
782
783 default:
784 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
785 return;
786 }
787
788 PAC97DRIVER pDrv;
789 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
790 {
791 PAC97INPUTSTREAM pStream;
792 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
793 pStream = &pDrv->MicIn;
794 else
795 pStream = &pDrv->LineIn;
796
797 pStream->pMixStrm = NULL;
798 }
799}
800
801static void ichac97DestroyOut(PAC97STATE pThis)
802{
803 AssertPtrReturnVoid(pThis);
804
805 LogFlowFuncEnter();
806
807 AudioMixerSinkDestroy(pThis->pSinkOut);
808 pThis->pSinkOut = NULL;
809
810 PAC97DRIVER pDrv;
811 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
812 {
813 pDrv->Out.pMixStrm = NULL;
814 }
815}
816
817static int ichac97CreateIn(PAC97STATE pThis,
818 const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg)
819{
820 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
821 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
822 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
823
824 PAUDMIXSINK pSink;
825 switch (enmRecSource)
826 {
827 case PDMAUDIORECSOURCE_MIC:
828 pSink = pThis->pSinkMicIn;
829 break;
830 case PDMAUDIORECSOURCE_LINE:
831 pSink = pThis->pSinkLineIn;
832 break;
833 default:
834 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
835 return VERR_NOT_SUPPORTED;
836 }
837
838 /* Update the sink's format. */
839 PDMAUDIOPCMPROPS PCMProps;
840 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps);
841 if (RT_SUCCESS(rc))
842 rc = AudioMixerSinkSetFormat(pSink, &PCMProps);
843
844 if (RT_FAILURE(rc))
845 return rc;
846
847 PAC97DRIVER pDrv;
848 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
849 {
850 if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s", pDrv->uLUN, pszName))
851 {
852 rc = VERR_BUFFER_OVERFLOW;
853 break;
854 }
855
856 PAC97INPUTSTREAM pStream;
857 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
858 pStream = &pDrv->MicIn;
859 else
860 pStream = &pDrv->LineIn;
861
862 AudioMixerSinkRemoveStream(pSink, pStream->pMixStrm);
863
864 AudioMixerStreamDestroy(pStream->pMixStrm);
865 pStream->pMixStrm = NULL;
866
867 int rc2 = AudioMixerSinkCreateStream(pSink, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStream->pMixStrm);
868 if (RT_SUCCESS(rc2))
869 {
870 rc2 = AudioMixerSinkAddStream(pSink, pStream->pMixStrm);
871 LogFlowFunc(("LUN#%RU8: Created input \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
872 }
873
874 if (RT_SUCCESS(rc))
875 rc = rc2;
876 }
877
878 LogFlowFuncLeaveRC(rc);
879 return rc;
880}
881
882static int ichac97CreateOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
883{
884 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
885 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
886 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
887
888 LogFunc(("%s\n", pszName));
889
890 /* Update the sink's format. */
891 PDMAUDIOPCMPROPS PCMProps;
892 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps);
893 if (RT_SUCCESS(rc))
894 rc = AudioMixerSinkSetFormat(pThis->pSinkOut, &PCMProps);
895
896 if (RT_FAILURE(rc))
897 return rc;
898
899 PAC97DRIVER pDrv;
900 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
901 {
902 if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
903 pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"))
904 {
905 rc = VERR_BUFFER_OVERFLOW;
906 break;
907 }
908
909 AudioMixerSinkRemoveStream(pThis->pSinkOut, pDrv->Out.pMixStrm);
910
911 AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
912 pDrv->Out.pMixStrm = NULL;
913
914 int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOut, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
915 if (RT_SUCCESS(rc2))
916 {
917 rc2 = AudioMixerSinkAddStream(pThis->pSinkOut, pDrv->Out.pMixStrm);
918 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
919 }
920
921 if (RT_SUCCESS(rc))
922 rc = rc2;
923 }
924
925 LogFlowFuncLeaveRC(rc);
926 return rc;
927}
928
929/**
930 * Opens an AC'97 stream, extended version.
931 *
932 * @returns IPRT status code.
933 * @param pThis AC'97 device state.
934 * @param pStream Stream to initialize.
935 * @param pCfg Audio stream configuration to initialize the stream with.
936 */
937static int ichac97StreamOpenEx(PAC97STATE pThis, PAC97STREAM pStream, PPDMAUDIOSTREAMCFG pCfg)
938{
939 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
940 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
941 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
942
943 LogFunc(("[SD%RU8] pCfg=%p\n", pStream->u8Strm, pCfg));
944
945 int rc;
946 switch (pStream->u8Strm)
947 {
948 case AC97SOUNDSOURCE_PI_INDEX:
949 rc = ichac97CreateIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE, pCfg);
950 break;
951
952 case AC97SOUNDSOURCE_MC_INDEX:
953 rc = ichac97CreateIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);
954 break;
955
956 case AC97SOUNDSOURCE_PO_INDEX:
957 rc = ichac97CreateOut(pThis, "ac97.po", pCfg);
958 break;
959
960 default:
961 AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
962 break;
963 }
964
965 if (RT_FAILURE(rc))
966 LogRel2(("AC97: Error opening stream #%RU8, rc=%Rrc\n", pStream->u8Strm, rc));
967
968 LogFlowFuncLeaveRC(rc);
969 return rc;
970}
971
972/**
973 * Opens an AC'97 stream.
974 * This will open an AC'97 stream with 2 (stereo) channels, 16-bit samples and
975 * the last set sample rate in the AC'97 mixer for this stream.
976 *
977 * @returns IPRT status code.
978 * @param pThis AC'97 device state.
979 * @param pStream Stream to initialize.
980 */
981static int ichac97StreamOpen(PAC97STATE pThis, PAC97STREAM pStream)
982{
983 int rc = VINF_SUCCESS;
984
985 LogFunc(("[SD%RU8]\n", pStream->u8Strm));
986
987 PDMAUDIOSTREAMCFG streamCfg;
988 RT_ZERO(streamCfg);
989
990 switch (pStream->u8Strm)
991 {
992 case AC97SOUNDSOURCE_PI_INDEX:
993 streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_LR_ADC_Rate);
994 streamCfg.enmDir = PDMAUDIODIR_IN;
995 streamCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE;
996 break;
997
998 case AC97SOUNDSOURCE_MC_INDEX:
999 streamCfg.uHz = ichac97MixerGet(pThis, AC97_MIC_ADC_Rate);
1000 streamCfg.enmDir = PDMAUDIODIR_IN;
1001 streamCfg.DestSource.Source = PDMAUDIORECSOURCE_MIC;
1002 break;
1003
1004 case AC97SOUNDSOURCE_PO_INDEX:
1005 streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_Front_DAC_Rate);
1006 streamCfg.enmDir = PDMAUDIODIR_OUT;
1007 streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
1008 break;
1009
1010 default:
1011 rc = VERR_NOT_SUPPORTED;
1012 break;
1013 }
1014
1015 if (RT_SUCCESS(rc))
1016 {
1017 if (streamCfg.uHz)
1018 {
1019 streamCfg.cChannels = 2;
1020 streamCfg.enmFormat = PDMAUDIOFMT_S16;
1021 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
1022
1023 rc = ichac97StreamOpenEx(pThis, pStream, &streamCfg);
1024 }
1025 else
1026 rc = VERR_INVALID_PARAMETER;
1027 }
1028
1029 LogFlowFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8Strm, rc));
1030 return rc;
1031}
1032
1033static void ichac97StreamClose(PAC97STREAM pStream)
1034{
1035 RT_NOREF(pStream);
1036
1037 LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
1038}
1039
1040/**
1041 * Re-opens an AC'97 stream on the backend side with the current AC'97 mixer
1042 * settings for this stream.
1043 *
1044 * @returns IPRT status code.
1045 * @param pThis AC'97 device state.
1046 * @param pStream Stream to re-open.
1047 */
1048static int ichac97StreamReOpen(PAC97STATE pThis, PAC97STREAM pStream)
1049{
1050 LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
1051
1052 ichac97StreamClose(pStream);
1053
1054 return ichac97StreamOpen(pThis, pStream);
1055}
1056
1057static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrm)
1058{
1059 AssertPtrReturnVoid(pThis);
1060 AssertPtrReturnVoid(pStrm);
1061
1062 LogFlowFunc(("[SD%RU8]\n", pStrm->u8Strm));
1063
1064 if (pStrm->State.au8FIFOW)
1065 {
1066 Assert(pStrm->State.cbFIFOW);
1067 RT_BZERO(pStrm->State.au8FIFOW, pStrm->State.cbFIFOW);
1068 }
1069
1070 pStrm->State.offFIFOW = 0;
1071}
1072
1073static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL enmMixerCtl, uint32_t uVal)
1074{
1075 bool fCntlMuted;
1076 uint8_t lCntlAtt, rCntlAtt;
1077
1078 /*
1079 * From AC'97 SoundMax Codec AD1981A/AD1981B:
1080 * "Because AC '97 defines 6-bit volume registers, to maintain compatibility whenever the
1081 * D5 or D13 bits are set to 1, their respective lower five volume bits are automatically
1082 * set to 1 by the Codec logic. On readback, all lower 5 bits will read ones whenever
1083 * these bits are set to 1."
1084 *
1085 * Linux ALSA depends on this behavior.
1086 */
1087 /// @todo Does this apply to anything other than the master volume control?
1088 if (uVal & RT_BIT(5))
1089 uVal |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0);
1090 if (uVal & RT_BIT(13))
1091 uVal |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
1092
1093 fCntlMuted = (uVal >> AC97_BARS_VOL_MUTE_SHIFT) & 1;
1094 lCntlAtt = (uVal >> 8) & AC97_BARS_VOL_MASK;
1095 rCntlAtt = uVal & AC97_BARS_VOL_MASK;
1096
1097 /* For the master and headphone volume, 0 corresponds to 0dB attenuation. For the other
1098 * volume controls, 0 means 12dB gain and 8 means unity gain.
1099 */
1100 if (index != AC97_Master_Volume_Mute && index != AC97_Headphone_Volume_Mute)
1101 {
1102#ifndef VBOX_WITH_AC97_GAIN_SUPPORT
1103 /* NB: Currently there is no gain support, only attenuation. */
1104 lCntlAtt = lCntlAtt < 8 ? 0 : lCntlAtt - 8;
1105 rCntlAtt = rCntlAtt < 8 ? 0 : rCntlAtt - 8;
1106#endif
1107 }
1108 Assert(lCntlAtt <= 255 / AC97_DB_FACTOR);
1109 Assert(rCntlAtt <= 255 / AC97_DB_FACTOR);
1110
1111 LogFunc(("index=0x%x, uVal=%RU32, enmMixerCtl=%RU32\n", index, uVal, enmMixerCtl));
1112 LogFunc(("lAtt=%RU8, rAtt=%RU8 ", lCntlAtt, rCntlAtt));
1113
1114 /*
1115 * For AC'97 volume controls, each additional step means -1.5dB attenuation with
1116 * zero being maximum. In contrast, we're internally using 255 (PDMAUDIO_VOLUME_MAX)
1117 * steps, each -0.375dB, where 0 corresponds to -96dB and 255 corresponds to 0dB.
1118 */
1119 uint8_t lVol = PDMAUDIO_VOLUME_MAX - lCntlAtt * AC97_DB_FACTOR;
1120 uint8_t rVol = PDMAUDIO_VOLUME_MAX - rCntlAtt * AC97_DB_FACTOR;
1121
1122 Log(("-> fMuted=%RTbool, lVol=%RU8, rVol=%RU8\n", fCntlMuted, lVol, rVol));
1123
1124 int rc = VINF_SUCCESS;
1125
1126 if (pThis->pMixer) /* Device can be in reset state, so no mixer available. */
1127 {
1128 PDMAUDIOVOLUME Vol = { fCntlMuted, lVol, rVol };
1129 PAUDMIXSINK pSink = NULL;
1130
1131 switch (enmMixerCtl)
1132 {
1133 case PDMAUDIOMIXERCTL_VOLUME_MASTER:
1134 rc = AudioMixerSetMasterVolume(pThis->pMixer, &Vol);
1135 break;
1136
1137 case PDMAUDIOMIXERCTL_FRONT:
1138 pSink = pThis->pSinkOut;
1139 break;
1140
1141 case PDMAUDIOMIXERCTL_MIC_IN:
1142 pSink = pThis->pSinkMicIn;
1143 break;
1144
1145 case PDMAUDIOMIXERCTL_LINE_IN:
1146 pSink = pThis->pSinkLineIn;
1147 break;
1148
1149 default:
1150 AssertFailed();
1151 rc = VERR_NOT_SUPPORTED;
1152 break;
1153 }
1154
1155 if (pSink)
1156 rc = AudioMixerSinkSetVolume(pSink, &Vol);
1157 }
1158
1159 ichac97MixerSet(pThis, index, uVal);
1160
1161 if (RT_FAILURE(rc))
1162 LogFlowFunc(("Failed with %Rrc\n", rc));
1163
1164 return rc;
1165}
1166
1167static PDMAUDIORECSOURCE ichac97IndextoRecSource(uint8_t i)
1168{
1169 switch (i)
1170 {
1171 case AC97_REC_MIC: return PDMAUDIORECSOURCE_MIC;
1172 case AC97_REC_CD: return PDMAUDIORECSOURCE_CD;
1173 case AC97_REC_VIDEO: return PDMAUDIORECSOURCE_VIDEO;
1174 case AC97_REC_AUX: return PDMAUDIORECSOURCE_AUX;
1175 case AC97_REC_LINE_IN: return PDMAUDIORECSOURCE_LINE;
1176 case AC97_REC_PHONE: return PDMAUDIORECSOURCE_PHONE;
1177 default:
1178 break;
1179 }
1180
1181 LogFlowFunc(("Unknown record source %d, using MIC\n", i));
1182 return PDMAUDIORECSOURCE_MIC;
1183}
1184
1185static uint8_t ichac97RecSourceToIndex(PDMAUDIORECSOURCE rs)
1186{
1187 switch (rs)
1188 {
1189 case PDMAUDIORECSOURCE_MIC: return AC97_REC_MIC;
1190 case PDMAUDIORECSOURCE_CD: return AC97_REC_CD;
1191 case PDMAUDIORECSOURCE_VIDEO: return AC97_REC_VIDEO;
1192 case PDMAUDIORECSOURCE_AUX: return AC97_REC_AUX;
1193 case PDMAUDIORECSOURCE_LINE: return AC97_REC_LINE_IN;
1194 case PDMAUDIORECSOURCE_PHONE: return AC97_REC_PHONE;
1195 default:
1196 break;
1197 }
1198
1199 LogFlowFunc(("Unknown audio recording source %d using MIC\n", rs));
1200 return AC97_REC_MIC;
1201}
1202
1203static void ichac97RecordSelect(PAC97STATE pThis, uint32_t val)
1204{
1205 uint8_t rs = val & AC97_REC_MASK;
1206 uint8_t ls = (val >> 8) & AC97_REC_MASK;
1207 PDMAUDIORECSOURCE ars = ichac97IndextoRecSource(rs);
1208 PDMAUDIORECSOURCE als = ichac97IndextoRecSource(ls);
1209 rs = ichac97RecSourceToIndex(ars);
1210 ls = ichac97RecSourceToIndex(als);
1211 ichac97MixerSet(pThis, AC97_Record_Select, rs | (ls << 8));
1212}
1213
1214static int ichac97MixerReset(PAC97STATE pThis)
1215{
1216 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
1217
1218 LogFlowFuncEnter();
1219
1220 RT_ZERO(pThis->mixer_data);
1221
1222 /* Note: Make sure to reset all registers first before bailing out on error. */
1223
1224 ichac97MixerSet(pThis, AC97_Reset , 0x0000); /* 6940 */
1225 ichac97MixerSet(pThis, AC97_Master_Volume_Mono_Mute , 0x8000);
1226 ichac97MixerSet(pThis, AC97_PC_BEEP_Volume_Mute , 0x0000);
1227
1228 ichac97MixerSet(pThis, AC97_Phone_Volume_Mute , 0x8008);
1229 ichac97MixerSet(pThis, AC97_Mic_Volume_Mute , 0x8008);
1230 ichac97MixerSet(pThis, AC97_CD_Volume_Mute , 0x8808);
1231 ichac97MixerSet(pThis, AC97_Aux_Volume_Mute , 0x8808);
1232 ichac97MixerSet(pThis, AC97_Record_Gain_Mic_Mute , 0x8000);
1233 ichac97MixerSet(pThis, AC97_General_Purpose , 0x0000);
1234 ichac97MixerSet(pThis, AC97_3D_Control , 0x0000);
1235 ichac97MixerSet(pThis, AC97_Powerdown_Ctrl_Stat , 0x000f);
1236
1237 ichac97MixerSet(pThis, AC97_Extended_Audio_ID , 0x0809);
1238 ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
1239 ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate , 0xbb80);
1240 ichac97MixerSet(pThis, AC97_PCM_Surround_DAC_Rate , 0xbb80);
1241 ichac97MixerSet(pThis, AC97_PCM_LFE_DAC_Rate , 0xbb80);
1242 ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate , 0xbb80);
1243 ichac97MixerSet(pThis, AC97_MIC_ADC_Rate , 0xbb80);
1244
1245 if (pThis->uCodecModel == AC97_CODEC_AD1980)
1246 {
1247 /* Analog Devices 1980 (AD1980) */
1248 ichac97MixerSet(pThis, AC97_Reset , 0x0010); /* Headphones. */
1249 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x4144);
1250 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x5370);
1251 ichac97MixerSet(pThis, AC97_Headphone_Volume_Mute , 0x8000);
1252 }
1253 else if (pThis->uCodecModel == AC97_CODEC_AD1981B)
1254 {
1255 /* Analog Devices 1981B (AD1981B) */
1256 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x4144);
1257 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x5374);
1258 }
1259 else
1260 {
1261 /* Sigmatel 9700 (STAC9700) */
1262 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x8384);
1263 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x7600); /* 7608 */
1264 }
1265 ichac97RecordSelect(pThis, 0);
1266
1267 ichac97MixerSetVolume(pThis, AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME_MASTER, 0x8000);
1268 ichac97MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT, 0x8808);
1269 ichac97MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808);
1270 ichac97MixerSetVolume(pThis, AC97_Mic_Volume_Mute, PDMAUDIOMIXERCTL_MIC_IN, 0x8808);
1271
1272 return VINF_SUCCESS;
1273}
1274
1275/**
1276 * Writes data from the device to the host backends.
1277 *
1278 * @return IPRT status code.
1279 * @param pThis
1280 * @param pStream
1281 * @param cbMax
1282 * @param pcbWritten
1283 */
1284static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
1285{
1286 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1287 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1288 AssertReturn(cbToWrite, VERR_INVALID_PARAMETER);
1289 /* pcbWritten is optional. */
1290
1291 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
1292 PAC97BMREGS pRegs = &pStream->Regs;
1293
1294 uint32_t uAddr = pRegs->bd.addr;
1295
1296 uint32_t cbWrittenTotal = 0;
1297
1298 Log3Func(("PICB=%RU16, cbToWrite=%RU32\n", pRegs->picb, cbToWrite));
1299
1300 uint32_t cbLeft = RT_MIN((uint32_t)(pRegs->picb << 1), cbToWrite); /** @todo r=andy Assumes 16bit sample size. */
1301 if (!cbLeft)
1302 {
1303 if (pcbWritten)
1304 *pcbWritten = 0;
1305 return VINF_EOF;
1306 }
1307
1308 int rc = VINF_SUCCESS;
1309
1310 Assert(pStream->State.offFIFOW <= pStream->State.cbFIFOW);
1311 uint32_t cbFIFOW = pStream->State.cbFIFOW - pStream->State.offFIFOW;
1312 uint8_t *pu8FIFOW = &pStream->State.au8FIFOW[pStream->State.offFIFOW];
1313
1314 uint32_t cbWritten = 0;
1315
1316 while (cbLeft)
1317 {
1318 uint32_t cbToRead = RT_MIN(cbLeft, cbFIFOW);
1319
1320 PDMDevHlpPhysRead(pDevIns, uAddr, pu8FIFOW, cbToRead); /** @todo r=andy Check rc? */
1321
1322#ifdef AC97_DEBUG_DUMP_PCM_DATA
1323 RTFILE fh;
1324 RTFileOpen(&fh, AC97_DEBUG_DUMP_PCM_DATA_PATH "ac97WriteAudio.pcm",
1325 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
1326 RTFileWrite(fh, pu8FIFOW, cbToRead, NULL);
1327 RTFileClose(fh);
1328#endif
1329 /*
1330 * Write data to the mixer sink.
1331 */
1332 rc = AudioMixerSinkWrite(pThis->pSinkOut, AUDMIXOP_COPY, pu8FIFOW, cbToRead, &cbWritten);
1333 if (RT_FAILURE(rc))
1334 break;
1335
1336 /* Advance. */
1337 Assert(cbLeft >= cbWritten);
1338 cbLeft -= cbWritten;
1339 cbWrittenTotal += cbWritten;
1340 uAddr += cbWritten;
1341 Assert(cbWrittenTotal <= cbToWrite);
1342
1343 LogFlowFunc(("%RU32 / %RU32\n", cbWrittenTotal, cbToWrite));
1344 }
1345
1346 /* Set new buffer descriptor address. */
1347 pRegs->bd.addr = uAddr;
1348
1349 if (RT_SUCCESS(rc))
1350 {
1351 if (!cbLeft) /* All data written? */
1352 {
1353 if (cbWritten < 4)
1354 {
1355 AssertMsgFailed(("Unable to save last written sample, cbWritten < 4 (is %RU32)\n", cbWritten));
1356 pThis->last_samp = 0;
1357 }
1358 else
1359 pThis->last_samp = *(uint32_t *)&pStream->State.au8FIFOW[pStream->State.offFIFOW + cbWritten - 4];
1360 }
1361
1362 if (pcbWritten)
1363 *pcbWritten = cbWrittenTotal;
1364 }
1365
1366 if (RT_FAILURE(rc))
1367 LogFlowFunc(("Failed with %Rrc\n", rc));
1368
1369 return rc;
1370}
1371
1372static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
1373{
1374 LogFlowFunc(("cbElapsed=%RU32\n", cbElapsed));
1375
1376 if (!(pThis->bup_flag & BUP_SET))
1377 {
1378 if (pThis->bup_flag & BUP_LAST)
1379 {
1380 unsigned int i;
1381 uint32_t *p = (uint32_t*)pThis->silence;
1382 for (i = 0; i < sizeof(pThis->silence) / 4; i++) /** @todo r=andy Assumes 16-bit samples, stereo. */
1383 *p++ = pThis->last_samp;
1384 }
1385 else
1386 RT_ZERO(pThis->silence);
1387
1388 pThis->bup_flag |= BUP_SET;
1389 }
1390
1391 while (cbElapsed)
1392 {
1393 uint32_t cbToWrite = RT_MIN(cbElapsed, (uint32_t)sizeof(pThis->silence));
1394 uint32_t cbWrittenToStream;
1395
1396 int rc2 = AudioMixerSinkWrite(pThis->pSinkOut, AUDMIXOP_COPY,
1397 pThis->silence, cbToWrite, &cbWrittenToStream);
1398 if (RT_SUCCESS(rc2))
1399 {
1400 if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
1401 LogFlowFunc(("Warning: Only written %RU32 / %RU32 bytes, expect lags\n", cbWrittenToStream, cbToWrite));
1402 }
1403
1404 /* Always report all data as being written;
1405 * backends who were not able to catch up have to deal with it themselves. */
1406 Assert(cbElapsed >= cbToWrite);
1407 cbElapsed -= cbToWrite;
1408 }
1409}
1410
1411static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
1412{
1413 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1414 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1415 AssertReturn(cbToRead, VERR_INVALID_PARAMETER);
1416 /* pcbRead is optional. */
1417
1418 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
1419 PAC97BMREGS pRegs = &pStream->Regs;
1420
1421 /* Select audio sink to process. */
1422 AssertMsg(pStream->u8Strm != AC97SOUNDSOURCE_PO_INDEX, ("Can't read from output\n"));
1423 PAUDMIXSINK pSink = pStream->u8Strm == AC97SOUNDSOURCE_MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
1424 AssertPtr(pSink);
1425
1426 uint32_t cbRead = 0;
1427
1428 cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1),
1429 RT_MIN(pStream->State.cbFIFOW, cbToRead)); /** @todo r=andy Assumes 16bit samples. */
1430
1431 if (!cbToRead)
1432 {
1433 if (pcbRead)
1434 *pcbRead = 0;
1435 return VINF_EOF;
1436 }
1437
1438 int rc;
1439
1440 rc = AudioMixerSinkRead(pSink, AUDMIXOP_BLEND, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbToRead, &cbRead);
1441 if ( RT_SUCCESS(rc)
1442 && cbRead)
1443 {
1444 PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, &pStream->State.au8FIFOW[pStream->State.offFIFOW], cbRead);
1445 pRegs->bd.addr += cbRead;
1446 }
1447
1448 if (RT_SUCCESS(rc))
1449 {
1450 if (!cbRead)
1451 rc = VINF_EOF;
1452
1453 if (pcbRead)
1454 *pcbRead = cbRead;
1455 }
1456
1457 return rc;
1458}
1459
1460#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
1461
1462static void ichac97TimerMaybeStart(PAC97STATE pThis)
1463{
1464 if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
1465 return;
1466
1467 if (!pThis->pTimer)
1468 return;
1469
1470 if (ASMAtomicReadBool(&pThis->fTimerActive) == true) /* Alredy started? */
1471 return;
1472
1473 LogFlowFunc(("Starting timer\n"));
1474
1475 /* Set timer flag. */
1476 ASMAtomicXchgBool(&pThis->fTimerActive, true);
1477
1478 /* Update current time timestamp. */
1479 pThis->uTimerTS = TMTimerGet(pThis->pTimer);
1480
1481 /* Fire off timer. */
1482 TMTimerSet(pThis->pTimer, 0 /* u64Expire */);
1483}
1484
1485static void ichac97TimerMaybeStop(PAC97STATE pThis)
1486{
1487 if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
1488 return;
1489
1490 if (!pThis->pTimer)
1491 return;
1492
1493 if (ASMAtomicReadBool(&pThis->fTimerActive) == false) /* Already stopped? */
1494 return;
1495
1496 LogFlowFunc(("Stopping timer\n"));
1497
1498 /* Set timer flag. */
1499 ASMAtomicXchgBool(&pThis->fTimerActive, false);
1500}
1501
1502static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1503{
1504 RT_NOREF(pDevIns);
1505 PAC97STATE pThis = (PAC97STATE)pvUser;
1506 Assert(pThis == PDMINS_2_DATA(pDevIns, PAC97STATE));
1507 AssertPtr(pThis);
1508
1509 int rc = RTCritSectEnter(&pThis->csTimer);
1510 if (RT_SUCCESS(rc))
1511 {
1512 STAM_PROFILE_START(&pThis->StatTimer, a);
1513
1514 uint64_t cTicksNow = TMTimerGet(pTimer);
1515
1516 /* Update current time timestamp. */
1517 pThis->uTimerTS = cTicksNow;
1518
1519 /* Flag indicating whether to kick the timer again for the next DMA transfer or sink processing. */
1520 bool fDoNextTransfer = false;
1521
1522 uint32_t cbToProcess;
1523
1524 rc = AudioMixerSinkUpdate(pThis->pSinkLineIn);
1525 if (RT_SUCCESS(rc))
1526 {
1527 cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkLineIn);
1528 if (cbToProcess)
1529 rc = ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbToProcess, NULL /* pcbProcessed */);
1530
1531 if (AudioMixerSinkGetStatus(pThis->pSinkLineIn) & AUDMIXSINK_STS_DIRTY)
1532 fDoNextTransfer = true;
1533 }
1534
1535 rc = AudioMixerSinkUpdate(pThis->pSinkMicIn);
1536 if (RT_SUCCESS(rc))
1537 {
1538 cbToProcess = AudioMixerSinkGetReadable(pThis->pSinkMicIn);
1539 if (cbToProcess)
1540 rc = ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbToProcess, NULL /* pcbProcessed */);
1541
1542 if (AudioMixerSinkGetStatus(pThis->pSinkMicIn) & AUDMIXSINK_STS_DIRTY)
1543 fDoNextTransfer = true;
1544 }
1545
1546 rc = AudioMixerSinkUpdate(pThis->pSinkOut);
1547 if (RT_SUCCESS(rc))
1548 {
1549 cbToProcess = AudioMixerSinkGetWritable(pThis->pSinkOut);
1550 if (cbToProcess)
1551 rc = ichac97TransferAudio(pThis, &pThis->StreamOut, cbToProcess, NULL /* pcbProcessed */);
1552
1553 if (AudioMixerSinkGetStatus(pThis->pSinkOut) & AUDMIXSINK_STS_DIRTY)
1554 fDoNextTransfer = true;
1555 }
1556
1557 if (fDoNextTransfer)
1558 {
1559 /* Kick the timer again. */
1560 uint64_t cTicks = pThis->cTimerTicks;
1561 /** @todo adjust cTicks down by now much cbOutMin represents. */
1562 TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
1563 }
1564 else
1565 {
1566 LogFunc(("Stopping timer\n"));
1567 LogRel3(("AC97: Stopping timer\n"));
1568 }
1569
1570 STAM_PROFILE_STOP(&pThis->StatTimer, a);
1571
1572 int rc2 = RTCritSectLeave(&pThis->csTimer);
1573 if (RT_SUCCESS(rc))
1574 rc2 = rc;
1575 }
1576}
1577#endif /* !VBOX_WITH_AUDIO_AC97_CALLBACKS */
1578
1579static int ichac97TransferAudio(PAC97STATE pThis, PAC97STREAM pStream, uint32_t cbToProcess, uint32_t *pcbProcessed)
1580{
1581 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1582 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1583 /* pcbProcessed is optional. */
1584
1585 int rc = RTCritSectEnter(&pStream->CritSect);
1586 if (RT_FAILURE(rc))
1587 return rc;
1588
1589 LogFunc(("[SD%RU8] cbToProcess=%RU32\n", pStream->u8Strm, cbToProcess));
1590
1591 PAC97BMREGS pRegs = &pStream->Regs;
1592
1593 if (pRegs->sr & AC97_SR_DCH) /* Controller halted? */
1594 {
1595 if (pRegs->cr & AC97_CR_RPBM) /* Bus master operation starts. */
1596 {
1597 switch (pStream->u8Strm)
1598 {
1599 case AC97SOUNDSOURCE_PO_INDEX:
1600 ichac97WriteBUP(pThis, cbToProcess);
1601 break;
1602
1603 default:
1604 break;
1605 }
1606 }
1607
1608 if (pcbProcessed)
1609 *pcbProcessed = 0;
1610
1611 Log3Func(("[SD%RU8] Halted\n", pStream->u8Strm));
1612
1613 rc = RTCritSectLeave(&pStream->CritSect);
1614 AssertRC(rc);
1615
1616 return VINF_SUCCESS;
1617 }
1618
1619 /* BCIS flag still set? Skip iteration. */
1620 if (pRegs->sr & AC97_SR_BCIS)
1621 {
1622 Log3Func(("[SD%RU8] BCIS set\n", pStream->u8Strm));
1623
1624 if (pcbProcessed)
1625 *pcbProcessed = 0;
1626
1627 rc = RTCritSectLeave(&pStream->CritSect);
1628 AssertRC(rc);
1629
1630 return VINF_SUCCESS;
1631 }
1632
1633 uint32_t cbLeft = RT_MIN((uint32_t)(pRegs->picb << 1), cbToProcess);
1634 uint32_t cbTotal = 0;
1635
1636 Log3Func(("[SD%RU8] cbLeft=%RU32\n", pStream->u8Strm, cbLeft));
1637
1638 while (cbLeft)
1639 {
1640 if (!pRegs->bd_valid)
1641 {
1642 LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n"));
1643 ichac97StreamFetchBDLE(pThis, pStream);
1644 }
1645
1646 if (!pRegs->picb) /* Got a new buffer descriptor, that is, the position is 0? */
1647 {
1648 LogFlowFunc(("Fresh buffer descriptor %RU8 is empty, addr=%#x, len=%#x, skipping\n",
1649 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len));
1650 if (pRegs->civ == pRegs->lvi)
1651 {
1652 pRegs->sr |= AC97_SR_DCH; /** @todo r=andy Also set CELV? */
1653 pThis->bup_flag = 0;
1654
1655 rc = VINF_EOF;
1656 break;
1657 }
1658
1659 pRegs->sr &= ~AC97_SR_CELV;
1660 pRegs->civ = pRegs->piv;
1661 pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */
1662
1663 ichac97StreamFetchBDLE(pThis, pStream);
1664 continue;
1665 }
1666
1667 uint32_t cbToTransfer, cbTransferred;
1668 switch (pStream->u8Strm)
1669 {
1670 case AC97SOUNDSOURCE_PO_INDEX:
1671 {
1672 cbToTransfer = RT_MIN((uint32_t)(pRegs->picb << 1), cbLeft); /** @todo r=andy Assumes 16bit samples. */
1673
1674 rc = ichac97WriteAudio(pThis, pStream, cbToTransfer, &cbTransferred);
1675 if ( RT_SUCCESS(rc)
1676 && cbTransferred)
1677 {
1678 cbTotal += cbTransferred;
1679 Assert(cbLeft >= cbTransferred);
1680 cbLeft -= cbTransferred;
1681 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
1682 pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
1683 }
1684 break;
1685 }
1686
1687 case AC97SOUNDSOURCE_PI_INDEX:
1688 case AC97SOUNDSOURCE_MC_INDEX:
1689 {
1690 cbToTransfer = RT_MIN((uint32_t)(pRegs->picb << 1), cbLeft); /** @todo r=andy Assumes 16bit samples. */
1691
1692 rc = ichac97ReadAudio(pThis, pStream, cbToTransfer, &cbTransferred);
1693 if ( RT_SUCCESS(rc)
1694 && cbTransferred)
1695 {
1696 cbTotal += cbTransferred;
1697 Assert(cbLeft >= cbTransferred);
1698 cbLeft -= cbTransferred;
1699 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
1700 pRegs->picb -= (cbTransferred >> 1); /** @todo r=andy Assumes 16bit samples. */
1701 }
1702 break;
1703 }
1704
1705 default:
1706 AssertMsgFailed(("Stream #%RU8 not supported\n", pStream->u8Strm));
1707 rc = VERR_NOT_SUPPORTED;
1708 break;
1709 }
1710
1711 LogFlowFunc(("[SD%RU8]: %RU32 / %RU32, rc=%Rrc\n", pStream->u8Strm, cbTotal, cbToProcess, rc));
1712
1713 if (!pRegs->picb)
1714 {
1715 uint32_t new_sr = pRegs->sr & ~AC97_SR_CELV;
1716
1717 if (pRegs->bd.ctl_len & AC97_BD_IOC)
1718 {
1719 new_sr |= AC97_SR_BCIS;
1720 }
1721
1722 if (pRegs->civ == pRegs->lvi)
1723 {
1724 /* Did we run out of data? */
1725 LogFunc(("Underrun CIV (%RU8) == LVI (%RU8)\n", pRegs->civ, pRegs->lvi));
1726
1727 new_sr |= AC97_SR_LVBCI | AC97_SR_DCH | AC97_SR_CELV;
1728 pThis->bup_flag = (pRegs->bd.ctl_len & AC97_BD_BUP) ? BUP_LAST : 0;
1729
1730 rc = VINF_EOF;
1731 }
1732 else
1733 {
1734 pRegs->civ = pRegs->piv;
1735 pRegs->piv = (pRegs->piv + 1) % 32; /** @todo r=andy Define for max BDLEs? */
1736 ichac97StreamFetchBDLE(pThis, pStream);
1737 }
1738
1739 ichac97StreamUpdateSR(pThis, pStream, new_sr);
1740 }
1741
1742 if (/* All data processed? */
1743 rc == VINF_EOF
1744 /* ... or an error occurred? */
1745 || RT_FAILURE(rc))
1746 {
1747 break;
1748 }
1749 }
1750
1751 int rc2 = RTCritSectLeave(&pStream->CritSect);
1752 AssertRC(rc2);
1753
1754 if (RT_SUCCESS(rc))
1755 {
1756 if (pcbProcessed)
1757 *pcbProcessed = cbTotal;
1758 }
1759
1760 LogFlowFuncLeaveRC(rc);
1761 return rc;
1762}
1763
1764/**
1765 * @callback_method_impl{FNIOMIOPORTIN}
1766 */
1767static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32Val, unsigned cbVal)
1768{
1769 RT_NOREF(pDevIns);
1770 PAC97STATE pThis = (PAC97STATE)pvUser;
1771
1772 /* Get the index of the NABMBAR port. */
1773 const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
1774
1775 PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
1776 PAC97BMREGS pRegs = NULL;
1777
1778 if (pStream)
1779 {
1780 pRegs = &pStream->Regs;
1781
1782 int rc2 = RTCritSectEnter(&pStream->CritSect);
1783 AssertRC(rc2);
1784 }
1785
1786 int rc = VINF_SUCCESS;
1787
1788 switch (cbVal)
1789 {
1790 case 1:
1791 {
1792 switch (uPortIdx)
1793 {
1794 case AC97_CAS:
1795 /* Codec Access Semaphore Register */
1796 Log3Func(("CAS %d\n", pThis->cas));
1797 *pu32Val = pThis->cas;
1798 pThis->cas = 1;
1799 break;
1800 case PI_CIV:
1801 case PO_CIV:
1802 case MC_CIV:
1803 /* Current Index Value Register */
1804 *pu32Val = pRegs->civ;
1805 Log3Func(("CIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1806 break;
1807 case PI_LVI:
1808 case PO_LVI:
1809 case MC_LVI:
1810 /* Last Valid Index Register */
1811 *pu32Val = pRegs->lvi;
1812 Log3Func(("LVI[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1813 break;
1814 case PI_PIV:
1815 case PO_PIV:
1816 case MC_PIV:
1817 /* Prefetched Index Value Register */
1818 *pu32Val = pRegs->piv;
1819 Log3Func(("PIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1820 break;
1821 case PI_CR:
1822 case PO_CR:
1823 case MC_CR:
1824 /* Control Register */
1825 *pu32Val = pRegs->cr;
1826 Log3Func(("CR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1827 break;
1828 case PI_SR:
1829 case PO_SR:
1830 case MC_SR:
1831 /* Status Register (lower part) */
1832 *pu32Val = RT_LO_U8(pRegs->sr);
1833 Log3Func(("SRb[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1834 break;
1835 default:
1836 *pu32Val = UINT32_MAX;
1837 LogFunc(("U nabm readb %#x -> %#x\n", Port, *pu32Val));
1838 break;
1839 }
1840 break;
1841 }
1842
1843 case 2:
1844 {
1845 switch (uPortIdx)
1846 {
1847 case PI_SR:
1848 case PO_SR:
1849 case MC_SR:
1850 /* Status Register */
1851 *pu32Val = pRegs->sr;
1852 Log3Func(("SR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1853 break;
1854 case PI_PICB:
1855 case PO_PICB:
1856 case MC_PICB:
1857 /* Position in Current Buffer */
1858 *pu32Val = pRegs->picb;
1859 Log3Func(("PICB[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1860 break;
1861 default:
1862 *pu32Val = UINT32_MAX;
1863 LogFunc(("U nabm readw %#x -> %#x\n", Port, *pu32Val));
1864 break;
1865 }
1866 break;
1867 }
1868
1869 case 4:
1870 {
1871 switch (uPortIdx)
1872 {
1873 case PI_BDBAR:
1874 case PO_BDBAR:
1875 case MC_BDBAR:
1876 /* Buffer Descriptor Base Address Register */
1877 *pu32Val = pRegs->bdbar;
1878 Log3Func(("BMADDR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1879 break;
1880 case PI_CIV:
1881 case PO_CIV:
1882 case MC_CIV:
1883 /* 32-bit access: Current Index Value Register +
1884 * Last Valid Index Register +
1885 * Status Register */
1886 *pu32Val = pRegs->civ | (pRegs->lvi << 8) | (pRegs->sr << 16); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
1887 Log3Func(("CIV LVI SR[%d] -> %#x, %#x, %#x\n",
1888 AC97_PORT2IDX(uPortIdx), pRegs->civ, pRegs->lvi, pRegs->sr));
1889 break;
1890 case PI_PICB:
1891 case PO_PICB:
1892 case MC_PICB:
1893 /* 32-bit access: Position in Current Buffer Register +
1894 * Prefetched Index Value Register +
1895 * Control Register */
1896 *pu32Val = pRegs->picb | (pRegs->piv << 16) | (pRegs->cr << 24); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
1897 Log3Func(("PICB PIV CR[%d] -> %#x %#x %#x %#x\n",
1898 AC97_PORT2IDX(uPortIdx), *pu32Val, pRegs->picb, pRegs->piv, pRegs->cr));
1899 break;
1900 case AC97_GLOB_CNT:
1901 /* Global Control */
1902 *pu32Val = pThis->glob_cnt;
1903 Log3Func(("glob_cnt -> %#x\n", *pu32Val));
1904 break;
1905 case AC97_GLOB_STA:
1906 /* Global Status */
1907 *pu32Val = pThis->glob_sta | AC97_GS_S0CR;
1908 Log3Func(("glob_sta -> %#x\n", *pu32Val));
1909 break;
1910 default:
1911 *pu32Val = UINT32_MAX;
1912 LogFunc(("U nabm readl %#x -> %#x\n", Port, *pu32Val));
1913 break;
1914 }
1915 break;
1916 }
1917
1918 default:
1919 {
1920 AssertFailed();
1921 rc = VERR_IOM_IOPORT_UNUSED;
1922 }
1923 }
1924
1925 if (pStream)
1926 {
1927 int rc2 = RTCritSectLeave(&pStream->CritSect);
1928 AssertRC(rc2);
1929 }
1930
1931 return rc;
1932}
1933
1934/**
1935 * @callback_method_impl{FNIOMIOPORTOUT}
1936 */
1937static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
1938 uint32_t u32Val, unsigned cbVal)
1939{
1940 RT_NOREF(pDevIns);
1941 PAC97STATE pThis = (PAC97STATE)pvUser;
1942
1943 /* Get the index of the NABMBAR register. */
1944 const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
1945
1946 PAC97STREAM pStream = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
1947 PAC97BMREGS pRegs = NULL;
1948
1949 if (pStream)
1950 {
1951 pRegs = &pStream->Regs;
1952
1953 int rc2 = RTCritSectEnter(&pStream->CritSect);
1954 AssertRC(rc2);
1955 }
1956
1957 switch (cbVal)
1958 {
1959 case 1:
1960 {
1961 switch (uPortIdx)
1962 {
1963 /*
1964 * Last Valid Index.
1965 */
1966 case PI_LVI:
1967 case PO_LVI:
1968 case MC_LVI:
1969 {
1970 if ( (pRegs->cr & AC97_CR_RPBM)
1971 && (pRegs->sr & AC97_SR_DCH))
1972 {
1973 pRegs->sr &= ~(AC97_SR_DCH | AC97_SR_CELV);
1974 pRegs->civ = pRegs->piv;
1975 pRegs->piv = (pRegs->piv + 1) % 32;
1976
1977 ichac97StreamFetchBDLE(pThis, pStream);
1978 }
1979 pRegs->lvi = u32Val % 32;
1980 Log3Func(("[SD%RU8] LVI <- %#x\n", pStream->u8Strm, u32Val));
1981 break;
1982 }
1983
1984 /*
1985 * Control Registers.
1986 */
1987 case PI_CR:
1988 case PO_CR:
1989 case MC_CR:
1990 {
1991 if (u32Val & AC97_CR_RR) /* Busmaster reset */
1992 {
1993 ichac97StreamResetBMRegs(pThis, pStream);
1994 }
1995 else
1996 {
1997 pRegs->cr = u32Val & AC97_CR_VALID_MASK;
1998 if (!(pRegs->cr & AC97_CR_RPBM))
1999 {
2000 ichac97StreamEnable(pThis, pStream, false /* fActive */);
2001
2002 pRegs->sr |= AC97_SR_DCH;
2003 }
2004 else
2005 {
2006 pRegs->civ = pRegs->piv;
2007 pRegs->piv = (pRegs->piv + 1) % 32;
2008
2009 pRegs->sr &= ~AC97_SR_DCH;
2010
2011 /* Fetch the initial BDLE descriptor. */
2012 ichac97StreamFetchBDLE(pThis, pStream);
2013
2014 ichac97StreamEnable(pThis, pStream, true /* fActive */);
2015 }
2016 }
2017 Log3Func(("[SD%RU8] CR <- %#x (cr %#x)\n", pStream->u8Strm, u32Val, pRegs->cr));
2018 break;
2019 }
2020
2021 /*
2022 * Status Registers.
2023 */
2024 case PI_SR:
2025 case PO_SR:
2026 case MC_SR:
2027 {
2028 pRegs->sr |= u32Val & ~(AC97_SR_RO_MASK | AC97_SR_WCLEAR_MASK);
2029 ichac97StreamUpdateSR(pThis, pStream, pRegs->sr & ~(u32Val & AC97_SR_WCLEAR_MASK));
2030 Log3Func(("[SD%RU8] SR <- %#x (sr %#x)\n", pStream->u8Strm, u32Val, pRegs->sr));
2031 break;
2032 }
2033
2034 default:
2035 LogFunc(("Unimplemented: %#x <- %#x (Byte)\n", Port, u32Val));
2036 break;
2037 }
2038 break;
2039 }
2040
2041 case 2:
2042 {
2043 switch (uPortIdx)
2044 {
2045 case PI_SR:
2046 case PO_SR:
2047 case MC_SR:
2048 /* Status Register */
2049 pRegs->sr |= u32Val & ~(AC97_SR_RO_MASK | AC97_SR_WCLEAR_MASK);
2050 ichac97StreamUpdateSR(pThis, pStream, pRegs->sr & ~(u32Val & AC97_SR_WCLEAR_MASK));
2051 Log3Func(("[SD%RU8] SR <- %#x (sr %#x)\n", pStream->u8Strm, u32Val, pRegs->sr));
2052 break;
2053 default:
2054 LogFunc(("Unimplemented: %#x <- %#x (Word)\n", Port, u32Val));
2055 break;
2056 }
2057 break;
2058 }
2059
2060 case 4:
2061 {
2062 switch (uPortIdx)
2063 {
2064 case PI_BDBAR:
2065 case PO_BDBAR:
2066 case MC_BDBAR:
2067 /* Buffer Descriptor list Base Address Register */
2068 pRegs->bdbar = u32Val & ~3;
2069 Log3Func(("[SD%RU8] BDBAR <- %#x (bdbar %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->bdbar));
2070 break;
2071 case AC97_GLOB_CNT:
2072 /* Global Control */
2073 if (u32Val & AC97_GC_WR)
2074 ichac97WarmReset(pThis);
2075 if (u32Val & AC97_GC_CR)
2076 ichac97ColdReset(pThis);
2077 if (!(u32Val & (AC97_GC_WR | AC97_GC_CR)))
2078 pThis->glob_cnt = u32Val & AC97_GC_VALID_MASK;
2079 Log3Func(("glob_cnt <- %#x (glob_cnt %#x)\n", u32Val, pThis->glob_cnt));
2080 break;
2081 case AC97_GLOB_STA:
2082 /* Global Status */
2083 pThis->glob_sta &= ~(u32Val & AC97_GS_WCLEAR_MASK);
2084 pThis->glob_sta |= (u32Val & ~(AC97_GS_WCLEAR_MASK | AC97_GS_RO_MASK)) & AC97_GS_VALID_MASK;
2085 Log3Func(("glob_sta <- %#x (glob_sta %#x)\n", u32Val, pThis->glob_sta));
2086 break;
2087 default:
2088 LogFunc(("Unimplemented: %#x <- %#x (DWord)\n", Port, u32Val));
2089 break;
2090 }
2091 break;
2092 }
2093
2094 default:
2095 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
2096 break;
2097 }
2098
2099 if (pStream)
2100 {
2101 int rc2 = RTCritSectLeave(&pStream->CritSect);
2102 AssertRC(rc2);
2103 }
2104
2105 return VINF_SUCCESS;
2106}
2107
2108/**
2109 * @callback_method_impl{FNIOMIOPORTIN}
2110 */
2111static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32Val, unsigned cbVal)
2112{
2113 RT_NOREF(pDevIns);
2114 PAC97STATE pThis = (PAC97STATE)pvUser;
2115
2116 int rc = VINF_SUCCESS;
2117
2118 switch (cbVal)
2119 {
2120 case 1:
2121 {
2122 Log3Func(("U nam readb %#x\n", Port));
2123 pThis->cas = 0;
2124 *pu32Val = UINT32_MAX;
2125 break;
2126 }
2127
2128 case 2:
2129 {
2130 uint32_t index = Port - pThis->IOPortBase[0];
2131 *pu32Val = UINT32_MAX;
2132 pThis->cas = 0;
2133 switch (index)
2134 {
2135 default:
2136 *pu32Val = ichac97MixerGet(pThis, index);
2137 Log3Func(("nam readw %#x -> %#x\n", Port, *pu32Val));
2138 break;
2139 }
2140 break;
2141 }
2142
2143 case 4:
2144 {
2145 Log3Func(("U nam readl %#x\n", Port));
2146 pThis->cas = 0;
2147 *pu32Val = UINT32_MAX;
2148 break;
2149 }
2150
2151 default:
2152 {
2153 AssertFailed();
2154 rc = VERR_IOM_IOPORT_UNUSED;
2155 }
2156 }
2157
2158 return rc;
2159}
2160
2161/**
2162 * @callback_method_impl{FNIOMIOPORTOUT}
2163 */
2164static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32Val, unsigned cbVal)
2165{
2166 RT_NOREF(pDevIns);
2167 PAC97STATE pThis = (PAC97STATE)pvUser;
2168
2169 switch (cbVal)
2170 {
2171 case 1:
2172 {
2173 Log3Func(("U nam writeb %#x <- %#x\n", Port, u32Val));
2174 pThis->cas = 0;
2175 break;
2176 }
2177
2178 case 2:
2179 {
2180 uint32_t index = Port - pThis->IOPortBase[0];
2181 pThis->cas = 0;
2182 switch (index)
2183 {
2184 case AC97_Reset:
2185 ichac97Reset(pThis->CTX_SUFF(pDevIns));
2186 break;
2187 case AC97_Powerdown_Ctrl_Stat:
2188 u32Val &= ~0xf;
2189 u32Val |= ichac97MixerGet(pThis, index) & 0xf;
2190 ichac97MixerSet(pThis, index, u32Val);
2191 break;
2192 case AC97_Master_Volume_Mute:
2193 if (pThis->uCodecModel == AC97_CODEC_AD1980)
2194 {
2195 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AC97_AD_MISC_LOSEL)
2196 break; /* Register controls surround (rear), do nothing. */
2197 }
2198 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME_MASTER, u32Val);
2199 break;
2200 case AC97_Headphone_Volume_Mute:
2201 if (pThis->uCodecModel == AC97_CODEC_AD1980)
2202 {
2203 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AC97_AD_MISC_HPSEL)
2204 {
2205 /* Register controls PCM (front) outputs. */
2206 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME_MASTER, u32Val);
2207 }
2208 }
2209 break;
2210 case AC97_PCM_Out_Volume_Mute:
2211 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_FRONT, u32Val);
2212 break;
2213 case AC97_Line_In_Volume_Mute:
2214 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
2215 break;
2216 case AC97_Record_Select:
2217 ichac97RecordSelect(pThis, u32Val);
2218 break;
2219 case AC97_Vendor_ID1:
2220 case AC97_Vendor_ID2:
2221 LogFunc(("Attempt to write vendor ID to %#x\n", u32Val));
2222 break;
2223 case AC97_Extended_Audio_ID:
2224 LogFunc(("Attempt to write extended audio ID to %#x\n", u32Val));
2225 break;
2226 case AC97_Extended_Audio_Ctrl_Stat:
2227 if (!(u32Val & AC97_EACS_VRA))
2228 {
2229 ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate, 48000);
2230 ichac97StreamReOpen(pThis, &pThis->StreamOut);
2231
2232 ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate, 48000);
2233 ichac97StreamReOpen(pThis, &pThis->StreamLineIn);
2234 }
2235 if (!(u32Val & AC97_EACS_VRM))
2236 {
2237 ichac97MixerSet(pThis, AC97_MIC_ADC_Rate, 48000);
2238 ichac97StreamReOpen(pThis, &pThis->StreamMicIn);
2239 }
2240 LogFunc(("Setting extended audio control to %#x\n", u32Val));
2241 ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, u32Val);
2242 break;
2243 case AC97_PCM_Front_DAC_Rate:
2244 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRA)
2245 {
2246 ichac97MixerSet(pThis, index, u32Val);
2247 LogFunc(("Set front DAC rate to %RU32\n", u32Val));
2248 ichac97StreamReOpen(pThis, &pThis->StreamOut);
2249 }
2250 else
2251 AssertMsgFailed(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
2252 break;
2253 case AC97_MIC_ADC_Rate:
2254 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRM)
2255 {
2256 ichac97MixerSet(pThis, index, u32Val);
2257 LogFunc(("Set MIC ADC rate to %RU32\n", u32Val));
2258 ichac97StreamReOpen(pThis, &pThis->StreamMicIn);
2259 }
2260 else
2261 AssertMsgFailed(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
2262 break;
2263 case AC97_PCM_LR_ADC_Rate:
2264 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRA)
2265 {
2266 ichac97MixerSet(pThis, index, u32Val);
2267 LogFunc(("Set front LR ADC rate to %RU32\n", u32Val));
2268 ichac97StreamReOpen(pThis, &pThis->StreamLineIn);
2269 }
2270 else
2271 AssertMsgFailed(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
2272 break;
2273 default:
2274 LogFunc(("U nam writew %#x <- %#x\n", Port, u32Val));
2275 ichac97MixerSet(pThis, index, u32Val);
2276 break;
2277 }
2278 break;
2279 }
2280
2281 case 4:
2282 {
2283 Log3Func(("U nam writel %#x <- %#x\n", Port, u32Val));
2284 pThis->cas = 0;
2285 break;
2286 }
2287
2288 default:
2289 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
2290 break;
2291 }
2292
2293 return VINF_SUCCESS;
2294}
2295
2296
2297/**
2298 * @callback_method_impl{FNPCIIOREGIONMAP}
2299 */
2300static DECLCALLBACK(int) ichac97IOPortMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
2301 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
2302{
2303 RT_NOREF(cb, enmType);
2304 PAC97STATE pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);
2305 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
2306
2307 Assert(enmType == PCI_ADDRESS_SPACE_IO);
2308 Assert(cb >= 0x20);
2309
2310 if (iRegion > 1) /* We support 2 regions max. at the moment. */
2311 return VERR_INVALID_PARAMETER;
2312
2313 int rc;
2314 if (iRegion == 0)
2315 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, pThis,
2316 ichac97IOPortNAMWrite, ichac97IOPortNAMRead,
2317 NULL, NULL, "ICHAC97 NAM");
2318 else
2319 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 64, pThis,
2320 ichac97IOPortNABMWrite, ichac97IOPortNABMRead,
2321 NULL, NULL, "ICHAC97 NABM");
2322 if (RT_FAILURE(rc))
2323 return rc;
2324
2325 pThis->IOPortBase[iRegion] = Port;
2326 return VINF_SUCCESS;
2327}
2328
2329DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID)
2330{
2331 switch (uID)
2332 {
2333 case AC97SOUNDSOURCE_PI_INDEX: return &pThis->StreamLineIn;
2334 case AC97SOUNDSOURCE_MC_INDEX: return &pThis->StreamMicIn;
2335 case AC97SOUNDSOURCE_PO_INDEX: return &pThis->StreamOut;
2336 default: break;
2337 }
2338
2339 return NULL;
2340}
2341
2342#ifdef IN_RING3
2343static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
2344{
2345 RT_NOREF(pDevIns);
2346 PAC97BMREGS pRegs = &pStream->Regs;
2347
2348 SSMR3PutU32(pSSM, pRegs->bdbar);
2349 SSMR3PutU8( pSSM, pRegs->civ);
2350 SSMR3PutU8( pSSM, pRegs->lvi);
2351 SSMR3PutU16(pSSM, pRegs->sr);
2352 SSMR3PutU16(pSSM, pRegs->picb);
2353 SSMR3PutU8( pSSM, pRegs->piv);
2354 SSMR3PutU8( pSSM, pRegs->cr);
2355 SSMR3PutS32(pSSM, pRegs->bd_valid);
2356 SSMR3PutU32(pSSM, pRegs->bd.addr);
2357 SSMR3PutU32(pSSM, pRegs->bd.ctl_len);
2358
2359 return VINF_SUCCESS;
2360}
2361
2362/**
2363 * @callback_method_impl{FNSSMDEVSAVEEXEC}
2364 */
2365static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
2366{
2367 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2368
2369 LogFlowFuncEnter();
2370
2371 SSMR3PutU32(pSSM, pThis->glob_cnt);
2372 SSMR3PutU32(pSSM, pThis->glob_sta);
2373 SSMR3PutU32(pSSM, pThis->cas);
2374
2375 /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
2376 /* Note: The order the streams are saved here is critical, so don't touch. */
2377 int rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StreamLineIn);
2378 AssertRC(rc2);
2379 rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StreamOut);
2380 AssertRC(rc2);
2381 rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StreamMicIn);
2382 AssertRC(rc2);
2383
2384 SSMR3PutMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
2385
2386 uint8_t active[AC97SOUNDSOURCE_LAST_INDEX];
2387
2388 active[AC97SOUNDSOURCE_PI_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamLineIn) ? 1 : 0;
2389 active[AC97SOUNDSOURCE_PO_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamOut) ? 1 : 0;
2390 active[AC97SOUNDSOURCE_MC_INDEX] = ichac97StreamIsEnabled(pThis, &pThis->StreamMicIn) ? 1 : 0;
2391
2392 SSMR3PutMem(pSSM, active, sizeof(active));
2393
2394 LogFlowFuncLeaveRC(VINF_SUCCESS);
2395 return VINF_SUCCESS;
2396}
2397
2398static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStream)
2399{
2400 RT_NOREF(pDevIns);
2401 PAC97BMREGS pRegs = &pStream->Regs;
2402
2403 SSMR3GetU32(pSSM, &pRegs->bdbar);
2404 SSMR3GetU8( pSSM, &pRegs->civ);
2405 SSMR3GetU8( pSSM, &pRegs->lvi);
2406 SSMR3GetU16(pSSM, &pRegs->sr);
2407 SSMR3GetU16(pSSM, &pRegs->picb);
2408 SSMR3GetU8( pSSM, &pRegs->piv);
2409 SSMR3GetU8( pSSM, &pRegs->cr);
2410 SSMR3GetS32(pSSM, &pRegs->bd_valid);
2411 SSMR3GetU32(pSSM, &pRegs->bd.addr);
2412 SSMR3GetU32(pSSM, &pRegs->bd.ctl_len);
2413
2414 return VINF_SUCCESS;
2415}
2416
2417/**
2418 * @callback_method_impl{FNSSMDEVLOADEXEC}
2419 */
2420static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
2421{
2422 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2423
2424 LogRel2(("ichac97LoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
2425
2426 AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%RU32\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
2427 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
2428
2429 SSMR3GetU32(pSSM, &pThis->glob_cnt);
2430 SSMR3GetU32(pSSM, &pThis->glob_sta);
2431 SSMR3GetU32(pSSM, &pThis->cas);
2432
2433 /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
2434 /* Note: The order the streams are loaded here is critical, so don't touch. */
2435 int rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StreamLineIn);
2436 AssertRC(rc2);
2437 rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StreamOut);
2438 AssertRC(rc2);
2439 rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StreamMicIn);
2440 AssertRC(rc2);
2441
2442 SSMR3GetMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
2443
2444 /** @todo r=andy Stream IDs are hardcoded to certain streams. */
2445 uint8_t uaStrmsActive[AC97SOUNDSOURCE_LAST_INDEX];
2446 SSMR3GetMem(pSSM, uaStrmsActive, sizeof(uaStrmsActive));
2447
2448 ichac97RecordSelect(pThis, ichac97MixerGet(pThis, AC97_Record_Select));
2449# define V_(a, b) ichac97MixerSetVolume(pThis, a, b, ichac97MixerGet(pThis, a))
2450 V_(AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME_MASTER);
2451 V_(AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_FRONT);
2452 V_(AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN);
2453 V_(AC97_Mic_Volume_Mute, PDMAUDIOMIXERCTL_MIC_IN);
2454# undef V_
2455 if (pThis->uCodecModel == AC97_CODEC_AD1980)
2456 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AC97_AD_MISC_HPSEL)
2457 ichac97MixerSetVolume(pThis, AC97_Headphone_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME_MASTER,
2458 ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
2459
2460 rc2 = ichac97StreamsCreate(pThis);
2461 if (RT_SUCCESS(rc2))
2462 {
2463 /** @todo r=andy Stream IDs are hardcoded to certain streams. */
2464 rc2 = ichac97StreamEnable(pThis, &pThis->StreamLineIn, RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PI_INDEX]));
2465 if (RT_SUCCESS(rc2))
2466 rc2 = ichac97StreamEnable(pThis, &pThis->StreamMicIn, RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_MC_INDEX]));
2467 if (RT_SUCCESS(rc2))
2468 rc2 = ichac97StreamEnable(pThis, &pThis->StreamOut, RT_BOOL(uaStrmsActive[AC97SOUNDSOURCE_PO_INDEX]));
2469 }
2470
2471 pThis->bup_flag = 0;
2472 pThis->last_samp = 0;
2473
2474 return VINF_SUCCESS;
2475}
2476
2477
2478/**
2479 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2480 */
2481static DECLCALLBACK(void *) ichac97QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
2482{
2483 PAC97STATE pThis = RT_FROM_MEMBER(pInterface, AC97STATE, IBase);
2484 Assert(&pThis->IBase == pInterface);
2485
2486 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
2487 return NULL;
2488}
2489
2490
2491/**
2492 * Powers off the device.
2493 *
2494 * @param pDevIns Device instance to power off.
2495 */
2496static DECLCALLBACK(void) ichac97PowerOff(PPDMDEVINS pDevIns)
2497{
2498 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2499
2500 LogRel2(("AC97: Powering off ...\n"));
2501
2502 /* Note: Involves mixer stream / sink destruction, so also do this here
2503 * instead of in ichac97Destruct(). */
2504 ichac97StreamsDestroy(pThis);
2505
2506 /**
2507 * Note: Destroy the mixer while powering off and *not* in ichac97Destruct,
2508 * giving the mixer the chance to release any references held to
2509 * PDM audio streams it maintains.
2510 */
2511 if (pThis->pMixer)
2512 {
2513 AudioMixerDestroy(pThis->pMixer);
2514 pThis->pMixer = NULL;
2515 }
2516}
2517
2518
2519/**
2520 * @interface_method_impl{PDMDEVREG,pfnReset}
2521 *
2522 * @remarks The original sources didn't install a reset handler, but it seems to
2523 * make sense to me so we'll do it.
2524 */
2525static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns)
2526{
2527 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2528
2529 LogFlowFuncEnter();
2530
2531 /*
2532 * Reset the device state (will need pDrv later).
2533 */
2534 ichac97StreamResetBMRegs(pThis, &pThis->StreamLineIn);
2535 ichac97StreamResetBMRegs(pThis, &pThis->StreamMicIn);
2536 ichac97StreamResetBMRegs(pThis, &pThis->StreamOut);
2537
2538 /*
2539 * Reset the mixer too. The Windows XP driver seems to rely on
2540 * this. At least it wants to read the vendor id before it resets
2541 * the codec manually.
2542 */
2543 ichac97MixerReset(pThis);
2544
2545 /*
2546 * Reset all streams.
2547 */
2548 ichac97StreamReset(pThis, &pThis->StreamLineIn);
2549 ichac97StreamReset(pThis, &pThis->StreamMicIn);
2550 ichac97StreamReset(pThis, &pThis->StreamOut);
2551
2552 LogRel(("AC97: Reset\n"));
2553}
2554
2555
2556/**
2557 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2558 */
2559static DECLCALLBACK(int) ichac97Destruct(PPDMDEVINS pDevIns)
2560{
2561 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2562
2563 LogFlowFuncEnter();
2564
2565 PAC97DRIVER pDrv, pDrvNext;
2566 RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, AC97DRIVER, Node)
2567 {
2568 RTListNodeRemove(&pDrv->Node);
2569 RTMemFree(pDrv);
2570 }
2571
2572 /* Sanity. */
2573 Assert(RTListIsEmpty(&pThis->lstDrv));
2574
2575 int rc;
2576#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
2577 rc = RTCritSectDelete(&pThis->csTimer);
2578#else
2579 rc = VINF_SUCCESS;
2580#endif
2581
2582 LogFlowFuncLeaveRC(rc);
2583 return rc;
2584}
2585
2586
2587/**
2588 * Attach command, internal version.
2589 *
2590 * This is called to let the device attach to a driver for a specified LUN
2591 * during runtime. This is not called during VM construction, the device
2592 * constructor has to attach to all the available drivers.
2593 *
2594 * @returns VBox status code.
2595 * @param pDevIns The device instance.
2596 * @param pDrv Driver to (re-)use for (re-)attaching to.
2597 * If NULL is specified, a new driver will be created and appended
2598 * to the driver list.
2599 * @param uLUN The logical unit which is being detached.
2600 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
2601 */
2602static DECLCALLBACK(int) ichac97AttachInternal(PPDMDEVINS pDevIns, PAC97DRIVER pDrv, unsigned uLUN, uint32_t fFlags)
2603{
2604 RT_NOREF(fFlags);
2605 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2606
2607 /*
2608 * Attach driver.
2609 */
2610 char *pszDesc = NULL;
2611 if (RTStrAPrintf(&pszDesc, "Audio driver port (AC'97) for LUN #%u", uLUN) <= 0)
2612 AssertReleaseMsgReturn(pszDesc,
2613 ("Not enough memory for AC'97 driver port description of LUN #%u\n", uLUN),
2614 VERR_NO_MEMORY);
2615
2616 PPDMIBASE pDrvBase;
2617 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
2618 &pThis->IBase, &pDrvBase, pszDesc);
2619 if (RT_SUCCESS(rc))
2620 {
2621 if (pDrv == NULL)
2622 pDrv = (PAC97DRIVER)RTMemAllocZ(sizeof(AC97DRIVER));
2623 if (pDrv)
2624 {
2625 pDrv->pDrvBase = pDrvBase;
2626 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
2627 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
2628 pDrv->pAC97State = pThis;
2629 pDrv->uLUN = uLUN;
2630
2631 /*
2632 * For now we always set the driver at LUN 0 as our primary
2633 * host backend. This might change in the future.
2634 */
2635 if (pDrv->uLUN == 0)
2636 pDrv->Flags |= PDMAUDIODRVFLAGS_PRIMARY;
2637
2638 LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
2639
2640 /* Attach to driver list if not attached yet. */
2641 if (!pDrv->fAttached)
2642 {
2643 RTListAppend(&pThis->lstDrv, &pDrv->Node);
2644 pDrv->fAttached = true;
2645 }
2646 }
2647 else
2648 rc = VERR_NO_MEMORY;
2649 }
2650 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2651 LogFunc(("No attached driver for LUN #%u\n", uLUN));
2652
2653 if (RT_FAILURE(rc))
2654 {
2655 /* Only free this string on failure;
2656 * must remain valid for the live of the driver instance. */
2657 RTStrFree(pszDesc);
2658 }
2659
2660 LogFunc(("iLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
2661 return rc;
2662}
2663
2664
2665/**
2666 * Attach command.
2667 *
2668 * This is called to let the device attach to a driver for a specified LUN
2669 * during runtime. This is not called during VM construction, the device
2670 * constructor has to attach to all the available drivers.
2671 *
2672 * @returns VBox status code.
2673 * @param pDevIns The device instance.
2674 * @param uLUN The logical unit which is being detached.
2675 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
2676 */
2677static DECLCALLBACK(int) ichac97Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
2678{
2679 return ichac97AttachInternal(pDevIns, NULL /* pDrv */, uLUN, fFlags);
2680}
2681
2682static DECLCALLBACK(void) ichac97Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
2683{
2684 RT_NOREF(pDevIns, uLUN, fFlags);
2685 LogFunc(("iLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
2686}
2687
2688/**
2689 * Re-attach.
2690 *
2691 * @returns VBox status code.
2692 * @param pThis Device instance.
2693 * @param pDrv Driver instance used for attaching to.
2694 * If NULL is specified, a new driver will be created and appended
2695 * to the driver list.
2696 * @param uLUN The logical unit which is being re-detached.
2697 * @param pszDriver Driver name.
2698 */
2699static int ichac97Reattach(PAC97STATE pThis, PAC97DRIVER pDrv, uint8_t uLUN, const char *pszDriver)
2700{
2701 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2702 AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
2703
2704 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
2705 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
2706 PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/ichac97/0/");
2707
2708 /* Remove LUN branch. */
2709 CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
2710
2711 if (pDrv)
2712 {
2713 /* Re-use a driver instance => detach the driver before. */
2714 int rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
2715 if (RT_FAILURE(rc))
2716 return rc;
2717 }
2718
2719#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
2720
2721 int rc;
2722 do
2723 {
2724 PCFGMNODE pLunL0;
2725 rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN); RC_CHECK();
2726 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
2727 rc = CFGMR3InsertNode(pLunL0, "Config/", NULL); RC_CHECK();
2728
2729 PCFGMNODE pLunL1, pLunL2;
2730 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver/", &pLunL1); RC_CHECK();
2731 rc = CFGMR3InsertNode (pLunL1, "Config/", &pLunL2); RC_CHECK();
2732 rc = CFGMR3InsertString(pLunL1, "Driver", pszDriver); RC_CHECK();
2733
2734 rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver); RC_CHECK();
2735
2736 } while (0);
2737
2738 if (RT_SUCCESS(rc))
2739 rc = ichac97AttachInternal(pThis->pDevInsR3, pDrv, uLUN, 0 /* fFlags */);
2740
2741 LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
2742
2743#undef RC_CHECK
2744
2745 return rc;
2746}
2747
2748/**
2749 * @interface_method_impl{PDMDEVREG,pfnConstruct}
2750 */
2751static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2752{
2753 RT_NOREF(iInstance);
2754 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2755
2756 /* NB: This must be done *before* any possible failure (and running the destructor). */
2757 RTListInit(&pThis->lstDrv);
2758
2759 Assert(iInstance == 0);
2760 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2761
2762 /*
2763 * Validations.
2764 */
2765 if (!CFGMR3AreValuesValid(pCfg,
2766 "Codec\0"
2767 "TimerHz\0"))
2768 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2769 N_("Invalid configuration for the AC'97 device"));
2770
2771 /*
2772 * Read config data.
2773 */
2774 char szCodec[20];
2775 int rc = CFGMR3QueryStringDef(pCfg, "Codec", &szCodec[0], sizeof(szCodec), "STAC9700");
2776 if (RT_FAILURE(rc))
2777 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2778 N_("AC'97 configuration error: Querying \"Codec\" as string failed"));
2779
2780#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
2781 uint16_t uTimerHz;
2782 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, AC97_TIMER_HZ /* Default value, if not set. */);
2783 if (RT_FAILURE(rc))
2784 return PDMDEV_SET_ERROR(pDevIns, rc,
2785 N_("AC'97 configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
2786#endif
2787
2788 /*
2789 * The AD1980 codec (with corresponding PCI subsystem vendor ID) is whitelisted
2790 * in the Linux kernel; Linux makes no attempt to measure the data rate and assumes
2791 * 48 kHz rate, which is exactly what we need. Same goes for AD1981B.
2792 */
2793 if (!strcmp(szCodec, "STAC9700"))
2794 pThis->uCodecModel = AC97_CODEC_STAC9700;
2795 else if (!strcmp(szCodec, "AD1980"))
2796 pThis->uCodecModel = AC97_CODEC_AD1980;
2797 else if (!strcmp(szCodec, "AD1981B"))
2798 pThis->uCodecModel = AC97_CODEC_AD1981B;
2799 else
2800 {
2801 return PDMDevHlpVMSetError(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, RT_SRC_POS,
2802 N_("AC'97 configuration error: The \"Codec\" value \"%s\" is unsupported"),
2803 szCodec);
2804 }
2805
2806 /*
2807 * Initialize data (most of it anyway).
2808 */
2809 pThis->pDevInsR3 = pDevIns;
2810 /* IBase */
2811 pThis->IBase.pfnQueryInterface = ichac97QueryInterface;
2812
2813 /* PCI Device (the assertions will be removed later) */
2814 PCIDevSetVendorId (&pThis->PciDev, 0x8086); /* 00 ro - intel. */ Assert(pThis->PciDev.abConfig[0x00] == 0x86); Assert(pThis->PciDev.abConfig[0x01] == 0x80);
2815 PCIDevSetDeviceId (&pThis->PciDev, 0x2415); /* 02 ro - 82801 / 82801aa(?). */ Assert(pThis->PciDev.abConfig[0x02] == 0x15); Assert(pThis->PciDev.abConfig[0x03] == 0x24);
2816 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */ Assert(pThis->PciDev.abConfig[0x04] == 0x00); Assert(pThis->PciDev.abConfig[0x05] == 0x00);
2817 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_DEVSEL_MEDIUM | VBOX_PCI_STATUS_FAST_BACK); /* 06 rwc?,ro? - pcists. */ Assert(pThis->PciDev.abConfig[0x06] == 0x80); Assert(pThis->PciDev.abConfig[0x07] == 0x02);
2818 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */ Assert(pThis->PciDev.abConfig[0x08] == 0x01);
2819 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */ Assert(pThis->PciDev.abConfig[0x09] == 0x00);
2820 PCIDevSetClassSub (&pThis->PciDev, 0x01); /* 0a ro - scc; 01 == Audio. */ Assert(pThis->PciDev.abConfig[0x0a] == 0x01);
2821 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */ Assert(pThis->PciDev.abConfig[0x0b] == 0x04);
2822 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */ Assert(pThis->PciDev.abConfig[0x0e] == 0x00);
2823 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - nambar - native audio mixer base. */
2824 true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.abConfig[0x10] == 0x01); Assert(pThis->PciDev.abConfig[0x11] == 0x00); Assert(pThis->PciDev.abConfig[0x12] == 0x00); Assert(pThis->PciDev.abConfig[0x13] == 0x00);
2825 PCIDevSetBaseAddress (&pThis->PciDev, 1, /* 14 rw - nabmbar - native audio bus mastering. */
2826 true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.abConfig[0x14] == 0x01); Assert(pThis->PciDev.abConfig[0x15] == 0x00); Assert(pThis->PciDev.abConfig[0x16] == 0x00); Assert(pThis->PciDev.abConfig[0x17] == 0x00);
2827 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */ Assert(pThis->PciDev.abConfig[0x3c] == 0x00);
2828 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */ Assert(pThis->PciDev.abConfig[0x3d] == 0x01);
2829
2830 if (pThis->uCodecModel == AC97_CODEC_AD1980)
2831 {
2832 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x1028); /* 2c ro - Dell.) */
2833 PCIDevSetSubSystemId (&pThis->PciDev, 0x0177); /* 2e ro. */
2834 }
2835 else if (pThis->uCodecModel == AC97_CODEC_AD1981B)
2836 {
2837 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x1028); /* 2c ro - Dell.) */
2838 PCIDevSetSubSystemId (&pThis->PciDev, 0x01ad); /* 2e ro. */
2839 }
2840 else
2841 {
2842 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x8086); /* 2c ro - Intel.) */
2843 PCIDevSetSubSystemId (&pThis->PciDev, 0x0000); /* 2e ro. */
2844 }
2845
2846 /*
2847 * Register the PCI device, it's I/O regions, the timer and the
2848 * saved state item.
2849 */
2850 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
2851 if (RT_FAILURE(rc))
2852 return rc;
2853
2854 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 256, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
2855 if (RT_FAILURE(rc))
2856 return rc;
2857
2858 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 64, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
2859 if (RT_FAILURE(rc))
2860 return rc;
2861
2862 rc = PDMDevHlpSSMRegister(pDevIns, AC97_SSM_VERSION, sizeof(*pThis), ichac97SaveExec, ichac97LoadExec);
2863 if (RT_FAILURE(rc))
2864 return rc;
2865
2866 /*
2867 * Attach driver.
2868 */
2869 uint8_t uLUN;
2870 for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
2871 {
2872 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN));
2873 rc = ichac97AttachInternal(pDevIns, NULL /* pDrv */, uLUN, 0 /* fFlags */);
2874 if (RT_FAILURE(rc))
2875 {
2876 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2877 rc = VINF_SUCCESS;
2878 else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
2879 {
2880 ichac97Reattach(pThis, NULL /* pDrv */, uLUN, "NullAudio");
2881 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2882 N_("Host audio backend initialization has failed. Selecting the NULL audio backend "
2883 "with the consequence that no sound is audible"));
2884 /* Attaching to the NULL audio backend will never fail. */
2885 rc = VINF_SUCCESS;
2886 }
2887 break;
2888 }
2889 }
2890
2891 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
2892
2893 if (RT_SUCCESS(rc))
2894 rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
2895
2896 ichac97Reset(pDevIns);
2897
2898 if (RT_SUCCESS(rc))
2899 {
2900 ichac97StreamsCreate(pThis);
2901
2902#ifdef VBOX_WITH_AUDIO_AC97_ONETIME_INIT
2903 PAC97DRIVER pDrv;
2904 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
2905 {
2906 /*
2907 * Only primary drivers are critical for the VM to run. Everything else
2908 * might not worth showing an own error message box in the GUI.
2909 */
2910 if (!(pDrv->Flags & PDMAUDIODRVFLAGS_PRIMARY))
2911 continue;
2912
2913 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
2914 AssertPtr(pCon);
2915
2916 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
2917 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
2918 bool fValidOut = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
2919
2920 if ( !fValidLineIn
2921 && !fValidMicIn
2922 && !fValidOut)
2923 {
2924 LogRel(("AC97: Falling back to NULL backend (no sound audible)\n"));
2925
2926 /* Destroy the streams before re-attaching the NULL driver. */
2927 ichac97StreamsDestroy(pThis);
2928
2929 ichac97Reset(pDevIns);
2930 ichac97Reattach(pThis, pDrv, pDrv->uLUN, "NullAudio");
2931
2932 /* Re-create the streams after re-attaching. */
2933 ichac97StreamsCreate(pThis);
2934
2935 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2936 N_("No audio devices could be opened. Selecting the NULL audio backend "
2937 "with the consequence that no sound is audible"));
2938 }
2939 else
2940 {
2941 bool fWarn = false;
2942
2943 PDMAUDIOBACKENDCFG backendCfg;
2944 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
2945 if (RT_SUCCESS(rc2))
2946 {
2947 if (backendCfg.cMaxStreamsIn)
2948 {
2949 /* If the audio backend supports two or more input streams at once,
2950 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
2951 if (backendCfg.cMaxStreamsIn >= 2)
2952 fWarn = !fValidLineIn || !fValidMicIn;
2953 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
2954 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
2955 * One of the two simply is not in use then. */
2956 else if (backendCfg.cMaxStreamsIn == 1)
2957 fWarn = !fValidLineIn && !fValidMicIn;
2958 /* Don't warn if our backend is not able of supporting any input streams at all. */
2959 }
2960
2961 if ( !fWarn
2962 && backendCfg.cMaxStreamsOut)
2963 {
2964 fWarn = !fValidOut;
2965 }
2966 }
2967 else
2968 {
2969 LogRel(("AC97: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
2970 fWarn = true;
2971 }
2972
2973 if (fWarn)
2974 {
2975 char szMissingStreams[255] = "";
2976 size_t len = 0;
2977 if (!fValidLineIn)
2978 {
2979 LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
2980 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
2981 }
2982 if (!fValidMicIn)
2983 {
2984 LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
2985 len += RTStrPrintf(szMissingStreams + len,
2986 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
2987 }
2988 if (!fValidOut)
2989 {
2990 LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
2991 len += RTStrPrintf(szMissingStreams + len,
2992 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
2993 }
2994
2995 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2996 N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
2997 "output or depending on audio input may hang. Make sure your host audio device "
2998 "is working properly. Check the logfile for error messages of the audio "
2999 "subsystem"), szMissingStreams);
3000 }
3001 }
3002 }
3003#endif /* VBOX_WITH_AUDIO_AC97_ONETIME_INIT */
3004 }
3005
3006#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
3007 if (RT_SUCCESS(rc))
3008 {
3009 rc = RTCritSectInit(&pThis->csTimer);
3010 if (RT_SUCCESS(rc))
3011 {
3012 /* Start the emulation timer. */
3013 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis,
3014 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer);
3015 AssertRCReturn(rc, rc);
3016
3017 if (RT_SUCCESS(rc))
3018 {
3019 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
3020 pThis->uTimerTS = TMTimerGet(pThis->pTimer);
3021 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
3022 }
3023 }
3024 }
3025#else /* !VBOX_WITH_AUDIO_AC97_CALLBACKS */
3026 if (RT_SUCCESS(rc))
3027 {
3028 PAC97DRIVER pDrv;
3029 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
3030 {
3031 /* Only register primary driver.
3032 * The device emulation does the output multiplexing then. */
3033 if (!(pDrv->Flags & PDMAUDIODRVFLAGS_PRIMARY))
3034 continue;
3035
3036 PDMAUDIOCALLBACK AudioCallbacks[2];
3037
3038 AC97CALLBACKCTX Ctx = { pThis, pDrv };
3039
3040 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT;
3041 AudioCallbacks[0].pfnCallback = ac97CallbackInput;
3042 AudioCallbacks[0].pvCtx = &Ctx;
3043 AudioCallbacks[0].cbCtx = sizeof(AC97CALLBACKCTX);
3044
3045 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT;
3046 AudioCallbacks[1].pfnCallback = ac97CallbackOutput;
3047 AudioCallbacks[1].pvCtx = &Ctx;
3048 AudioCallbacks[1].cbCtx = sizeof(AC97CALLBACKCTX);
3049
3050 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
3051 if (RT_FAILURE(rc))
3052 break;
3053 }
3054 }
3055#endif /* VBOX_WITH_AUDIO_AC97_CALLBACKS */
3056
3057#ifdef VBOX_WITH_STATISTICS
3058 if (RT_SUCCESS(rc))
3059 {
3060 /*
3061 * Register statistics.
3062 */
3063 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/AC97/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling ichac97Timer.");
3064 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/AC97/BytesRead" , STAMUNIT_BYTES, "Bytes read from AC97 emulation.");
3065 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/AC97/BytesWritten", STAMUNIT_BYTES, "Bytes written to AC97 emulation.");
3066 }
3067#endif
3068
3069 LogFlowFuncLeaveRC(rc);
3070 return rc;
3071}
3072
3073/**
3074 * The device registration structure.
3075 */
3076const PDMDEVREG g_DeviceICHAC97 =
3077{
3078 /* u32Version */
3079 PDM_DEVREG_VERSION,
3080 /* szName */
3081 "ichac97",
3082 /* szRCMod */
3083 "",
3084 /* szR0Mod */
3085 "",
3086 /* pszDescription */
3087 "ICH AC'97 Audio Controller",
3088 /* fFlags */
3089 PDM_DEVREG_FLAGS_DEFAULT_BITS,
3090 /* fClass */
3091 PDM_DEVREG_CLASS_AUDIO,
3092 /* cMaxInstances */
3093 1,
3094 /* cbInstance */
3095 sizeof(AC97STATE),
3096 /* pfnConstruct */
3097 ichac97Construct,
3098 /* pfnDestruct */
3099 ichac97Destruct,
3100 /* pfnRelocate */
3101 NULL,
3102 /* pfnMemSetup */
3103 NULL,
3104 /* pfnPowerOn */
3105 NULL,
3106 /* pfnReset */
3107 ichac97Reset,
3108 /* pfnSuspend */
3109 NULL,
3110 /* pfnResume */
3111 NULL,
3112 /* pfnAttach */
3113 ichac97Attach,
3114 /* pfnDetach */
3115 ichac97Detach,
3116 /* pfnQueryInterface. */
3117 NULL,
3118 /* pfnInitComplete */
3119 NULL,
3120 /* pfnPowerOff */
3121 ichac97PowerOff,
3122 /* pfnSoftReset */
3123 NULL,
3124 /* u32VersionEnd */
3125 PDM_DEVREG_VERSION
3126};
3127
3128#endif /* !IN_RING3 */
3129#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

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