VirtualBox

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

Last change on this file since 58450 was 58443, checked in by vboxsync, 9 years ago

AC97: Fixed AD1980 volume control, added AD1981B chip.

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