mirror of https://github.com/xemu-project/xemu.git
[Core Change] Port AC97 factorization from XQEMU 1.x
This commit is contained in:
parent
cbadd93124
commit
7aa5985eba
255
hw/audio/ac97.c
255
hw/audio/ac97.c
|
@ -23,6 +23,7 @@
|
|||
#include "audio/audio.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "ac97_int.h"
|
||||
|
||||
enum {
|
||||
AC97_Reset = 0x00,
|
||||
|
@ -115,8 +116,9 @@ enum {
|
|||
#define GS_VALID_MASK ((1 << 18) - 1)
|
||||
#define GS_WCLEAR_MASK (GS_RCS|GS_S1R1|GS_S0R1|GS_GSCI)
|
||||
|
||||
#define BD_IOC (1<<31)
|
||||
#define BD_BUP (1<<30)
|
||||
/* Buffer Descriptor */
|
||||
#define BD_IOC (1<<31) /* Interrupt on Completion */
|
||||
#define BD_BUP (1<<30) /* Buffer Underrun Policy */
|
||||
|
||||
#define EACS_VRA 1
|
||||
#define EACS_VRM 8
|
||||
|
@ -135,43 +137,6 @@ enum {
|
|||
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 {
|
||||
BUP_SET = 1,
|
||||
BUP_LAST = 2
|
||||
|
@ -194,16 +159,10 @@ enum { \
|
|||
prefix ## _CR = start + 11 \
|
||||
}
|
||||
|
||||
enum {
|
||||
PI_INDEX = 0,
|
||||
PO_INDEX,
|
||||
MC_INDEX,
|
||||
LAST_INDEX
|
||||
};
|
||||
|
||||
MKREGS (PI, PI_INDEX * 16);
|
||||
MKREGS (PO, PO_INDEX * 16);
|
||||
MKREGS (MC, MC_INDEX * 16);
|
||||
MKREGS (SO, SO_INDEX * 16);
|
||||
|
||||
enum {
|
||||
GLOB_CNT = 0x2c,
|
||||
|
@ -231,7 +190,7 @@ static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r)
|
|||
{
|
||||
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.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the BM status register
|
||||
*/
|
||||
static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
|
||||
{
|
||||
int event = 0;
|
||||
|
@ -281,12 +244,12 @@ static void update_sr (AC97LinkState *s, AC97BusMasterRegs *r, uint32_t new_sr)
|
|||
if (level) {
|
||||
s->glob_sta |= masks[r - s->bm_regs];
|
||||
dolog ("set irq level=1\n");
|
||||
pci_irq_assert(&s->dev);
|
||||
pci_irq_assert(s->pci_dev);
|
||||
}
|
||||
else {
|
||||
s->glob_sta &= ~masks[r - s->bm_regs];
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -723,6 +686,7 @@ static uint32_t nabm_readb (void *opaque, uint32_t addr)
|
|||
case PI_CIV:
|
||||
case PO_CIV:
|
||||
case MC_CIV:
|
||||
case SO_CIV:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->civ;
|
||||
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 PO_LVI:
|
||||
case MC_LVI:
|
||||
case SO_LVI:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->lvi;
|
||||
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 PO_PIV:
|
||||
case MC_PIV:
|
||||
case SO_PIV:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->piv;
|
||||
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 PO_CR:
|
||||
case MC_CR:
|
||||
case SO_CR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->cr;
|
||||
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 PO_SR:
|
||||
case MC_SR:
|
||||
case SO_SR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->sr & 0xff;
|
||||
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 PO_SR:
|
||||
case MC_SR:
|
||||
case SO_SR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->sr;
|
||||
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 PO_PICB:
|
||||
case MC_PICB:
|
||||
case SO_PICB:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->picb;
|
||||
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 PO_BDBAR:
|
||||
case MC_BDBAR:
|
||||
case SO_BDBAR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->bdbar;
|
||||
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 PO_CIV:
|
||||
case MC_CIV:
|
||||
case SO_CIV:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->civ | (r->lvi << 8) | (r->sr << 16);
|
||||
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 PO_PICB:
|
||||
case MC_PICB:
|
||||
case SO_PICB:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
val = r->picb | (r->piv << 16) | (r->cr << 24);
|
||||
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 PO_LVI:
|
||||
case MC_LVI:
|
||||
case SO_LVI:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
if ((r->cr & CR_RPBM) && (r->sr & SR_DCH)) {
|
||||
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 PO_CR:
|
||||
case MC_CR:
|
||||
case SO_CR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
if (val & CR_RR) {
|
||||
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 PO_SR:
|
||||
case MC_SR:
|
||||
case SO_SR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
r->sr |= val & ~(SR_RO_MASK | 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 PO_SR:
|
||||
case MC_SR:
|
||||
case SO_SR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
r->sr |= val & ~(SR_RO_MASK | 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 PO_BDBAR:
|
||||
case MC_BDBAR:
|
||||
case SO_BDBAR:
|
||||
r = &s->bm_regs[GET_BM (index)];
|
||||
r->bdbar = val & ~3;
|
||||
dolog ("BDBAR[%d] <- %#x (bdbar %#x)\n",
|
||||
|
@ -969,7 +947,7 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r,
|
|||
while (temp) {
|
||||
int copied;
|
||||
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);
|
||||
dolog ("write_audio max=%x to_copy=%x copied=%x\n",
|
||||
max, to_copy, copied);
|
||||
|
@ -1050,7 +1028,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r,
|
|||
*stop = 1;
|
||||
break;
|
||||
}
|
||||
pci_dma_write (&s->dev, addr, tmpbuf, acquired);
|
||||
dma_memory_write (s->as, addr, tmpbuf, acquired);
|
||||
temp -= acquired;
|
||||
addr += acquired;
|
||||
nread += acquired;
|
||||
|
@ -1160,25 +1138,6 @@ static void po_callback (void *opaque, int 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)
|
||||
{
|
||||
uint8_t active[LAST_INDEX];
|
||||
|
@ -1202,31 +1161,10 @@ static int ac97_post_load (void *opaque, int version_id)
|
|||
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)
|
||||
{
|
||||
dolog("nam_read [0x%llx] (%d)\n", addr, size);
|
||||
|
||||
if ((addr / size) > 256) {
|
||||
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,
|
||||
unsigned size)
|
||||
{
|
||||
dolog("nam_write [0x%llx] = 0x%llx (%d)\n", addr, val, size);
|
||||
|
||||
if ((addr / size) > 256) {
|
||||
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,
|
||||
.write = nam_write,
|
||||
.impl = {
|
||||
|
@ -1275,9 +1215,11 @@ static const MemoryRegionOps ac97_io_nam_ops = {
|
|||
|
||||
static uint64_t nabm_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
if ((addr / size) > 64) {
|
||||
return -1;
|
||||
}
|
||||
dolog("nabm_read [0x%llx] (%d)\n", addr, size);
|
||||
// if ((addr / size) > 64) {
|
||||
// // assert(0);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
switch (size) {
|
||||
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,
|
||||
unsigned size)
|
||||
{
|
||||
if ((addr / size) > 64) {
|
||||
return;
|
||||
}
|
||||
dolog("nabm_write [0x%llx] = 0x%llx (%d)\n", addr, val, size);
|
||||
// if ((addr / size) > 64) {
|
||||
// // assert(0);
|
||||
// return;
|
||||
// }
|
||||
|
||||
switch (size) {
|
||||
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,
|
||||
.write = nabm_write,
|
||||
.impl = {
|
||||
|
@ -1322,9 +1266,9 @@ static const MemoryRegionOps ac97_io_nabm_ops = {
|
|||
.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[1]);
|
||||
|
@ -1338,9 +1282,83 @@ static void ac97_on_reset (DeviceState *dev)
|
|||
mixer_reset (s);
|
||||
}
|
||||
|
||||
static void ac97_realize(PCIDevice *dev, Error **errp)
|
||||
void ac97_common_init (AC97LinkState *s,
|
||||
PCIDevice* pci_dev,
|
||||
AddressSpace *as)
|
||||
{
|
||||
AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
|
||||
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)
|
||||
{
|
||||
AC97DeviceState *s = AC97_DEVICE(dev);
|
||||
uint8_t *c = s->dev.config;
|
||||
|
||||
/* 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_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
AUD_close_out(&s->card, s->voice_po);
|
||||
AUD_close_in(&s->card, s->voice_mc);
|
||||
AUD_remove_card(&s->card);
|
||||
memory_region_destroy (&s->io_nam);
|
||||
memory_region_destroy (&s->io_nabm);
|
||||
}
|
||||
|
||||
static int ac97_init (PCIBus *bus)
|
||||
|
@ -1404,7 +1420,7 @@ static int ac97_init (PCIBus *bus)
|
|||
}
|
||||
|
||||
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 (),
|
||||
};
|
||||
|
||||
|
@ -1423,13 +1439,13 @@ static void ac97_class_init (ObjectClass *klass, void *data)
|
|||
dc->desc = "Intel 82801AA AC97 Audio";
|
||||
dc->vmsd = &vmstate_ac97;
|
||||
dc->props = ac97_properties;
|
||||
dc->reset = ac97_on_reset;
|
||||
dc->reset = (DeviceReset)ac97_on_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo ac97_info = {
|
||||
.name = "AC97",
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof (AC97LinkState),
|
||||
.instance_size = sizeof (AC97DeviceState),
|
||||
.class_init = ac97_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
|
@ -1444,3 +1460,4 @@ static void ac97_register_types (void)
|
|||
}
|
||||
|
||||
type_init (ac97_register_types)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue