VirtualBox

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

Last change on this file since 44630 was 44630, checked in by vboxsync, 12 years ago

DevIchAc97.cpp: Some code style cleanups.

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