VirtualBox

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

Last change on this file since 50686 was 50686, checked in by vboxsync, 11 years ago

src/VBox/Devices/Audio, src/VBox/Main/src-client, include/VBox/vmm:

src/VBox/Devices/Audio: part of restructuring of audio code. Devices files correspondin to Hda, AC97 and SB16 audio. The structure of files have been modifed as per PDM specs. The modified code is under #ifdef VBOX_WITH_PDM_AUDIO_DRIVER

src/VBox/Main/src-client: Driver for the VRDE that interacts with DrvAudio. Enhancement of the CFGM tree for audio.

Config.kmk : addition of one configuration parameter that will control whether new audio code is disabled or enabled. "VBOX_WITH_PDM_AUDIO_DRIVER"

pdmaudioifs.h: common header file between Device , Intermediate audio driver and Backends specific to audio.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 68.1 KB
Line 
1/* $Id: DevIchAc97.cpp 50686 2014-03-04 19:21:18Z vboxsync $ */
2/** @file
3 * DevIchAc97 - VBox ICH AC97 Audio Controller.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DEV_AUDIO
22#include <VBox/vmm/pdmdev.h>
23#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
24#include <VBox/vmm/pdmaudioifs.h>
25#endif
26#include <iprt/assert.h>
27#include <iprt/uuid.h>
28#include <iprt/string.h>
29
30#include "VBoxDD.h"
31#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
32extern "C" {
33#include "audio.h"
34}
35#endif
36
37
38/*******************************************************************************
39* Defined Constants And Macros *
40*******************************************************************************/
41#undef LOG_VOICES
42#ifndef VBOX
43//#define USE_MIXER
44#else
45# define USE_MIXER
46#endif
47
48#define AC97_SSM_VERSION 1
49
50#ifndef VBOX
51# define SOFT_VOLUME
52#else
53# undef SOFT_VOLUME
54#endif
55#define SR_FIFOE RT_BIT(4) /* rwc, fifo error */
56#define SR_BCIS RT_BIT(3) /* rwc, buffer completion interrupt status */
57#define SR_LVBCI RT_BIT(2) /* rwc, last valid buffer completion interrupt */
58#define SR_CELV RT_BIT(1) /* ro, current equals last valid */
59#define SR_DCH RT_BIT(0) /* ro, controller halted */
60#define SR_VALID_MASK (RT_BIT(5) - 1)
61#define SR_WCLEAR_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
62#define SR_RO_MASK (SR_DCH | SR_CELV)
63#define SR_INT_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
64
65#define CR_IOCE RT_BIT(4) /* rw */
66#define CR_FEIE RT_BIT(3) /* rw */
67#define CR_LVBIE RT_BIT(2) /* rw */
68#define CR_RR RT_BIT(1) /* rw */
69#define CR_RPBM RT_BIT(0) /* rw */
70#define CR_VALID_MASK (RT_BIT(5) - 1)
71#define CR_DONT_CLEAR_MASK (CR_IOCE | CR_FEIE | CR_LVBIE)
72
73#define GC_WR 4 /* rw */
74#define GC_CR 2 /* rw */
75#define GC_VALID_MASK (RT_BIT(6) - 1)
76
77#define GS_MD3 RT_BIT(17) /* rw */
78#define GS_AD3 RT_BIT(16) /* rw */
79#define GS_RCS RT_BIT(15) /* rwc */
80#define GS_B3S12 RT_BIT(14) /* ro */
81#define GS_B2S12 RT_BIT(13) /* ro */
82#define GS_B1S12 RT_BIT(12) /* ro */
83#define GS_S1R1 RT_BIT(11) /* rwc */
84#define GS_S0R1 RT_BIT(10) /* rwc */
85#define GS_S1CR RT_BIT(9) /* ro */
86#define GS_S0CR RT_BIT(8) /* ro */
87#define GS_MINT RT_BIT(7) /* ro */
88#define GS_POINT RT_BIT(6) /* ro */
89#define GS_PIINT RT_BIT(5) /* ro */
90#define GS_RSRVD (RT_BIT(4)|RT_BIT(3))
91#define GS_MOINT RT_BIT(2) /* ro */
92#define GS_MIINT RT_BIT(1) /* ro */
93#define GS_GSCI RT_BIT(0) /* rwc */
94#define GS_RO_MASK (GS_B3S12 | \
95 GS_B2S12 | \
96 GS_B1S12 | \
97 GS_S1CR | \
98 GS_S0CR | \
99 GS_MINT | \
100 GS_POINT | \
101 GS_PIINT | \
102 GS_RSRVD | \
103 GS_MOINT | \
104 GS_MIINT)
105#define GS_VALID_MASK (RT_BIT(18) - 1)
106#define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI)
107
108/** @name Buffer Descriptor
109 * @{ */
110#define BD_IOC RT_BIT(31) /**< Interrupt on Completion */
111#define BD_BUP RT_BIT(30) /**< Buffer Underrun Policy */
112/** @} */
113
114#define EACS_VRA 1
115#define EACS_VRM 8
116
117#define VOL_MASK 0x1f
118#define MUTE_SHIFT 15
119
120#define REC_MASK 7
121enum
122{
123 REC_MIC = 0,
124 REC_CD,
125 REC_VIDEO,
126 REC_AUX,
127 REC_LINE_IN,
128 REC_STEREO_MIX,
129 REC_MONO_MIX,
130 REC_PHONE
131};
132
133enum
134{
135 AC97_Reset = 0x00,
136 AC97_Master_Volume_Mute = 0x02,
137 AC97_Headphone_Volume_Mute = 0x04,
138 AC97_Master_Volume_Mono_Mute = 0x06,
139 AC97_Master_Tone_RL = 0x08,
140 AC97_PC_BEEP_Volume_Mute = 0x0A,
141 AC97_Phone_Volume_Mute = 0x0C,
142 AC97_Mic_Volume_Mute = 0x0E,
143 AC97_Line_In_Volume_Mute = 0x10,
144 AC97_CD_Volume_Mute = 0x12,
145 AC97_Video_Volume_Mute = 0x14,
146 AC97_Aux_Volume_Mute = 0x16,
147 AC97_PCM_Out_Volume_Mute = 0x18,
148 AC97_Record_Select = 0x1A,
149 AC97_Record_Gain_Mute = 0x1C,
150 AC97_Record_Gain_Mic_Mute = 0x1E,
151 AC97_General_Purpose = 0x20,
152 AC97_3D_Control = 0x22,
153 AC97_AC_97_RESERVED = 0x24,
154 AC97_Powerdown_Ctrl_Stat = 0x26,
155 AC97_Extended_Audio_ID = 0x28,
156 AC97_Extended_Audio_Ctrl_Stat = 0x2A,
157 AC97_PCM_Front_DAC_Rate = 0x2C,
158 AC97_PCM_Surround_DAC_Rate = 0x2E,
159 AC97_PCM_LFE_DAC_Rate = 0x30,
160 AC97_PCM_LR_ADC_Rate = 0x32,
161 AC97_MIC_ADC_Rate = 0x34,
162 AC97_6Ch_Vol_C_LFE_Mute = 0x36,
163 AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
164 AC97_Vendor_Reserved = 0x58,
165 AC97_Vendor_ID1 = 0x7c,
166 AC97_Vendor_ID2 = 0x7e
167};
168
169
170/*******************************************************************************
171* Structures and Typedefs *
172*******************************************************************************/
173typedef struct BD
174{
175 uint32_t addr;
176 uint32_t ctl_len;
177} BD;
178
179typedef struct AC97BusMasterRegs
180{
181 uint32_t bdbar; /**< rw 0, buffer descriptor list base address register */
182 uint8_t civ; /**< ro 0, current index value */
183 uint8_t lvi; /**< rw 0, last valid index */
184 uint16_t sr; /**< rw 1, status register */
185 uint16_t picb; /**< ro 0, position in current buffer */
186 uint8_t piv; /**< ro 0, prefetched index value */
187 uint8_t cr; /**< rw 0, control register */
188 int bd_valid; /**< initialized? */
189 BD bd;
190} AC97BusMasterRegs;
191/** Pointer to a AC97 bus master register. */
192typedef AC97BusMasterRegs *PAC97BMREG;
193
194typedef struct AC97STATE
195{
196 /** The PCI device state. */
197 PCIDevice PciDev;
198
199 /** Audio stuff. */
200#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
201 QEMUSoundCard card;
202#endif
203 /** Global Control (Bus Master Control Register) */
204 uint32_t glob_cnt;
205 /** Global Status (Bus Master Control Register) */
206 uint32_t glob_sta;
207 /** Codec Access Semaphore Register (Bus Master Control Register) */
208 uint32_t cas;
209 uint32_t last_samp;
210 /** Bus Master Control Registers for PCM in, PCM out, and Mic in */
211 AC97BusMasterRegs bm_regs[3];
212 uint8_t mixer_data[256];
213#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
214 /** PCM in */
215 PPDMGSTVOICEIN voice_pi[2];
216 /** PCM out */
217 PPDMGSTVOICEOUT voice_po[2];
218 /** Mic in */
219 PPDMGSTVOICEIN voice_mc[2];
220#else
221 /** PCM in */
222 SWVoiceIn *voice_pi;
223 /** PCM out */
224 SWVoiceOut *voice_po;
225 /** Mic in */
226 SWVoiceIn *voice_mc;
227#endif
228 uint8_t silence[128];
229 int bup_flag;
230 /** Pointer to the device instance. */
231 PPDMDEVINSR3 pDevIns;
232 /** Pointer to the connector of the attached audio driver. */
233#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
234 PPDMIAUDIOCONNECTOR pDrv[2];
235#else
236 PPDMIAUDIOCONNECTOR pDrv;
237#endif
238 /** Pointer to the attached audio driver. */
239 PPDMIBASE pDrvBase;
240 /** The base interface for LUN\#0. */
241 PDMIBASE IBase;
242 /** Base port of the I/O space region. */
243 RTIOPORT IOPortBase[2];
244} AC97STATE;
245/** Pointer to the AC97 device state. */
246typedef AC97STATE *PAC97STATE;
247
248#define ICHAC97STATE_2_DEVINS(a_pAC97) ((a_pAC97)->pDevIns)
249
250enum
251{
252 BUP_SET = RT_BIT(0),
253 BUP_LAST = RT_BIT(1)
254};
255
256#define MKREGS(prefix, start) \
257 enum { \
258 prefix ## _BDBAR = start, \
259 prefix ## _CIV = start + 4, \
260 prefix ## _LVI = start + 5, \
261 prefix ## _SR = start + 6, \
262 prefix ## _PICB = start + 8, \
263 prefix ## _PIV = start + 10, \
264 prefix ## _CR = start + 11 \
265 }
266
267enum
268{
269 PI_INDEX = 0, /* PCM in */
270 PO_INDEX, /* PCM out */
271 MC_INDEX, /* Mic in */
272 LAST_INDEX
273};
274
275MKREGS (PI, PI_INDEX * 16);
276MKREGS (PO, PO_INDEX * 16);
277MKREGS (MC, MC_INDEX * 16);
278
279enum
280{
281 GLOB_CNT = 0x2c,
282 GLOB_STA = 0x30,
283 CAS = 0x34
284};
285
286#define GET_BM(a_idx) ( ((a_idx) >> 4) & 3 )
287
288static void po_callback(void *opaque, int free);
289static void pi_callback(void *opaque, int avail);
290static void mc_callback(void *opaque, int avail);
291
292static void warm_reset(PAC97STATE pThis)
293{
294 NOREF(pThis);
295}
296
297static void cold_reset(PAC97STATE pThis)
298{
299 NOREF(pThis);
300}
301
302/** Fetch Buffer Descriptor at _CIV */
303static void fetch_bd(PAC97STATE pThis, PAC97BMREG pReg)
304{
305 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
306 uint8_t b[8];
307
308 PDMDevHlpPhysRead(pDevIns, pReg->bdbar + pReg->civ * 8, b, sizeof(b));
309 pReg->bd_valid = 1;
310#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
311# error Please adapt the code (audio buffers are little endian)!
312#else
313 pReg->bd.addr = (*(uint32_t *) &b[0]) & ~3;
314 pReg->bd.ctl_len = (*(uint32_t *) &b[4]);
315#endif
316 pReg->picb = pReg->bd.ctl_len & 0xffff;
317 Log(("ac97: bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
318 pReg->civ, pReg->bd.addr, pReg->bd.ctl_len >> 16,
319 pReg->bd.ctl_len & 0xffff, (pReg->bd.ctl_len & 0xffff) << 1));
320}
321
322/**
323 * Update the BM status register
324 */
325static void update_sr(PAC97STATE pThis, PAC97BMREG pReg, uint32_t new_sr)
326{
327 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
328 int event = 0;
329 int level = 0;
330 uint32_t new_mask = new_sr & SR_INT_MASK;
331 uint32_t old_mask = pReg->sr & SR_INT_MASK;
332 static uint32_t const masks[] = { GS_PIINT, GS_POINT, GS_MINT };
333
334 if (new_mask ^ old_mask)
335 {
336 /** @todo is IRQ deasserted when only one of status bits is cleared? */
337 if (!new_mask)
338 {
339 event = 1;
340 level = 0;
341 }
342 else if ((new_mask & SR_LVBCI) && (pReg->cr & CR_LVBIE))
343 {
344 event = 1;
345 level = 1;
346 }
347 else if ((new_mask & SR_BCIS) && (pReg->cr & CR_IOCE))
348 {
349 event = 1;
350 level = 1;
351 }
352 }
353
354 pReg->sr = new_sr;
355
356 Log(("ac97: IOC%d LVB%d sr=%#x event=%d level=%d\n",
357 pReg->sr & SR_BCIS, pReg->sr & SR_LVBCI, pReg->sr, event, level));
358
359 if (event)
360 {
361 if (level)
362 pThis->glob_sta |= masks[pReg - pThis->bm_regs];
363 else
364 pThis->glob_sta &= ~masks[pReg - pThis->bm_regs];
365
366 Log(("ac97: set irq level=%d\n", !!level));
367 PDMDevHlpPCISetIrq(pDevIns, 0, !!level);
368 }
369}
370
371static void voice_set_active(PAC97STATE pThis, int bm_index, int on)
372{
373 switch (bm_index)
374 {
375#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
376 uint32_t lun;
377 case PI_INDEX:
378 for (lun = 0; lun < 2; lun++)
379 pThis->pDrv[lun]->pfnEnableIn(pThis->pDrv[lun], pThis->voice_pi[lun], on);
380 break;
381 case PO_INDEX:
382 for (lun = 0; lun < 2; lun++)
383 pThis->pDrv[lun]->pfnEnableOut(pThis->pDrv[lun], pThis->voice_po[lun], on);
384 break;
385 case MC_INDEX:
386 for (lun = 0; lun < 2; lun++)
387 pThis->pDrv[lun]->pfnEnableIn(pThis->pDrv[lun], pThis->voice_mc[lun], on);
388 break;
389#else
390 case PI_INDEX: AUD_set_active_in( pThis->voice_pi, on); break;
391 case PO_INDEX: AUD_set_active_out(pThis->voice_po, on); break;
392 case MC_INDEX: AUD_set_active_in( pThis->voice_mc, on); break;
393#endif
394 default: AssertFailed (); break;
395 }
396}
397
398static void reset_bm_regs(PAC97STATE pThis, PAC97BMREG pReg)
399{
400 Log(("ac97: reset_bm_regs\n"));
401 pReg->bdbar = 0;
402 pReg->civ = 0;
403 pReg->lvi = 0;
404 /** @todo do we need to do that? */
405 update_sr(pThis, pReg, SR_DCH);
406 pReg->picb = 0;
407 pReg->piv = 0;
408 pReg->cr = pReg->cr & CR_DONT_CLEAR_MASK;
409 pReg->bd_valid = 0;
410 voice_set_active(pThis, pReg - pThis->bm_regs, 0);
411 memset(pThis->silence, 0, sizeof(pThis->silence));
412}
413
414static void mixer_store(PAC97STATE pThis, uint32_t i, uint16_t v)
415{
416 if (i + 2 > sizeof(pThis->mixer_data))
417 {
418 Log(("ac97: mixer_store: index %d out of bounds %d\n", i, sizeof(pThis->mixer_data)));
419 return;
420 }
421
422 pThis->mixer_data[i + 0] = v & 0xff;
423 pThis->mixer_data[i + 1] = v >> 8;
424}
425
426static uint16_t mixer_load(PAC97STATE pThis, uint32_t i)
427{
428 uint16_t val;
429
430 if (i + 2 > sizeof(pThis->mixer_data))
431 {
432 Log(("ac97: mixer_store: index %d out of bounds %d\n", i, sizeof(pThis->mixer_data)));
433 val = 0xffff;
434 }
435 else
436 val = pThis->mixer_data[i + 0] | (pThis->mixer_data[i + 1] << 8);
437
438 return val;
439}
440
441static void open_voice(PAC97STATE pThis, int index, int freq)
442{
443#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
444 int rc;
445#endif
446 LogFlow(("DevIchAC97: open_voice freq = %d\n", freq));
447 if (freq)
448 {
449#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
450 audsettings_t as;
451 as.freq = freq;
452 as.nchannels = 2;
453 as.fmt = AUD_FMT_S16;
454 as.endianness = 0;
455 uint32_t lun;
456#endif
457 switch (index)
458 {
459 case PI_INDEX: /* PCM in */
460#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
461 for (uint32_t lun = 0; lun < 2; lun++)
462 rc = pThis->pDrv[lun]->pfnOpenIn(pThis->pDrv[lun], &pThis->voice_pi[lun], "ac97.pi",
463 pThis, pi_callback, freq, 2, AUD_FMT_S16, 0);
464#else
465 pThis->voice_pi = AUD_open_in(&pThis->card, pThis->voice_pi, "ac97.pi", pThis, pi_callback, &as);
466#endif
467#ifdef LOG_VOICES
468 LogRel(("AC97: open PI freq=%d (%s)\n", freq, pThis->voice_pi ? "ok" : "FAIL"));
469#endif
470 break;
471
472 case PO_INDEX: /* PCM out */
473#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
474 for (int lun = 0; lun < 2; lun++)
475 {
476 LogFlow(("LUN###%d\n", lun));
477 rc = pThis->pDrv[lun]->pfnOpenOut(pThis->pDrv[lun], &pThis->voice_po[lun], "ac97.po",
478 pThis, po_callback, freq, 2, AUD_FMT_S16, 0);
479 }
480#else
481 pThis->voice_po = AUD_open_out(&pThis->card, pThis->voice_po, "ac97.po", pThis, po_callback, &as);
482#endif
483#ifdef LOG_VOICES
484 LogRel(("AC97: open PO freq=%d (%s)\n", freq, pThis->voice_po ? "ok" : "FAIL"));
485#endif
486 break;
487
488 case MC_INDEX: /* Mic in */
489#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
490 for (uint32_t lun = 0; lun < 2; lun++)
491 rc = pThis->pDrv[lun]->pfnOpenIn(pThis->pDrv[lun], &pThis->voice_mc[lun], "ac97.mc",
492 pThis, mc_callback, freq, 2, AUD_FMT_S16, 0);
493#else
494 pThis->voice_mc = AUD_open_in(&pThis->card, pThis->voice_mc, "ac97.mc", pThis, mc_callback, &as);
495#endif
496#ifdef LOG_VOICES
497 LogRel(("AC97: open MC freq=%d (%s)\n", freq, pThis->voice_mc ? "ok" : "FAIL"));
498#endif
499 break;
500 }
501 }
502 else
503 {
504 switch (index)
505 {
506 case PI_INDEX:
507#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
508 for (uint32_t lun = 0; lun < 2; lun++)
509 {
510 pThis->pDrv[lun]->pfnCloseIn(pThis->pDrv[lun], pThis->voice_pi[lun]);
511 pThis->voice_pi[lun] = NULL;
512 }
513#else
514 AUD_close_in(&pThis->card, pThis->voice_pi);
515 pThis->voice_pi = NULL;
516#endif
517#ifdef LOG_VOICES
518 LogRel(("AC97: Closing PCM IN\n"));
519#endif
520 break;
521
522 case PO_INDEX:
523#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
524 for (uint32_t lun = 0; lun < 2; lun++)
525 {
526 pThis->pDrv[lun]->pfnCloseOut(pThis->pDrv[lun], pThis->voice_po[lun]);
527 pThis->voice_po[lun] = NULL;
528 }
529#else
530 AUD_close_out(&pThis->card, pThis->voice_po);
531 pThis->voice_po = NULL;
532#endif
533#ifdef LOG_VOICES
534 LogRel(("AC97: Closing PCM OUT\n"));
535#endif
536 break;
537
538 case MC_INDEX:
539#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
540 for (uint32_t lun = 0; lun < 2; lun++)
541 {
542 pThis->pDrv[lun]->pfnCloseIn(pThis->pDrv[lun], pThis->voice_mc[lun]);
543 pThis->voice_mc[lun] = NULL;
544 }
545#else
546 AUD_close_in(&pThis->card, pThis->voice_mc);
547 pThis->voice_mc = NULL;
548#endif
549#ifdef LOG_VOICES
550 LogRel(("AC97: Closing MIC IN\n"));
551#endif
552 break;
553 }
554 }
555}
556
557static void reset_voices(PAC97STATE pThis, uint8_t active[LAST_INDEX])
558{
559 uint16_t freq;
560
561 freq = mixer_load(pThis, AC97_PCM_LR_ADC_Rate);
562 open_voice(pThis, PI_INDEX, freq);
563#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
564 for (uint32_t lun = 0; lun < 2; lun++)
565 pThis->pDrv[lun]->pfnEnableIn(pThis->pDrv[lun], pThis->voice_pi[lun], active[PI_INDEX]);
566#else
567 AUD_set_active_in(pThis->voice_pi, active[PI_INDEX]);
568#endif
569 freq = mixer_load(pThis, AC97_PCM_Front_DAC_Rate);
570 LogFlow(("DevIchAC97: reset_voices calling open_voice freq = %d\n", freq));
571 open_voice(pThis, PO_INDEX, freq);
572#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
573 for (uint32_t lun = 0; lun < 2; lun++)
574 pThis->pDrv[lun]->pfnEnableOut(pThis->pDrv[lun], pThis->voice_po[lun], active[PO_INDEX]);
575#else
576 AUD_set_active_out(pThis->voice_po, active[PO_INDEX]);
577#endif
578
579 freq = mixer_load(pThis, AC97_MIC_ADC_Rate);
580 open_voice(pThis, MC_INDEX, freq);
581#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
582 for (uint32_t lun = 0; lun < 2; lun++)
583 pThis->pDrv[lun]->pfnEnableIn(pThis->pDrv[lun], pThis->voice_mc[lun], active[MC_INDEX]);
584#else
585 AUD_set_active_in(pThis->voice_mc, active[MC_INDEX]);
586#endif
587}
588
589#ifdef USE_MIXER
590
591static void set_volume(PAC97STATE pThis, int index, audmixerctl_t mt, uint32_t val)
592{
593 int mute = (val >> MUTE_SHIFT) & 1;
594 uint8_t rvol = VOL_MASK - (val & VOL_MASK);
595 uint8_t lvol = VOL_MASK - ((val >> 8) & VOL_MASK);
596 rvol = 255 * rvol / VOL_MASK;
597 lvol = 255 * lvol / VOL_MASK;
598
599# ifdef SOFT_VOLUME
600 if (index == AC97_Master_Volume_Mute)
601 {
602# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
603 for (uint32_t lun = 0; lun < 1; lun++)
604 pThis->pDrv[lun]->pfnIsSetOutVolume(pThis->pDrv[lun], pThis->voice_po[lun], mute, lvol, rvol);
605# else
606 AUD_set_volume_out(pThis->voice_po, mute, lvol, rvol);
607# endif
608 }
609 else
610 {
611# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
612 for (uint32_t lun = 0; lun < 1; lun++)
613 /* @tod0 in SetVolume no passing audmixerctl_in as its not used in DrvAudio.c */
614 pThis->pDrv[lun]->pfnSetVolume(pThis->pDrv[lun], &mute, &lvol, &rvol);
615# else
616 AUD_set_volume(mt, &mute, &lvol, &rvol);
617# endif
618 }
619# else
620# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
621 for (uint32_t lun = 0; lun < 1; lun++)
622 pThis->pDrv[lun]->pfnSetVolume(pThis->pDrv[lun], &mute, &lvol, &rvol);
623# else
624 AUD_set_volume(mt, &mute, &lvol, &rvol);
625# endif
626# endif
627
628 rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
629 lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
630
631 /*
632 * From AC'97 SoundMax Codec AD1981A: "Because AC '97 defines 6-bit volume registers, to
633 * maintain compatibility whenever the D5 or D13 bits are set to `1,' their respective
634 * lower five volume bits are automatically set to `1' by the Codec logic. On readback,
635 * all lower 5 bits will read ones whenever these bits are set to `1.'"
636 *
637 * Linux ALSA depends on this behavior.
638 */
639 if (val & RT_BIT(5))
640 val |= RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0);
641 if (val & RT_BIT(13))
642 val |= RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8);
643
644 mixer_store(pThis, index, val);
645}
646
647static audrecsource_t ac97_to_aud_record_source(uint8_t i)
648{
649 switch (i)
650 {
651 case REC_MIC: return AUD_REC_MIC;
652 case REC_CD: return AUD_REC_CD;
653 case REC_VIDEO: return AUD_REC_VIDEO;
654 case REC_AUX: return AUD_REC_AUX;
655 case REC_LINE_IN: return AUD_REC_LINE_IN;
656 case REC_PHONE: return AUD_REC_PHONE;
657 default:
658 Log(("ac97: Unknown record source %d, using MIC\n", i));
659 return AUD_REC_MIC;
660 }
661}
662
663static uint8_t aud_to_ac97_record_source(audrecsource_t rs)
664{
665 switch (rs)
666 {
667 case AUD_REC_MIC: return REC_MIC;
668 case AUD_REC_CD: return REC_CD;
669 case AUD_REC_VIDEO: return REC_VIDEO;
670 case AUD_REC_AUX: return REC_AUX;
671 case AUD_REC_LINE_IN: return REC_LINE_IN;
672 case AUD_REC_PHONE: return REC_PHONE;
673 default:
674 Log(("ac97: Unknown audio recording source %d using MIC\n", rs));
675 return REC_MIC;
676 }
677}
678
679static void record_select(PAC97STATE pThis, uint32_t val)
680{
681 uint8_t rs = val & REC_MASK;
682 uint8_t ls = (val >> 8) & REC_MASK;
683 audrecsource_t ars = ac97_to_aud_record_source(rs);
684 audrecsource_t als = ac97_to_aud_record_source(ls);
685 //AUD_set_record_source(&als, &ars);
686 rs = aud_to_ac97_record_source(ars);
687 ls = aud_to_ac97_record_source(als);
688 mixer_store(pThis, AC97_Record_Select, rs | (ls << 8));
689}
690
691#endif /* USE_MIXER */
692
693static void mixer_reset(PAC97STATE pThis)
694{
695 uint8_t active[LAST_INDEX];
696
697 Log(("ac97: mixer_reset\n"));
698 memset(pThis->mixer_data, 0, sizeof(pThis->mixer_data));
699 memset(active, 0, sizeof(active));
700 mixer_store(pThis, AC97_Reset , 0x0000); /* 6940 */
701 mixer_store(pThis, AC97_Master_Volume_Mono_Mute , 0x8000);
702 mixer_store(pThis, AC97_PC_BEEP_Volume_Mute , 0x0000);
703
704 mixer_store(pThis, AC97_Phone_Volume_Mute , 0x8008);
705 mixer_store(pThis, AC97_Mic_Volume_Mute , 0x8008);
706 mixer_store(pThis, AC97_CD_Volume_Mute , 0x8808);
707 mixer_store(pThis, AC97_Aux_Volume_Mute , 0x8808);
708 mixer_store(pThis, AC97_Record_Gain_Mic_Mute , 0x8000);
709 mixer_store(pThis, AC97_General_Purpose , 0x0000);
710 mixer_store(pThis, AC97_3D_Control , 0x0000);
711 mixer_store(pThis, AC97_Powerdown_Ctrl_Stat , 0x000f);
712
713 /*
714 * Sigmatel 9700 (STAC9700)
715 */
716 mixer_store(pThis, AC97_Vendor_ID1 , 0x8384);
717 mixer_store(pThis, AC97_Vendor_ID2 , 0x7600); /* 7608 */
718
719 mixer_store(pThis, AC97_Extended_Audio_ID , 0x0809);
720 mixer_store(pThis, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
721 mixer_store(pThis, AC97_PCM_Front_DAC_Rate , 0xbb80);
722 mixer_store(pThis, AC97_PCM_Surround_DAC_Rate , 0xbb80);
723 mixer_store(pThis, AC97_PCM_LFE_DAC_Rate , 0xbb80);
724 mixer_store(pThis, AC97_PCM_LR_ADC_Rate , 0xbb80);
725 mixer_store(pThis, AC97_MIC_ADC_Rate , 0xbb80);
726
727
728
729#ifdef USE_MIXER
730 record_select(pThis, 0);
731 set_volume(pThis, AC97_Master_Volume_Mute, AUD_MIXER_VOLUME, 0x8000);
732 set_volume(pThis, AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM, 0x8808);
733 set_volume(pThis, AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN, 0x8808);
734#else
735 mixer_store(pThis, AC97_Record_Select, 0);
736 mixer_store(pThis, AC97_Master_Volume_Mute, 0x8000);
737 mixer_store(pThis, AC97_PCM_Out_Volume_Mute, 0x8808);
738 mixer_store(pThis, AC97_Line_In_Volume_Mute, 0x8808);
739#endif
740
741 reset_voices(pThis, active);
742}
743
744static int write_audio(PAC97STATE pThis, PAC97BMREG pReg, int max, int *stop)
745{
746 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
747 uint8_t tmpbuf[4096];
748 uint32_t addr = pReg->bd.addr;
749 uint32_t temp = pReg->picb << 1;
750 uint32_t written = 0;
751 int to_copy = 0;
752#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
753 /* count of bytes left in buf to read = samples left in buffer (each of 16 bit) to read denoted by picb * 2) */
754 uint32_t cbToRead = pReg->picb << 1;
755 uint32_t cbMinToRead;
756 uint8_t tmpbufCopy[4096];
757 int lun = 0;
758 uint32_t slowestLun;
759 uint32_t cSamplesLeft;
760#endif
761
762 temp = audio_MIN(temp, (uint32_t)max);
763 if (!temp)
764 {
765 *stop = 1;
766 return 0;
767 }
768
769 while (temp)
770 {
771 int copied;
772 to_copy = audio_MIN(temp, sizeof(tmpbuf));
773 PDMDevHlpPhysRead(pDevIns, addr, tmpbuf, to_copy);
774#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
775 /* save a copy of the audio samples read */
776 memcpy(tmpbufCopy, tmpbuf, to_copy);
777 uint32_t slowlun = 0;
778 for (lun = 0; lun < 2; lun++)
779 {
780 LogFlow(("DevIchAC97: write_audio to_copy = %d LUN##%d\n", to_copy, lun));
781 copied = pThis->pDrv[lun]->pfnWrite(pThis->pDrv[lun], pThis->voice_po[lun], tmpbuf, to_copy);
782 /* call pfnwrite with the same data that has been read from the guest physical memory */
783 LogFlow(("DevIchAC97: write_audio copied = %d\n", copied));
784 }
785#else
786 copied = AUD_write(pThis->voice_po, tmpbuf, to_copy);
787#endif
788 if (!copied)
789 {
790 *stop = 1;
791 break;
792 }
793 temp -= copied;
794 addr += copied;
795 written += copied;
796 }
797
798 if (!temp)
799 {
800 if (to_copy < 4)
801 {
802 Log(("ac97: whoops\n"));
803 pThis->last_samp = 0;
804 }
805 else
806 pThis->last_samp = *(uint32_t *)&tmpbuf[to_copy - 4];
807 }
808
809 pReg->bd.addr = addr;
810 return written;
811}
812
813static void write_bup(PAC97STATE pThis, int elapsed)
814{
815 int written = 0;
816 Log(("ac97: write_bup\n"));
817 if (!(pThis->bup_flag & BUP_SET))
818 {
819 if (pThis->bup_flag & BUP_LAST)
820 {
821 unsigned int i;
822 uint32_t *p = (uint32_t*)pThis->silence;
823 for (i = 0; i < sizeof(pThis->silence) / 4; i++)
824 *p++ = pThis->last_samp;
825 }
826 else
827 memset(pThis->silence, 0, sizeof(pThis->silence));
828
829 pThis->bup_flag |= BUP_SET;
830 }
831
832 while (elapsed)
833 {
834 unsigned int temp = audio_MIN((unsigned int)elapsed, sizeof(pThis->silence));
835 int copied;
836 while (temp)
837 {
838#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
839 for (int lun = 0; lun < 2; lun++)
840 {
841 LogFlow(("DevIchAC97: write_silence LUN##%d , to_copy=%d\n", lun, temp));
842 copied = pThis->pDrv[lun]->pfnWrite(pThis->pDrv[lun], pThis->voice_po[lun], pThis->silence, temp);
843 LogFlow(("DevIchAC97: write_silence LUN##%d , copied=%d\n", lun, copied));
844 }
845#else
846 int copied = AUD_write(pThis->voice_po, pThis->silence, temp);
847#endif
848 if (!copied)
849 return;
850 temp -= copied;
851 elapsed -= copied;
852 written += copied;
853 }
854 }
855}
856
857static int read_audio(PAC97STATE pThis, PAC97BMREG pReg, int max, int *stop)
858{
859 PPDMDEVINS pDevIns = ICHAC97STATE_2_DEVINS(pThis);
860
861 uint32_t addr = pReg->bd.addr;
862 uint32_t temp = pReg->picb << 1;
863 uint32_t nread = 0;
864 int to_copy = 0;
865#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
866 uint8_t u8DupBuf[4096];
867 PDMHOSTSTEREOSAMPLE tmpbuf[4096];
868 PDMHOSTSTEREOSAMPLE MixBuf[2000];
869 PDMHOSTSTEREOSAMPLE InputBuf[2000];
870 PPDMHOSTSTEREOSAMPLE SrcBuf;
871 uint32_t cSamplesMixed = 0;
872 uint32_t cTotalSamplesMixed = 0;
873 uint32_t cSamplesRead = 0;
874 uint32_t offRead = 0;
875 uint32_t offWrite = 0;
876 uint32_t cTotalSamplesRead = 0;
877 uint32_t isamp = 0, osamp = 0;
878 uint32_t lun =0;
879 PPDMGSTVOICEIN voice[2];
880 memset(MixBuf, 0, sizeof(MixBuf));
881 memset(InputBuf, 0, sizeof(InputBuf));
882 memset(u8DupBuf, 0, sizeof(u8DupBuf));
883 void * rate[2];
884
885 for (lun = 0; lun < 2; lun++)
886 voice[lun] = (pReg - pThis->bm_regs) == MC_INDEX ? pThis->voice_mc[lun] : pThis->voice_pi[lun];
887#else
888 SWVoiceIn *voice = (pReg - pThis->bm_regs) == MC_INDEX ? pThis->voice_mc : pThis->voice_pi;
889#endif
890
891 temp = audio_MIN(temp, (uint32_t)max);
892 if (!temp)
893 {
894 *stop = 1;
895 return 0;
896 }
897
898#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
899 rate[0] = pThis->pDrv[0]->pfnPrepareAudioConversion(pThis->pDrv[0], 48000, 48000);
900 //rate[1] = pThis->pDrv[1]->pfnPrepareAudioConversion(pThis->pDrv[1], 22100, 22100);
901 rate[1] = pThis->pDrv[1]->pfnPrepareAudioConversion(pThis->pDrv[1], 48000, 48000);
902 for (lun = 0; lun < 2; lun++)
903 {
904 temp = pReg->picb << 1;
905 temp = audio_MIN(temp, (uint32_t)max);
906 LogFlow(("DevIchAC97: temp = %d and max = %d\n", temp, max));
907 if (!temp)
908 {
909 *stop = 1;
910 return 0;
911 }
912 memset(tmpbuf, 0, sizeof(tmpbuf));
913 offRead = 0;
914 offWrite = 0;
915 cSamplesMixed = 0;
916 nread = 0;
917 while (temp)
918 {
919 int acquired;
920 to_copy = audio_MIN(temp, sizeof(tmpbuf));
921 acquired = pThis->pDrv[lun]->pfnRead(pThis->pDrv[lun], voice[lun], tmpbuf, to_copy);
922 cSamplesRead = acquired >> voice[lun]->Props.cShift;
923 while (cSamplesRead)
924 {
925 SrcBuf = tmpbuf + offRead;
926 isamp = cSamplesRead;
927 if (!isamp)
928 {
929 LogFlow(("DevichAC97: No Input samples \n"));
930 break;
931 }
932 osamp = cSamplesRead - cSamplesMixed; /*sizeof(MixBuf)*/;
933 pThis->pDrv[lun]->pfnDoRateConvAndMix(pThis->pDrv[lun], rate[lun], SrcBuf,
934 MixBuf, &isamp, &osamp);
935 cSamplesRead -= isamp;
936 offRead += isamp;
937 offWrite += osamp;
938 cSamplesMixed += isamp;
939 }
940 if (!acquired)
941 {
942 *stop = 1;
943 break;
944 }
945 pThis->pDrv[lun]->pfnConvStSampleToDevFmt(pThis->pDrv[lun], u8DupBuf, MixBuf, cSamplesMixed);
946 temp -= acquired;
947 //addr += acquired;
948 //addr += (ctotalSamplexMixed << voice->Props.cShift);
949 //nread += (cSamplesMixed << voice->Props.cShift);
950 nread += acquired;
951 LogFlow(("DevIchAC97: looping temp = %d\n", temp));
952 cTotalSamplesRead = audio_MAX(cTotalSamplesRead, nread);
953 cTotalSamplesMixed = audio_MAX(cTotalSamplesMixed, cSamplesMixed);
954 }
955 }
956 if (cTotalSamplesMixed)
957 PDMDevHlpPCIPhysWrite(pDevIns, addr, u8DupBuf, (cTotalSamplesMixed << voice[0]->Props.cShift));
958 addr += (cTotalSamplesMixed << voice[0]->Props.cShift);
959 nread = cTotalSamplesRead;
960#else
961 uint8_t tmpbuf[4096];
962 while (temp)
963 {
964 int acquired;
965 to_copy = audio_MIN(temp, sizeof(tmpbuf));
966 acquired = AUD_read(voice, tmpbuf, to_copy);
967 if (!acquired)
968 {
969 *stop = 1;
970 break;
971 }
972 PDMDevHlpPCIPhysWrite(pDevIns, addr, tmpbuf, acquired);
973 temp -= acquired;
974 addr += acquired;
975 nread += acquired;
976 }
977#endif
978 pReg->bd.addr = addr;
979 return nread;
980}
981
982static void transfer_audio(PAC97STATE pThis, int index, int elapsed)
983{
984 PAC97BMREG pReg = &pThis->bm_regs[index];
985 int written = 0;
986 int stop = 0;
987
988 if (pReg->sr & SR_DCH)
989 {
990 if (pReg->cr & CR_RPBM)
991 {
992 switch (index)
993 {
994 case PO_INDEX:
995 write_bup(pThis, elapsed);
996 break;
997 }
998 }
999 return;
1000 }
1001
1002 while ((elapsed >> 1) && !stop)
1003 {
1004 int temp;
1005
1006 if (!pReg->bd_valid)
1007 {
1008 Log(("ac97: invalid bd\n"));
1009 fetch_bd(pThis, pReg);
1010 }
1011
1012 if (!pReg->picb)
1013 {
1014 Log(("ac97: fresh bd %d is empty %#x %#x, skipping\n", pReg->civ, pReg->bd.addr, pReg->bd.ctl_len));
1015 if (pReg->civ == pReg->lvi)
1016 {
1017 pReg->sr |= SR_DCH; /* CELV? */
1018 pThis->bup_flag = 0;
1019 break;
1020 }
1021 pReg->sr &= ~SR_CELV;
1022 pReg->civ = pReg->piv;
1023 pReg->piv = (pReg->piv + 1) % 32;
1024 fetch_bd(pThis, pReg);
1025 continue;
1026 }
1027
1028 switch (index)
1029 {
1030 case PO_INDEX:
1031 temp = write_audio(pThis, pReg, elapsed, &stop);
1032 written += temp;
1033 elapsed -= temp;
1034 Assert((temp & 1) == 0); /* Else the following shift won't work */
1035 pReg->picb -= (temp >> 1);
1036 break;
1037
1038 case PI_INDEX:
1039 case MC_INDEX:
1040 temp = read_audio(pThis, pReg, elapsed, &stop);
1041 elapsed -= temp;
1042 Assert((temp & 1) == 0); /* Else the following shift won't work */
1043 pReg->picb -= (temp >> 1);
1044 break;
1045 }
1046 Log(("pReg->picb = %d\n", pReg->picb));
1047
1048 if (!pReg->picb)
1049 {
1050 uint32_t new_sr = pReg->sr & ~SR_CELV;
1051
1052 if (pReg->bd.ctl_len & BD_IOC)
1053 {
1054 new_sr |= SR_BCIS;
1055 }
1056
1057 if (pReg->civ == pReg->lvi)
1058 {
1059 Log(("ac97: Underrun civ (%d) == lvi (%d)\n", pReg->civ, pReg->lvi));
1060 new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
1061 stop = 1;
1062 pThis->bup_flag = (pReg->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
1063 }
1064 else
1065 {
1066 pReg->civ = pReg->piv;
1067 pReg->piv = (pReg->piv + 1) % 32;
1068 fetch_bd(pThis, pReg);
1069 }
1070 update_sr(pThis, pReg, new_sr);
1071 }
1072 }
1073}
1074
1075static void pi_callback(void *opaque, int avail)
1076{
1077 transfer_audio((AC97STATE *)opaque, PI_INDEX, avail);
1078}
1079
1080static void mc_callback(void *opaque, int avail)
1081{
1082 transfer_audio((AC97STATE *)opaque, MC_INDEX, avail);
1083}
1084
1085static void po_callback(void *opaque, int free)
1086{
1087 transfer_audio((AC97STATE *)opaque, PO_INDEX, free);
1088}
1089
1090/**
1091 * @callback_method_impl{FNIOMIOPORTIN}
1092 */
1093static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1094{
1095 PAC97STATE pThis = (PAC97STATE)pvUser;
1096
1097 switch (cb)
1098 {
1099 case 1:
1100 {
1101 PAC97BMREG pReg = NULL;
1102 uint32_t index = Port - pThis->IOPortBase[1];
1103 *pu32 = ~0U;
1104
1105 switch (index)
1106 {
1107 case CAS:
1108 /* Codec Access Semaphore Register */
1109 Log(("ac97: CAS %d\n", pThis->cas));
1110 *pu32 = pThis->cas;
1111 pThis->cas = 1;
1112 break;
1113 case PI_CIV:
1114 case PO_CIV:
1115 case MC_CIV:
1116 /* Current Index Value Register */
1117 pReg = &pThis->bm_regs[GET_BM(index)];
1118 *pu32 = pReg->civ;
1119 Log(("ac97: CIV[%d] -> %#x\n", GET_BM(index), *pu32));
1120 break;
1121 case PI_LVI:
1122 case PO_LVI:
1123 case MC_LVI:
1124 /* Last Valid Index Register */
1125 pReg = &pThis->bm_regs[GET_BM(index)];
1126 *pu32 = pReg->lvi;
1127 Log(("ac97: LVI[%d] -> %#x\n", GET_BM(index), *pu32));
1128 break;
1129 case PI_PIV:
1130 case PO_PIV:
1131 case MC_PIV:
1132 /* Prefetched Index Value Register */
1133 pReg = &pThis->bm_regs[GET_BM(index)];
1134 *pu32 = pReg->piv;
1135 Log(("ac97: PIV[%d] -> %#x\n", GET_BM(index), *pu32));
1136 break;
1137 case PI_CR:
1138 case PO_CR:
1139 case MC_CR:
1140 /* Control Register */
1141 pReg = &pThis->bm_regs[GET_BM(index)];
1142 *pu32 = pReg->cr;
1143 Log(("ac97: CR[%d] -> %#x\n", GET_BM(index), *pu32));
1144 break;
1145 case PI_SR:
1146 case PO_SR:
1147 case MC_SR:
1148 /* Status Register (lower part) */
1149 pReg = &pThis->bm_regs[GET_BM(index)];
1150 *pu32 = pReg->sr & 0xff;
1151 Log(("ac97: SRb[%d] -> %#x\n", GET_BM(index), *pu32));
1152 break;
1153 default:
1154 Log(("ac97: U nabm readb %#x -> %#x\n", Port, *pu32));
1155 break;
1156 }
1157 break;
1158 }
1159
1160 case 2:
1161 {
1162 PAC97BMREG pReg = NULL;
1163 uint32_t index = Port - pThis->IOPortBase[1];
1164 *pu32 = ~0U;
1165
1166 switch (index)
1167 {
1168 case PI_SR:
1169 case PO_SR:
1170 case MC_SR:
1171 /* Status Register */
1172 pReg = &pThis->bm_regs[GET_BM(index)];
1173 *pu32 = pReg->sr;
1174 Log(("ac97: SR[%d] -> %#x\n", GET_BM(index), *pu32));
1175 break;
1176 case PI_PICB:
1177 case PO_PICB:
1178 case MC_PICB:
1179 /* Position in Current Buffer Register */
1180 pReg = &pThis->bm_regs[GET_BM(index)];
1181 *pu32 = pReg->picb;
1182 Log(("ac97: PICB[%d] -> %#x\n", GET_BM(index), *pu32));
1183 break;
1184 default:
1185 Log(("ac97: U nabm readw %#x -> %#x\n", Port, *pu32));
1186 break;
1187 }
1188 break;
1189 }
1190
1191 case 4:
1192 {
1193 PAC97BMREG pReg = NULL;
1194 uint32_t index = Port - pThis->IOPortBase[1];
1195 *pu32 = ~0U;
1196
1197 switch (index)
1198 {
1199 case PI_BDBAR:
1200 case PO_BDBAR:
1201 case MC_BDBAR:
1202 /* Buffer Descriptor Base Address Register */
1203 pReg = &pThis->bm_regs[GET_BM(index)];
1204 *pu32 = pReg->bdbar;
1205 Log(("ac97: BMADDR[%d] -> %#x\n", GET_BM(index), *pu32));
1206 break;
1207 case PI_CIV:
1208 case PO_CIV:
1209 case MC_CIV:
1210 /* 32-bit access: Current Index Value Register +
1211 * Last Valid Index Register +
1212 * Status Register */
1213 pReg = &pThis->bm_regs[GET_BM(index)];
1214 *pu32 = pReg->civ | (pReg->lvi << 8) | (pReg->sr << 16);
1215 Log(("ac97: CIV LVI SR[%d] -> %#x, %#x, %#x\n", GET_BM(index), pReg->civ, pReg->lvi, pReg->sr));
1216 break;
1217 case PI_PICB:
1218 case PO_PICB:
1219 case MC_PICB:
1220 /* 32-bit access: Position in Current Buffer Register +
1221 * Prefetched Index Value Register +
1222 * Control Register */
1223 pReg = &pThis->bm_regs[GET_BM(index)];
1224 *pu32 = pReg->picb | (pReg->piv << 16) | (pReg->cr << 24);
1225 Log(("ac97: PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM(index), *pu32, pReg->picb, pReg->piv, pReg->cr));
1226 break;
1227 case GLOB_CNT:
1228 /* Global Control */
1229 *pu32 = pThis->glob_cnt;
1230 Log(("ac97: glob_cnt -> %#x\n", *pu32));
1231 break;
1232 case GLOB_STA:
1233 /* Global Status */
1234 *pu32 = pThis->glob_sta | GS_S0CR;
1235 Log(("ac97: glob_sta -> %#x\n", *pu32));
1236 break;
1237 default:
1238 Log(("ac97: U nabm readl %#x -> %#x\n", Port, *pu32));
1239 break;
1240 }
1241 break;
1242 }
1243
1244 default:
1245 return VERR_IOM_IOPORT_UNUSED;
1246 }
1247 return VINF_SUCCESS;
1248}
1249
1250/**
1251 * @callback_method_impl{FNIOMIOPORTOUT}
1252 */
1253static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1254{
1255 PAC97STATE pThis = (PAC97STATE)pvUser;
1256
1257 switch (cb)
1258 {
1259 case 1:
1260 {
1261 PAC97BMREG pReg = NULL;
1262 uint32_t index = Port - pThis->IOPortBase[1];
1263 switch (index)
1264 {
1265 case PI_LVI:
1266 case PO_LVI:
1267 case MC_LVI:
1268 /* Last Valid Index */
1269 pReg = &pThis->bm_regs[GET_BM(index)];
1270 if ((pReg->cr & CR_RPBM) && (pReg->sr & SR_DCH))
1271 {
1272 pReg->sr &= ~(SR_DCH | SR_CELV);
1273 pReg->civ = pReg->piv;
1274 pReg->piv = (pReg->piv + 1) % 32;
1275 fetch_bd(pThis, pReg);
1276 }
1277 pReg->lvi = u32 % 32;
1278 Log(("ac97: LVI[%d] <- %#x\n", GET_BM(index), u32));
1279 break;
1280 case PI_CR:
1281 case PO_CR:
1282 case MC_CR:
1283 /* Control Register */
1284 pReg = &pThis->bm_regs[GET_BM(index)];
1285 if (u32 & CR_RR)
1286 reset_bm_regs(pThis, pReg);
1287 else
1288 {
1289 pReg->cr = u32 & CR_VALID_MASK;
1290 if (!(pReg->cr & CR_RPBM))
1291 {
1292 voice_set_active(pThis, pReg - pThis->bm_regs, 0);
1293 pReg->sr |= SR_DCH;
1294 }
1295 else
1296 {
1297 pReg->civ = pReg->piv;
1298 pReg->piv = (pReg->piv + 1) % 32;
1299 fetch_bd(pThis, pReg);
1300 pReg->sr &= ~SR_DCH;
1301 voice_set_active(pThis, pReg - pThis->bm_regs, 1);
1302 }
1303 }
1304 Log(("ac97: CR[%d] <- %#x (cr %#x)\n", GET_BM(index), u32, pReg->cr));
1305 break;
1306 case PI_SR:
1307 case PO_SR:
1308 case MC_SR:
1309 /* Status Register */
1310 pReg = &pThis->bm_regs[GET_BM(index)];
1311 pReg->sr |= u32 & ~(SR_RO_MASK | SR_WCLEAR_MASK);
1312 update_sr(pThis, pReg, pReg->sr & ~(u32 & SR_WCLEAR_MASK));
1313 Log(("ac97: SR[%d] <- %#x (sr %#x)\n", GET_BM(index), u32, pReg->sr));
1314 break;
1315 default:
1316 Log(("ac97: U nabm writeb %#x <- %#x\n", Port, u32));
1317 break;
1318 }
1319 break;
1320 }
1321
1322 case 2:
1323 {
1324 PAC97BMREG pReg = NULL;
1325 uint32_t index = Port - pThis->IOPortBase[1];
1326 switch (index)
1327 {
1328 case PI_SR:
1329 case PO_SR:
1330 case MC_SR:
1331 /* Status Register */
1332 pReg = &pThis->bm_regs[GET_BM(index)];
1333 pReg->sr |= u32 & ~(SR_RO_MASK | SR_WCLEAR_MASK);
1334 update_sr(pThis, pReg, pReg->sr & ~(u32 & SR_WCLEAR_MASK));
1335 Log(("ac97: SR[%d] <- %#x (sr %#x)\n", GET_BM(index), u32, pReg->sr));
1336 break;
1337 default:
1338 Log(("ac97: U nabm writew %#x <- %#x\n", Port, u32));
1339 break;
1340 }
1341 break;
1342 }
1343
1344 case 4:
1345 {
1346 PAC97BMREG pReg = NULL;
1347 uint32_t index = Port - pThis->IOPortBase[1];
1348 switch (index)
1349 {
1350 case PI_BDBAR:
1351 case PO_BDBAR:
1352 case MC_BDBAR:
1353 /* Buffer Descriptor list Base Address Register */
1354 pReg = &pThis->bm_regs[GET_BM(index)];
1355 pReg->bdbar = u32 & ~3;
1356 Log(("ac97: BDBAR[%d] <- %#x (bdbar %#x)\n", GET_BM(index), u32, pReg->bdbar));
1357 break;
1358 case GLOB_CNT:
1359 /* Global Control */
1360 if (u32 & GC_WR)
1361 warm_reset(pThis);
1362 if (u32 & GC_CR)
1363 cold_reset(pThis);
1364 if (!(u32 & (GC_WR | GC_CR)))
1365 pThis->glob_cnt = u32 & GC_VALID_MASK;
1366 Log(("ac97: glob_cnt <- %#x (glob_cnt %#x)\n", u32, pThis->glob_cnt));
1367 break;
1368 case GLOB_STA:
1369 /* Global Status */
1370 pThis->glob_sta &= ~(u32 & GS_WCLEAR_MASK);
1371 pThis->glob_sta |= (u32 & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
1372 Log(("ac97: glob_sta <- %#x (glob_sta %#x)\n", u32, pThis->glob_sta));
1373 break;
1374 default:
1375 Log(("ac97: U nabm writel %#x <- %#x\n", Port, u32));
1376 break;
1377 }
1378 break;
1379 }
1380
1381 default:
1382 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1383 break;
1384 }
1385 return VINF_SUCCESS;
1386}
1387
1388/**
1389 * @callback_method_impl{FNIOMIOPORTIN}
1390 */
1391static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
1392{
1393 PAC97STATE pThis = (PAC97STATE)pvUser;
1394
1395 switch (cb)
1396 {
1397 case 1:
1398 {
1399 Log(("ac97: U nam readb %#x\n", Port));
1400 pThis->cas = 0;
1401 *pu32 = ~0U;
1402 break;
1403 }
1404
1405 case 2:
1406 {
1407 uint32_t index = Port - pThis->IOPortBase[0];
1408 *pu32 = ~0U;
1409 pThis->cas = 0;
1410 switch (index)
1411 {
1412 default:
1413 *pu32 = mixer_load(pThis, index);
1414 Log(("ac97: nam readw %#x -> %#x\n", Port, *pu32));
1415 break;
1416 }
1417 break;
1418 }
1419
1420 case 4:
1421 {
1422 Log(("ac97: U nam readl %#x\n", Port));
1423 pThis->cas = 0;
1424 *pu32 = ~0U;
1425 break;
1426 }
1427
1428 default:
1429 return VERR_IOM_IOPORT_UNUSED;
1430 }
1431 return VINF_SUCCESS;
1432}
1433
1434/**
1435 * @callback_method_impl{FNIOMIOPORTOUT}
1436 */
1437static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
1438{
1439 PAC97STATE pThis = (PAC97STATE)pvUser;
1440
1441 switch (cb)
1442 {
1443 case 1:
1444 {
1445 Log(("ac97: U nam writeb %#x <- %#x\n", Port, u32));
1446 pThis->cas = 0;
1447 break;
1448 }
1449
1450 case 2:
1451 {
1452 uint32_t index = Port - pThis->IOPortBase[0];
1453 pThis->cas = 0;
1454 switch (index)
1455 {
1456 case AC97_Reset:
1457 mixer_reset(pThis);
1458 break;
1459 case AC97_Powerdown_Ctrl_Stat:
1460 u32 &= ~0xf;
1461 u32 |= mixer_load(pThis, index) & 0xf;
1462 mixer_store(pThis, index, u32);
1463 break;
1464#ifdef USE_MIXER
1465 case AC97_Master_Volume_Mute:
1466 set_volume(pThis, index, AUD_MIXER_VOLUME, u32);
1467 break;
1468 case AC97_PCM_Out_Volume_Mute:
1469 set_volume(pThis, index, AUD_MIXER_PCM, u32);
1470 break;
1471 case AC97_Line_In_Volume_Mute:
1472 set_volume(pThis, index, AUD_MIXER_LINE_IN, u32);
1473 break;
1474 case AC97_Record_Select:
1475 record_select(pThis, u32);
1476 break;
1477#else /* !USE_MIXER */
1478 case AC97_Master_Volume_Mute:
1479 case AC97_PCM_Out_Volume_Mute:
1480 case AC97_Line_In_Volume_Mute:
1481 case AC97_Record_Select:
1482 mixer_store(pThis, index, u32);
1483 break;
1484#endif /* !USE_MIXER */
1485 case AC97_Vendor_ID1:
1486 case AC97_Vendor_ID2:
1487 Log(("ac97: Attempt to write vendor ID to %#x\n", u32));
1488 break;
1489 case AC97_Extended_Audio_ID:
1490 Log(("ac97: Attempt to write extended audio ID to %#x\n", u32));
1491 break;
1492 case AC97_Extended_Audio_Ctrl_Stat:
1493 if (!(u32 & EACS_VRA))
1494 {
1495 mixer_store(pThis, AC97_PCM_Front_DAC_Rate, 0xbb80);
1496 mixer_store(pThis, AC97_PCM_LR_ADC_Rate, 0xbb80);
1497 open_voice(pThis, PI_INDEX, 48000);
1498 open_voice(pThis, PO_INDEX, 48000);
1499 }
1500 if (!(u32 & EACS_VRM))
1501 {
1502 mixer_store(pThis, AC97_MIC_ADC_Rate, 0xbb80);
1503 open_voice(pThis, MC_INDEX, 48000);
1504 }
1505 Log(("ac97: Setting extended audio control to %#x\n", u32));
1506 mixer_store(pThis, AC97_Extended_Audio_Ctrl_Stat, u32);
1507 break;
1508 case AC97_PCM_Front_DAC_Rate:
1509 if (mixer_load(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
1510 {
1511 mixer_store(pThis, index, u32);
1512 Log(("ac97: Set front DAC rate to %d\n", u32));
1513 open_voice(pThis, PO_INDEX, u32);
1514 }
1515 else
1516 Log(("ac97: Attempt to set front DAC rate to %d, but VRA is not set\n", u32));
1517 break;
1518 case AC97_MIC_ADC_Rate:
1519 if (mixer_load(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM)
1520 {
1521 mixer_store(pThis, index, u32);
1522 Log(("ac97: Set MIC ADC rate to %d\n", u32));
1523 open_voice(pThis, MC_INDEX, u32);
1524 }
1525 else
1526 Log(("ac97: Attempt to set MIC ADC rate to %d, but VRM is not set\n", u32));
1527 break;
1528 case AC97_PCM_LR_ADC_Rate:
1529 if (mixer_load(pThis, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA)
1530 {
1531 mixer_store(pThis, index, u32);
1532 Log(("ac97: Set front LR ADC rate to %d\n", u32));
1533 open_voice(pThis, PI_INDEX, u32);
1534 }
1535 else
1536 Log(("ac97: Attempt to set LR ADC rate to %d, but VRA is not set\n", u32));
1537 break;
1538 default:
1539 Log(("ac97: U nam writew %#x <- %#x\n", Port, u32));
1540 mixer_store(pThis, index, u32);
1541 break;
1542 }
1543 break;
1544 }
1545
1546 case 4:
1547 {
1548 Log(("ac97: U nam writel %#x <- %#x\n", Port, u32));
1549 pThis->cas = 0;
1550 break;
1551 }
1552
1553 default:
1554 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
1555 break;
1556 }
1557 return VINF_SUCCESS;
1558}
1559
1560
1561/**
1562 * @callback_method_impl{FNPCIIOREGIONMAP}
1563 */
1564static DECLCALLBACK(int) ichac97IOPortMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
1565 PCIADDRESSSPACE enmType)
1566{
1567 PPDMDEVINS pDevIns = pPciDev->pDevIns;
1568 PAC97STATE pThis = RT_FROM_MEMBER(pPciDev, AC97STATE, PciDev);
1569 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
1570 int rc;
1571
1572 Assert(enmType == PCI_ADDRESS_SPACE_IO);
1573 Assert(cb >= 0x20);
1574
1575 if (iRegion == 0)
1576 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, pThis,
1577 ichac97IOPortNAMWrite, ichac97IOPortNAMRead,
1578 NULL, NULL, "ICHAC97 NAM");
1579 else
1580 rc = PDMDevHlpIOPortRegister(pDevIns, Port, 64, pThis,
1581 ichac97IOPortNABMWrite, ichac97IOPortNABMRead,
1582 NULL, NULL, "ICHAC97 NABM");
1583 if (RT_FAILURE(rc))
1584 return rc;
1585
1586 pThis->IOPortBase[iRegion] = Port;
1587 return VINF_SUCCESS;
1588}
1589
1590
1591/**
1592 * @callback_method_impl{FNSSMDEVSAVEEXEC}
1593 */
1594static DECLCALLBACK(int) ichac97SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1595{
1596 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
1597
1598 SSMR3PutU32(pSSM, pThis->glob_cnt);
1599 SSMR3PutU32(pSSM, pThis->glob_sta);
1600 SSMR3PutU32(pSSM, pThis->cas);
1601
1602 for (unsigned i = 0; i < RT_ELEMENTS(pThis->bm_regs); i++)
1603 {
1604 PAC97BMREG pReg = &pThis->bm_regs[i];
1605 SSMR3PutU32(pSSM, pReg->bdbar);
1606 SSMR3PutU8( pSSM, pReg->civ);
1607 SSMR3PutU8( pSSM, pReg->lvi);
1608 SSMR3PutU16(pSSM, pReg->sr);
1609 SSMR3PutU16(pSSM, pReg->picb);
1610 SSMR3PutU8( pSSM, pReg->piv);
1611 SSMR3PutU8( pSSM, pReg->cr);
1612 SSMR3PutS32(pSSM, pReg->bd_valid);
1613 SSMR3PutU32(pSSM, pReg->bd.addr);
1614 SSMR3PutU32(pSSM, pReg->bd.ctl_len);
1615 }
1616 SSMR3PutMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
1617
1618 uint8_t active[LAST_INDEX];
1619#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1620 /* writing only host backend values here and ignoring for webm and VRDE */
1621 active[PI_INDEX] = pThis->pDrv[0]->pfnIsActiveIn(pThis->pDrv[0], pThis->voice_pi[0]) ? 1 : 0;
1622 active[PO_INDEX] = pThis->pDrv[0]->pfnIsActiveOut(pThis->pDrv[0], pThis->voice_po[0]) ? 1 : 0;
1623 active[MC_INDEX] = pThis->pDrv[0]->pfnIsActiveIn(pThis->pDrv[0], pThis->voice_mc[0]) ? 1 : 0;
1624#else
1625 active[PI_INDEX] = AUD_is_active_in( pThis->voice_pi) ? 1 : 0;
1626 active[PO_INDEX] = AUD_is_active_out(pThis->voice_po) ? 1 : 0;
1627 active[MC_INDEX] = AUD_is_active_in( pThis->voice_mc) ? 1 : 0;
1628#endif
1629 SSMR3PutMem(pSSM, active, sizeof(active));
1630
1631 return VINF_SUCCESS;
1632}
1633
1634
1635/**
1636 * @callback_method_impl{FNSSMDEVLOADEXEC}
1637 */
1638static DECLCALLBACK(int) ichac97LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1639{
1640 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
1641
1642 AssertMsgReturn (uVersion == AC97_SSM_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1643 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
1644
1645 SSMR3GetU32(pSSM, &pThis->glob_cnt);
1646 SSMR3GetU32(pSSM, &pThis->glob_sta);
1647 SSMR3GetU32(pSSM, &pThis->cas);
1648
1649 for (unsigned i = 0; i < RT_ELEMENTS(pThis->bm_regs); i++)
1650 {
1651 PAC97BMREG pReg = &pThis->bm_regs[i];
1652 SSMR3GetU32(pSSM, &pReg->bdbar);
1653 SSMR3GetU8( pSSM, &pReg->civ);
1654 SSMR3GetU8( pSSM, &pReg->lvi);
1655 SSMR3GetU16(pSSM, &pReg->sr);
1656 SSMR3GetU16(pSSM, &pReg->picb);
1657 SSMR3GetU8( pSSM, &pReg->piv);
1658 SSMR3GetU8( pSSM, &pReg->cr);
1659 SSMR3GetS32(pSSM, &pReg->bd_valid);
1660 SSMR3GetU32(pSSM, &pReg->bd.addr);
1661 SSMR3GetU32(pSSM, &pReg->bd.ctl_len);
1662 }
1663
1664 SSMR3GetMem(pSSM, pThis->mixer_data, sizeof(pThis->mixer_data));
1665 uint8_t active[LAST_INDEX];
1666 SSMR3GetMem(pSSM, active, sizeof(active));
1667
1668#ifdef USE_MIXER
1669 record_select(pThis, mixer_load(pThis, AC97_Record_Select));
1670# define V_(a, b) set_volume(pThis, a, b, mixer_load(pThis, a))
1671 V_(AC97_Master_Volume_Mute, AUD_MIXER_VOLUME);
1672 V_(AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM);
1673 V_(AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN);
1674# undef V_
1675#endif /* USE_MIXER */
1676 reset_voices(pThis, active);
1677
1678 pThis->bup_flag = 0;
1679 pThis->last_samp = 0;
1680
1681 return VINF_SUCCESS;
1682}
1683
1684
1685/**
1686 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1687 */
1688static DECLCALLBACK(void *) ichac97QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
1689{
1690 PAC97STATE pThis = RT_FROM_MEMBER(pInterface, AC97STATE, IBase);
1691 Assert(&pThis->IBase == pInterface);
1692
1693 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
1694 return NULL;
1695}
1696
1697
1698/**
1699 * @interface_method_impl{PDMDEVREG,pfnReset}
1700 *
1701 * @remarks The original sources didn't install a reset handler, but it seems to
1702 * make sense to me so we'll do it.
1703 */
1704static DECLCALLBACK(void) ac97Reset(PPDMDEVINS pDevIns)
1705{
1706 PAC97STATE pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
1707
1708 /*
1709 * Reset the device state (will need pDrv later).
1710 */
1711 reset_bm_regs(pThis, &pThis->bm_regs[0]);
1712 reset_bm_regs(pThis, &pThis->bm_regs[1]);
1713 reset_bm_regs(pThis, &pThis->bm_regs[2]);
1714
1715 /*
1716 * Reset the mixer too. The Windows XP driver seems to rely on
1717 * this. At least it wants to read the vendor id before it resets
1718 * the codec manually.
1719 */
1720 mixer_reset(pThis);
1721}
1722
1723
1724/**
1725 * @interface_method_impl{PDMDEVREG,pfnConstruct}
1726 */
1727static DECLCALLBACK(int) ichac97Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
1728{
1729 AC97STATE *pThis = PDMINS_2_DATA(pDevIns, AC97STATE *);
1730 int rc;
1731
1732 Assert(iInstance == 0);
1733 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1734
1735 /*
1736 * Validations.
1737 */
1738 if (!CFGMR3AreValuesValid(pCfg, "\0"))
1739 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1740 N_("Invalid configuration for the AC97 device"));
1741
1742 /*
1743 * Initialize data (most of it anyway).
1744 */
1745 pThis->pDevIns = pDevIns;
1746 /* IBase */
1747 pThis->IBase.pfnQueryInterface = ichac97QueryInterface;
1748
1749 /* PCI Device (the assertions will be removed later) */
1750 PCIDevSetVendorId (&pThis->PciDev, 0x8086); /* 00 ro - intel. */ Assert(pThis->PciDev.config[0x00] == 0x86); Assert(pThis->PciDev.config[0x01] == 0x80);
1751 PCIDevSetDeviceId (&pThis->PciDev, 0x2415); /* 02 ro - 82801 / 82801aa(?). */ Assert(pThis->PciDev.config[0x02] == 0x15); Assert(pThis->PciDev.config[0x03] == 0x24);
1752 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */ Assert(pThis->PciDev.config[0x04] == 0x00); Assert(pThis->PciDev.config[0x05] == 0x00);
1753 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);
1754 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */ Assert(pThis->PciDev.config[0x08] == 0x01);
1755 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */ Assert(pThis->PciDev.config[0x09] == 0x00);
1756 PCIDevSetClassSub (&pThis->PciDev, 0x01); /* 0a ro - scc; 01 == Audio. */ Assert(pThis->PciDev.config[0x0a] == 0x01);
1757 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */ Assert(pThis->PciDev.config[0x0b] == 0x04);
1758 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */ Assert(pThis->PciDev.config[0x0e] == 0x00);
1759 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - nambar - native audio mixer base. */
1760 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);
1761 PCIDevSetBaseAddress (&pThis->PciDev, 1, /* 14 rw - nabmbar - native audio bus mastering. */
1762 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);
1763 PCIDevSetSubSystemVendorId(&pThis->PciDev, 0x8086); /* 2c ro - intel.) */ Assert(pThis->PciDev.config[0x2c] == 0x86); Assert(pThis->PciDev.config[0x2d] == 0x80);
1764 PCIDevSetSubSystemId (&pThis->PciDev, 0x0000); /* 2e ro. */ Assert(pThis->PciDev.config[0x2e] == 0x00); Assert(pThis->PciDev.config[0x2f] == 0x00);
1765 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */ Assert(pThis->PciDev.config[0x3c] == 0x00);
1766 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */ Assert(pThis->PciDev.config[0x3d] == 0x01);
1767
1768 /*
1769 * Register the PCI device, it's I/O regions, the timer and the
1770 * saved state item.
1771 */
1772 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
1773 if (RT_FAILURE (rc))
1774 return rc;
1775
1776 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 256, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
1777 if (RT_FAILURE (rc))
1778 return rc;
1779
1780 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 64, PCI_ADDRESS_SPACE_IO, ichac97IOPortMap);
1781 if (RT_FAILURE (rc))
1782 return rc;
1783
1784 rc = PDMDevHlpSSMRegister(pDevIns, AC97_SSM_VERSION, sizeof(*pThis), ichac97SaveExec, ichac97LoadExec);
1785 if (RT_FAILURE (rc))
1786 return rc;
1787
1788 /*
1789 * Attach driver.
1790 */
1791#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1792 for (uint32_t lun = 0; lun < 2; lun++)
1793 {
1794 rc = PDMDevHlpDriverAttach(pDevIns, lun, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port");
1795 if (RT_SUCCESS(rc))
1796 {
1797 pThis->pDrv[lun] = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR);
1798 AssertMsgReturn(pThis->pDrv[lun],
1799 ("Configuration error: instance %d has no host audio interface!\n", iInstance),
1800 VERR_PDM_MISSING_INTERFACE);
1801 }
1802 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1803 Log(("ac97: No attached driver!\n"));
1804 else if (RT_FAILURE(rc))
1805 {
1806 AssertMsgFailed(("Failed to attach AC97 LUN #%d! rc=%Rrc\n", lun, rc));
1807 return rc;
1808 }
1809 }
1810#else
1811 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port");
1812 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1813 Log(("ac97: No attached driver!\n"));
1814 else if (RT_FAILURE(rc))
1815 {
1816 AssertMsgFailed(("Failed to attach AC97 LUN #0! rc=%Rrc\n", rc));
1817 return rc;
1818 }
1819#endif
1820
1821
1822#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1823 pThis->pDrv[0]->pfnRegisterCard(pThis->pDrv[0], "ICH0" );
1824#else
1825 AUD_register_card("ICH0", &pThis->card);
1826#endif
1827 ac97Reset(pDevIns);
1828
1829#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1830 for (uint32_t lun =0; lun < 2; lun++)
1831 {
1832 if (!pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_pi[lun]))
1833 LogRel(("AC97: WARNING: Unable to open PCM IN!\n"));
1834 if (!pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_mc[lun]))
1835 LogRel(("AC97: WARNING: Unable to open PCM MC!\n"));
1836 if (!pThis->pDrv[lun]->pfnIsHostVoiceOutOK(pThis->pDrv[lun], pThis->voice_po[lun]))
1837 LogRel(("AC97: WARNING: Unable to open PCM OUT!\n"));
1838 }
1839#else
1840 if (!AUD_is_host_voice_in_ok(pThis->voice_pi))
1841 LogRel(("AC97: WARNING: Unable to open PCM IN!\n"));
1842 if (!AUD_is_host_voice_in_ok(pThis->voice_mc))
1843 LogRel(("AC97: WARNING: Unable to open PCM MC!\n"));
1844 if (!AUD_is_host_voice_out_ok(pThis->voice_po))
1845 LogRel(("AC97: WARNING: Unable to open PCM OUT!\n"));
1846
1847#endif
1848
1849#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1850 for (uint32_t lun = 0; lun < 2; lun++)
1851 {
1852 if ( !pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_pi[lun])
1853 && !pThis->pDrv[lun]->pfnIsHostVoiceOutOK(pThis->pDrv[lun], pThis->voice_po[lun])
1854 && !pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_mc[lun]))
1855 {
1856 /* Was not able initialize *any* voice. Select the NULL audio driver instead */
1857 pThis->pDrv[lun]->pfnCloseIn(pThis->pDrv[lun], pThis->voice_pi[lun]);
1858 pThis->pDrv[lun]->pfnCloseOut(pThis->pDrv[lun], pThis->voice_po[lun]);
1859 pThis->pDrv[lun]->pfnCloseIn(pThis->pDrv[lun], pThis->voice_mc[lun]);
1860
1861 pThis->voice_po[lun] = NULL;
1862 pThis->voice_pi[lun] = NULL;
1863 pThis->voice_mc[lun] = NULL;
1864
1865 pThis->pDrv[lun]->pfnInitNull(pThis->pDrv[lun]);
1866 ac97Reset(pDevIns);
1867
1868 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1869 N_("No audio devices could be opened. Selecting the NULL audio backend "
1870 "with the consequence that no sound is audible"));
1871 }
1872 else if ( !pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_pi[lun])
1873 || !pThis->pDrv[lun]->pfnIsHostVoiceOutOK(pThis->pDrv[lun], pThis->voice_po[lun])
1874 || !pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_mc[lun]))
1875 {
1876 char szMissingVoices[128];
1877 size_t len = 0;
1878 if (!pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_pi[lun]))
1879 len = RTStrPrintf(szMissingVoices, sizeof(szMissingVoices), "PCM_in");
1880 if (!pThis->pDrv[lun]->pfnIsHostVoiceOutOK(pThis->pDrv[lun], pThis->voice_po[lun]))
1881 len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
1882 if (!pThis->pDrv[lun]->pfnIsHostVoiceInOK(pThis->pDrv[lun], pThis->voice_mc[lun]))
1883 len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_mic" : "PCM_mic");
1884
1885 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1886 N_("Some audio devices (%s) could not be opened. Guest applications generating audio "
1887 "output or depending on audio input may hang. Make sure your host audio device "
1888 "is working properly. Check the logfile for error messages of the audio "
1889 "subsystem"), szMissingVoices);
1890 }
1891 }
1892#else
1893 if ( !AUD_is_host_voice_in_ok( pThis->voice_pi)
1894 && !AUD_is_host_voice_out_ok(pThis->voice_po)
1895 && !AUD_is_host_voice_in_ok( pThis->voice_mc))
1896 {
1897 AUD_close_in(&pThis->card, pThis->voice_pi);
1898 AUD_close_out(&pThis->card, pThis->voice_po);
1899 AUD_close_in(&pThis->card, pThis->voice_mc);
1900
1901 pThis->voice_po = NULL;
1902 pThis->voice_pi = NULL;
1903 pThis->voice_mc = NULL;
1904 AUD_init_null();
1905 ac97Reset(pDevIns);
1906
1907 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1908 N_("No audio devices could be opened. Selecting the NULL audio backend "
1909 "with the consequence that no sound is audible"));
1910 }
1911 else if ( !AUD_is_host_voice_in_ok( pThis->voice_pi)
1912 || !AUD_is_host_voice_out_ok(pThis->voice_po)
1913 || !AUD_is_host_voice_in_ok( pThis->voice_mc))
1914 {
1915 char szMissingVoices[128];
1916 size_t len = 0;
1917 if (!AUD_is_host_voice_in_ok(pThis->voice_pi))
1918 len = RTStrPrintf(szMissingVoices, sizeof(szMissingVoices), "PCM_in");
1919 if (!AUD_is_host_voice_out_ok(pThis->voice_po))
1920 len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
1921 if (!AUD_is_host_voice_in_ok(pThis->voice_mc))
1922 len += RTStrPrintf(szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_mic" : "PCM_mic");
1923
1924 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1925 N_("Some audio devices (%s) could not be opened. Guest applications generating audio "
1926 "output or depending on audio input may hang. Make sure your host audio device "
1927 "is working properly. Check the logfile for error messages of the audio "
1928 "subsystem"), szMissingVoices);
1929 }
1930#endif
1931 return VINF_SUCCESS;
1932}
1933
1934/**
1935 * The device registration structure.
1936 */
1937const PDMDEVREG g_DeviceICHAC97 =
1938{
1939 /* u32Version */
1940 PDM_DEVREG_VERSION,
1941 /* szName */
1942 "ichac97",
1943 /* szRCMod */
1944 "",
1945 /* szR0Mod */
1946 "",
1947 /* pszDescription */
1948 "ICH AC'97 Audio Controller",
1949 /* fFlags */
1950 PDM_DEVREG_FLAGS_DEFAULT_BITS,
1951 /* fClass */
1952 PDM_DEVREG_CLASS_AUDIO,
1953 /* cMaxInstances */
1954 1,
1955 /* cbInstance */
1956 sizeof(AC97STATE),
1957 /* pfnConstruct */
1958 ichac97Construct,
1959 /* pfnDestruct */
1960 NULL,
1961 /* pfnRelocate */
1962 NULL,
1963 /* pfnMemSetup */
1964 NULL,
1965 /* pfnPowerOn */
1966 NULL,
1967 /* pfnReset */
1968 ac97Reset,
1969 /* pfnSuspend */
1970 NULL,
1971 /* pfnResume */
1972 NULL,
1973 /* pfnAttach */
1974 NULL,
1975 /* pfnDetach */
1976 NULL,
1977 /* pfnQueryInterface. */
1978 NULL,
1979 /* pfnInitComplete */
1980 NULL,
1981 /* pfnPowerOff */
1982 NULL,
1983 /* pfnSoftReset */
1984 NULL,
1985 /* u32VersionEnd */
1986 PDM_DEVREG_VERSION
1987};
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