[Core Change] Port AC97 factorization from XQEMU 1.x

This commit is contained in:
Matt Borgerson 2018-06-26 14:33:50 -07:00
parent cbadd93124
commit 7aa5985eba
2 changed files with 216 additions and 119 deletions

View File

@ -23,6 +23,7 @@
#include "audio/audio.h" #include "audio/audio.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "ac97_int.h"
enum { enum {
AC97_Reset = 0x00, AC97_Reset = 0x00,
@ -115,8 +116,9 @@ enum {
#define GS_VALID_MASK ((1 << 18) - 1) #define GS_VALID_MASK ((1 << 18) - 1)
#define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI) #define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI)
#define BD_IOC (1<<31) /* Buffer Descriptor */
#define BD_BUP (1<<30) #define BD_IOC (1<<31) /* Interrupt on Completion */
#define BD_BUP (1<<30) /* Buffer Underrun Policy */
#define EACS_VRA 1 #define EACS_VRA 1
#define EACS_VRM 8 #define EACS_VRM 8
@ -135,43 +137,6 @@ enum {
REC_PHONE REC_PHONE
}; };
typedef struct BD {
uint32_t addr;
uint32_t ctl_len;
} BD;
typedef struct AC97BusMasterRegs {
uint32_t bdbar; /* rw 0 */
uint8_t civ; /* ro 0 */
uint8_t lvi; /* rw 0 */
uint16_t sr; /* rw 1 */
uint16_t picb; /* ro 0 */
uint8_t piv; /* ro 0 */
uint8_t cr; /* rw 0 */
unsigned int bd_valid;
BD bd;
} AC97BusMasterRegs;
typedef struct AC97LinkState {
PCIDevice dev;
QEMUSoundCard card;
uint32_t use_broken_id;
uint32_t glob_cnt;
uint32_t glob_sta;
uint32_t cas;
uint32_t last_samp;
AC97BusMasterRegs bm_regs[3];
uint8_t mixer_data[256];
SWVoiceIn *voice_pi;
SWVoiceOut *voice_po;
SWVoiceIn *voice_mc;
int invalid_freq[3];
uint8_t silence[128];
int bup_flag;
MemoryRegion io_nam;
MemoryRegion io_nabm;
} AC97LinkState;
enum { enum {
BUP_SET = 1, BUP_SET = 1,
BUP_LAST = 2 BUP_LAST = 2
@ -194,16 +159,10 @@ enum { \
prefix ## _CR = start + 11 \ prefix ## _CR = start + 11 \
} }
enum {
PI_INDEX = 0,
PO_INDEX,
MC_INDEX,
LAST_INDEX
};
MKREGS (PI, PI_INDEX * 16); MKREGS (PI, PI_INDEX * 16);
MKREGS (PO, PO_INDEX * 16); MKREGS (PO, PO_INDEX * 16);
MKREGS (MC, MC_INDEX * 16); MKREGS (MC, MC_INDEX * 16);
MKREGS (SO, SO_INDEX * 16);
enum { enum {
GLOB_CNT = 0x2c, GLOB_CNT = 0x2c,
@ -231,7 +190,7 @@ static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r)
{ {
uint8_t b[8]; uint8_t b[8];
pci_dma_read (&s->dev, r->bdbar + r->civ * 8, b, 8); dma_memory_read(s->as, r->bdbar + r->civ * 8, b, 8);
r->bd_valid = 1; r->bd_valid = 1;
r->bd.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3; r->bd.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3;
r->bd.ctl_len = le32_to_cpu (*(uint32_t *) &b[4]); r->bd.ctl_len = le32_to_cpu (*(uint32_t *) &b[4]);
@ -242,6 +201,10 @@ static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r)
(r->bd.ctl_len & 0xffff) << 1); (r->bd.ctl_len & 0xffff) << 1);
} }
/**
* Update the BM status register
*/
static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr) static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
{ {
int event = 0; int event = 0;
@ -281,12 +244,12 @@ static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
if (level) { if (level) {
s->glob_sta |= masks[r - s->bm_regs]; s->glob_sta |= masks[r - s->bm_regs];
dolog ("set irq level=1\n"); dolog ("set irq level=1\n");
pci_irq_assert(&s->dev); pci_irq_assert(s->pci_dev);
} }
else { else {
s->glob_sta &= ~masks[r - s->bm_regs]; s->glob_sta &= ~masks[r - s->bm_regs];
dolog ("set irq level=0\n"); dolog ("set irq level=0\n");
pci_irq_deassert(&s->dev); pci_irq_deassert(s->pci_dev);
} }
} }
@ -306,7 +269,7 @@ static void voice_set_active (AC97LinkState *s, int bm_index, int on)
break; break;
default: default:
AUD_log ("ac97", "invalid bm_index(%d) in voice_set_active", bm_index); AUD_log ("ac97", "invalid bm_index(%d) in voice_set_active\n", bm_index);
break; break;
} }
} }
@ -723,6 +686,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
case PI_CIV: case PI_CIV:
case PO_CIV: case PO_CIV:
case MC_CIV: case MC_CIV:
case SO_CIV:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->civ; val = r->civ;
dolog ("CIV[%d] -> %#x\n", GET_BM (index), val); dolog ("CIV[%d] -> %#x\n", GET_BM (index), val);
@ -730,6 +694,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
case PI_LVI: case PI_LVI:
case PO_LVI: case PO_LVI:
case MC_LVI: case MC_LVI:
case SO_LVI:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->lvi; val = r->lvi;
dolog ("LVI[%d] -> %#x\n", GET_BM (index), val); dolog ("LVI[%d] -> %#x\n", GET_BM (index), val);
@ -737,6 +702,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
case PI_PIV: case PI_PIV:
case PO_PIV: case PO_PIV:
case MC_PIV: case MC_PIV:
case SO_PIV:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->piv; val = r->piv;
dolog ("PIV[%d] -> %#x\n", GET_BM (index), val); dolog ("PIV[%d] -> %#x\n", GET_BM (index), val);
@ -744,6 +710,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
case PI_CR: case PI_CR:
case PO_CR: case PO_CR:
case MC_CR: case MC_CR:
case SO_CR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->cr; val = r->cr;
dolog ("CR[%d] -> %#x\n", GET_BM (index), val); dolog ("CR[%d] -> %#x\n", GET_BM (index), val);
@ -751,6 +718,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
case PI_SR: case PI_SR:
case PO_SR: case PO_SR:
case MC_SR: case MC_SR:
case SO_SR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->sr & 0xff; val = r->sr & 0xff;
dolog ("SRb[%d] -> %#x\n", GET_BM (index), val); dolog ("SRb[%d] -> %#x\n", GET_BM (index), val);
@ -773,6 +741,7 @@ static uint32_t nabm_readw (void *opaque, uint32_t addr)
case PI_SR: case PI_SR:
case PO_SR: case PO_SR:
case MC_SR: case MC_SR:
case SO_SR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->sr; val = r->sr;
dolog ("SR[%d] -> %#x\n", GET_BM (index), val); dolog ("SR[%d] -> %#x\n", GET_BM (index), val);
@ -780,6 +749,7 @@ static uint32_t nabm_readw (void *opaque, uint32_t addr)
case PI_PICB: case PI_PICB:
case PO_PICB: case PO_PICB:
case MC_PICB: case MC_PICB:
case SO_PICB:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->picb; val = r->picb;
dolog ("PICB[%d] -> %#x\n", GET_BM (index), val); dolog ("PICB[%d] -> %#x\n", GET_BM (index), val);
@ -802,6 +772,7 @@ static uint32_t nabm_readl (void *opaque, uint32_t addr)
case PI_BDBAR: case PI_BDBAR:
case PO_BDBAR: case PO_BDBAR:
case MC_BDBAR: case MC_BDBAR:
case SO_BDBAR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->bdbar; val = r->bdbar;
dolog ("BMADDR[%d] -> %#x\n", GET_BM (index), val); dolog ("BMADDR[%d] -> %#x\n", GET_BM (index), val);
@ -809,6 +780,7 @@ static uint32_t nabm_readl (void *opaque, uint32_t addr)
case PI_CIV: case PI_CIV:
case PO_CIV: case PO_CIV:
case MC_CIV: case MC_CIV:
case SO_CIV:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->civ | (r->lvi << 8) | (r->sr << 16); val = r->civ | (r->lvi << 8) | (r->sr << 16);
dolog ("CIV LVI SR[%d] -> %#x, %#x, %#x\n", GET_BM (index), dolog ("CIV LVI SR[%d] -> %#x, %#x, %#x\n", GET_BM (index),
@ -817,6 +789,7 @@ static uint32_t nabm_readl (void *opaque, uint32_t addr)
case PI_PICB: case PI_PICB:
case PO_PICB: case PO_PICB:
case MC_PICB: case MC_PICB:
case SO_PICB:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
val = r->picb | (r->piv << 16) | (r->cr << 24); val = r->picb | (r->piv << 16) | (r->cr << 24);
dolog ("PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM (index), dolog ("PICB PIV CR[%d] -> %#x %#x %#x %#x\n", GET_BM (index),
@ -850,6 +823,7 @@ static void nabm_writeb (void *opaque, uint32_t addr, uint32_t val)
case PI_LVI: case PI_LVI:
case PO_LVI: case PO_LVI:
case MC_LVI: case MC_LVI:
case SO_LVI:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) { if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) {
r->sr &= ~(SR_DCH | SR_CELV); r->sr &= ~(SR_DCH | SR_CELV);
@ -863,6 +837,7 @@ static void nabm_writeb (void *opaque, uint32_t addr, uint32_t val)
case PI_CR: case PI_CR:
case PO_CR: case PO_CR:
case MC_CR: case MC_CR:
case SO_CR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
if (val & CR_RR) { if (val & CR_RR) {
reset_bm_regs (s, r); reset_bm_regs (s, r);
@ -886,6 +861,7 @@ static void nabm_writeb (void *opaque, uint32_t addr, uint32_t val)
case PI_SR: case PI_SR:
case PO_SR: case PO_SR:
case MC_SR: case MC_SR:
case SO_SR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK); r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK)); update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK));
@ -906,6 +882,7 @@ static void nabm_writew (void *opaque, uint32_t addr, uint32_t val)
case PI_SR: case PI_SR:
case PO_SR: case PO_SR:
case MC_SR: case MC_SR:
case SO_SR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK); r->sr |= val & ~(SR_RO_MASK | SR_WCLEAR_MASK);
update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK)); update_sr (s, r, r->sr & ~(val & SR_WCLEAR_MASK));
@ -926,6 +903,7 @@ static void nabm_writel (void *opaque, uint32_t addr, uint32_t val)
case PI_BDBAR: case PI_BDBAR:
case PO_BDBAR: case PO_BDBAR:
case MC_BDBAR: case MC_BDBAR:
case SO_BDBAR:
r = &s->bm_regs[GET_BM (index)]; r = &s->bm_regs[GET_BM (index)];
r->bdbar = val & ~3; r->bdbar = val & ~3;
dolog ("BDBAR[%d] <- %#x (bdbar %#x)\n", dolog ("BDBAR[%d] <- %#x (bdbar %#x)\n",
@ -969,7 +947,7 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
while (temp) { while (temp) {
int copied; int copied;
to_copy = audio_MIN (temp, sizeof (tmpbuf)); to_copy = audio_MIN (temp, sizeof (tmpbuf));
pci_dma_read (&s->dev, addr, tmpbuf, to_copy); dma_memory_read (s->as, addr, tmpbuf, to_copy);
copied = AUD_write (s->voice_po, tmpbuf, to_copy); copied = AUD_write (s->voice_po, tmpbuf, to_copy);
dolog ("write_audio max=%x to_copy=%x copied=%x\n", dolog ("write_audio max=%x to_copy=%x copied=%x\n",
max, to_copy, copied); max, to_copy, copied);
@ -1050,7 +1028,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
*stop = 1; *stop = 1;
break; break;
} }
pci_dma_write (&s->dev, addr, tmpbuf, acquired); dma_memory_write (s->as, addr, tmpbuf, acquired);
temp -= acquired; temp -= acquired;
addr += acquired; addr += acquired;
nread += acquired; nread += acquired;
@ -1160,25 +1138,6 @@ static void po_callback (void *opaque, int free)
transfer_audio (opaque, PO_INDEX, free); transfer_audio (opaque, PO_INDEX, free);
} }
static const VMStateDescription vmstate_ac97_bm_regs = {
.name = "ac97_bm_regs",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32 (bdbar, AC97BusMasterRegs),
VMSTATE_UINT8 (civ, AC97BusMasterRegs),
VMSTATE_UINT8 (lvi, AC97BusMasterRegs),
VMSTATE_UINT16 (sr, AC97BusMasterRegs),
VMSTATE_UINT16 (picb, AC97BusMasterRegs),
VMSTATE_UINT8 (piv, AC97BusMasterRegs),
VMSTATE_UINT8 (cr, AC97BusMasterRegs),
VMSTATE_UINT32 (bd_valid, AC97BusMasterRegs),
VMSTATE_UINT32 (bd.addr, AC97BusMasterRegs),
VMSTATE_UINT32 (bd.ctl_len, AC97BusMasterRegs),
VMSTATE_END_OF_LIST ()
}
};
static int ac97_post_load (void *opaque, int version_id) static int ac97_post_load (void *opaque, int version_id)
{ {
uint8_t active[LAST_INDEX]; uint8_t active[LAST_INDEX];
@ -1202,31 +1161,10 @@ static int ac97_post_load (void *opaque, int version_id)
return 0; return 0;
} }
static bool is_version_2 (void *opaque, int version_id)
{
return version_id == 2;
}
static const VMStateDescription vmstate_ac97 = {
.name = "ac97",
.version_id = 3,
.minimum_version_id = 2,
.post_load = ac97_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE (dev, AC97LinkState),
VMSTATE_UINT32 (glob_cnt, AC97LinkState),
VMSTATE_UINT32 (glob_sta, AC97LinkState),
VMSTATE_UINT32 (cas, AC97LinkState),
VMSTATE_STRUCT_ARRAY (bm_regs, AC97LinkState, 3, 1,
vmstate_ac97_bm_regs, AC97BusMasterRegs),
VMSTATE_BUFFER (mixer_data, AC97LinkState),
VMSTATE_UNUSED_TEST (is_version_2, 3),
VMSTATE_END_OF_LIST ()
}
};
static uint64_t nam_read(void *opaque, hwaddr addr, unsigned size) static uint64_t nam_read(void *opaque, hwaddr addr, unsigned size)
{ {
dolog("nam_read [0x%llx] (%d)\n", addr, size);
if ((addr / size) > 256) { if ((addr / size) > 256) {
return -1; return -1;
} }
@ -1246,6 +1184,8 @@ static uint64_t nam_read(void *opaque, hwaddr addr, unsigned size)
static void nam_write(void *opaque, hwaddr addr, uint64_t val, static void nam_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size) unsigned size)
{ {
dolog("nam_write [0x%llx] = 0x%llx (%d)\n", addr, val, size);
if ((addr / size) > 256) { if ((addr / size) > 256) {
return; return;
} }
@ -1263,7 +1203,7 @@ static void nam_write(void *opaque, hwaddr addr, uint64_t val,
} }
} }
static const MemoryRegionOps ac97_io_nam_ops = { const MemoryRegionOps ac97_io_nam_ops = {
.read = nam_read, .read = nam_read,
.write = nam_write, .write = nam_write,
.impl = { .impl = {
@ -1275,9 +1215,11 @@ static const MemoryRegionOps ac97_io_nam_ops = {
static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size) static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size)
{ {
if ((addr / size) > 64) { dolog("nabm_read [0x%llx] (%d)\n", addr, size);
return -1; // if ((addr / size) > 64) {
} // // assert(0);
// return -1;
// }
switch (size) { switch (size) {
case 1: case 1:
@ -1294,9 +1236,11 @@ static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size)
static void nabm_write(void *opaque, hwaddr addr, uint64_t val, static void nabm_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size) unsigned size)
{ {
if ((addr / size) > 64) { dolog("nabm_write [0x%llx] = 0x%llx (%d)\n", addr, val, size);
return; // if ((addr / size) > 64) {
} // // assert(0);
// return;
// }
switch (size) { switch (size) {
case 1: case 1:
@ -1312,7 +1256,7 @@ static void nabm_write(void *opaque, hwaddr addr, uint64_t val,
} }
static const MemoryRegionOps ac97_io_nabm_ops = { const MemoryRegionOps ac97_io_nabm_ops = {
.read = nabm_read, .read = nabm_read,
.write = nabm_write, .write = nabm_write,
.impl = { .impl = {
@ -1322,9 +1266,9 @@ static const MemoryRegionOps ac97_io_nabm_ops = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
static void ac97_on_reset (DeviceState *dev) static void ac97_on_reset (void *opaque)
{ {
AC97LinkState *s = container_of(dev, AC97LinkState, dev.qdev); AC97LinkState *s = opaque;
reset_bm_regs (s, &s->bm_regs[0]); reset_bm_regs (s, &s->bm_regs[0]);
reset_bm_regs (s, &s->bm_regs[1]); reset_bm_regs (s, &s->bm_regs[1]);
@ -1338,9 +1282,83 @@ static void ac97_on_reset (DeviceState *dev)
mixer_reset (s); mixer_reset (s);
} }
void ac97_common_init (AC97LinkState *s,
PCIDevice* pci_dev,
AddressSpace *as)
{
s->pci_dev = pci_dev;
s->as = as;
qemu_register_reset (ac97_on_reset, s);
AUD_register_card ("ac97", &s->card);
ac97_on_reset (s);
}
typedef struct AC97DeviceState {
PCIDevice dev;
AC97LinkState state;
uint32_t use_broken_id;
MemoryRegion io_nam;
MemoryRegion io_nabm;
} AC97DeviceState;
#define AC97_DEVICE(obj) \
OBJECT_CHECK(AC97DeviceState, (obj), "AC97")
static const VMStateDescription vmstate_ac97_bm_regs = {
.name = "ac97_bm_regs",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_UINT32 (bdbar, AC97BusMasterRegs),
VMSTATE_UINT8 (civ, AC97BusMasterRegs),
VMSTATE_UINT8 (lvi, AC97BusMasterRegs),
VMSTATE_UINT16 (sr, AC97BusMasterRegs),
VMSTATE_UINT16 (picb, AC97BusMasterRegs),
VMSTATE_UINT8 (piv, AC97BusMasterRegs),
VMSTATE_UINT8 (cr, AC97BusMasterRegs),
VMSTATE_UINT32 (bd_valid, AC97BusMasterRegs),
VMSTATE_UINT32 (bd.addr, AC97BusMasterRegs),
VMSTATE_UINT32 (bd.ctl_len, AC97BusMasterRegs),
VMSTATE_END_OF_LIST ()
}
};
static bool is_version_2 (void *opaque, int version_id)
{
return version_id == 2;
}
static const VMStateDescription vmstate_ac97 = {
.name = "ac97",
.version_id = 3,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
.post_load = ac97_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE (dev, AC97DeviceState),
VMSTATE_UINT32 (state.glob_cnt, AC97DeviceState),
VMSTATE_UINT32 (state.glob_sta, AC97DeviceState),
VMSTATE_UINT32 (state.cas, AC97DeviceState),
VMSTATE_STRUCT_ARRAY (state.bm_regs, AC97DeviceState, LAST_INDEX, 1,
vmstate_ac97_bm_regs, AC97BusMasterRegs),
VMSTATE_BUFFER (state.mixer_data, AC97DeviceState),
VMSTATE_UNUSED_TEST (is_version_2, 3),
VMSTATE_END_OF_LIST ()
}
};
static void ac97_realize (PCIDevice *dev, Error **errp) static void ac97_realize (PCIDevice *dev, Error **errp)
{ {
AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev); AC97DeviceState *s = AC97_DEVICE(dev);
uint8_t *c = s->dev.config; uint8_t *c = s->dev.config;
/* TODO: no need to override */ /* TODO: no need to override */
@ -1377,24 +1395,22 @@ static void ac97_realize(PCIDevice *dev, Error **errp)
c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */ c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */
c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */ c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */
memory_region_init_io (&s->io_nam, OBJECT(s), &ac97_io_nam_ops, s, memory_region_init_io (&s->io_nam, OBJECT(s), &ac97_io_nam_ops, &s->state,
"ac97-nam", 1024); "ac97-nam", 1024);
memory_region_init_io (&s->io_nabm, OBJECT(s), &ac97_io_nabm_ops, s, memory_region_init_io (&s->io_nabm, OBJECT(s), &ac97_io_nabm_ops, &s->state,
"ac97-nabm", 256); "ac97-nabm", 256);
pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam); pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam);
pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm); pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm);
AUD_register_card ("ac97", &s->card);
ac97_on_reset (&s->dev.qdev); ac97_common_init(&s->state, &s->dev, pci_get_address_space(&s->dev));
} }
static void ac97_exit (PCIDevice *dev) static void ac97_exit (PCIDevice *dev)
{ {
AC97LinkState *s = DO_UPCAST(AC97LinkState, dev, dev); AC97DeviceState *s = AC97_DEVICE(dev);
AUD_close_in(&s->card, s->voice_pi); memory_region_destroy (&s->io_nam);
AUD_close_out(&s->card, s->voice_po); memory_region_destroy (&s->io_nabm);
AUD_close_in(&s->card, s->voice_mc);
AUD_remove_card(&s->card);
} }
static int ac97_init (PCIBus *bus) static int ac97_init (PCIBus *bus)
@ -1404,7 +1420,7 @@ static int ac97_init (PCIBus *bus)
} }
static Property ac97_properties[] = { static Property ac97_properties[] = {
DEFINE_PROP_UINT32 ("use_broken_id", AC97LinkState, use_broken_id, 0), DEFINE_PROP_UINT32 ("use_broken_id", AC97DeviceState, use_broken_id, 0),
DEFINE_PROP_END_OF_LIST (), DEFINE_PROP_END_OF_LIST (),
}; };
@ -1423,13 +1439,13 @@ static void ac97_class_init (ObjectClass *klass, void *data)
dc->desc = "Intel 82801AA AC97 Audio"; dc->desc = "Intel 82801AA AC97 Audio";
dc->vmsd = &vmstate_ac97; dc->vmsd = &vmstate_ac97;
dc->props = ac97_properties; dc->props = ac97_properties;
dc->reset = ac97_on_reset; dc->reset = (DeviceReset)ac97_on_reset;
} }
static const TypeInfo ac97_info = { static const TypeInfo ac97_info = {
.name = "AC97", .name = "AC97",
.parent = TYPE_PCI_DEVICE, .parent = TYPE_PCI_DEVICE,
.instance_size = sizeof (AC97LinkState), .instance_size = sizeof (AC97DeviceState),
.class_init = ac97_class_init, .class_init = ac97_class_init,
.interfaces = (InterfaceInfo[]) { .interfaces = (InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE }, { INTERFACE_CONVENTIONAL_PCI_DEVICE },
@ -1444,3 +1460,4 @@ static void ac97_register_types (void)
} }
type_init (ac97_register_types) type_init (ac97_register_types)

80
hw/audio/ac97_int.h Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2006 InnoTek Systemberatung GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
#ifndef HW_AC97_INT_H
#define HW_AC97_INT_H
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/pci/pci.h"
#include "sysemu/dma.h"
enum {
PI_INDEX = 0, /* PCM in */
PO_INDEX, /* PCM out */
MC_INDEX, /* Mic in */
SO_INDEX = 7, /* SPDIF out */
LAST_INDEX
};
typedef struct BD {
uint32_t addr;
uint32_t ctl_len;
} BD;
typedef struct AC97BusMasterRegs {
uint32_t bdbar; /* rw 0, buffer descriptor list base address register */
uint8_t civ; /* ro 0, current index value */
uint8_t lvi; /* rw 0, last valid index */
uint16_t sr; /* rw 1, status register */
uint16_t picb; /* ro 0, position in current buffer */
uint8_t piv; /* ro 0, prefetched index value */
uint8_t cr; /* rw 0, control register */
unsigned int bd_valid;
BD bd;
} AC97BusMasterRegs;
typedef struct AC97LinkState {
PCIDevice *pci_dev;
AddressSpace *as;
QEMUSoundCard card;
uint32_t glob_cnt;
uint32_t glob_sta;
uint32_t cas; /* Codec Access Semaphore Register */
uint32_t last_samp;
AC97BusMasterRegs bm_regs[LAST_INDEX];
uint8_t mixer_data[256];
SWVoiceIn *voice_pi;
SWVoiceOut *voice_po;
SWVoiceIn *voice_mc;
int invalid_freq[LAST_INDEX];
uint8_t silence[128];
int bup_flag;
} AC97LinkState;
void ac97_common_init (AC97LinkState *s,
PCIDevice *pci_dev,
AddressSpace *as);
extern const MemoryRegionOps ac97_io_nam_ops;
extern const MemoryRegionOps ac97_io_nabm_ops;
#endif