VirtualBox

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

Last change on this file since 59201 was 59191, checked in by vboxsync, 9 years ago

Audio: Included "TimerHz" in CFGMR3AreValuesValid checks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 88.5 KB
Line 
1/* $Id: DevIchAc97.cpp 59191 2015-12-18 15:20:24Z vboxsync $ */
2/** @file
3 * DevIchAc97 - VBox ICH AC97 Audio Controller.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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# include <iprt/mem.h>
30# include <iprt/string.h>
31# include <iprt/uuid.h>
32#endif
33
34#include "VBoxDD.h"
35
36#include "AudioMixBuffer.h"
37#include "AudioMixer.h"
38
39
40/*********************************************************************************************************************************
41* Defined Constants And Macros *
42*********************************************************************************************************************************/
43
44#ifdef DEBUG
45//#define DEBUG_LUN
46# ifdef DEBUG_LUN
47# define DEBUG_LUN_NUM 1
48# endif
49#endif /* DEBUG */
50
51#define AC97_SSM_VERSION 1
52
53#ifdef VBOX
54# define SOFT_VOLUME /** @todo Get rid of this crap. */
55#else
56# define SOFT_VOLUME
57#endif
58
59#define SR_FIFOE RT_BIT(4) /* rwc, FIFO error. */
60#define SR_BCIS RT_BIT(3) /* rwc, Buffer completion interrupt status. */
61#define SR_LVBCI RT_BIT(2) /* rwc, Last valid buffer completion interrupt. */
62#define SR_CELV RT_BIT(1) /* ro, Current equals last valid. */
63#define SR_DCH RT_BIT(0) /* ro, Controller halted. */
64#define SR_VALID_MASK (RT_BIT(5) - 1)
65#define SR_WCLEAR_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
66#define SR_RO_MASK (SR_DCH | SR_CELV)
67#define SR_INT_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
68
69#define CR_IOCE RT_BIT(4) /* rw, Interrupt On Completion Enable. */
70#define CR_FEIE RT_BIT(3) /* rw FIFO Error Interrupt Enable. */
71#define CR_LVBIE RT_BIT(2) /* rw */
72#define CR_RR RT_BIT(1) /* rw */
73#define CR_RPBM RT_BIT(0) /* rw */
74#define CR_VALID_MASK (RT_BIT(5) - 1)
75#define CR_DONT_CLEAR_MASK (CR_IOCE | CR_FEIE | CR_LVBIE)
76
77#define GC_WR 4 /* rw */
78#define GC_CR 2 /* rw */
79#define GC_VALID_MASK (RT_BIT(6) - 1)
80
81#define GS_MD3 RT_BIT(17) /* rw */
82#define GS_AD3 RT_BIT(16) /* rw */
83#define GS_RCS RT_BIT(15) /* rwc */
84#define GS_B3S12 RT_BIT(14) /* ro */
85#define GS_B2S12 RT_BIT(13) /* ro */
86#define GS_B1S12 RT_BIT(12) /* ro */
87#define GS_S1R1 RT_BIT(11) /* rwc */
88#define GS_S0R1 RT_BIT(10) /* rwc */
89#define GS_S1CR RT_BIT(9) /* ro */
90#define GS_S0CR RT_BIT(8) /* ro */
91#define GS_MINT RT_BIT(7) /* ro */
92#define GS_POINT RT_BIT(6) /* ro */
93#define GS_PIINT RT_BIT(5) /* ro */
94#define GS_RSRVD (RT_BIT(4)|RT_BIT(3))
95#define GS_MOINT RT_BIT(2) /* ro */
96#define GS_MIINT RT_BIT(1) /* ro */
97#define GS_GSCI RT_BIT(0) /* rwc */
98#define GS_RO_MASK (GS_B3S12 | \
99 GS_B2S12 | \
100 GS_B1S12 | \
101 GS_S1CR | \
102 GS_S0CR | \
103 GS_MINT | \
104 GS_POINT | \
105 GS_PIINT | \
106 GS_RSRVD | \
107 GS_MOINT | \
108 GS_MIINT)
109#define GS_VALID_MASK (RT_BIT(18) - 1)
110#define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI)
111
112/** @name Buffer Descriptor
113 * @{ */
114#define BD_IOC RT_BIT(31) /**< Interrupt on Completion */
115#define BD_BUP RT_BIT(30) /**< Buffer Underrun Policy */
116/** @} */
117
118#define EACS_VRA 1
119#define EACS_VRM 8
120
121#define VOL_MASK 0x1f
122#define MUTE_SHIFT 15
123
124#define REC_MASK 7
125enum
126{
127 REC_MIC = 0,
128 REC_CD,
129 REC_VIDEO,
130 REC_AUX,
131 REC_LINE_IN,
132 REC_STEREO_MIX,
133 REC_MONO_MIX,
134 REC_PHONE
135};
136
137enum
138{
139 AC97_Reset = 0x00,
140 AC97_Master_Volume_Mute = 0x02,
141 AC97_Headphone_Volume_Mute = 0x04, /** Also known as AUX, see table 16, section 5.7. */
142 AC97_Master_Volume_Mono_Mute = 0x06,
143 AC97_Master_Tone_RL = 0x08,
144 AC97_PC_BEEP_Volume_Mute = 0x0A,
145 AC97_Phone_Volume_Mute = 0x0C,
146 AC97_Mic_Volume_Mute = 0x0E,
147 AC97_Line_In_Volume_Mute = 0x10,
148 AC97_CD_Volume_Mute = 0x12,
149 AC97_Video_Volume_Mute = 0x14,
150 AC97_Aux_Volume_Mute = 0x16,
151 AC97_PCM_Out_Volume_Mute = 0x18,
152 AC97_Record_Select = 0x1A,
153 AC97_Record_Gain_Mute = 0x1C,
154 AC97_Record_Gain_Mic_Mute = 0x1E,
155 AC97_General_Purpose = 0x20,
156 AC97_3D_Control = 0x22,
157 AC97_AC_97_RESERVED = 0x24,
158 AC97_Powerdown_Ctrl_Stat = 0x26,
159 AC97_Extended_Audio_ID = 0x28,
160 AC97_Extended_Audio_Ctrl_Stat = 0x2A,
161 AC97_PCM_Front_DAC_Rate = 0x2C,
162 AC97_PCM_Surround_DAC_Rate = 0x2E,
163 AC97_PCM_LFE_DAC_Rate = 0x30,
164 AC97_PCM_LR_ADC_Rate = 0x32,
165 AC97_MIC_ADC_Rate = 0x34,
166 AC97_6Ch_Vol_C_LFE_Mute = 0x36,
167 AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
168 AC97_Vendor_Reserved = 0x58,
169 AC97_AD_Misc = 0x76,
170 AC97_Vendor_ID1 = 0x7c,
171 AC97_Vendor_ID2 = 0x7e
172};
173
174/* Codec models. */
175enum {
176 Codec_STAC9700 = 0, /* SigmaTel STAC9700 */
177 Codec_AD1980, /* Analog Devices AD1980 */
178 Codec_AD1981B /* Analog Devices AD1981B */
179};
180
181/* Analog Devices miscellaneous regiter bits used in AD1980. */
182#define AD_MISC_LOSEL RT_BIT(5) /* Surround (rear) goes to line out outputs. */
183#define AD_MISC_HPSEL RT_BIT(10) /* PCM (front) goes to headphone outputs. */
184
185#define ICHAC97STATE_2_DEVINS(a_pAC97) ((a_pAC97)->pDevInsR3)
186
187enum
188{
189 BUP_SET = RT_BIT(0),
190 BUP_LAST = RT_BIT(1)
191};
192
193/** Emits registers for a specific (Native Audio Bus Master BAR) NABMBAR. */
194#define AC97_NABMBAR_REGS(prefix, off) \
195 enum { \
196 prefix ## _BDBAR = off, \
197 prefix ## _CIV = off + 4, \
198 prefix ## _LVI = off + 5, \
199 prefix ## _SR = off + 6, \
200 prefix ## _PICB = off + 8, \
201 prefix ## _PIV = off + 10, \
202 prefix ## _CR = off + 11 \
203 }
204
205#ifndef VBOX_DEVICE_STRUCT_TESTCASE
206typedef enum
207{
208 PI_INDEX = 0, /** PCM in */
209 PO_INDEX, /** PCM out */
210 MC_INDEX, /** Mic in */
211 LAST_INDEX
212} AC97SOUNDSOURCE;
213
214AC97_NABMBAR_REGS(PI, PI_INDEX * 16);
215AC97_NABMBAR_REGS(PO, PO_INDEX * 16);
216AC97_NABMBAR_REGS(MC, MC_INDEX * 16);
217#endif
218
219enum
220{
221 /** NABMBAR: Global Control Register. */
222 GLOB_CNT = 0x2c,
223 /** NABMBAR Global Status. */
224 GLOB_STA = 0x30,
225 /** Codec Access Semaphore Register. */
226 CAS = 0x34
227};
228
229#define AC97_PORT2IDX(a_idx) ( ((a_idx) >> 4) & 3 )
230
231/*********************************************************************************************************************************
232* Structures and Typedefs *
233*********************************************************************************************************************************/
234
235/**
236 * Buffer Descriptor List Entry (BDLE).
237 */
238typedef struct AC97BDLE
239{
240 uint32_t addr;
241 uint32_t ctl_len;
242} AC97BDLE, *PAC97BDLE;
243
244/**
245 * Bus master register set for an audio stream.
246 */
247typedef struct AC97BMREGS
248{
249 uint32_t bdbar; /** rw 0, Buffer Descriptor List: BAR (Base Address Register). */
250 uint8_t civ; /** ro 0, Current index value. */
251 uint8_t lvi; /** rw 0, Last valid index. */
252 uint16_t sr; /** rw 1, Status register. */
253 uint16_t picb; /** ro 0, Position in current buffer. */
254 uint8_t piv; /** ro 0, Prefetched index value. */
255 uint8_t cr; /** rw 0, Control register. */
256 int bd_valid; /** Whether current BDLE is initialized or not. */
257 AC97BDLE bd; /** Current Buffer Descriptor List Entry (BDLE). */
258} AC97BMREGS, *PAC97BMREGS;
259
260/**
261 * Internal state of an AC97 stream.
262 */
263typedef struct AC97STREAMSTATE
264{
265 /* Nothing yet. */
266} AC97STREAMSTATE, *PAC97STREAMSTATE;
267
268/**
269 * Structure for keeping an AC97 stream state.
270 *
271 * Contains only register values which do *not* change until a
272 * stream reset occurs.
273 */
274typedef struct AC97STREAM
275{
276 /** Stream number (SDn). */
277 uint8_t u8Strm;
278 /** Bus master registers of this stream. */
279 AC97BMREGS Regs;
280 /** Internal state of this stream. */
281 AC97STREAMSTATE State;
282} AC97STREAM, *PAC97STREAM;
283
284typedef struct AC97INPUTSTREAM
285{
286 /** PCM line input stream. */
287 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn;
288 /** Mixer handle for line input stream. */
289 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn;
290} AC97INPUTSTREAM, *PAC97INPUTSTREAM;
291
292typedef struct AC97OUTPUTSTREAM
293{
294 /** PCM output stream. */
295 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut;
296 /** Mixer handle for output stream. */
297 R3PTRTYPE(PAUDMIXSTREAM) phStrmOut;
298} AC97OUTPUTSTREAM, *PAC97OUTPUTSTREAM;
299
300/**
301 * Struct for maintaining a host backend driver.
302 */
303typedef struct AC97STATE *PAC97STATE;
304typedef struct AC97DRIVER
305{
306 /** Node for storing this driver in our device driver list of AC97STATE. */
307 RTLISTNODER3 Node;
308 /** Pointer to AC97 controller (state). */
309 R3PTRTYPE(PAC97STATE) pAC97State;
310 /** Driver flags. */
311 PDMAUDIODRVFLAGS Flags;
312 uint32_t PaddingFlags;
313 /** LUN # to which this driver has been assigned. */
314 uint8_t uLUN;
315 uint8_t Padding[5];
316 /** Audio connector interface to the underlying
317 * host backend. */
318 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
319 /** Stream for line input. */
320 AC97INPUTSTREAM LineIn;
321 /** Stream for mic input. */
322 AC97INPUTSTREAM MicIn;
323 /** Stream for output. */
324 AC97OUTPUTSTREAM Out;
325} AC97DRIVER, *PAC97DRIVER;
326
327typedef struct AC97STATE
328{
329 /** The PCI device state. */
330 PCIDevice PciDev;
331 /** R3 Pointer to the device instance. */
332 PPDMDEVINSR3 pDevInsR3;
333 /** Global Control (Bus Master Control Register) */
334 uint32_t glob_cnt;
335 /** Global Status (Bus Master Control Register) */
336 uint32_t glob_sta;
337 /** Codec Access Semaphore Register (Bus Master Control Register) */
338 uint32_t cas;
339 uint32_t last_samp;
340 uint8_t mixer_data[256];
341 /** Stream state for line-in. */
342 AC97STREAM StrmStLineIn;
343 /** Stream state for microphone-in. */
344 AC97STREAM StrmStMicIn;
345 /** Stream state for output. */
346 AC97STREAM StrmStOut;
347#ifndef VBOX_WITH_AUDIO_CALLBACKS
348 /** The timer for pumping data thru the attached LUN drivers. */
349 PTMTIMERR3 pTimer;
350 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
351 uint64_t cTimerTicks;
352 /** Timestamp of the last timer callback (ac97Timer).
353 * Used to calculate the time actually elapsed between two timer callbacks. */
354 uint64_t uTimerTS;
355#endif
356#ifdef VBOX_WITH_STATISTICS
357 STAMPROFILE StatTimer;
358 STAMCOUNTER StatBytesRead;
359 STAMCOUNTER StatBytesWritten;
360#endif
361 /** List of associated LUN drivers (AC97DRIVER). */
362 RTLISTANCHOR lstDrv;
363 /** The device' software mixer. */
364 R3PTRTYPE(PAUDIOMIXER) pMixer;
365 /** Audio sink for PCM output. */
366 R3PTRTYPE(PAUDMIXSINK) pSinkOutput;
367 /** Audio sink for line input. */
368 R3PTRTYPE(PAUDMIXSINK) pSinkLineIn;
369 /** Audio sink for microphone input. */
370 R3PTRTYPE(PAUDMIXSINK) pSinkMicIn;
371 uint8_t silence[128];
372 int bup_flag;
373 /** Pointer to the attached audio driver. */
374 PPDMIBASE pDrvBase;
375 /** The base interface for LUN\#0. */
376 PDMIBASE IBase;
377 /** Base port of the I/O space region. */
378 RTIOPORT IOPortBase[2];
379 /** Pointer to temporary scratch read/write buffer. */
380 R3PTRTYPE(uint8_t *) pvReadWriteBuf;
381 /** Size of the temporary scratch read/write buffer. */
382 uint32_t cbReadWriteBuf;
383 /** Codec model. */
384 uint32_t uCodecModel;
385} AC97STATE, *PAC97STATE;
386
387#ifdef VBOX_WITH_STATISTICS
388AssertCompileMemberAlignment(AC97STATE, StatTimer, 8);
389#endif
390
391#ifndef VBOX_DEVICE_STRUCT_TESTCASE
392
393DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
394static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns);
395#ifndef VBOX_WITH_AUDIO_CALLBACKS
396static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
397#endif
398static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed);
399
400static void ichac97WarmReset(PAC97STATE pThis)
401{
402 NOREF(pThis);
403}
404
405static void ichac97ColdReset(PAC97STATE pThis)
406{
407 NOREF(pThis);
408}
409
410/** Fetches the buffer descriptor at _CIV. */
411static void ichac97StreamFetchBDLE(PAC97STATE pThis, PAC97STREAM pStrmSt)
412{
413 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
414 PAC97BMREGS pRegs = &pStrmSt->Regs;
415
416 uint32_t u32[2];
417
418 PDMDevHlpPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * 8, &u32[0], sizeof(u32));
419 pRegs->bd_valid = 1;
420#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
421# error Please adapt the code (audio buffers are little endian)!
422#else
423 pRegs->bd.addr = RT_H2LE_U32(u32[0] & ~3);
424 pRegs->bd.ctl_len = RT_H2LE_U32(u32[1]);
425#endif
426 pRegs->picb = pRegs->bd.ctl_len & 0xffff;
427 LogFlowFunc(("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
428 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len >> 16,
429 pRegs->bd.ctl_len & 0xffff, (pRegs->bd.ctl_len & 0xffff) << 1));
430}
431
432/**
433 * Update the BM status register
434 */
435static void ichac97StreamUpdateStatus(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t new_sr)
436{
437 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
438 PAC97BMREGS pRegs = &pStrmSt->Regs;
439
440 bool fSignal = false;
441 bool iIrqLevel;
442
443 uint32_t new_mask = new_sr & SR_INT_MASK;
444 uint32_t old_mask = pRegs->sr & SR_INT_MASK;
445
446 static uint32_t const masks[] = { GS_PIINT, GS_POINT, GS_MINT };
447
448 if (new_mask ^ old_mask)
449 {
450 /** @todo Is IRQ deasserted when only one of status bits is cleared? */
451 if (!new_mask)
452 {
453 fSignal = true;
454 iIrqLevel = 0;
455 }
456 else if ((new_mask & SR_LVBCI) && (pRegs->cr & CR_LVBIE))
457 {
458 fSignal = true;
459 iIrqLevel = 1;
460 }
461 else if ((new_mask & SR_BCIS) && (pRegs->cr & CR_IOCE))
462 {
463 fSignal = true;
464 iIrqLevel = 1;
465 }
466 }
467
468 pRegs->sr = new_sr;
469
470 LogFlowFunc(("IOC%d, LVB%d, sr=%#x, fSignal=%RTbool, iIrqLevel=%d\n",
471 pRegs->sr & SR_BCIS, pRegs->sr & SR_LVBCI, pRegs->sr, fSignal, iIrqLevel));
472
473 if (fSignal)
474 {
475 if (iIrqLevel)
476 pThis->glob_sta |= masks[pStrmSt->u8Strm];
477 else
478 pThis->glob_sta &= ~masks[pStrmSt->u8Strm];
479
480 LogFlowFunc(("set irq level=%d\n", !!iIrqLevel));
481 PDMDevHlpPCISetIrq(pDevIns, 0, !!iIrqLevel);
482 }
483}
484
485static int ichac97StreamSetActive(PAC97STATE pThis, PAC97STREAM pStrmSt, bool fActive)
486{
487 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
488 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
489
490 LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool\n", pStrmSt->u8Strm, fActive));
491
492 int rc = VINF_SUCCESS;
493
494 PAC97DRIVER pDrv;
495 switch (pStrmSt->u8Strm)
496 {
497 case PI_INDEX:
498 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
499 {
500 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
501 pDrv->LineIn.pStrmIn, fActive);
502 if (RT_SUCCESS(rc))
503 rc = rc2;
504 }
505 break;
506
507 case PO_INDEX:
508 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
509 {
510 int rc2 = pDrv->pConnector->pfnEnableOut(pDrv->pConnector,
511 pDrv->Out.pStrmOut, fActive);
512 if (RT_SUCCESS(rc))
513 rc = rc2;
514 }
515 break;
516
517 case MC_INDEX:
518 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
519 {
520 int rc2 = pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
521 pDrv->MicIn.pStrmIn, fActive);
522 if (RT_SUCCESS(rc))
523 rc = rc2;
524 }
525 break;
526
527 default:
528 AssertMsgFailed(("Wrong index %RU32\n", pStrmSt->u8Strm));
529 rc = VERR_NOT_SUPPORTED;
530 break;
531 }
532
533 return rc;
534}
535
536static void ichac97StreamResetBMRegs(PAC97STATE pThis, PAC97STREAM pStrmSt)
537{
538 AssertPtrReturnVoid(pThis);
539 AssertPtrReturnVoid(pStrmSt);
540
541 LogFlowFuncEnter();
542
543 PAC97BMREGS pRegs = &pStrmSt->Regs;
544
545 pRegs->bdbar = 0;
546 pRegs->civ = 0;
547 pRegs->lvi = 0;
548
549 ichac97StreamUpdateStatus(pThis, pStrmSt, SR_DCH); /** @todo Do we need to do that? */
550
551 pRegs->picb = 0;
552 pRegs->piv = 0;
553 pRegs->cr = pRegs->cr & CR_DONT_CLEAR_MASK;
554 pRegs->bd_valid = 0;
555
556 int rc = ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
557 AssertRC(rc);
558
559 RT_ZERO(pThis->silence);
560}
561
562static void ichac97MixerSet(PAC97STATE pThis, uint32_t u8Idx, uint16_t v)
563{
564 if (u8Idx + 2 > sizeof(pThis->mixer_data))
565 {
566 AssertMsgFailed(("Index %RU8 out of bounds(%zu)\n", u8Idx, sizeof(pThis->mixer_data)));
567 return;
568 }
569
570 pThis->mixer_data[u8Idx + 0] = RT_LO_U8(v);
571 pThis->mixer_data[u8Idx + 1] = RT_HI_U8(v);
572}
573
574static uint16_t ichac97MixerGet(PAC97STATE pThis, uint32_t u8Idx)
575{
576 uint16_t uVal;
577
578 if (u8Idx + 2 > sizeof(pThis->mixer_data))
579 {
580 AssertMsgFailed(("Index %RU8 out of bounds (%zu)\n", u8Idx, sizeof(pThis->mixer_data)));
581 uVal = UINT16_MAX;
582 }
583 else
584 uVal = RT_MAKE_U16(pThis->mixer_data[u8Idx + 0], pThis->mixer_data[u8Idx + 1]);
585
586 return uVal;
587}
588
589static DECLCALLBACK(void) ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
590{
591 NOREF(pThis);
592 NOREF(enmRecSource);
593 LogFlowFuncEnter();
594}
595
596static DECLCALLBACK(void) ichac97CloseOut(PAC97STATE pThis)
597{
598 NOREF(pThis);
599 LogFlowFuncEnter();
600}
601
602static int ichac97OpenIn(PAC97STATE pThis,
603 const char *pszName, PDMAUDIORECSOURCE enmRecSource,
604 PPDMAUDIOSTREAMCFG pCfg)
605{
606 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
607 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
608 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
609
610 PAUDMIXSINK pSink;
611 switch (enmRecSource)
612 {
613 case PDMAUDIORECSOURCE_MIC:
614 pSink = pThis->pSinkMicIn;
615 break;
616 case PDMAUDIORECSOURCE_LINE_IN:
617 pSink = pThis->pSinkLineIn;
618 break;
619 default:
620 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
621 return VERR_NOT_SUPPORTED;
622 }
623
624 int rc = VINF_SUCCESS;
625
626 PAC97DRIVER pDrv;
627 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
628 {
629 char *pszDesc;
630 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
631 {
632 rc = VERR_NO_MEMORY;
633 break;
634 }
635
636 PAC97INPUTSTREAM pStrmIn;
637 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
638 pStrmIn = &pDrv->MicIn;
639 else
640 pStrmIn = &pDrv->LineIn;
641
642 rc = pDrv->pConnector->pfnCreateIn(pDrv->pConnector, pszDesc, enmRecSource, pCfg, &pStrmIn->pStrmIn);
643
644 LogFlowFunc(("LUN#%RU8: Created input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
645 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
646 {
647 AudioMixerRemoveStream(pSink, pStrmIn->phStrmIn);
648 rc = AudioMixerAddStreamIn(pSink,
649 pDrv->pConnector, pStrmIn->pStrmIn,
650 0 /* uFlags */, &pStrmIn->phStrmIn);
651 }
652
653 RTStrFree(pszDesc);
654 }
655
656 LogFlowFuncLeaveRC(rc);
657 return rc;
658}
659
660static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
661{
662 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
663 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
664 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
665
666 int rc = VINF_SUCCESS;
667 char *pszDesc;
668
669 PAC97DRIVER pDrv;
670 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
671 {
672 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s (%RU32Hz, %RU8 %s)",
673 pDrv->uLUN, pszName, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel") <= 0)
674 {
675 rc = VERR_NO_MEMORY;
676 break;
677 }
678
679 rc = pDrv->pConnector->pfnCreateOut(pDrv->pConnector, pszDesc, pCfg, &pDrv->Out.pStrmOut);
680 LogFlowFunc(("LUN#%RU8: Created output \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
681 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
682 {
683 AudioMixerRemoveStream(pThis->pSinkOutput, pDrv->Out.phStrmOut);
684 rc = AudioMixerAddStreamOut(pThis->pSinkOutput,
685 pDrv->pConnector, pDrv->Out.pStrmOut,
686 0 /* uFlags */, &pDrv->Out.phStrmOut);
687 }
688
689 RTStrFree(pszDesc);
690 }
691
692 LogFlowFuncLeaveRC(rc);
693 return rc;
694}
695
696static int ichac97StreamInitEx(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm, PPDMAUDIOSTREAMCFG pCfg)
697{
698 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
699 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
700 AssertReturn(u8Strm <= LAST_INDEX, VERR_INVALID_PARAMETER);
701 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
702
703 pStrmSt->u8Strm = u8Strm;
704
705 LogFlowFunc(("u8Strm=%RU8, %RU32Hz, %RU8 %s\n",
706 pStrmSt->u8Strm, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"));
707
708 int rc;
709 switch (pStrmSt->u8Strm)
710 {
711 case PI_INDEX:
712 rc = ichac97OpenIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE_IN, pCfg);
713 break;
714
715 case MC_INDEX:
716 rc = ichac97OpenIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);
717 break;
718
719 case PO_INDEX:
720 rc = ichac97OpenOut(pThis, "ac97.po", pCfg);
721 break;
722
723 default:
724 rc = VERR_NOT_SUPPORTED;
725 break;
726 }
727
728 LogFlowFuncLeaveRC(rc);
729 return rc;
730}
731
732static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStrmSt, uint8_t u8Strm)
733{
734 int rc = VINF_SUCCESS;
735
736 PDMAUDIOSTREAMCFG streamCfg;
737 RT_ZERO(streamCfg);
738
739 switch (u8Strm)
740 {
741 case PI_INDEX:
742 streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_LR_ADC_Rate);
743 break;
744
745 case MC_INDEX:
746 streamCfg.uHz = ichac97MixerGet(pThis, AC97_MIC_ADC_Rate);
747 break;
748
749 case PO_INDEX:
750 streamCfg.uHz = ichac97MixerGet(pThis, AC97_PCM_Front_DAC_Rate);
751 break;
752
753 default:
754 rc = VERR_NOT_SUPPORTED;
755 break;
756 }
757
758 if (RT_FAILURE(rc))
759 return rc;
760
761 if (streamCfg.uHz)
762 {
763 streamCfg.cChannels = 2;
764 streamCfg.enmFormat = AUD_FMT_S16;
765 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
766
767 return ichac97StreamInitEx(pThis, pStrmSt, u8Strm, &streamCfg);
768 }
769
770 /* If no frequency is given, disable the stream. */
771 return ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
772}
773
774static int ichac97StreamReInit(PAC97STATE pThis, PAC97STREAM pStrmSt)
775{
776 return ichac97StreamInit(pThis, pStrmSt, pStrmSt->u8Strm);
777}
778
779static void ichac97StreamReset(PAC97STATE pThis, PAC97STREAM pStrmSt)
780{
781 AssertPtrReturnVoid(pThis);
782 AssertPtrReturnVoid(pStrmSt);
783
784 LogFlowFunc(("uStrm=%RU8\n", pStrmSt->u8Strm));
785}
786
787static int ichac97MixerSetVolume(PAC97STATE pThis, int index, PDMAUDIOMIXERCTL mt, uint32_t val)
788{
789 int mute = (val >> MUTE_SHIFT) & 1;
790 uint8_t rvol = val & VOL_MASK;
791 uint8_t lvol = (val >> 8) & VOL_MASK;
792
793 /* For the master volume, 0 corresponds to 0dB gain. But for the other
794 * volume controls, 0 corresponds to +12dB and 8 to 0dB. */
795 if (mt != PDMAUDIOMIXERCTL_VOLUME)
796 {
797 /* NB: Currently there is no gain support, only attenuation. */
798 lvol = lvol < 8 ? 0 : lvol - 8;
799 rvol = rvol < 8 ? 0 : rvol - 8;
800 }
801
802 /* AC'97 has 1.5dB steps; we use 0.375dB steps. */
803 rvol = 255 - rvol * 4;
804 lvol = 255 - lvol * 4;
805
806 LogFunc(("mt=%ld, val=%RX32, mute=%RTbool\n", mt, val, RT_BOOL(mute)));
807
808 int rc;
809
810#ifdef SOFT_VOLUME
811 if (pThis->pMixer) /* Device can be in reset state, so no mixer available. */
812 {
813 PDMAUDIOVOLUME vol = { RT_BOOL(mute), lvol, rvol };
814 switch (mt)
815 {
816 case PDMAUDIOMIXERCTL_VOLUME:
817 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
818 break;
819
820 case PDMAUDIOMIXERCTL_PCM:
821 rc = AudioMixerSetSinkVolume(pThis->pSinkOutput, &vol);
822 break;
823
824 case PDMAUDIOMIXERCTL_MIC_IN:
825 rc = AudioMixerSetSinkVolume(pThis->pSinkMicIn, &vol);
826 break;
827
828 case PDMAUDIOMIXERCTL_LINE_IN:
829 rc = AudioMixerSetSinkVolume(pThis->pSinkLineIn, &vol);
830 break;
831
832 default:
833 rc = VERR_NOT_SUPPORTED;
834 break;
835 }
836 }
837 else
838 rc = VERR_NOT_SUPPORTED;
839
840 if (RT_FAILURE(rc))
841 return rc;
842#else
843 rc = VINF_SUCCESS;
844#endif /* SOFT_VOLUME */
845
846 rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
847 lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
848
849 /*
850 * From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
851 * maintain compatibility whenever the D5 or D13 bits are set to `1,' their respective
852 * lower five volume bits are automatically set to `1' by the Codec logic. On readback,
853 * all lower 5 bits will read ones whenever these bits are set to `1.'"
854 *
855 * Linux ALSA depends on this behavior.
856 */
857 if (val & RT_BIT(5))
858 val |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0);
859 if (val & RT_BIT(13))
860 val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
861
862 ichac97MixerSet(pThis, index, val);
863
864 return rc;
865}
866
867static PDMAUDIORECSOURCE ichac97IndextoRecSource(uint8_t i)
868{
869 switch (i)
870 {
871 case REC_MIC: return PDMAUDIORECSOURCE_MIC;
872 case REC_CD: return PDMAUDIORECSOURCE_CD;
873 case REC_VIDEO: return PDMAUDIORECSOURCE_VIDEO;
874 case REC_AUX: return PDMAUDIORECSOURCE_AUX;
875 case REC_LINE_IN: return PDMAUDIORECSOURCE_LINE_IN;
876 case REC_PHONE: return PDMAUDIORECSOURCE_PHONE;
877 default:
878 break;
879 }
880
881 LogFlowFunc(("Unknown record source %d, using MIC\n", i));
882 return PDMAUDIORECSOURCE_MIC;
883}
884
885static uint8_t ichac97RecSourceToIndex(PDMAUDIORECSOURCE rs)
886{
887 switch (rs)
888 {
889 case PDMAUDIORECSOURCE_MIC: return REC_MIC;
890 case PDMAUDIORECSOURCE_CD: return REC_CD;
891 case PDMAUDIORECSOURCE_VIDEO: return REC_VIDEO;
892 case PDMAUDIORECSOURCE_AUX: return REC_AUX;
893 case PDMAUDIORECSOURCE_LINE_IN: return REC_LINE_IN;
894 case PDMAUDIORECSOURCE_PHONE: return REC_PHONE;
895 default:
896 break;
897 }
898
899 LogFlowFunc(("Unknown audio recording source %d using MIC\n", rs));
900 return REC_MIC;
901}
902
903static void ichac97RecordSelect(PAC97STATE pThis, uint32_t val)
904{
905 uint8_t rs = val & REC_MASK;
906 uint8_t ls = (val >> 8) & REC_MASK;
907 PDMAUDIORECSOURCE ars = ichac97IndextoRecSource(rs);
908 PDMAUDIORECSOURCE als = ichac97IndextoRecSource(ls);
909 //AUD_set_record_source(&als, &ars);
910 rs = ichac97RecSourceToIndex(ars);
911 ls = ichac97RecSourceToIndex(als);
912 ichac97MixerSet(pThis, AC97_Record_Select, rs | (ls << 8));
913}
914
915static int ichac97MixerReset(PAC97STATE pThis)
916{
917 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
918
919 LogFlowFuncEnter();
920
921 RT_ZERO(pThis->mixer_data);
922
923 /* Note: Make sure to reset all registers first before bailing out on error. */
924
925 ichac97MixerSet(pThis, AC97_Reset , 0x0000); /* 6940 */
926 ichac97MixerSet(pThis, AC97_Master_Volume_Mono_Mute , 0x8000);
927 ichac97MixerSet(pThis, AC97_PC_BEEP_Volume_Mute , 0x0000);
928
929 ichac97MixerSet(pThis, AC97_Phone_Volume_Mute , 0x8008);
930 ichac97MixerSet(pThis, AC97_Mic_Volume_Mute , 0x8008);
931 ichac97MixerSet(pThis, AC97_CD_Volume_Mute , 0x8808);
932 ichac97MixerSet(pThis, AC97_Aux_Volume_Mute , 0x8808);
933 ichac97MixerSet(pThis, AC97_Record_Gain_Mic_Mute , 0x8000);
934 ichac97MixerSet(pThis, AC97_General_Purpose , 0x0000);
935 ichac97MixerSet(pThis, AC97_3D_Control , 0x0000);
936 ichac97MixerSet(pThis, AC97_Powerdown_Ctrl_Stat , 0x000f);
937
938 ichac97MixerSet(pThis, AC97_Extended_Audio_ID , 0x0809);
939 ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
940 ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate , 0xbb80);
941 ichac97MixerSet(pThis, AC97_PCM_Surround_DAC_Rate , 0xbb80);
942 ichac97MixerSet(pThis, AC97_PCM_LFE_DAC_Rate , 0xbb80);
943 ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate , 0xbb80);
944 ichac97MixerSet(pThis, AC97_MIC_ADC_Rate , 0xbb80);
945
946 if (pThis->uCodecModel == Codec_AD1980)
947 {
948 /* Analog Devices 1980 (AD1980) */
949 ichac97MixerSet(pThis, AC97_Reset , 0x0010); /* Headphones. */
950 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x4144);
951 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x5370);
952 ichac97MixerSet(pThis, AC97_Headphone_Volume_Mute , 0x8000);
953 }
954 else if (pThis->uCodecModel == Codec_AD1981B)
955 {
956 /* Analog Devices 1981B (AD1981B) */
957 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x4144);
958 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x5374);
959 }
960 else
961 {
962 /* Sigmatel 9700 (STAC9700) */
963 ichac97MixerSet(pThis, AC97_Vendor_ID1 , 0x8384);
964 ichac97MixerSet(pThis, AC97_Vendor_ID2 , 0x7600); /* 7608 */
965 }
966 ichac97RecordSelect(pThis, 0);
967
968 ichac97MixerSetVolume(pThis, AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME, 0x8000);
969 ichac97MixerSetVolume(pThis, AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_PCM, 0x8808);
970 ichac97MixerSetVolume(pThis, AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN, 0x8808);
971
972 return VINF_SUCCESS;
973}
974
975/**
976 * Writes data from the device to the host backends.
977 *
978 * @return IPRT status code.
979 * @param pThis
980 * @param pStrmSt
981 * @param cbMax
982 * @param pcbWritten
983 */
984static int ichac97WriteAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbWritten)
985{
986 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
987 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
988 AssertReturn(cbMax, VERR_INVALID_PARAMETER);
989 /* pcbWritten is optional. */
990
991 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
992 PAC97BMREGS pRegs = &pStrmSt->Regs;
993
994 uint32_t addr = pRegs->bd.addr;
995 uint32_t cbWrittenTotal = 0;
996 uint32_t cbToRead;
997
998 uint32_t cbToWrite = RT_MIN((uint32_t)(pRegs->picb << 1), cbMax);
999 if (!cbToWrite)
1000 {
1001 if (pcbWritten)
1002 *pcbWritten = 0;
1003 return VINF_EOF;
1004 }
1005
1006 int rc = VINF_SUCCESS;
1007
1008 LogFlowFunc(("pReg=%p, cbMax=%RU32, cbToWrite=%RU32\n", pRegs, cbMax, cbToWrite));
1009
1010 while (cbToWrite)
1011 {
1012 cbToRead = RT_MIN(cbToWrite, pThis->cbReadWriteBuf);
1013 PDMDevHlpPhysRead(pDevIns, addr, pThis->pvReadWriteBuf, cbToRead); /** @todo Check rc? */
1014
1015 uint32_t cbWritten;
1016
1017 /* Just multiplex the output to the connected backends.
1018 * No need to utilize the virtual mixer here (yet). */
1019 PAC97DRIVER pDrv;
1020 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
1021 {
1022 int rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
1023 pThis->pvReadWriteBuf, cbToRead, &cbWritten);
1024 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWritten=%RU32\n", pDrv->uLUN, rc2, cbWritten));
1025 }
1026
1027 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbLeft=%RU32\n",
1028 cbToRead, cbToWrite, cbToWrite - cbWrittenTotal));
1029
1030 Assert(cbToWrite >= cbToRead);
1031 cbToWrite -= cbToRead;
1032 addr += cbToRead;
1033 cbWrittenTotal += cbToRead;
1034 }
1035
1036 pRegs->bd.addr = addr;
1037
1038 if (RT_SUCCESS(rc))
1039 {
1040 if (!cbToWrite) /* All data written? */
1041 {
1042 if (cbToRead < 4)
1043 {
1044 AssertMsgFailed(("Unable to save last written sample, cbToRead < 4 (is %RU32)\n", cbToRead));
1045 pThis->last_samp = 0;
1046 }
1047 else
1048 pThis->last_samp = *(uint32_t *)&pThis->pvReadWriteBuf[cbToRead - 4];
1049 }
1050
1051 if (pcbWritten)
1052 *pcbWritten = cbWrittenTotal;
1053 }
1054
1055 LogFlowFunc(("cbWrittenTotal=%RU32, rc=%Rrc\n", cbWrittenTotal, rc));
1056 return rc;
1057}
1058
1059static void ichac97WriteBUP(PAC97STATE pThis, uint32_t cbElapsed)
1060{
1061 if (!(pThis->bup_flag & BUP_SET))
1062 {
1063 if (pThis->bup_flag & BUP_LAST)
1064 {
1065 unsigned int i;
1066 uint32_t *p = (uint32_t*)pThis->silence;
1067 for (i = 0; i < sizeof(pThis->silence) / 4; i++)
1068 *p++ = pThis->last_samp;
1069 }
1070 else
1071 RT_ZERO(pThis->silence);
1072
1073 pThis->bup_flag |= BUP_SET;
1074 }
1075
1076 while (cbElapsed)
1077 {
1078 uint32_t cbToWrite = RT_MIN(cbElapsed, (uint32_t)sizeof(pThis->silence));
1079 uint32_t cbWrittenToStream;
1080 int rc2;
1081
1082 PAC97DRIVER pDrv;
1083 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
1084 {
1085 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
1086 {
1087 rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
1088 pThis->silence, cbToWrite, &cbWrittenToStream);
1089 if (RT_SUCCESS(rc2))
1090 {
1091 if (cbWrittenToStream < cbToWrite) /* Lagging behind? */
1092 LogFlowFunc(("\tLUN#%RU8: Warning: Only written %RU32 / %RU32 bytes, expect lags\n",
1093 pDrv->uLUN, cbWrittenToStream, cbToWrite));
1094 }
1095 }
1096 else /* Stream disabled, not fatal. */
1097 {
1098 cbWrittenToStream = 0;
1099 rc2 = VERR_NOT_AVAILABLE;
1100 /* Keep going. */
1101 }
1102 }
1103
1104 /* Always report all data as being written;
1105 * backends who were not able to catch up have to deal with it themselves. */
1106 Assert(cbElapsed >= cbToWrite);
1107 cbElapsed -= cbToWrite;
1108 }
1109}
1110
1111static int ichac97ReadAudio(PAC97STATE pThis, PAC97STREAM pStrmSt, uint32_t cbMax, uint32_t *pcbRead)
1112{
1113 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1114 AssertPtrReturn(pStrmSt, VERR_INVALID_POINTER);
1115 AssertReturn(cbMax, VERR_INVALID_PARAMETER);
1116 /* pcbRead is optional. */
1117
1118 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
1119 PAC97BMREGS pRegs = &pStrmSt->Regs;
1120
1121 /* Select audio sink to process. */
1122 AssertMsg(pStrmSt->u8Strm != PO_INDEX, ("Can't read from output\n"));
1123 PAUDMIXSINK pSink = pStrmSt->u8Strm == MC_INDEX ? pThis->pSinkMicIn : pThis->pSinkLineIn;
1124 AssertPtr(pSink);
1125
1126 uint32_t cbRead = 0;
1127
1128 uint32_t cbMixBuf = cbMax;
1129 uint32_t cbToRead = RT_MIN((uint32_t)(pRegs->picb << 1), cbMixBuf);
1130
1131 if (!cbToRead)
1132 {
1133 if (pcbRead)
1134 *pcbRead = 0;
1135 return VINF_EOF;
1136 }
1137
1138 int rc;
1139
1140 uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbMixBuf);
1141 if (pvMixBuf)
1142 {
1143 rc = AudioMixerProcessSinkIn(pSink, AUDMIXOP_BLEND, pvMixBuf, cbToRead, &cbRead);
1144 if ( RT_SUCCESS(rc)
1145 && cbRead)
1146 {
1147 PDMDevHlpPCIPhysWrite(pDevIns, pRegs->bd.addr, pvMixBuf, cbRead);
1148 pRegs->bd.addr += cbRead;
1149 }
1150
1151 RTMemFree(pvMixBuf);
1152 }
1153 else
1154 rc = VERR_NO_MEMORY;
1155
1156 if (RT_SUCCESS(rc))
1157 {
1158 if (pcbRead)
1159 *pcbRead = cbRead;
1160 }
1161
1162 return rc;
1163}
1164
1165#ifndef VBOX_WITH_AUDIO_CALLBACKS
1166
1167static DECLCALLBACK(void) ichac97Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1168{
1169 PAC97STATE pThis = (PAC97STATE)pvUser;
1170 Assert(pThis == PDMINS_2_DATA(pDevIns, PAC97STATE));
1171 AssertPtr(pThis);
1172
1173 STAM_PROFILE_START(&pThis->StatTimer, a);
1174
1175 int rc = VINF_SUCCESS;
1176
1177 uint32_t cbInMax = 0;
1178 uint32_t cbOutMin = UINT32_MAX;
1179
1180 PAC97DRIVER pDrv;
1181
1182 uint64_t cTicksNow = TMTimerGet(pTimer);
1183 uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS;
1184 uint64_t cTicksPerSec = TMTimerGetFreq(pTimer);
1185
1186 pThis->uTimerTS = cTicksNow;
1187
1188 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
1189 {
1190 uint32_t cbIn = 0;
1191 uint32_t cbOut = 0;
1192
1193 rc = pDrv->pConnector->pfnQueryStatus(pDrv->pConnector,
1194 &cbIn, &cbOut, NULL /* cSamplesLive */);
1195 if (RT_SUCCESS(rc))
1196 rc = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, NULL /* cSamplesPlayed */);
1197
1198#ifdef DEBUG_TIMER
1199 LogFlowFunc(("LUN#%RU8: rc=%Rrc, cbIn=%RU32, cbOut=%RU32\n", pDrv->uLUN, rc, cbIn, cbOut));
1200#endif
1201 const bool fIsActiveOut = pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut);
1202
1203 /* If we there was an error handling (available) output or there simply is no output available,
1204 * then calculate the minimum data rate which must be processed by the device emulation in order
1205 * to function correctly.
1206 *
1207 * This is not the optimal solution, but as we have to deal with this on a timer-based approach
1208 * (until we have the audio callbacks) we need to have device' DMA engines running. */
1209 if ( RT_FAILURE(rc)
1210 || !fIsActiveOut)
1211 {
1212 uint32_t cSamplesMin = (int)((2 * cTicksElapsed * pDrv->Out.pStrmOut->Props.uHz + cTicksPerSec) / cTicksPerSec / 2);
1213 uint32_t cbSamplesMin = AUDIOMIXBUF_S2B(&pDrv->Out.pStrmOut->MixBuf, cSamplesMin);
1214
1215#ifdef DEBUG_TIMER
1216 LogFlowFunc(("\trc=%Rrc, cSamplesMin=%RU32, cbSamplesMin=%RU32\n", rc, cSamplesMin, cbSamplesMin));
1217#endif
1218 cbOut = RT_MAX(cbOut, cbSamplesMin);
1219 }
1220
1221 cbOutMin = RT_MIN(cbOutMin, cbOut);
1222 cbInMax = RT_MAX(cbInMax, cbIn);
1223 }
1224
1225#ifdef DEBUG_TIMER
1226 LogFlowFunc(("cbInMax=%RU32, cbOutMin=%RU32\n", cbInMax, cbOutMin));
1227#endif
1228
1229 if (cbOutMin == UINT32_MAX)
1230 cbOutMin = 0;
1231
1232 /*
1233 * Playback.
1234 */
1235 if (cbOutMin)
1236 {
1237 Assert(cbOutMin != UINT32_MAX);
1238 ichac97TransferAudio(pThis, PO_INDEX, cbOutMin); /** @todo Add rc! */
1239 }
1240
1241 /*
1242 * Recording.
1243 */
1244 if (cbInMax)
1245 ichac97TransferAudio(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */
1246
1247 /* Kick the timer again. */
1248 uint64_t cTicks = pThis->cTimerTicks;
1249 /** @todo adjust cTicks down by now much cbOutMin represents. */
1250 TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
1251
1252 STAM_PROFILE_STOP(&pThis->StatTimer, a);
1253}
1254
1255#endif
1256
1257static int ichac97TransferAudio(PAC97STATE pThis, AC97SOUNDSOURCE enmSrc, uint32_t cbElapsed)
1258{
1259 LogFlowFunc(("pThis=%p, enmSrc=%RU32, cbElapsed=%RU32\n", pThis, enmSrc, cbElapsed));
1260
1261 PAC97STREAM pStrmSt;
1262 switch (enmSrc)
1263 {
1264 case PI_INDEX: pStrmSt = &pThis->StrmStLineIn; break;
1265 case MC_INDEX: pStrmSt = &pThis->StrmStMicIn; break;
1266 case PO_INDEX: pStrmSt = &pThis->StrmStOut; break;
1267 default:
1268 {
1269 AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
1270 return VERR_NOT_SUPPORTED;
1271 }
1272 }
1273
1274 PAC97BMREGS pRegs = &pStrmSt->Regs;
1275
1276 if (pRegs->sr & SR_DCH) /* Controller halted? */
1277 {
1278 if (pRegs->cr & CR_RPBM)
1279 {
1280 switch (enmSrc)
1281 {
1282 case PO_INDEX:
1283 ichac97WriteBUP(pThis, cbElapsed);
1284 break;
1285
1286 default:
1287 break;
1288 }
1289 }
1290
1291 return VINF_SUCCESS;
1292 }
1293
1294 int rc = VINF_SUCCESS;
1295 uint32_t cbWrittenTotal = 0;
1296
1297 while (cbElapsed >> 1)
1298 {
1299 if (!pRegs->bd_valid)
1300 {
1301 LogFlowFunc(("Invalid buffer descriptor, fetching next one ...\n"));
1302 ichac97StreamFetchBDLE(pThis, pStrmSt);
1303 }
1304
1305 if (!pRegs->picb) /* Got a new buffer descriptor, that is, the position is 0? */
1306 {
1307 LogFlowFunc(("Fresh buffer descriptor %RU8 is empty, addr=%#x, len=%#x, skipping\n",
1308 pRegs->civ, pRegs->bd.addr, pRegs->bd.ctl_len));
1309 if (pRegs->civ == pRegs->lvi)
1310 {
1311 pRegs->sr |= SR_DCH; /* CELV? */
1312 pThis->bup_flag = 0;
1313
1314 rc = VINF_EOF;
1315 break;
1316 }
1317
1318 pRegs->sr &= ~SR_CELV;
1319 pRegs->civ = pRegs->piv;
1320 pRegs->piv = (pRegs->piv + 1) % 32;
1321
1322 ichac97StreamFetchBDLE(pThis, pStrmSt);
1323 continue;
1324 }
1325
1326 uint32_t cbTransferred;
1327 switch (enmSrc)
1328 {
1329 case PO_INDEX:
1330 {
1331 rc = ichac97WriteAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
1332 if ( RT_SUCCESS(rc)
1333 && cbTransferred)
1334 {
1335 cbWrittenTotal += cbTransferred;
1336 Assert(cbElapsed >= cbTransferred);
1337 cbElapsed -= cbTransferred;
1338 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
1339 pRegs->picb -= (cbTransferred >> 1);
1340 }
1341 break;
1342 }
1343
1344 case PI_INDEX:
1345 case MC_INDEX:
1346 {
1347 rc = ichac97ReadAudio(pThis, pStrmSt, cbElapsed, &cbTransferred);
1348 if ( RT_SUCCESS(rc)
1349 && cbTransferred)
1350 {
1351 Assert(cbElapsed >= cbTransferred);
1352 cbElapsed -= cbTransferred;
1353 Assert((cbTransferred & 1) == 0); /* Else the following shift won't work */
1354 pRegs->picb -= (cbTransferred >> 1);
1355 }
1356 break;
1357 }
1358
1359 default:
1360 AssertMsgFailed(("Source %RU32 not supported\n", enmSrc));
1361 rc = VERR_NOT_SUPPORTED;
1362 break;
1363 }
1364
1365 LogFlowFunc(("pReg->picb=%#x, cbWrittenTotal=%RU32\n", pRegs->picb, cbWrittenTotal));
1366
1367 if (!pRegs->picb)
1368 {
1369 uint32_t new_sr = pRegs->sr & ~SR_CELV;
1370
1371 if (pRegs->bd.ctl_len & BD_IOC)
1372 {
1373 new_sr |= SR_BCIS;
1374 }
1375
1376 if (pRegs->civ == pRegs->lvi)
1377 {
1378 LogFlowFunc(("Underrun civ (%RU8) == lvi (%RU8)\n", pRegs->civ, pRegs->lvi));
1379 new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
1380 pThis->bup_flag = (pRegs->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
1381
1382 rc = VINF_EOF;
1383 }
1384 else
1385 {
1386 pRegs->civ = pRegs->piv;
1387 pRegs->piv = (pRegs->piv + 1) % 32;
1388 ichac97StreamFetchBDLE(pThis, pStrmSt);
1389 }
1390
1391 ichac97StreamUpdateStatus(pThis, pStrmSt, new_sr);
1392 }
1393
1394 if ( RT_FAILURE(rc)
1395 || rc == VINF_EOF) /* All data processed? */
1396 {
1397 break;
1398 }
1399 }
1400
1401 LogFlowFuncLeaveRC(rc);
1402 return rc;
1403}
1404
1405/**
1406 * @callback_method_impl{FNIOMIOPORTIN}
1407 */
1408static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
1409 uint32_t *pu32Val, unsigned cbVal)
1410{
1411 PAC97STATE pThis = (PAC97STATE)pvUser;
1412
1413 /* Get the index of the NABMBAR port. */
1414 const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
1415
1416 PAC97STREAM pStrmSt = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
1417 PAC97BMREGS pRegs = pStrmSt ? &pStrmSt->Regs : NULL;
1418
1419 switch (cbVal)
1420 {
1421 case 1:
1422 {
1423 switch (uPortIdx)
1424 {
1425 case CAS:
1426 /* Codec Access Semaphore Register */
1427 LogFlowFunc(("CAS %d\n", pThis->cas));
1428 *pu32Val = pThis->cas;
1429 pThis->cas = 1;
1430 break;
1431 case PI_CIV:
1432 case PO_CIV:
1433 case MC_CIV:
1434 /* Current Index Value Register */
1435 *pu32Val = pRegs->civ;
1436 LogFlowFunc(("CIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1437 break;
1438 case PI_LVI:
1439 case PO_LVI:
1440 case MC_LVI:
1441 /* Last Valid Index Register */
1442 *pu32Val = pRegs->lvi;
1443 LogFlowFunc(("LVI[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1444 break;
1445 case PI_PIV:
1446 case PO_PIV:
1447 case MC_PIV:
1448 /* Prefetched Index Value Register */
1449 *pu32Val = pRegs->piv;
1450 LogFlowFunc(("PIV[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1451 break;
1452 case PI_CR:
1453 case PO_CR:
1454 case MC_CR:
1455 /* Control Register */
1456 *pu32Val = pRegs->cr;
1457 LogFlowFunc(("CR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1458 break;
1459 case PI_SR:
1460 case PO_SR:
1461 case MC_SR:
1462 /* Status Register (lower part) */
1463 *pu32Val = pRegs->sr & 0xff; /** @todo r=andy Use RT_LO_U8. */
1464 LogFlowFunc(("SRb[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1465 break;
1466 default:
1467 *pu32Val = UINT32_MAX;
1468 LogFlowFunc(("U nabm readb %#x -> %#x\n", Port, *pu32Val));
1469 break;
1470 }
1471 break;
1472 }
1473
1474 case 2:
1475 {
1476 switch (uPortIdx)
1477 {
1478 case PI_SR:
1479 case PO_SR:
1480 case MC_SR:
1481 /* Status Register */
1482 *pu32Val = pRegs->sr;
1483 LogFlowFunc(("SR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1484 break;
1485 case PI_PICB:
1486 case PO_PICB:
1487 case MC_PICB:
1488 /* Position in Current Buffer Register */
1489 *pu32Val = pRegs->picb;
1490 LogFlowFunc(("PICB[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1491 break;
1492 default:
1493 *pu32Val = UINT32_MAX;
1494 LogFlowFunc(("U nabm readw %#x -> %#x\n", Port, *pu32Val));
1495 break;
1496 }
1497 break;
1498 }
1499
1500 case 4:
1501 {
1502 switch (uPortIdx)
1503 {
1504 case PI_BDBAR:
1505 case PO_BDBAR:
1506 case MC_BDBAR:
1507 /* Buffer Descriptor Base Address Register */
1508 *pu32Val = pRegs->bdbar;
1509 LogFlowFunc(("BMADDR[%d] -> %#x\n", AC97_PORT2IDX(uPortIdx), *pu32Val));
1510 break;
1511 case PI_CIV:
1512 case PO_CIV:
1513 case MC_CIV:
1514 /* 32-bit access: Current Index Value Register +
1515 * Last Valid Index Register +
1516 * Status Register */
1517 *pu32Val = pRegs->civ | (pRegs->lvi << 8) | (pRegs->sr << 16); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
1518 LogFlowFunc(("CIV LVI SR[%d] -> %#x, %#x, %#x\n",
1519 AC97_PORT2IDX(uPortIdx), pRegs->civ, pRegs->lvi, pRegs->sr));
1520 break;
1521 case PI_PICB:
1522 case PO_PICB:
1523 case MC_PICB:
1524 /* 32-bit access: Position in Current Buffer Register +
1525 * Prefetched Index Value Register +
1526 * Control Register */
1527 *pu32Val = pRegs->picb | (pRegs->piv << 16) | (pRegs->cr << 24); /** @todo r=andy Use RT_MAKE_U32_FROM_U8. */
1528 LogFlowFunc(("PICB PIV CR[%d] -> %#x %#x %#x %#x\n",
1529 AC97_PORT2IDX(uPortIdx), *pu32Val, pRegs->picb, pRegs->piv, pRegs->cr));
1530 break;
1531 case GLOB_CNT:
1532 /* Global Control */
1533 *pu32Val = pThis->glob_cnt;
1534 LogFlowFunc(("glob_cnt -> %#x\n", *pu32Val));
1535 break;
1536 case GLOB_STA:
1537 /* Global Status */
1538 *pu32Val = pThis->glob_sta | GS_S0CR;
1539 LogFlowFunc(("glob_sta -> %#x\n", *pu32Val));
1540 break;
1541 default:
1542 *pu32Val = UINT32_MAX;
1543 LogFlowFunc(("U nabm readl %#x -> %#x\n", Port, *pu32Val));
1544 break;
1545 }
1546 break;
1547 }
1548
1549 default:
1550 return VERR_IOM_IOPORT_UNUSED;
1551 }
1552 return VINF_SUCCESS;
1553}
1554
1555/**
1556 * @callback_method_impl{FNIOMIOPORTOUT}
1557 */
1558static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
1559 uint32_t u32Val, unsigned cbVal)
1560{
1561 PAC97STATE pThis = (PAC97STATE)pvUser;
1562
1563 /* Get the index of the NABMBAR register. */
1564 const uint32_t uPortIdx = Port - pThis->IOPortBase[1];
1565
1566 PAC97STREAM pStrmSt = ichac97GetStreamFromID(pThis, AC97_PORT2IDX(uPortIdx));
1567 PAC97BMREGS pRegs = pStrmSt ? &pStrmSt->Regs : NULL;
1568
1569 switch (cbVal)
1570 {
1571 case 1:
1572 {
1573 switch (uPortIdx)
1574 {
1575 case PI_LVI:
1576 case PO_LVI:
1577 case MC_LVI:
1578 /* Last Valid Index */
1579 if ((pRegs->cr & CR_RPBM) && (pRegs->sr & SR_DCH))
1580 {
1581 pRegs->sr &= ~(SR_DCH | SR_CELV);
1582 pRegs->civ = pRegs->piv;
1583 pRegs->piv = (pRegs->piv + 1) % 32;
1584
1585 ichac97StreamFetchBDLE(pThis, pStrmSt);
1586 }
1587 pRegs->lvi = u32Val % 32;
1588 LogFlowFunc(("LVI[%d] <- %#x\n", AC97_PORT2IDX(uPortIdx), u32Val));
1589 break;
1590 case PI_CR:
1591 case PO_CR:
1592 case MC_CR:
1593 {
1594 /* Control Register */
1595 if (u32Val & CR_RR) /* Busmaster reset */
1596 {
1597 ichac97StreamResetBMRegs(pThis, pStrmSt);
1598 }
1599 else
1600 {
1601 pRegs->cr = u32Val & CR_VALID_MASK;
1602 if (!(pRegs->cr & CR_RPBM))
1603 {
1604 ichac97StreamSetActive(pThis, pStrmSt, false /* fActive */);
1605 pRegs->sr |= SR_DCH;
1606 }
1607 else
1608 {
1609 pRegs->civ = pRegs->piv;
1610 pRegs->piv = (pRegs->piv + 1) % 32;
1611
1612 ichac97StreamFetchBDLE(pThis, pStrmSt);
1613
1614 pRegs->sr &= ~SR_DCH;
1615 ichac97StreamSetActive(pThis, pStrmSt, true /* fActive */);
1616 }
1617 }
1618 LogFlowFunc(("CR[%d] <- %#x (cr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->cr));
1619 break;
1620 }
1621 case PI_SR:
1622 case PO_SR:
1623 case MC_SR:
1624 /* Status Register */
1625 pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
1626 ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
1627 LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
1628 break;
1629 default:
1630 LogFlowFunc(("U nabm writeb %#x <- %#x\n", Port, u32Val));
1631 break;
1632 }
1633 break;
1634 }
1635
1636 case 2:
1637 {
1638 switch (uPortIdx)
1639 {
1640 case PI_SR:
1641 case PO_SR:
1642 case MC_SR:
1643 /* Status Register */
1644 pRegs->sr |= u32Val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
1645 ichac97StreamUpdateStatus(pThis, pStrmSt, pRegs->sr & ~(u32Val & SR_WCLEAR_MASK));
1646 LogFlowFunc(("SR[%d] <- %#x (sr %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->sr));
1647 break;
1648 default:
1649 LogFlowFunc(("U nabm writew %#x <- %#x\n", Port, u32Val));
1650 break;
1651 }
1652 break;
1653 }
1654
1655 case 4:
1656 {
1657 switch (uPortIdx)
1658 {
1659 case PI_BDBAR:
1660 case PO_BDBAR:
1661 case MC_BDBAR:
1662 /* Buffer Descriptor list Base Address Register */
1663 pRegs->bdbar = u32Val & ~3;
1664 LogFlowFunc(("BDBAR[%d] <- %#x (bdbar %#x)\n", AC97_PORT2IDX(uPortIdx), u32Val, pRegs->bdbar));
1665 break;
1666 case GLOB_CNT:
1667 /* Global Control */
1668 if (u32Val & GC_WR)
1669 ichac97WarmReset(pThis);
1670 if (u32Val & GC_CR)
1671 ichac97ColdReset(pThis);
1672 if (!(u32Val & (GC_WR | GC_CR)))
1673 pThis->glob_cnt = u32Val & GC_VALID_MASK;
1674 LogFlowFunc(("glob_cnt <- %#x (glob_cnt %#x)\n", u32Val, pThis->glob_cnt));
1675 break;
1676 case GLOB_STA:
1677 /* Global Status */
1678 pThis->glob_sta &= ~(u32Val & GS_WCLEAR_MASK);
1679 pThis->glob_sta |= (u32Val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
1680 LogFlowFunc(("glob_sta <- %#x (glob_sta %#x)\n", u32Val, pThis->glob_sta));
1681 break;
1682 default:
1683 LogFlowFunc(("U nabm writel %#x <- %#x\n", Port, u32Val));
1684 break;
1685 }
1686 break;
1687 }
1688
1689 default:
1690 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
1691 break;
1692 }
1693 return VINF_SUCCESS;
1694}
1695
1696/**
1697 * @callback_method_impl{FNIOMIOPORTIN}
1698 */
1699static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32Val, unsigned cbVal)
1700{
1701 PAC97STATE pThis = (PAC97STATE)pvUser;
1702
1703 switch (cbVal)
1704 {
1705 case 1:
1706 {
1707 LogFlowFunc(("U nam readb %#x\n", Port));
1708 pThis->cas = 0;
1709 *pu32Val = UINT32_MAX;
1710 break;
1711 }
1712
1713 case 2:
1714 {
1715 uint32_t index = Port - pThis->IOPortBase[0];
1716 *pu32Val = UINT32_MAX;
1717 pThis->cas = 0;
1718 switch (index)
1719 {
1720 default:
1721 *pu32Val = ichac97MixerGet(pThis, index);
1722 LogFlowFunc(("nam readw %#x -> %#x\n", Port, *pu32Val));
1723 break;
1724 }
1725 break;
1726 }
1727
1728 case 4:
1729 {
1730 LogFlowFunc(("U nam readl %#x\n", Port));
1731 pThis->cas = 0;
1732 *pu32Val = UINT32_MAX;
1733 break;
1734 }
1735
1736 default:
1737 return VERR_IOM_IOPORT_UNUSED;
1738 }
1739 return VINF_SUCCESS;
1740}
1741
1742/**
1743 * @callback_method_impl{FNIOMIOPORTOUT}
1744 */
1745static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns,
1746 void *pvUser, RTIOPORT Port, uint32_t u32Val, unsigned cbVal)
1747{
1748 PAC97STATE pThis = (PAC97STATE)pvUser;
1749
1750 switch (cbVal)
1751 {
1752 case 1:
1753 {
1754 LogFlowFunc(("U nam writeb %#x <- %#x\n", Port, u32Val));
1755 pThis->cas = 0;
1756 break;
1757 }
1758
1759 case 2:
1760 {
1761 uint32_t index = Port - pThis->IOPortBase[0];
1762 pThis->cas = 0;
1763 switch (index)
1764 {
1765 case AC97_Reset:
1766 ichac97Reset(pThis->CTX_SUFF(pDevIns));
1767 break;
1768 case AC97_Powerdown_Ctrl_Stat:
1769 u32Val &= ~0xf;
1770 u32Val |= ichac97MixerGet(pThis, index) & 0xf;
1771 ichac97MixerSet(pThis, index, u32Val);
1772 break;
1773 case AC97_Master_Volume_Mute:
1774 if (pThis->uCodecModel == Codec_AD1980)
1775 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_LOSEL)
1776 break; /* Register controls surround (rear), do nothing. */
1777 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val);
1778 break;
1779 case AC97_Headphone_Volume_Mute:
1780 if (pThis->uCodecModel == Codec_AD1980)
1781 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
1782 /* Register controls PCM (front) outputs. */
1783 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_VOLUME, u32Val);
1784 break;
1785 case AC97_PCM_Out_Volume_Mute:
1786 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_PCM, u32Val);
1787 break;
1788 case AC97_Line_In_Volume_Mute:
1789 ichac97MixerSetVolume(pThis, index, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
1790 break;
1791 case AC97_Record_Select:
1792 ichac97RecordSelect(pThis, u32Val);
1793 break;
1794 case AC97_Vendor_ID1:
1795 case AC97_Vendor_ID2:
1796 LogFlowFunc(("Attempt to write vendor ID to %#x\n", u32Val));
1797 break;
1798 case AC97_Extended_Audio_ID:
1799 LogFlowFunc(("Attempt to write extended audio ID to %#x\n", u32Val));
1800 break;
1801 case AC97_Extended_Audio_Ctrl_Stat:
1802 if (!(u32Val & EACS_VRA))
1803 {
1804 ichac97MixerSet(pThis, AC97_PCM_Front_DAC_Rate, 48000);
1805 ichac97StreamReInit(pThis, &pThis->StrmStOut);
1806
1807 ichac97MixerSet(pThis, AC97_PCM_LR_ADC_Rate, 48000);
1808 ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
1809 }
1810 if (!(u32Val & EACS_VRM))
1811 {
1812 ichac97MixerSet(pThis, AC97_MIC_ADC_Rate, 48000);
1813 ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
1814 }
1815 LogFlowFunc(("Setting extended audio control to %#x\n", u32Val));
1816 ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, u32Val);
1817 break;
1818 case AC97_PCM_Front_DAC_Rate:
1819 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
1820 {
1821 ichac97MixerSet(pThis, index, u32Val);
1822 LogFlowFunc(("Set front DAC rate to %RU32\n", u32Val));
1823 ichac97StreamReInit(pThis, &pThis->StrmStOut);
1824 }
1825 else
1826 LogFlowFunc(("Attempt to set front DAC rate to %RU32, but VRA is not set\n", u32Val));
1827 break;
1828 case AC97_MIC_ADC_Rate:
1829 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM)
1830 {
1831 ichac97MixerSet(pThis, index, u32Val);
1832 LogFlowFunc(("Set MIC ADC rate to %RU32\n", u32Val));
1833 ichac97StreamReInit(pThis, &pThis->StrmStMicIn);
1834 }
1835 else
1836 LogFlowFunc(("Attempt to set MIC ADC rate to %RU32, but VRM is not set\n", u32Val));
1837 break;
1838 case AC97_PCM_LR_ADC_Rate:
1839 if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
1840 {
1841 ichac97MixerSet(pThis, index, u32Val);
1842 LogFlowFunc(("Set front LR ADC rate to %RU32\n", u32Val));
1843 ichac97StreamReInit(pThis, &pThis->StrmStLineIn);
1844 }
1845 else
1846 LogFlowFunc(("Attempt to set LR ADC rate to %RU32, but VRA is not set\n", u32Val));
1847 break;
1848 default:
1849 LogFlowFunc(("U nam writew %#x <- %#x\n", Port, u32Val));
1850 ichac97MixerSet(pThis, index, u32Val);
1851 break;
1852 }
1853 break;
1854 }
1855
1856 case 4:
1857 {
1858 LogFlowFunc(("U nam writel %#x <- %#x\n", Port, u32Val));
1859 pThis->cas = 0;
1860 break;
1861 }
1862
1863 default:
1864 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cbVal, u32Val));
1865 break;
1866 }
1867
1868 return VINF_SUCCESS;
1869}
1870
1871
1872/**
1873 * @callback_method_impl{FNPCIIOREGIONMAP}
1874 */
1875static DECLCALLBACK(int) ichac97IOPortMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
1876 PCIADDRESSSPACE enmType)
1877{
1878 PPDMDEVINS pDevIns = pPciDev->pDevIns;
1879 PAC97STATE pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);
1880 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
1881
1882 Assert(enmType == PCI_ADDRESS_SPACE_IO);
1883 Assert(cb >= 0x20);
1884
1885 if (iRegion < 0 || iRegion > 1) /* We support 2 regions max. at the moment. */
1886 return VERR_INVALID_PARAMETER;
1887
1888 int rc;
1889 if (iRegion == 0)
1890 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, pThis,
1891 ichac97IOPortNAMWrite, ichac97IOPortNAMRead,
1892 NULL, NULL, "ICHAC97 NAM");
1893 else
1894 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 64, pThis,
1895 ichac97IOPortNABMWrite, ichac97IOPortNABMRead,
1896 NULL, NULL, "ICHAC97 NABM");
1897 if (RT_FAILURE(rc))
1898 return rc;
1899
1900 pThis->IOPortBase[iRegion] = Port;
1901 return VINF_SUCCESS;
1902}
1903
1904DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID)
1905{
1906 switch (uID)
1907 {
1908 case PI_INDEX: return &pThis->StrmStLineIn;
1909 case MC_INDEX: return &pThis->StrmStMicIn;
1910 case PO_INDEX: return &pThis->StrmStOut;
1911 default: break;
1912 }
1913
1914 return NULL;
1915}
1916
1917#ifdef IN_RING3
1918static int ichac97SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
1919{
1920 PAC97BMREGS pRegs = &pStrmSt->Regs;
1921
1922 SSMR3PutU32(pSSM, pRegs->bdbar);
1923 SSMR3PutU8( pSSM, pRegs->civ);
1924 SSMR3PutU8( pSSM, pRegs->lvi);
1925 SSMR3PutU16(pSSM, pRegs->sr);
1926 SSMR3PutU16(pSSM, pRegs->picb);
1927 SSMR3PutU8( pSSM, pRegs->piv);
1928 SSMR3PutU8( pSSM, pRegs->cr);
1929 SSMR3PutS32(pSSM, pRegs->bd_valid);
1930 SSMR3PutU32(pSSM, pRegs->bd.addr);
1931 SSMR3PutU32(pSSM, pRegs->bd.ctl_len);
1932
1933 return VINF_SUCCESS;
1934}
1935
1936/**
1937 * @callback_method_impl{FNSSMDEVSAVEEXEC}
1938 */
1939static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1940{
1941 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
1942
1943 SSMR3PutU32(pSSM, pThis->glob_cnt);
1944 SSMR3PutU32(pSSM, pThis->glob_sta);
1945 SSMR3PutU32(pSSM, pThis->cas);
1946
1947 /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
1948 /* Note: The order the streams are saved here is critical, so don't touch. */
1949 int rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStLineIn);
1950 AssertRC(rc2);
1951 rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStOut);
1952 AssertRC(rc2);
1953 rc2 = ichac97SaveStream(pDevIns, pSSM, &pThis->StrmStMicIn);
1954 AssertRC(rc2);
1955
1956 SSMR3PutMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
1957
1958 uint8_t active[LAST_INDEX];
1959
1960 PAC97DRIVER pDrv;
1961 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
1962 {
1963 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
1964 AssertPtr(pCon);
1965 active[PI_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->LineIn.pStrmIn) ? 1 : 0;
1966 active[PO_INDEX] = pCon->pfnIsActiveOut(pCon, pDrv->Out.pStrmOut) ? 1 : 0;
1967 active[MC_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->MicIn.pStrmIn) ? 1 : 0;
1968 }
1969
1970 SSMR3PutMem(pSSM, active, sizeof(active));
1971
1972 return VINF_SUCCESS;
1973}
1974
1975static int ichac97LoadStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PAC97STREAM pStrmSt)
1976{
1977 PAC97BMREGS pRegs = &pStrmSt->Regs;
1978
1979 SSMR3GetU32(pSSM, &pRegs->bdbar);
1980 SSMR3GetU8( pSSM, &pRegs->civ);
1981 SSMR3GetU8( pSSM, &pRegs->lvi);
1982 SSMR3GetU16(pSSM, &pRegs->sr);
1983 SSMR3GetU16(pSSM, &pRegs->picb);
1984 SSMR3GetU8( pSSM, &pRegs->piv);
1985 SSMR3GetU8( pSSM, &pRegs->cr);
1986 SSMR3GetS32(pSSM, &pRegs->bd_valid);
1987 SSMR3GetU32(pSSM, &pRegs->bd.addr);
1988 SSMR3GetU32(pSSM, &pRegs->bd.ctl_len);
1989
1990 return VINF_SUCCESS;
1991}
1992
1993/**
1994 * @callback_method_impl{FNSSMDEVLOADEXEC}
1995 */
1996static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1997{
1998 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
1999
2000 AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%RU32\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
2001 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
2002
2003 SSMR3GetU32(pSSM, &pThis->glob_cnt);
2004 SSMR3GetU32(pSSM, &pThis->glob_sta);
2005 SSMR3GetU32(pSSM, &pThis->cas);
2006
2007 /** @todo r=andy For the next saved state version, add unique stream identifiers and a stream count. */
2008 /* Note: The order the streams are loaded here is critical, so don't touch. */
2009 int rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStLineIn);
2010 AssertRC(rc2);
2011 rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStOut);
2012 AssertRC(rc2);
2013 rc2 = ichac97LoadStream(pDevIns, pSSM, &pThis->StrmStMicIn);
2014 AssertRC(rc2);
2015
2016 SSMR3GetMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
2017
2018 /** @todo r=andy Stream IDs are hardcoded to certain streams. */
2019 uint8_t uaStrmsActive[LAST_INDEX];
2020 SSMR3GetMem(pSSM, uaStrmsActive, sizeof(uaStrmsActive));
2021
2022 ichac97RecordSelect(pThis, ichac97MixerGet(pThis, AC97_Record_Select));
2023# define V_(a, b) ichac97MixerSetVolume(pThis, a, b, ichac97MixerGet(pThis, a))
2024 V_(AC97_Master_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME);
2025 V_(AC97_PCM_Out_Volume_Mute, PDMAUDIOMIXERCTL_PCM);
2026 V_(AC97_Line_In_Volume_Mute, PDMAUDIOMIXERCTL_LINE_IN);
2027# undef V_
2028 if (pThis->uCodecModel == Codec_AD1980)
2029 if (ichac97MixerGet(pThis, AC97_AD_Misc) & AD_MISC_HPSEL)
2030 ichac97MixerSetVolume(pThis, AC97_Headphone_Volume_Mute, PDMAUDIOMIXERCTL_VOLUME,
2031 ichac97MixerGet(pThis, AC97_Headphone_Volume_Mute));
2032
2033 int rc;
2034 rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
2035 AssertRC(rc);
2036 rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn, MC_INDEX);
2037 AssertRC(rc);
2038 rc = ichac97StreamInit(pThis, &pThis->StrmStOut, PO_INDEX);
2039 AssertRC(rc);
2040
2041 /** @todo r=andy Stream IDs are hardcoded to certain streams. */
2042 rc = ichac97StreamSetActive(pThis, &pThis->StrmStLineIn, RT_BOOL(uaStrmsActive[PI_INDEX]));
2043 AssertRC(rc);
2044 rc = ichac97StreamSetActive(pThis, &pThis->StrmStMicIn, RT_BOOL(uaStrmsActive[MC_INDEX]));
2045 AssertRC(rc);
2046 rc = ichac97StreamSetActive(pThis, &pThis->StrmStOut, RT_BOOL(uaStrmsActive[PO_INDEX]));
2047 AssertRC(rc);
2048
2049 pThis->bup_flag = 0;
2050 pThis->last_samp = 0;
2051
2052 return VINF_SUCCESS;
2053}
2054
2055
2056/**
2057 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2058 */
2059static DECLCALLBACK(void *) ichac97QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
2060{
2061 PAC97STATE pThis = RT_FROM_MEMBER(pInterface, AC97STATE, IBase);
2062 Assert(&pThis->IBase == pInterface);
2063
2064 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
2065 return NULL;
2066}
2067
2068
2069/**
2070 * @interface_method_impl{PDMDEVREG,pfnReset}
2071 *
2072 * @remarks The original sources didn't install a reset handler, but it seems to
2073 * make sense to me so we'll do it.
2074 */
2075static DECLCALLBACK(void) ichac97Reset(PPDMDEVINS pDevIns)
2076{
2077 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2078
2079 LogFlowFuncEnter();
2080
2081 /*
2082 * Reset the device state (will need pDrv later).
2083 */
2084 ichac97StreamResetBMRegs(pThis, &pThis->StrmStLineIn);
2085 ichac97StreamResetBMRegs(pThis, &pThis->StrmStMicIn);
2086 ichac97StreamResetBMRegs(pThis, &pThis->StrmStOut);
2087
2088 /*
2089 * Reset the mixer too. The Windows XP driver seems to rely on
2090 * this. At least it wants to read the vendor id before it resets
2091 * the codec manually.
2092 */
2093 ichac97MixerReset(pThis);
2094
2095 /*
2096 * Stop any audio currently playing.
2097 */
2098 PAC97DRIVER pDrv;
2099 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
2100 {
2101 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, false /* Disable */);
2102 /* Ignore rc. */
2103 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, false /* Disable */);
2104 /* Ditto. */
2105 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, false /* Disable */);
2106 /* Ditto. */
2107 }
2108
2109 /*
2110 * Reset all streams.
2111 */
2112 ichac97StreamReset(pThis, &pThis->StrmStLineIn);
2113 ichac97StreamReset(pThis, &pThis->StrmStMicIn);
2114 ichac97StreamReset(pThis, &pThis->StrmStOut);
2115
2116 LogRel(("AC97: Reset\n"));
2117}
2118
2119
2120/**
2121 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2122 */
2123static DECLCALLBACK(int) ichac97Destruct(PPDMDEVINS pDevIns)
2124{
2125 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2126
2127 LogFlowFuncEnter();
2128
2129 PAC97DRIVER pDrv;
2130 while (!RTListIsEmpty(&pThis->lstDrv))
2131 {
2132 pDrv = RTListGetFirst(&pThis->lstDrv, AC97DRIVER, Node);
2133
2134 RTListNodeRemove(&pDrv->Node);
2135 RTMemFree(pDrv);
2136 }
2137
2138 if (pThis->pMixer)
2139 {
2140 AudioMixerDestroy(pThis->pMixer);
2141 pThis->pMixer = NULL;
2142 }
2143
2144 if (pThis->pvReadWriteBuf)
2145 {
2146 RTMemFree(pThis->pvReadWriteBuf);
2147 pThis->pvReadWriteBuf = NULL;
2148 pThis->cbReadWriteBuf = 0;
2149 }
2150
2151 LogFlowFuncLeave();
2152 return VINF_SUCCESS;
2153}
2154
2155
2156/**
2157 * Attach command.
2158 *
2159 * This is called to let the device attach to a driver for a specified LUN
2160 * during runtime. This is not called during VM construction, the device
2161 * constructor have to attach to all the available drivers.
2162 *
2163 * @returns VBox status code.
2164 * @param pDevIns The device instance.
2165 * @param uLUN The logical unit which is being detached.
2166 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
2167 */
2168static DECLCALLBACK(int) ichac97Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
2169{
2170 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2171
2172 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2173 ("AC'97 device does not support hotplugging\n"),
2174 VERR_INVALID_PARAMETER);
2175
2176 /*
2177 * Attach driver.
2178 */
2179 char *pszDesc = NULL;
2180 if (RTStrAPrintf(&pszDesc, "Audio driver port (AC'97) for LUN #%u", uLUN) <= 0)
2181 AssertMsgReturn(pszDesc,
2182 ("Not enough memory for AC'97 driver port description of LUN #%u\n", uLUN),
2183 VERR_NO_MEMORY);
2184
2185 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
2186 &pThis->IBase, &pThis->pDrvBase, pszDesc);
2187 if (RT_SUCCESS(rc))
2188 {
2189 PAC97DRIVER pDrv = (PAC97DRIVER)RTMemAllocZ(sizeof(AC97DRIVER));
2190 if (pDrv)
2191 {
2192 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR);
2193 AssertMsg(pDrv->pConnector != NULL,
2194 ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n",
2195 uLUN, rc));
2196 pDrv->pAC97State = pThis;
2197 pDrv->uLUN = uLUN;
2198
2199 /*
2200 * For now we always set the driver at LUN 0 as our primary
2201 * host backend. This might change in the future.
2202 */
2203 if (pDrv->uLUN == 0)
2204 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
2205
2206 LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
2207
2208 /* Attach to driver list. */
2209 RTListAppend(&pThis->lstDrv, &pDrv->Node);
2210 }
2211 else
2212 rc = VERR_NO_MEMORY;
2213 }
2214 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2215 {
2216 LogFunc(("No attached driver for LUN #%u\n", uLUN));
2217 }
2218 else if (RT_FAILURE(rc))
2219 AssertMsgFailed(("Failed to attach AC'97 LUN #%u (\"%s\"), rc=%Rrc\n",
2220 uLUN, pszDesc, rc));
2221
2222 RTStrFree(pszDesc);
2223
2224 LogFunc(("iLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
2225 return rc;
2226}
2227
2228
2229/**
2230 * @interface_method_impl{PDMDEVREG,pfnConstruct}
2231 */
2232static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2233{
2234 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
2235
2236 /* NB: This must be done *before* any possible failure (and running the destructor). */
2237 RTListInit(&pThis->lstDrv);
2238
2239 Assert(iInstance == 0);
2240 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2241
2242 /*
2243 * Validations.
2244 */
2245 if (!CFGMR3AreValuesValid(pCfg,
2246 "Codec\0"
2247 "TimerHz\0"))
2248 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2249 N_("Invalid configuration for the AC'97 device"));
2250
2251 /*
2252 * Read config data.
2253 */
2254 char szCodec[20];
2255 int rc = CFGMR3QueryStringDef(pCfg, "Codec", &szCodec[0], sizeof(szCodec), "STAC9700");
2256 if (RT_FAILURE(rc))
2257 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2258 N_("AC'97 configuration error: Querying \"Codec\" as string failed"));
2259
2260#ifndef VBOX_WITH_AUDIO_CALLBACKS
2261 uint16_t uTimerHz;
2262 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
2263 if (RT_FAILURE(rc))
2264 return PDMDEV_SET_ERROR(pDevIns, rc,
2265 N_("AC'97 configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
2266#endif
2267
2268 /*
2269 * The AD1980 codec (with corresponding PCI subsystem vendor ID) is whitelisted
2270 * in the Linux kernel; Linux makes no attempt to measure the data rate and assumes
2271 * 48 kHz rate, which is exactly what we need. Same goes for AD1981B.
2272 */
2273 bool fChipAD1980 = false;
2274 if (!strcmp(szCodec, "STAC9700"))
2275 pThis->uCodecModel = Codec_STAC9700;
2276 else if (!strcmp(szCodec, "AD1980"))
2277 pThis->uCodecModel = Codec_AD1980;
2278 else if (!strcmp(szCodec, "AD1981B"))
2279 pThis->uCodecModel = Codec_AD1981B;
2280 else
2281 {
2282 return PDMDevHlpVMSetError(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, RT_SRC_POS,
2283 N_("AC'97 configuration error: The \"Codec\" value \"%s\" is unsupported"),
2284 szCodec);
2285 }
2286
2287 /*
2288 * Initialize data (most of it anyway).
2289 */
2290 pThis->pDevInsR3 = pDevIns;
2291 /* IBase */
2292 pThis->IBase.pfnQueryInterface = ichac97QueryInterface;
2293
2294 /* PCI Device (the assertions will be removed later) */
2295 PCIDevSetVendorId (&pThis->PciDev, 0x8086); /* 00 ro - intel. */ Assert(pThis->PciDev.config[0x00] == 0x86); Assert(pThis->PciDev.config[0x01] == 0x80);
2296 PCIDevSetDeviceId (&pThis->PciDev, 0x2415); /* 02 ro - 82801 / 82801aa(?). */ Assert(pThis->PciDev.config[0x02] == 0x15); Assert(pThis->PciDev.config[0x03] == 0x24);
2297 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */ Assert(pThis->PciDev.config[0x04] == 0x00); Assert(pThis->PciDev.config[0x05] == 0x00);
2298 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_DEVSEL_MEDIUM | VBOX_PCI_STATUS_FAST_BACK); /* 06 rwc?,ro? - pcists. */ Assert(pThis->PciDev.config[0x06] == 0x80); Assert(pThis->PciDev.config[0x07] == 0x02);
2299 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */ Assert(pThis->PciDev.config[0x08] == 0x01);
2300 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */ Assert(pThis->PciDev.config[0x09] == 0x00);
2301 PCIDevSetClassSub (&pThis->PciDev, 0x01); /* 0a ro - scc; 01 == Audio. */ Assert(pThis->PciDev.config[0x0a] == 0x01);
2302 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */ Assert(pThis->PciDev.config[0x0b] == 0x04);
2303 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */ Assert(pThis->PciDev.config[0x0e] == 0x00);
2304 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - nambar - native audio mixer base. */
2305 true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.config[0x10] == 0x01); Assert(pThis->PciDev.config[0x11] == 0x00); Assert(pThis->PciDev.config[0x12] == 0x00); Assert(pThis->PciDev.config[0x13] == 0x00);
2306 PCIDevSetBaseAddress (&pThis->PciDev, 1, /* 14 rw - nabmbar - native audio bus mastering. */
2307 true /* fIoSpace */, false /* fPrefetchable */, false /* f64Bit */, 0x00000000); Assert(pThis->PciDev.config[0x14] == 0x01); Assert(pThis->PciDev.config[0x15] == 0x00); Assert(pThis->PciDev.config[0x16] == 0x00); Assert(pThis->PciDev.config[0x17] == 0x00);
2308 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */ Assert(pThis->PciDev.config[0x3c] == 0x00);
2309 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */ Assert(pThis->PciDev.config[0x3d] == 0x01);
2310
2311 if (pThis->uCodecModel == Codec_AD1980)
2312 {
2313 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x1028); /* 2c ro - Dell.) */
2314 PCIDevSetSubSystemId (&pThis->PciDev, 0x0177); /* 2e ro. */
2315 }
2316 else if (pThis->uCodecModel == Codec_AD1981B)
2317 {
2318 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x1028); /* 2c ro - Dell.) */
2319 PCIDevSetSubSystemId (&pThis->PciDev, 0x01ad); /* 2e ro. */
2320 }
2321 else
2322 {
2323 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x8086); /* 2c ro - Intel.) */
2324 PCIDevSetSubSystemId (&pThis->PciDev, 0x0000); /* 2e ro. */
2325 }
2326
2327 /*
2328 * Register the PCI device, it's I/O regions, the timer and the
2329 * saved state item.
2330 */
2331 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
2332 if (RT_FAILURE(rc))
2333 return rc;
2334
2335 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 256, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
2336 if (RT_FAILURE(rc))
2337 return rc;
2338
2339 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 64, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
2340 if (RT_FAILURE(rc))
2341 return rc;
2342
2343 rc = PDMDevHlpSSMRegister(pDevIns, AC97_SSM_VERSION, sizeof(*pThis), ichac97SaveExec, ichac97LoadExec);
2344 if (RT_FAILURE(rc))
2345 return rc;
2346
2347 /*
2348 * Attach driver.
2349 */
2350 uint8_t uLUN;
2351 for (uLUN = 0; uLUN < UINT8_MAX; uLUN)
2352 {
2353 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN));
2354 rc = ichac97Attach(pDevIns, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG);
2355 if (RT_FAILURE(rc))
2356 {
2357 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2358 rc = VINF_SUCCESS;
2359 break;
2360 }
2361
2362 uLUN++;
2363 }
2364
2365 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
2366
2367 if (RT_SUCCESS(rc))
2368 {
2369 rc = AudioMixerCreate("AC'97 Mixer", 0 /* uFlags */, &pThis->pMixer);
2370 if (RT_SUCCESS(rc))
2371 {
2372 /* Set a default audio format for our mixer. */
2373 PDMAUDIOSTREAMCFG streamCfg;
2374 streamCfg.uHz = 44100;
2375 streamCfg.cChannels = 2;
2376 streamCfg.enmFormat = AUD_FMT_S16;
2377 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
2378
2379 rc = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
2380 AssertRC(rc);
2381
2382 /* Add all required audio sinks. */
2383 rc = AudioMixerAddSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
2384 AssertRC(rc);
2385
2386 rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThis->pSinkLineIn);
2387 AssertRC(rc);
2388
2389 rc = AudioMixerAddSink(pThis->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThis->pSinkMicIn);
2390 AssertRC(rc);
2391 }
2392 }
2393
2394 ichac97Reset(pDevIns);
2395
2396 if (RT_SUCCESS(rc))
2397 {
2398 rc = ichac97StreamInit(pThis, &pThis->StrmStLineIn, PI_INDEX);
2399 if (RT_FAILURE(rc))
2400 return rc;
2401 rc = ichac97StreamInit(pThis, &pThis->StrmStMicIn, MC_INDEX);
2402 if (RT_FAILURE(rc))
2403 return rc;
2404 rc = ichac97StreamInit(pThis, &pThis->StrmStOut, PO_INDEX);
2405 if (RT_FAILURE(rc))
2406 return rc;
2407
2408 PAC97DRIVER pDrv;
2409 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
2410 {
2411 /*
2412 * Only primary drivers are critical for the VM to run. Everything else
2413 * might not worth showing an own error message box in the GUI.
2414 */
2415 if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
2416 continue;
2417
2418 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
2419 AssertPtr(pCon);
2420
2421 uint8_t cFailed = 0;
2422 if (!pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn))
2423 cFailed++;
2424 if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn))
2425 cFailed++;
2426 if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
2427 cFailed++;
2428
2429 if (cFailed == 3)
2430 {
2431 LogRel(("AC97: Falling back to NULL driver (no sound audible)\n"));
2432
2433 ichac97Reset(pDevIns);
2434
2435 /* Was not able initialize *any* stream.
2436 * Select the NULL audio driver instead. */
2437 pCon->pfnInitNull(pCon);
2438
2439 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2440 N_("No audio devices could be opened. Selecting the NULL audio backend "
2441 "with the consequence that no sound is audible"));
2442 }
2443 else if (cFailed)
2444 {
2445 if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->LineIn.pStrmIn))
2446 LogRel(("AC97: WARNING: Unable to open PCM line input for LUN #%RU32!\n", pDrv->uLUN));
2447 if (!pDrv->pConnector->pfnIsInputOK(pDrv->pConnector, pDrv->MicIn.pStrmIn))
2448 LogRel(("AC97: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", pDrv->uLUN));
2449 if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut))
2450 LogRel(("AC97: WARNING: Unable to open PCM output for LUN #%RU32!\n", pDrv->uLUN));
2451
2452 char szMissingStreams[255];
2453 size_t len = 0;
2454 if (!pCon->pfnIsInputOK (pCon, pDrv->LineIn.pStrmIn))
2455 len = RTStrPrintf(szMissingStreams,
2456 sizeof(szMissingStreams), "PCM Input");
2457 if (!pCon->pfnIsOutputOK(pCon, pDrv->Out.pStrmOut))
2458 len += RTStrPrintf(szMissingStreams + len,
2459 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
2460 if (!pCon->pfnIsInputOK (pCon, pDrv->MicIn.pStrmIn))
2461 len += RTStrPrintf(szMissingStreams + len,
2462 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
2463
2464 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2465 N_("Some AC'97 audio streams (%s) could not be opened. Guest applications generating audio "
2466 "output or depending on audio input may hang. Make sure your host audio device "
2467 "is working properly. Check the logfile for error messages of the audio "
2468 "subsystem"), szMissingStreams);
2469 }
2470 }
2471 }
2472
2473 if (RT_SUCCESS(rc))
2474 {
2475 pThis->cbReadWriteBuf = _4K; /** @todo Make this configurable. */
2476 pThis->pvReadWriteBuf = (uint8_t *)RTMemAllocZ(pThis->cbReadWriteBuf);
2477 if (!pThis->pvReadWriteBuf)
2478 rc = VERR_NO_MEMORY;
2479 }
2480
2481# ifndef VBOX_WITH_AUDIO_CALLBACKS
2482 if (RT_SUCCESS(rc))
2483 {
2484 /* Start the emulation timer. */
2485 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ichac97Timer, pThis,
2486 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchAc97", &pThis->pTimer);
2487 AssertRCReturn(rc, rc);
2488
2489 if (RT_SUCCESS(rc))
2490 {
2491 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
2492 pThis->uTimerTS = TMTimerGet(pThis->pTimer);
2493 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
2494
2495 /* Fire off timer. */
2496 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->cTimerTicks);
2497 }
2498 }
2499# else
2500 if (RT_SUCCESS(rc))
2501 {
2502 PAC97DRIVER pDrv;
2503 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
2504 {
2505 /* Only register primary driver.
2506 * The device emulation does the output multiplexing then. */
2507 if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
2508 continue;
2509
2510 PDMAUDIOCALLBACK AudioCallbacks[2];
2511
2512 AC97CALLBACKCTX Ctx = { pThis, pDrv };
2513
2514 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT;
2515 AudioCallbacks[0].pfnCallback = ac97CallbackInput;
2516 AudioCallbacks[0].pvCtx = &Ctx;
2517 AudioCallbacks[0].cbCtx = sizeof(AC97CALLBACKCTX);
2518
2519 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT;
2520 AudioCallbacks[1].pfnCallback = ac97CallbackOutput;
2521 AudioCallbacks[1].pvCtx = &Ctx;
2522 AudioCallbacks[1].cbCtx = sizeof(AC97CALLBACKCTX);
2523
2524 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
2525 if (RT_FAILURE(rc))
2526 break;
2527 }
2528 }
2529# endif
2530
2531# ifdef VBOX_WITH_STATISTICS
2532 if (RT_SUCCESS(rc))
2533 {
2534 /*
2535 * Register statistics.
2536 */
2537 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/AC97/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling ichac97Timer.");
2538 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/AC97/BytesRead" , STAMUNIT_BYTES, "Bytes read from AC97 emulation.");
2539 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/AC97/BytesWritten", STAMUNIT_BYTES, "Bytes written to AC97 emulation.");
2540 }
2541# endif
2542
2543 LogFlowFuncLeaveRC(rc);
2544 return rc;
2545}
2546
2547/**
2548 * The device registration structure.
2549 */
2550const PDMDEVREG g_DeviceICHAC97 =
2551{
2552 /* u32Version */
2553 PDM_DEVREG_VERSION,
2554 /* szName */
2555 "ichac97",
2556 /* szRCMod */
2557 "",
2558 /* szR0Mod */
2559 "",
2560 /* pszDescription */
2561 "ICH AC'97 Audio Controller",
2562 /* fFlags */
2563 PDM_DEVREG_FLAGS_DEFAULT_BITS,
2564 /* fClass */
2565 PDM_DEVREG_CLASS_AUDIO,
2566 /* cMaxInstances */
2567 1,
2568 /* cbInstance */
2569 sizeof(AC97STATE),
2570 /* pfnConstruct */
2571 ichac97Construct,
2572 /* pfnDestruct */
2573 ichac97Destruct,
2574 /* pfnRelocate */
2575 NULL,
2576 /* pfnMemSetup */
2577 NULL,
2578 /* pfnPowerOn */
2579 NULL,
2580 /* pfnReset */
2581 ichac97Reset,
2582 /* pfnSuspend */
2583 NULL,
2584 /* pfnResume */
2585 NULL,
2586 /* pfnAttach */
2587 NULL,
2588 /* pfnDetach */
2589 NULL,
2590 /* pfnQueryInterface. */
2591 NULL,
2592 /* pfnInitComplete */
2593 NULL,
2594 /* pfnPowerOff */
2595 NULL,
2596 /* pfnSoftReset */
2597 NULL,
2598 /* u32VersionEnd */
2599 PDM_DEVREG_VERSION
2600};
2601
2602#endif /* !IN_RING3 */
2603#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