Commit e5c9a13e2670b1cf23faa4b7793b3eae4ad428a5

Authored by balrog
1 parent ca9cc28c

PCI AC97 emulation by malc.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3918 c046a42c-6fe2-441c-8c8c-71466251a162
configure
@@ -85,6 +85,7 @@ EXESUF="" @@ -85,6 +85,7 @@ EXESUF=""
85 gdbstub="yes" 85 gdbstub="yes"
86 slirp="yes" 86 slirp="yes"
87 adlib="no" 87 adlib="no"
  88 +ac97="no"
88 oss="no" 89 oss="no"
89 dsound="no" 90 dsound="no"
90 coreaudio="no" 91 coreaudio="no"
@@ -280,6 +281,8 @@ for opt do @@ -280,6 +281,8 @@ for opt do
280 ;; 281 ;;
281 --enable-adlib) adlib="yes" 282 --enable-adlib) adlib="yes"
282 ;; 283 ;;
  284 + --enable-ac97) ac97="yes"
  285 + ;;
283 --disable-kqemu) kqemu="no" 286 --disable-kqemu) kqemu="no"
284 ;; 287 ;;
285 --enable-profiler) profiler="yes" 288 --enable-profiler) profiler="yes"
@@ -406,6 +409,7 @@ echo " --disable-sdl disable SDL" @@ -406,6 +409,7 @@ echo " --disable-sdl disable SDL"
406 echo " --enable-cocoa enable COCOA (Mac OS X only)" 409 echo " --enable-cocoa enable COCOA (Mac OS X only)"
407 echo " --enable-mingw32 enable Win32 cross compilation with mingw32" 410 echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
408 echo " --enable-adlib enable Adlib emulation" 411 echo " --enable-adlib enable Adlib emulation"
  412 +echo " --enable-ac97 enable AC97 emulation"
409 echo " --enable-coreaudio enable Coreaudio audio driver" 413 echo " --enable-coreaudio enable Coreaudio audio driver"
410 echo " --enable-alsa enable ALSA audio driver" 414 echo " --enable-alsa enable ALSA audio driver"
411 echo " --enable-esd enable EsoundD audio driver" 415 echo " --enable-esd enable EsoundD audio driver"
@@ -719,6 +723,7 @@ if test "$sdl" != "no" ; then @@ -719,6 +723,7 @@ if test "$sdl" != "no" ; then
719 fi 723 fi
720 echo "mingw32 support $mingw32" 724 echo "mingw32 support $mingw32"
721 echo "Adlib support $adlib" 725 echo "Adlib support $adlib"
  726 +echo "AC97 support $ac97"
722 echo "CoreAudio support $coreaudio" 727 echo "CoreAudio support $coreaudio"
723 echo "ALSA support $alsa" 728 echo "ALSA support $alsa"
724 echo "EsounD support $esd" 729 echo "EsounD support $esd"
@@ -895,6 +900,10 @@ if test "$adlib" = "yes" ; then @@ -895,6 +900,10 @@ if test "$adlib" = "yes" ; then
895 echo "CONFIG_ADLIB=yes" >> $config_mak 900 echo "CONFIG_ADLIB=yes" >> $config_mak
896 echo "#define CONFIG_ADLIB 1" >> $config_h 901 echo "#define CONFIG_ADLIB 1" >> $config_h
897 fi 902 fi
  903 +if test "$ac97" = "yes" ; then
  904 + echo "CONFIG_AC97=yes" >> $config_mak
  905 + echo "#define CONFIG_AC97 1" >> $config_h
  906 +fi
898 if test "$oss" = "yes" ; then 907 if test "$oss" = "yes" ; then
899 echo "CONFIG_OSS=yes" >> $config_mak 908 echo "CONFIG_OSS=yes" >> $config_mak
900 echo "#define CONFIG_OSS 1" >> $config_h 909 echo "#define CONFIG_OSS 1" >> $config_h
hw/ac97.c 0 → 100644
  1 +/*
  2 + * Copyright (C) 2006 InnoTek Systemberatung GmbH
  3 + *
  4 + * This file is part of VirtualBox Open Source Edition (OSE), as
  5 + * available from http://www.virtualbox.org. This file is free software;
  6 + * you can redistribute it and/or modify it under the terms of the GNU
  7 + * General Public License as published by the Free Software Foundation,
  8 + * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
  9 + * distribution. VirtualBox OSE is distributed in the hope that it will
  10 + * be useful, but WITHOUT ANY WARRANTY of any kind.
  11 + *
  12 + * If you received this file as part of a commercial VirtualBox
  13 + * distribution, then only the terms of your commercial VirtualBox
  14 + * license agreement apply instead of the previous paragraph.
  15 + */
  16 +
  17 +#include "hw.h"
  18 +#include "audiodev.h"
  19 +#include "audio/audio.h"
  20 +#include "pci.h"
  21 +
  22 +enum {
  23 + AC97_Reset = 0x00,
  24 + AC97_Master_Volume_Mute = 0x02,
  25 + AC97_Headphone_Volume_Mute = 0x04,
  26 + AC97_Master_Volume_Mono_Mute = 0x06,
  27 + AC97_Master_Tone_RL = 0x08,
  28 + AC97_PC_BEEP_Volume_Mute = 0x0A,
  29 + AC97_Phone_Volume_Mute = 0x0C,
  30 + AC97_Mic_Volume_Mute = 0x0E,
  31 + AC97_Line_In_Volume_Mute = 0x10,
  32 + AC97_CD_Volume_Mute = 0x12,
  33 + AC97_Video_Volume_Mute = 0x14,
  34 + AC97_Aux_Volume_Mute = 0x16,
  35 + AC97_PCM_Out_Volume_Mute = 0x18,
  36 + AC97_Record_Select = 0x1A,
  37 + AC97_Record_Gain_Mute = 0x1C,
  38 + AC97_Record_Gain_Mic_Mute = 0x1E,
  39 + AC97_General_Purpose = 0x20,
  40 + AC97_3D_Control = 0x22,
  41 + AC97_AC_97_RESERVED = 0x24,
  42 + AC97_Powerdown_Ctrl_Stat = 0x26,
  43 + AC97_Extended_Audio_ID = 0x28,
  44 + AC97_Extended_Audio_Ctrl_Stat = 0x2A,
  45 + AC97_PCM_Front_DAC_Rate = 0x2C,
  46 + AC97_PCM_Surround_DAC_Rate = 0x2E,
  47 + AC97_PCM_LFE_DAC_Rate = 0x30,
  48 + AC97_PCM_LR_ADC_Rate = 0x32,
  49 + AC97_MIC_ADC_Rate = 0x34,
  50 + AC97_6Ch_Vol_C_LFE_Mute = 0x36,
  51 + AC97_6Ch_Vol_L_R_Surround_Mute = 0x38,
  52 + AC97_Vendor_Reserved = 0x58,
  53 + AC97_Vendor_ID1 = 0x7c,
  54 + AC97_Vendor_ID2 = 0x7e
  55 +};
  56 +
  57 +#define SOFT_VOLUME
  58 +#define SR_FIFOE 16 /* rwc */
  59 +#define SR_BCIS 8 /* rwc */
  60 +#define SR_LVBCI 4 /* rwc */
  61 +#define SR_CELV 2 /* ro */
  62 +#define SR_DCH 1 /* ro */
  63 +#define SR_VALID_MASK ((1 << 5) - 1)
  64 +#define SR_WCLEAR_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
  65 +#define SR_RO_MASK (SR_DCH | SR_CELV)
  66 +#define SR_INT_MASK (SR_FIFOE | SR_BCIS | SR_LVBCI)
  67 +
  68 +#define CR_IOCE 16 /* rw */
  69 +#define CR_FEIE 8 /* rw */
  70 +#define CR_LVBIE 4 /* rw */
  71 +#define CR_RR 2 /* rw */
  72 +#define CR_RPBM 1 /* rw */
  73 +#define CR_VALID_MASK ((1 << 5) - 1)
  74 +#define CR_DONT_CLEAR_MASK (CR_IOCE | CR_FEIE | CR_LVBIE)
  75 +
  76 +#define GC_WR 4 /* rw */
  77 +#define GC_CR 2 /* rw */
  78 +#define GC_VALID_MASK ((1 << 6) - 1)
  79 +
  80 +#define GS_MD3 (1<<17) /* rw */
  81 +#define GS_AD3 (1<<16) /* rw */
  82 +#define GS_RCS (1<<15) /* rwc */
  83 +#define GS_B3S12 (1<<14) /* ro */
  84 +#define GS_B2S12 (1<<13) /* ro */
  85 +#define GS_B1S12 (1<<12) /* ro */
  86 +#define GS_S1R1 (1<<11) /* rwc */
  87 +#define GS_S0R1 (1<<10) /* rwc */
  88 +#define GS_S1CR (1<<9) /* ro */
  89 +#define GS_S0CR (1<<8) /* ro */
  90 +#define GS_MINT (1<<7) /* ro */
  91 +#define GS_POINT (1<<6) /* ro */
  92 +#define GS_PIINT (1<<5) /* ro */
  93 +#define GS_RSRVD ((1<<4)|(1<<3))
  94 +#define GS_MOINT (1<<2) /* ro */
  95 +#define GS_MIINT (1<<1) /* ro */
  96 +#define GS_GSCI 1 /* rwc */
  97 +#define GS_RO_MASK (GS_B3S12| \
  98 + GS_B2S12| \
  99 + GS_B1S12| \
  100 + GS_S1CR| \
  101 + GS_S0CR| \
  102 + GS_MINT| \
  103 + GS_POINT| \
  104 + GS_PIINT| \
  105 + GS_RSRVD| \
  106 + GS_MOINT| \
  107 + GS_MIINT)
  108 +#define GS_VALID_MASK ((1 << 18) - 1)
  109 +#define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI)
  110 +
  111 +#define BD_IOC (1<<31)
  112 +#define BD_BUP (1<<30)
  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
  121 +enum {
  122 + REC_MIC = 0,
  123 + REC_CD,
  124 + REC_VIDEO,
  125 + REC_AUX,
  126 + REC_LINE_IN,
  127 + REC_STEREO_MIX,
  128 + REC_MONO_MIX,
  129 + REC_PHONE
  130 +};
  131 +
  132 +typedef struct BD {
  133 + uint32_t addr;
  134 + uint32_t ctl_len;
  135 +} BD;
  136 +
  137 +typedef struct AC97BusMasterRegs {
  138 + uint32_t bdbar; /* rw 0 */
  139 + uint8_t civ; /* ro 0 */
  140 + uint8_t lvi; /* rw 0 */
  141 + uint16_t sr; /* rw 1 */
  142 + uint16_t picb; /* ro 0 */
  143 + uint8_t piv; /* ro 0 */
  144 + uint8_t cr; /* rw 0 */
  145 + unsigned int bd_valid;
  146 + BD bd;
  147 +} AC97BusMasterRegs;
  148 +
  149 +typedef struct AC97LinkState {
  150 + PCIDevice *pci_dev;
  151 + QEMUSoundCard card;
  152 + uint32_t glob_cnt;
  153 + uint32_t glob_sta;
  154 + uint32_t cas;
  155 + uint32_t last_samp;
  156 + AC97BusMasterRegs bm_regs[3];
  157 + uint8_t mixer_data[256];
  158 + SWVoiceIn *voice_pi;
  159 + SWVoiceOut *voice_po;
  160 + SWVoiceIn *voice_mc;
  161 + uint8_t silence[128];
  162 + uint32_t base[2];
  163 + int bup_flag;
  164 +} AC97LinkState;
  165 +
  166 +enum {
  167 + BUP_SET = 1,
  168 + BUP_LAST = 2
  169 +};
  170 +
  171 +#ifdef DEBUG_AC97
  172 +#define dolog(...) AUD_log ("ac97", __VA_ARGS__)
  173 +#else
  174 +#define dolog(...)
  175 +#endif
  176 +
  177 +typedef struct PCIAC97LinkState {
  178 + PCIDevice dev;
  179 + AC97LinkState ac97;
  180 +} PCIAC97LinkState;
  181 +
  182 +#define MKREGS(prefix, start) \
  183 +enum { \
  184 + prefix ## _BDBAR = start, \
  185 + prefix ## _CIV = start + 4, \
  186 + prefix ## _LVI = start + 5, \
  187 + prefix ## _SR = start + 6, \
  188 + prefix ## _PICB = start + 8, \
  189 + prefix ## _PIV = start + 10, \
  190 + prefix ## _CR = start + 11 \
  191 +}
  192 +
  193 +enum {
  194 + PI_INDEX = 0,
  195 + PO_INDEX,
  196 + MC_INDEX,
  197 + LAST_INDEX
  198 +};
  199 +
  200 +MKREGS (PI, PI_INDEX * 16);
  201 +MKREGS (PO, PO_INDEX * 16);
  202 +MKREGS (MC, MC_INDEX * 16);
  203 +
  204 +enum {
  205 + GLOB_CNT = 0x2c,
  206 + GLOB_STA = 0x30,
  207 + CAS = 0x34
  208 +};
  209 +
  210 +#define GET_BM(index) (((index) >> 4) & 3)
  211 +
  212 +static void po_callback (void *opaque, int free);
  213 +static void pi_callback (void *opaque, int avail);
  214 +static void mc_callback (void *opaque, int avail);
  215 +
  216 +static void warm_reset (AC97LinkState *s)
  217 +{
  218 + (void) s;
  219 +}
  220 +
  221 +static void cold_reset (AC97LinkState * s)
  222 +{
  223 + (void) s;
  224 +}
  225 +
  226 +static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r)
  227 +{
  228 + uint8_t b[8];
  229 +
  230 + cpu_physical_memory_read (r->bdbar + r->civ * 8, b, 8);
  231 + r->bd_valid = 1;
  232 + r->bd.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3;
  233 + r->bd.ctl_len = le32_to_cpu (*(uint32_t *) &b[4]);
  234 + r->picb = r->bd.ctl_len & 0xffff;
  235 + dolog ("bd %2d addr=%#x ctl=%#06x len=%#x(%d bytes)\n",
  236 + r->civ, r->bd.addr, r->bd.ctl_len >> 16,
  237 + r->bd.ctl_len & 0xffff,
  238 + (r->bd.ctl_len & 0xffff) << 1);
  239 +}
  240 +
  241 +static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
  242 +{
  243 + int event = 0;
  244 + int level = 0;
  245 + uint32_t new_mask = new_sr & SR_INT_MASK;
  246 + uint32_t old_mask = r->sr & SR_INT_MASK;
  247 + uint32_t masks[] = {GS_PIINT, GS_POINT, GS_MINT};
  248 +
  249 + if (new_mask ^ old_mask) {
  250 + /** @todo is IRQ deasserted when only one of status bits is cleared? */
  251 + if (!new_mask) {
  252 + event = 1;
  253 + level = 0;
  254 + }
  255 + else {
  256 + if ((new_mask & SR_LVBCI) && (r->cr & CR_LVBIE)) {
  257 + event = 1;
  258 + level = 1;
  259 + }
  260 + if ((new_mask & SR_BCIS) && (r->cr & CR_IOCE)) {
  261 + event = 1;
  262 + level = 1;
  263 + }
  264 + }
  265 + }
  266 +
  267 + r->sr = new_sr;
  268 +
  269 + dolog ("IOC%d LVB%d sr=%#x event=%d level=%d\n",
  270 + r->sr & SR_BCIS, r->sr & SR_LVBCI,
  271 + r->sr,
  272 + event, level);
  273 +
  274 + if (!event)
  275 + return;
  276 +
  277 + if (level) {
  278 + s->glob_sta |= masks[r - s->bm_regs];
  279 + dolog ("set irq level=1\n");
  280 + qemu_set_irq(s->pci_dev->irq[0], 1);
  281 + }
  282 + else {
  283 + s->glob_sta &= ~masks[r - s->bm_regs];
  284 + dolog ("set irq level=0\n");
  285 + qemu_set_irq(s->pci_dev->irq[0], 0);
  286 + }
  287 +}
  288 +
  289 +static void voice_set_active (AC97LinkState *s, int bm_index, int on)
  290 +{
  291 + switch (bm_index) {
  292 + case PI_INDEX:
  293 + AUD_set_active_in (s->voice_pi, on);
  294 + break;
  295 +
  296 + case PO_INDEX:
  297 + AUD_set_active_out (s->voice_po, on);
  298 + break;
  299 +
  300 + case MC_INDEX:
  301 + AUD_set_active_in (s->voice_mc, on);
  302 + break;
  303 +
  304 + default:
  305 + AUD_log ("ac97", "invalid bm_index(%d) in voice_set_active", bm_index);
  306 + break;
  307 + }
  308 +}
  309 +
  310 +static void reset_bm_regs (AC97LinkState *s, AC97BusMasterRegs *r)
  311 +{
  312 + dolog ("reset_bm_regs\n");
  313 + r->bdbar = 0;
  314 + r->civ = 0;
  315 + r->lvi = 0;
  316 + /** todo do we need to do that? */
  317 + update_sr (s, r, SR_DCH);
  318 + r->picb = 0;
  319 + r->piv = 0;
  320 + r->cr = r->cr & CR_DONT_CLEAR_MASK;
  321 + r->bd_valid = 0;
  322 +
  323 + voice_set_active (s, r - s->bm_regs, 0);
  324 + memset (s->silence, 0, sizeof (s->silence));
  325 +}
  326 +
  327 +static void mixer_store (AC97LinkState *s, uint32_t i, uint16_t v)
  328 +{
  329 + if (i + 2 > sizeof (s->mixer_data)) {
  330 + dolog ("mixer_store: index %d out of bounds %d\n",
  331 + i, sizeof (s->mixer_data));
  332 + return;
  333 + }
  334 +
  335 + s->mixer_data[i + 0] = v & 0xff;
  336 + s->mixer_data[i + 1] = v >> 8;
  337 +}
  338 +
  339 +static uint16_t mixer_load (AC97LinkState *s, uint32_t i)
  340 +{
  341 + uint16_t val = 0xffff;
  342 +
  343 + if (i + 2 > sizeof (s->mixer_data)) {
  344 + dolog ("mixer_store: index %d out of bounds %d\n",
  345 + i, sizeof (s->mixer_data));
  346 + }
  347 + else {
  348 + val = s->mixer_data[i + 0] | (s->mixer_data[i + 1] << 8);
  349 + }
  350 +
  351 + return val;
  352 +}
  353 +
  354 +static void open_voice (AC97LinkState *s, int index, int freq)
  355 +{
  356 + audsettings_t as;
  357 +
  358 + as.freq = freq;
  359 + as.nchannels = 2;
  360 + as.fmt = AUD_FMT_S16;
  361 + as.endianness = 0;
  362 +
  363 + switch (index) {
  364 + case PI_INDEX:
  365 + s->voice_pi = AUD_open_in (
  366 + &s->card,
  367 + s->voice_pi,
  368 + "ac97.pi",
  369 + s,
  370 + pi_callback,
  371 + &as
  372 + );
  373 + break;
  374 +
  375 + case PO_INDEX:
  376 + s->voice_po = AUD_open_out (
  377 + &s->card,
  378 + s->voice_po,
  379 + "ac97.po",
  380 + s,
  381 + po_callback,
  382 + &as
  383 + );
  384 + break;
  385 +
  386 + case MC_INDEX:
  387 + s->voice_mc = AUD_open_in (
  388 + &s->card,
  389 + s->voice_mc,
  390 + "ac97.mc",
  391 + s,
  392 + mc_callback,
  393 + &as
  394 + );
  395 + break;
  396 + }
  397 +}
  398 +
  399 +static void reset_voices (AC97LinkState *s, uint8_t active[LAST_INDEX])
  400 +{
  401 + uint16_t freq;
  402 +
  403 + freq = mixer_load (s, AC97_PCM_LR_ADC_Rate);
  404 + open_voice (s, PI_INDEX, freq);
  405 + AUD_set_active_in (s->voice_pi, active[PI_INDEX]);
  406 +
  407 + freq = mixer_load (s, AC97_PCM_Front_DAC_Rate);
  408 + open_voice (s, PO_INDEX, freq);
  409 + AUD_set_active_out (s->voice_po, active[PO_INDEX]);
  410 +
  411 + freq = mixer_load (s, AC97_MIC_ADC_Rate);
  412 + open_voice (s, MC_INDEX, freq);
  413 + AUD_set_active_in (s->voice_mc, active[MC_INDEX]);
  414 +}
  415 +
  416 +#ifdef USE_MIXER
  417 +static void set_volume (AC97LinkState *s, int index,
  418 + audmixerctl_t mt, uint32_t val)
  419 +{
  420 + int mute = (val >> MUTE_SHIFT) & 1;
  421 + uint8_t rvol = VOL_MASK - (val & VOL_MASK);
  422 + uint8_t lvol = VOL_MASK - ((val >> 8) & VOL_MASK);
  423 + rvol = 255 * rvol / VOL_MASK;
  424 + lvol = 255 * lvol / VOL_MASK;
  425 +
  426 +#ifdef SOFT_VOLUME
  427 + if (index == AC97_Master_Volume_Mute) {
  428 + AUD_set_volume_out (s->voice_po, mute, lvol, rvol);
  429 + }
  430 + else {
  431 + AUD_set_volume (mt, &mute, &lvol, &rvol);
  432 + }
  433 +#else
  434 + AUD_set_volume (mt, &mute, &lvol, &rvol);
  435 +#endif
  436 +
  437 + rvol = VOL_MASK - ((VOL_MASK * rvol) / 255);
  438 + lvol = VOL_MASK - ((VOL_MASK * lvol) / 255);
  439 + mixer_store (s, index, val);
  440 +}
  441 +
  442 +static audrecsource_t ac97_to_aud_record_source (uint8_t i)
  443 +{
  444 + switch (i) {
  445 + case REC_MIC:
  446 + return AUD_REC_MIC;
  447 +
  448 + case REC_CD:
  449 + return AUD_REC_CD;
  450 +
  451 + case REC_VIDEO:
  452 + return AUD_REC_VIDEO;
  453 +
  454 + case REC_AUX:
  455 + return AUD_REC_AUX;
  456 +
  457 + case REC_LINE_IN:
  458 + return AUD_REC_LINE_IN;
  459 +
  460 + case REC_PHONE:
  461 + return AUD_REC_PHONE;
  462 +
  463 + default:
  464 + dolog ("Unknown record source %d, using MIC\n", i);
  465 + return AUD_REC_MIC;
  466 + }
  467 +}
  468 +
  469 +static uint8_t aud_to_ac97_record_source (audrecsource_t rs)
  470 +{
  471 + switch (rs) {
  472 + case AUD_REC_MIC:
  473 + return REC_MIC;
  474 +
  475 + case AUD_REC_CD:
  476 + return REC_CD;
  477 +
  478 + case AUD_REC_VIDEO:
  479 + return REC_VIDEO;
  480 +
  481 + case AUD_REC_AUX:
  482 + return REC_AUX;
  483 +
  484 + case AUD_REC_LINE_IN:
  485 + return REC_LINE_IN;
  486 +
  487 + case AUD_REC_PHONE:
  488 + return REC_PHONE;
  489 +
  490 + default:
  491 + dolog ("Unknown audio recording source %d using MIC\n", rs);
  492 + return REC_MIC;
  493 + }
  494 +}
  495 +
  496 +static void record_select (AC97LinkState *s, uint32_t val)
  497 +{
  498 + uint8_t rs = val & REC_MASK;
  499 + uint8_t ls = (val >> 8) & REC_MASK;
  500 + audrecsource_t ars = ac97_to_aud_record_source (rs);
  501 + audrecsource_t als = ac97_to_aud_record_source (ls);
  502 + AUD_set_record_source (&als, &ars);
  503 + rs = aud_to_ac97_record_source (ars);
  504 + ls = aud_to_ac97_record_source (als);
  505 + mixer_store (s, AC97_Record_Select, rs | (ls << 8));
  506 +}
  507 +#endif
  508 +
  509 +static void mixer_reset (AC97LinkState *s)
  510 +{
  511 + uint8_t active[LAST_INDEX];
  512 +
  513 + dolog ("mixer_reset\n");
  514 + memset (s->mixer_data, 0, sizeof (s->mixer_data));
  515 + memset (active, 0, sizeof (active));
  516 + mixer_store (s, AC97_Reset , 0x0000); /* 6940 */
  517 + mixer_store (s, AC97_Master_Volume_Mono_Mute , 0x8000);
  518 + mixer_store (s, AC97_PC_BEEP_Volume_Mute , 0x0000);
  519 +
  520 + mixer_store (s, AC97_Phone_Volume_Mute , 0x8008);
  521 + mixer_store (s, AC97_Mic_Volume_Mute , 0x8008);
  522 + mixer_store (s, AC97_CD_Volume_Mute , 0x8808);
  523 + mixer_store (s, AC97_Aux_Volume_Mute , 0x8808);
  524 + mixer_store (s, AC97_Record_Gain_Mic_Mute , 0x8000);
  525 + mixer_store (s, AC97_General_Purpose , 0x0000);
  526 + mixer_store (s, AC97_3D_Control , 0x0000);
  527 + mixer_store (s, AC97_Powerdown_Ctrl_Stat , 0x000f);
  528 +
  529 + /*
  530 + * Sigmatel 9700 (STAC9700)
  531 + */
  532 + mixer_store (s, AC97_Vendor_ID1 , 0x8384);
  533 + mixer_store (s, AC97_Vendor_ID2 , 0x7600); /* 7608 */
  534 +
  535 + mixer_store (s, AC97_Extended_Audio_ID , 0x0809);
  536 + mixer_store (s, AC97_Extended_Audio_Ctrl_Stat, 0x0009);
  537 + mixer_store (s, AC97_PCM_Front_DAC_Rate , 0xbb80);
  538 + mixer_store (s, AC97_PCM_Surround_DAC_Rate , 0xbb80);
  539 + mixer_store (s, AC97_PCM_LFE_DAC_Rate , 0xbb80);
  540 + mixer_store (s, AC97_PCM_LR_ADC_Rate , 0xbb80);
  541 + mixer_store (s, AC97_MIC_ADC_Rate , 0xbb80);
  542 +
  543 +#ifdef USE_MIXER
  544 + record_select (s, 0);
  545 + set_volume (s, AC97_Master_Volume_Mute, AUD_MIXER_VOLUME , 0x8000);
  546 + set_volume (s, AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM , 0x8808);
  547 + set_volume (s, AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN, 0x8808);
  548 +#endif
  549 + reset_voices (s, active);
  550 +}
  551 +
  552 +/**
  553 + * Native audio mixer
  554 + * I/O Reads
  555 + */
  556 +static uint32_t nam_readb (void *opaque, uint32_t addr)
  557 +{
  558 + PCIAC97LinkState *d = opaque;
  559 + AC97LinkState *s = &d->ac97;
  560 + dolog ("U nam readb %#x\n", addr);
  561 + s->cas = 0;
  562 + return ~0U;
  563 +}
  564 +
  565 +static uint32_t nam_readw (void *opaque, uint32_t addr)
  566 +{
  567 + PCIAC97LinkState *d = opaque;
  568 + AC97LinkState *s = &d->ac97;
  569 + uint32_t val = ~0U;
  570 + uint32_t index = addr - s->base[0];
  571 + s->cas = 0;
  572 + val = mixer_load (s, index);
  573 + return val;
  574 +}
  575 +
  576 +static uint32_t nam_readl (void *opaque, uint32_t addr)
  577 +{
  578 + PCIAC97LinkState *d = opaque;
  579 + AC97LinkState *s = &d->ac97;
  580 + dolog ("U nam readl %#x\n", addr);
  581 + s->cas = 0;
  582 + return ~0U;
  583 +}
  584 +
  585 +/**
  586 + * Native audio mixer
  587 + * I/O Writes
  588 + */
  589 +static void nam_writeb (void *opaque, uint32_t addr, uint32_t val)
  590 +{
  591 + PCIAC97LinkState *d = opaque;
  592 + AC97LinkState *s = &d->ac97;
  593 + dolog ("U nam writeb %#x <- %#x\n", addr, val);
  594 + s->cas = 0;
  595 +}
  596 +
  597 +static void nam_writew (void *opaque, uint32_t addr, uint32_t val)
  598 +{
  599 + PCIAC97LinkState *d = opaque;
  600 + AC97LinkState *s = &d->ac97;
  601 + uint32_t index = addr - s->base[0];
  602 + s->cas = 0;
  603 + switch (index) {
  604 + case AC97_Reset:
  605 + mixer_reset (s);
  606 + break;
  607 + case AC97_Powerdown_Ctrl_Stat:
  608 + val &= ~0xf;
  609 + val |= mixer_load (s, index) & 0xf;
  610 + mixer_store (s, index, val);
  611 + break;
  612 +#ifdef USE_MIXER
  613 + case AC97_Master_Volume_Mute:
  614 + set_volume (s, index, AUD_MIXER_VOLUME, val);
  615 + break;
  616 + case AC97_PCM_Out_Volume_Mute:
  617 + set_volume (s, index, AUD_MIXER_PCM, val);
  618 + break;
  619 + case AC97_Line_In_Volume_Mute:
  620 + set_volume (s, index, AUD_MIXER_LINE_IN, val);
  621 + break;
  622 + case AC97_Record_Select:
  623 + record_select (s, val);
  624 + break;
  625 +#endif
  626 + case AC97_Vendor_ID1:
  627 + case AC97_Vendor_ID2:
  628 + dolog ("Attempt to write vendor ID to %#x\n", val);
  629 + break;
  630 + case AC97_Extended_Audio_ID:
  631 + dolog ("Attempt to write extended audio ID to %#x\n", val);
  632 + break;
  633 + case AC97_Extended_Audio_Ctrl_Stat:
  634 + if (!(val & EACS_VRA)) {
  635 + mixer_store (s, AC97_PCM_Front_DAC_Rate, 0xbb80);
  636 + mixer_store (s, AC97_PCM_LR_ADC_Rate, 0xbb80);
  637 + open_voice (s, PI_INDEX, 48000);
  638 + open_voice (s, PO_INDEX, 48000);
  639 + }
  640 + if (!(val & EACS_VRM)) {
  641 + mixer_store (s, AC97_MIC_ADC_Rate, 0xbb80);
  642 + open_voice (s, MC_INDEX, 48000);
  643 + }
  644 + dolog ("Setting extended audio control to %#x\n", val);
  645 + mixer_store (s, AC97_Extended_Audio_Ctrl_Stat, val);
  646 + break;
  647 + case AC97_PCM_Front_DAC_Rate:
  648 + if (mixer_load (s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
  649 + mixer_store (s, index, val);
  650 + dolog ("Set front DAC rate to %d\n", val);
  651 + open_voice (s, PO_INDEX, val);
  652 + }
  653 + else {
  654 + dolog ("Attempt to set front DAC rate to %d, "
  655 + "but VRA is not set\n",
  656 + val);
  657 + }
  658 + break;
  659 + case AC97_MIC_ADC_Rate:
  660 + if (mixer_load (s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRM) {
  661 + mixer_store (s, index, val);
  662 + dolog ("Set MIC ADC rate to %d\n", val);
  663 + open_voice (s, MC_INDEX, val);
  664 + }
  665 + else {
  666 + dolog ("Attempt to set MIC ADC rate to %d, "
  667 + "but VRM is not set\n",
  668 + val);
  669 + }
  670 + break;
  671 + case AC97_PCM_LR_ADC_Rate:
  672 + if (mixer_load (s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
  673 + mixer_store (s, index, val);
  674 + dolog ("Set front LR ADC rate to %d\n", val);
  675 + open_voice (s, PI_INDEX, val);
  676 + }
  677 + else {
  678 + dolog ("Attempt to set LR ADC rate to %d, but VRA is not set\n",
  679 + val);
  680 + }
  681 + break;
  682 + default:
  683 + dolog ("U nam writew %#x <- %#x\n", addr, val);
  684 + mixer_store (s, index, val);
  685 + break;
  686 + }
  687 +}
  688 +
  689 +static void nam_writel (void *opaque, uint32_t addr, uint32_t val)
  690 +{
  691 + PCIAC97LinkState *d = opaque;
  692 + AC97LinkState *s = &d->ac97;
  693 + dolog ("U nam writel %#x <- %#x\n", addr, val);
  694 + s->cas = 0;
  695 +}
  696 +
  697 +/**
  698 + * Native audio bus master
  699 + * I/O Reads
  700 + */
  701 +static uint32_t nabm_readb (void *opaque, uint32_t addr)
  702 +{
  703 + PCIAC97LinkState *d = opaque;
  704 + AC97LinkState *s = &d->ac97;
  705 + AC97BusMasterRegs *r = NULL;
  706 + uint32_t index = addr - s->base[1];
  707 + uint32_t val = ~0U;
  708 +
  709 + switch (index) {
  710 + case CAS:
  711 + dolog ("CAS %d\n", s->cas);
  712 + val = s->cas;
  713 + s->cas = 1;
  714 + break;
  715 + case PI_CIV:
  716 + case PO_CIV:
  717 + case MC_CIV:
  718 + r = &s->bm_regs[GET_BM (index)];
  719 + val = r->civ;
  720 + dolog ("CIV[%d] -> %#x\n", GET_BM (index), val);
  721 + break;
  722 + case PI_LVI:
  723 + case PO_LVI:
  724 + case MC_LVI:
  725 + r = &s->bm_regs[GET_BM (index)];
  726 + val = r->lvi;
  727 + dolog ("LVI[%d] -> %#x\n", GET_BM (index), val);
  728 + break;
  729 + case PI_PIV:
  730 + case PO_PIV:
  731 + case MC_PIV:
  732 + r = &s->bm_regs[GET_BM (index)];
  733 + val = r->piv;
  734 + dolog ("PIV[%d] -> %#x\n", GET_BM (index), val);
  735 + break;
  736 + case PI_CR:
  737 + case PO_CR:
  738 + case MC_CR:
  739 + r = &s->bm_regs[GET_BM (index)];
  740 + val = r->cr;
  741 + dolog ("CR[%d] -> %#x\n", GET_BM (index), val);
  742 + break;
  743 + case PI_SR:
  744 + case PO_SR:
  745 + case MC_SR:
  746 + r = &s->bm_regs[GET_BM (index)];
  747 + val = r->sr & 0xff;
  748 + dolog ("SRb[%d] -> %#x\n", GET_BM (index), val);
  749 + break;
  750 + default:
  751 + dolog ("U nabm readb %#x -> %#x\n", addr, val);
  752 + break;
  753 + }
  754 + return val;
  755 +}
  756 +
  757 +static uint32_t nabm_readw (void *opaque, uint32_t addr)
  758 +{
  759 + PCIAC97LinkState *d = opaque;
  760 + AC97LinkState *s = &d->ac97;
  761 + AC97BusMasterRegs *r = NULL;
  762 + uint32_t index = addr - s->base[1];
  763 + uint32_t val = ~0U;
  764 +
  765 + switch (index) {
  766 + case PI_SR:
  767 + case PO_SR:
  768 + case MC_SR:
  769 + r = &s->bm_regs[GET_BM (index)];
  770 + val = r->sr;
  771 + dolog ("SR[%d] -> %#x\n", GET_BM (index), val);
  772 + break;
  773 + case PI_PICB:
  774 + case PO_PICB:
  775 + case MC_PICB:
  776 + r = &s->bm_regs[GET_BM (index)];
  777 + val = r->picb;
  778 + dolog ("PICB[%d] -> %#x\n", GET_BM (index), val);
  779 + break;
  780 + default:
  781 + dolog ("U nabm readw %#x -> %#x\n", addr, val);
  782 + break;
  783 + }
  784 + return val;
  785 +}
  786 +
  787 +static uint32_t nabm_readl (void *opaque, uint32_t addr)
  788 +{
  789 + PCIAC97LinkState *d = opaque;
  790 + AC97LinkState *s = &d->ac97;
  791 + AC97BusMasterRegs *r = NULL;
  792 + uint32_t index = addr - s->base[1];
  793 + uint32_t val = ~0U;
  794 +
  795 + switch (index) {
  796 + case PI_BDBAR:
  797 + case PO_BDBAR:
  798 + case MC_BDBAR:
  799 + r = &s->bm_regs[GET_BM (index)];
  800 + val = r->bdbar;
  801 + dolog ("BMADDR[%d] -> %#x\n", GET_BM (index), val);
  802 + break;
  803 + case PI_CIV:
  804 + case PO_CIV:
  805 + case MC_CIV:
  806 + r = &s->bm_regs[GET_BM (index)];
  807 + val = r->civ | (r->lvi << 8) | (r->sr << 16);
  808 + dolog ("CIV LVI SR[%d] -> %#x, %#x, %#x\n", GET_BM (index),
  809 + r->civ, r->lvi, r->sr);
  810 + break;
  811 + case PI_PICB:
  812 + case PO_PICB:
  813 + case MC_PICB:
  814 + r = &s->bm_regs[GET_BM (index)];
  815 + val = r->picb | (r->piv << 16) | (r->cr << 24);
  816 + dolog ("PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM (index),
  817 + val, r->picb, r->piv, r->cr);
  818 + break;
  819 + case GLOB_CNT:
  820 + val = s->glob_cnt;
  821 + dolog ("glob_cnt -> %#x\n", val);
  822 + break;
  823 + case GLOB_STA:
  824 + val = s->glob_sta | GS_S0CR;
  825 + dolog ("glob_sta -> %#x\n", val);
  826 + break;
  827 + default:
  828 + dolog ("U nabm readl %#x -> %#x\n", addr, val);
  829 + break;
  830 + }
  831 + return val;
  832 +}
  833 +
  834 +/**
  835 + * Native audio bus master
  836 + * I/O Writes
  837 + */
  838 +static void nabm_writeb (void *opaque, uint32_t addr, uint32_t val)
  839 +{
  840 + PCIAC97LinkState *d = opaque;
  841 + AC97LinkState *s = &d->ac97;
  842 + AC97BusMasterRegs *r = NULL;
  843 + uint32_t index = addr - s->base[1];
  844 + switch (index) {
  845 + case PI_LVI:
  846 + case PO_LVI:
  847 + case MC_LVI:
  848 + r = &s->bm_regs[GET_BM (index)];
  849 + if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) {
  850 + r->sr &= ~(SR_DCH | SR_CELV);
  851 + r->civ = r->piv;
  852 + r->piv = (r->piv + 1) % 32;
  853 + fetch_bd (s, r);
  854 + }
  855 + r->lvi = val % 32;
  856 + dolog ("LVI[%d] <- %#x\n", GET_BM (index), val);
  857 + break;
  858 + case PI_CR:
  859 + case PO_CR:
  860 + case MC_CR:
  861 + r = &s->bm_regs[GET_BM (index)];
  862 + if (val & CR_RR) {
  863 + reset_bm_regs (s, r);
  864 + }
  865 + else {
  866 + r->cr = val & CR_VALID_MASK;
  867 + if (!(r->cr & CR_RPBM)) {
  868 + voice_set_active (s, r - s->bm_regs, 0);
  869 + r->sr |= SR_DCH;
  870 + }
  871 + else {
  872 + r->civ = r->piv;
  873 + r->piv = (r->piv + 1) % 32;
  874 + fetch_bd (s, r);
  875 + r->sr &= ~SR_DCH;
  876 + voice_set_active (s, r - s->bm_regs, 1);
  877 + }
  878 + }
  879 + dolog ("CR[%d] <- %#x (cr %#x)\n", GET_BM (index), val, r->cr);
  880 + break;
  881 + case PI_SR:
  882 + case PO_SR:
  883 + case MC_SR:
  884 + r = &s->bm_regs[GET_BM (index)];
  885 + r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
  886 + update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK));
  887 + dolog ("SR[%d] <- %#x (sr %#x)\n", GET_BM (index), val, r->sr);
  888 + break;
  889 + default:
  890 + dolog ("U nabm writeb %#x <- %#x\n", addr, val);
  891 + break;
  892 + }
  893 +}
  894 +
  895 +static void nabm_writew (void *opaque, uint32_t addr, uint32_t val)
  896 +{
  897 + PCIAC97LinkState *d = opaque;
  898 + AC97LinkState *s = &d->ac97;
  899 + AC97BusMasterRegs *r = NULL;
  900 + uint32_t index = addr - s->base[1];
  901 + switch (index) {
  902 + case PI_SR:
  903 + case PO_SR:
  904 + case MC_SR:
  905 + r = &s->bm_regs[GET_BM (index)];
  906 + r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
  907 + update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK));
  908 + dolog ("SR[%d] <- %#x (sr %#x)\n", GET_BM (index), val, r->sr);
  909 + break;
  910 + default:
  911 + dolog ("U nabm writew %#x <- %#x\n", addr, val);
  912 + break;
  913 + }
  914 +}
  915 +
  916 +static void nabm_writel (void *opaque, uint32_t addr, uint32_t val)
  917 +{
  918 + PCIAC97LinkState *d = opaque;
  919 + AC97LinkState *s = &d->ac97;
  920 + AC97BusMasterRegs *r = NULL;
  921 + uint32_t index = addr - s->base[1];
  922 + switch (index) {
  923 + case PI_BDBAR:
  924 + case PO_BDBAR:
  925 + case MC_BDBAR:
  926 + r = &s->bm_regs[GET_BM (index)];
  927 + r->bdbar = val & ~3;
  928 + dolog ("BDBAR[%d] <- %#x (bdbar %#x)\n",
  929 + GET_BM (index), val, r->bdbar);
  930 + break;
  931 + case GLOB_CNT:
  932 + if (val & GC_WR)
  933 + warm_reset (s);
  934 + if (val & GC_CR)
  935 + cold_reset (s);
  936 + if (!(val & (GC_WR | GC_CR)))
  937 + s->glob_cnt = val & GC_VALID_MASK;
  938 + dolog ("glob_cnt <- %#x (glob_cnt %#x)\n", val, s->glob_cnt);
  939 + break;
  940 + case GLOB_STA:
  941 + s->glob_sta &= ~(val & GS_WCLEAR_MASK);
  942 + s->glob_sta |= (val & ~(GS_WCLEAR_MASK | GS_RO_MASK)) & GS_VALID_MASK;
  943 + dolog ("glob_sta <- %#x (glob_sta %#x)\n", val, s->glob_sta);
  944 + break;
  945 + default:
  946 + dolog ("U nabm writel %#x <- %#x\n", addr, val);
  947 + break;
  948 + }
  949 +}
  950 +
  951 +static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
  952 + int max, int *stop)
  953 +{
  954 + uint8_t tmpbuf[4096];
  955 + uint32_t addr = r->bd.addr;
  956 + uint32_t temp = r->picb << 1;
  957 + uint32_t written = 0;
  958 + int to_copy = 0;
  959 + temp = audio_MIN (temp, max);
  960 +
  961 + if (!temp) {
  962 + *stop = 1;
  963 + return 0;
  964 + }
  965 +
  966 + while (temp) {
  967 + int copied;
  968 + to_copy = audio_MIN (temp, sizeof (tmpbuf));
  969 + cpu_physical_memory_read (addr, tmpbuf, to_copy);
  970 + copied = AUD_write (s->voice_po, tmpbuf, to_copy);
  971 + dolog ("write_audio max=%x to_copy=%x copied=%x\n",
  972 + max, to_copy, copied);
  973 + if (!copied) {
  974 + *stop = 1;
  975 + break;
  976 + }
  977 + temp -= copied;
  978 + addr += copied;
  979 + written += copied;
  980 + }
  981 +
  982 + if (!temp) {
  983 + if (to_copy < 4) {
  984 + dolog ("whoops\n");
  985 + s->last_samp = 0;
  986 + }
  987 + else {
  988 + s->last_samp = *(uint32_t *) &tmpbuf[to_copy - 4];
  989 + }
  990 + }
  991 +
  992 + r->bd.addr = addr;
  993 + return written;
  994 +}
  995 +
  996 +static void write_bup (AC97LinkState *s, int elapsed)
  997 +{
  998 + int written = 0;
  999 +
  1000 + dolog ("write_bup\n");
  1001 + if (!(s->bup_flag & BUP_SET)) {
  1002 + if (s->bup_flag & BUP_LAST) {
  1003 + int i;
  1004 + uint8_t *p = s->silence;
  1005 + for (i = 0; i < sizeof (s->silence) / 4; i++, p += 4) {
  1006 + *(uint32_t *) p = s->last_samp;
  1007 + }
  1008 + }
  1009 + else {
  1010 + memset (s->silence, 0, sizeof (s->silence));
  1011 + }
  1012 + s->bup_flag |= BUP_SET;
  1013 + }
  1014 +
  1015 + while (elapsed) {
  1016 + int temp = audio_MIN (elapsed, sizeof (s->silence));
  1017 + while (temp) {
  1018 + int copied = AUD_write (s->voice_po, s->silence, temp);
  1019 + if (!copied)
  1020 + return;
  1021 + temp -= copied;
  1022 + elapsed -= copied;
  1023 + written += copied;
  1024 + }
  1025 + }
  1026 +}
  1027 +
  1028 +static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
  1029 + int max, int *stop)
  1030 +{
  1031 + uint8_t tmpbuf[4096];
  1032 + uint32_t addr = r->bd.addr;
  1033 + uint32_t temp = r->picb << 1;
  1034 + uint32_t nread = 0;
  1035 + int to_copy = 0;
  1036 + SWVoiceIn *voice = (r - s->bm_regs) == MC_INDEX ? s->voice_mc : s->voice_pi;
  1037 +
  1038 + temp = audio_MIN (temp, max);
  1039 +
  1040 + if (!temp) {
  1041 + *stop = 1;
  1042 + return 0;
  1043 + }
  1044 +
  1045 + while (temp) {
  1046 + int acquired;
  1047 + to_copy = audio_MIN (temp, sizeof (tmpbuf));
  1048 + acquired = AUD_read (voice, tmpbuf, to_copy);
  1049 + if (!acquired) {
  1050 + *stop = 1;
  1051 + break;
  1052 + }
  1053 + cpu_physical_memory_write (addr, tmpbuf, acquired);
  1054 + temp -= acquired;
  1055 + addr += acquired;
  1056 + nread += acquired;
  1057 + }
  1058 +
  1059 + r->bd.addr = addr;
  1060 + return nread;
  1061 +}
  1062 +
  1063 +static void transfer_audio (AC97LinkState *s, int index, int elapsed)
  1064 +{
  1065 + AC97BusMasterRegs *r = &s->bm_regs[index];
  1066 + int written = 0, stop = 0;
  1067 +
  1068 + if (r->sr & SR_DCH) {
  1069 + if (r->cr & CR_RPBM) {
  1070 + switch (index) {
  1071 + case PO_INDEX:
  1072 + write_bup (s, elapsed);
  1073 + break;
  1074 + }
  1075 + }
  1076 + return;
  1077 + }
  1078 +
  1079 + while ((elapsed >> 1) && !stop) {
  1080 + int temp;
  1081 +
  1082 + if (!r->bd_valid) {
  1083 + dolog ("invalid bd\n");
  1084 + fetch_bd (s, r);
  1085 + }
  1086 +
  1087 + if (!r->picb) {
  1088 + dolog ("fresh bd %d is empty %#x %#x\n",
  1089 + r->civ, r->bd.addr, r->bd.ctl_len);
  1090 + if (r->civ == r->lvi) {
  1091 + r->sr |= SR_DCH; /* CELV? */
  1092 + s->bup_flag = 0;
  1093 + break;
  1094 + }
  1095 + r->sr &= ~SR_CELV;
  1096 + r->civ = r->piv;
  1097 + r->piv = (r->piv + 1) % 32;
  1098 + fetch_bd (s, r);
  1099 + return;
  1100 + }
  1101 +
  1102 + switch (index) {
  1103 + case PO_INDEX:
  1104 + temp = write_audio (s, r, elapsed, &stop);
  1105 + written += temp;
  1106 + elapsed -= temp;
  1107 + r->picb -= (temp >> 1);
  1108 + break;
  1109 +
  1110 + case PI_INDEX:
  1111 + case MC_INDEX:
  1112 + temp = read_audio (s, r, elapsed, &stop);
  1113 + elapsed -= temp;
  1114 + r->picb -= (temp >> 1);
  1115 + break;
  1116 + }
  1117 +
  1118 + if (!r->picb) {
  1119 + uint32_t new_sr = r->sr & ~SR_CELV;
  1120 +
  1121 + if (r->bd.ctl_len & BD_IOC) {
  1122 + new_sr |= SR_BCIS;
  1123 + }
  1124 +
  1125 + if (r->civ == r->lvi) {
  1126 + dolog ("Underrun civ (%d) == lvi (%d)\n", r->civ, r->lvi);
  1127 +
  1128 + new_sr |= SR_LVBCI | SR_DCH | SR_CELV;
  1129 + stop = 1;
  1130 + s->bup_flag = (r->bd.ctl_len & BD_BUP) ? BUP_LAST : 0;
  1131 + }
  1132 + else {
  1133 + r->civ = r->piv;
  1134 + r->piv = (r->piv + 1) % 32;
  1135 + fetch_bd (s, r);
  1136 + }
  1137 +
  1138 + update_sr (s, r, new_sr);
  1139 + }
  1140 + }
  1141 +}
  1142 +
  1143 +static void pi_callback (void *opaque, int avail)
  1144 +{
  1145 + transfer_audio (opaque, PI_INDEX, avail);
  1146 +}
  1147 +
  1148 +static void mc_callback (void *opaque, int avail)
  1149 +{
  1150 + transfer_audio (opaque, MC_INDEX, avail);
  1151 +}
  1152 +
  1153 +static void po_callback (void *opaque, int free)
  1154 +{
  1155 + transfer_audio (opaque, PO_INDEX, free);
  1156 +}
  1157 +
  1158 +static void ac97_save (QEMUFile *f, void *opaque)
  1159 +{
  1160 + size_t i;
  1161 + uint8_t active[LAST_INDEX];
  1162 + AC97LinkState *s = opaque;
  1163 +
  1164 + qemu_put_be32s (f, &s->glob_cnt);
  1165 + qemu_put_be32s (f, &s->glob_sta);
  1166 + qemu_put_be32s (f, &s->cas);
  1167 +
  1168 + for (i = 0; i < sizeof (s->bm_regs) / sizeof (s->bm_regs[0]); ++i) {
  1169 + AC97BusMasterRegs *r = &s->bm_regs[i];
  1170 + qemu_put_be32s (f, &r->bdbar);
  1171 + qemu_put_8s (f, &r->civ);
  1172 + qemu_put_8s (f, &r->lvi);
  1173 + qemu_put_be16s (f, &r->sr);
  1174 + qemu_put_be16s (f, &r->picb);
  1175 + qemu_put_8s (f, &r->piv);
  1176 + qemu_put_8s (f, &r->cr);
  1177 + qemu_put_be32s (f, &r->bd_valid);
  1178 + qemu_put_be32s (f, &r->bd.addr);
  1179 + qemu_put_be32s (f, &r->bd.ctl_len);
  1180 + }
  1181 + qemu_put_buffer (f, s->mixer_data, sizeof (s->mixer_data));
  1182 +
  1183 + active[PI_INDEX] = AUD_is_active_in (s->voice_pi) ? 1 : 0;
  1184 + active[PO_INDEX] = AUD_is_active_out (s->voice_po) ? 1 : 0;
  1185 + active[MC_INDEX] = AUD_is_active_in (s->voice_mc) ? 1 : 0;
  1186 + qemu_put_buffer (f, active, sizeof (active));
  1187 +}
  1188 +
  1189 +static int ac97_load (QEMUFile *f, void *opaque, int version_id)
  1190 +{
  1191 + size_t i;
  1192 + uint8_t active[LAST_INDEX];
  1193 + AC97LinkState *s = opaque;
  1194 +
  1195 + if (version_id != 1)
  1196 + return -EINVAL;
  1197 +
  1198 + qemu_get_be32s (f, &s->glob_cnt);
  1199 + qemu_get_be32s (f, &s->glob_sta);
  1200 + qemu_get_be32s (f, &s->cas);
  1201 +
  1202 + for (i = 0; i < sizeof (s->bm_regs) / sizeof (s->bm_regs[0]); ++i) {
  1203 + AC97BusMasterRegs *r = &s->bm_regs[i];
  1204 + qemu_get_be32s (f, &r->bdbar);
  1205 + qemu_get_8s (f, &r->civ);
  1206 + qemu_get_8s (f, &r->lvi);
  1207 + qemu_get_be16s (f, &r->sr);
  1208 + qemu_get_be16s (f, &r->picb);
  1209 + qemu_get_8s (f, &r->piv);
  1210 + qemu_get_8s (f, &r->cr);
  1211 + qemu_get_be32s (f, &r->bd_valid);
  1212 + qemu_get_be32s (f, &r->bd.addr);
  1213 + qemu_get_be32s (f, &r->bd.ctl_len);
  1214 + }
  1215 + qemu_get_buffer (f, s->mixer_data, sizeof (s->mixer_data));
  1216 + qemu_get_buffer (f, active, sizeof (active));
  1217 +
  1218 +#ifdef USE_MIXER
  1219 + record_select (s, mixer_load (s, AC97_Record_Select));
  1220 +#define V_(a, b) set_volume (s, a, b, mixer_load (s, a))
  1221 + V_ (AC97_Master_Volume_Mute, AUD_MIXER_VOLUME);
  1222 + V_ (AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM);
  1223 + V_ (AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN);
  1224 +#undef V_
  1225 +#endif
  1226 + reset_voices (s, active);
  1227 +
  1228 + s->bup_flag = 0;
  1229 + s->last_samp = 0;
  1230 + return 0;
  1231 +}
  1232 +
  1233 +static void ac97_map (PCIDevice *pci_dev, int region_num,
  1234 + uint32_t addr, uint32_t size, int type)
  1235 +{
  1236 + PCIAC97LinkState *d = (PCIAC97LinkState *) pci_dev;
  1237 + AC97LinkState *s = &d->ac97;
  1238 +
  1239 + if (!region_num) {
  1240 + s->base[0] = addr;
  1241 + register_ioport_read (addr, 256 * 1, 1, nam_readb, d);
  1242 + register_ioport_read (addr, 256 * 2, 2, nam_readw, d);
  1243 + register_ioport_read (addr, 256 * 4, 4, nam_readl, d);
  1244 + register_ioport_write (addr, 256 * 1, 1, nam_writeb, d);
  1245 + register_ioport_write (addr, 256 * 2, 2, nam_writew, d);
  1246 + register_ioport_write (addr, 256 * 4, 4, nam_writel, d);
  1247 + }
  1248 + else {
  1249 + s->base[1] = addr;
  1250 + register_ioport_read (addr, 64 * 1, 1, nabm_readb, d);
  1251 + register_ioport_read (addr, 64 * 2, 2, nabm_readw, d);
  1252 + register_ioport_read (addr, 64 * 4, 4, nabm_readl, d);
  1253 + register_ioport_write (addr, 64 * 1, 1, nabm_writeb, d);
  1254 + register_ioport_write (addr, 64 * 2, 2, nabm_writew, d);
  1255 + register_ioport_write (addr, 64 * 4, 4, nabm_writel, d);
  1256 + }
  1257 +}
  1258 +
  1259 +static void ac97_on_reset (void *opaque)
  1260 +{
  1261 + AC97LinkState *s = opaque;
  1262 +
  1263 + reset_bm_regs (s, &s->bm_regs[0]);
  1264 + reset_bm_regs (s, &s->bm_regs[1]);
  1265 + reset_bm_regs (s, &s->bm_regs[2]);
  1266 +
  1267 + /*
  1268 + * Reset the mixer too. The Windows XP driver seems to rely on
  1269 + * this. At least it wants to read the vendor id before it resets
  1270 + * the codec manually.
  1271 + */
  1272 + mixer_reset (s);
  1273 +}
  1274 +
  1275 +int ac97_init (PCIBus *bus, AudioState *audio)
  1276 +{
  1277 + PCIAC97LinkState *d;
  1278 + AC97LinkState *s;
  1279 + uint8_t *c;
  1280 +
  1281 + if (!bus) {
  1282 + AUD_log ("ac97", "No PCI bus\n");
  1283 + return -1;
  1284 + }
  1285 +
  1286 + if (!audio) {
  1287 + AUD_log ("ac97", "No audio state\n");
  1288 + return -1;
  1289 + }
  1290 +
  1291 + d = (PCIAC97LinkState *) pci_register_device (bus, "AC97",
  1292 + sizeof (PCIAC97LinkState),
  1293 + -1, NULL, NULL);
  1294 +
  1295 + if (!d) {
  1296 + AUD_log ("ac97", "Failed to register PCI device\n");
  1297 + return -1;
  1298 + }
  1299 +
  1300 + s = &d->ac97;
  1301 + s->pci_dev = &d->dev;
  1302 + c = d->dev.config;
  1303 + c[0x00] = 0x86; /* vid vendor id intel ro */
  1304 + c[0x01] = 0x80; /* intel */
  1305 +
  1306 + c[0x02] = 0x15; /* did device id 82801 ro */
  1307 + c[0x03] = 0x24; /* 82801aa */
  1308 +
  1309 + c[0x04] = 0x00; /* pcicmd pci command rw, ro */
  1310 + c[0x05] = 0x00;
  1311 +
  1312 + c[0x06] = 0x80; /* pcists pci status rwc, ro */
  1313 + c[0x07] = 0x02;
  1314 +
  1315 + c[0x08] = 0x01; /* rid revision ro */
  1316 + c[0x09] = 0x00; /* pi programming interface ro */
  1317 + c[0x0a] = 0x01; /* scc sub class code ro */
  1318 + c[0x0b] = 0x04; /* bcc base class code ro */
  1319 + c[0x0e] = 0x00; /* headtyp header type ro */
  1320 +
  1321 + c[0x10] = 0x01; /* nabmar native audio mixer base
  1322 + address rw */
  1323 + c[0x11] = 0x00;
  1324 + c[0x12] = 0x00;
  1325 + c[0x13] = 0x00;
  1326 +
  1327 + c[0x14] = 0x01; /* nabmbar native audio bus mastering
  1328 + base address rw */
  1329 + c[0x15] = 0x00;
  1330 + c[0x16] = 0x00;
  1331 + c[0x17] = 0x00;
  1332 +
  1333 + c[0x2c] = 0x86; /* svid subsystem vendor id rwo */
  1334 + c[0x2d] = 0x80;
  1335 +
  1336 + c[0x2e] = 0x00; /* sid subsystem id rwo */
  1337 + c[0x2f] = 0x00;
  1338 +
  1339 + c[0x3c] = 0x00; /* intr_ln interrupt line rw */
  1340 + c[0x3d] = 0x01; /* intr_pn interrupt pin ro */
  1341 +
  1342 + pci_register_io_region (&d->dev, 0, 256 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);
  1343 + pci_register_io_region (&d->dev, 1, 64 * 4, PCI_ADDRESS_SPACE_IO, ac97_map);
  1344 + register_savevm ("ac97", 0, 1, ac97_save, ac97_load, s);
  1345 + qemu_register_reset (ac97_on_reset, s);
  1346 + AUD_register_card (audio, "ac97", &s->card);
  1347 + ac97_on_reset (s);
  1348 + return 0;
  1349 +}
hw/audiodev.h
@@ -10,3 +10,5 @@ int Adlib_init (AudioState *s, qemu_irq *pic); @@ -10,3 +10,5 @@ int Adlib_init (AudioState *s, qemu_irq *pic);
10 /* gus.c */ 10 /* gus.c */
11 int GUS_init (AudioState *s, qemu_irq *pic); 11 int GUS_init (AudioState *s, qemu_irq *pic);
12 12
  13 +/* ac97.c */
  14 +int ac97_init (PCIBus *buf, AudioState *s);
qemu-doc.texi
@@ -166,6 +166,8 @@ Creative SoundBlaster 16 sound card @@ -166,6 +166,8 @@ Creative SoundBlaster 16 sound card
166 @item 166 @item
167 ENSONIQ AudioPCI ES1370 sound card 167 ENSONIQ AudioPCI ES1370 sound card
168 @item 168 @item
  169 +Intel 82801AA AC97 Audio compatible sound card
  170 +@item
169 Adlib(OPL2) - Yamaha YM3812 compatible chip 171 Adlib(OPL2) - Yamaha YM3812 compatible chip
170 @item 172 @item
171 PCI UHCI USB controller and a virtual USB hub. 173 PCI UHCI USB controller and a virtual USB hub.
@@ -173,8 +175,8 @@ PCI UHCI USB controller and a virtual USB hub. @@ -173,8 +175,8 @@ PCI UHCI USB controller and a virtual USB hub.
173 175
174 SMP is supported with up to 255 CPUs. 176 SMP is supported with up to 255 CPUs.
175 177
176 -Note that adlib is only available when QEMU was configured with  
177 --enable-adlib 178 +Note that adlib and ac97 are only available when QEMU was configured
  179 +with --enable-adlib, --enable-ac97 respectively.
178 180
179 QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL 181 QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL
180 VGA BIOS. 182 VGA BIOS.
@@ -334,10 +336,18 @@ available sound hardware. @@ -334,10 +336,18 @@ available sound hardware.
334 @example 336 @example
335 qemu -soundhw sb16,adlib hda 337 qemu -soundhw sb16,adlib hda
336 qemu -soundhw es1370 hda 338 qemu -soundhw es1370 hda
  339 +qemu -soundhw ac97 hda
337 qemu -soundhw all hda 340 qemu -soundhw all hda
338 qemu -soundhw ? 341 qemu -soundhw ?
339 @end example 342 @end example
340 343
  344 +Note that Linux's i810_audio OSS kernel (for AC97) module might
  345 +require manually specifying clocking.
  346 +
  347 +@example
  348 +modprobe i810_audio clocking=48000
  349 +@end example
  350 +
341 @item -localtime 351 @item -localtime
342 Set the real time clock to local time (the default is to UTC 352 Set the real time clock to local time (the default is to UTC
343 time). This option is needed to have correct date in MS-DOS or 353 time). This option is needed to have correct date in MS-DOS or
@@ -7990,6 +7990,16 @@ struct soundhw soundhw[] = { @@ -7990,6 +7990,16 @@ struct soundhw soundhw[] = {
7990 }, 7990 },
7991 #endif 7991 #endif
7992 7992
  7993 +#ifdef CONFIG_AC97
  7994 + {
  7995 + "ac97",
  7996 + "Intel 82801AA AC97 Audio",
  7997 + 0,
  7998 + 0,
  7999 + { .init_pci = ac97_init }
  8000 + },
  8001 +#endif
  8002 +
7993 { 8003 {
7994 "es1370", 8004 "es1370",
7995 "ENSONIQ AudioPCI ES1370", 8005 "ENSONIQ AudioPCI ES1370",