Message ID | 1299537165-16711-2-git-send-email-michael@walle.cc |
---|---|
State | New |
Headers | show |
On 03/07/2011 11:32 PM, Michael Walle wrote: > This patch adds support for the Milkymist AC97 compatible sound output and > input core. Malc, could you please take a look at this? :) > Signed-off-by: Michael Walle<michael@walle.cc> > --- > Makefile.target | 1 + > configure | 3 + > hw/milkymist-ac97.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++ > trace-events | 12 ++ > 4 files changed, 351 insertions(+), 0 deletions(-) > create mode 100644 hw/milkymist-ac97.c > > diff --git a/Makefile.target b/Makefile.target > index f0df98e..3be7868 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -256,6 +256,7 @@ obj-lm32-y += lm32_juart.o > obj-lm32-y += lm32_timer.o > obj-lm32-y += lm32_uart.o > obj-lm32-y += lm32_sys.o > +obj-lm32-y += milkymist-ac97.o > > obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o > obj-mips-y += mips_addr.o mips_timer.o mips_int.o > diff --git a/configure b/configure > index 5513d3e..e75e1a2 100755 > --- a/configure > +++ b/configure > @@ -3281,6 +3281,9 @@ if test "$target_softmmu" = "yes" ; then > arm) > cflags="-DHAS_AUDIO $cflags" > ;; > + lm32) > + cflags="-DHAS_AUDIO $cflags" > + ;; > i386|mips|ppc) > cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags" > ;; > diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c > new file mode 100644 > index 0000000..6c9e318 > --- /dev/null > +++ b/hw/milkymist-ac97.c > @@ -0,0 +1,335 @@ > +/* > + * QEMU model of the Milkymist System Controller. > + * > + * Copyright (c) 2010 Michael Walle<michael@walle.cc> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see<http://www.gnu.org/licenses/>. > + * > + * > + * Specification available at: > + * http://www.milkymist.org/socdoc/ac97.pdf > + */ > + > +#include "hw.h" > +#include "sysbus.h" > +#include "trace.h" > +#include "audio/audio.h" > +#include "qemu-error.h" > + > +enum { > + R_AC97_CTRL = 0, > + R_AC97_ADDR, > + R_AC97_DATAOUT, > + R_AC97_DATAIN, > + R_D_CTRL, > + R_D_ADDR, > + R_D_REMAINING, > + R_RESERVED, > + R_U_CTRL, > + R_U_ADDR, > + R_U_REMAINING, > + R_MAX > +}; > + > +enum { > + AC97_CTRL_RQEN = (1<<0), > + AC97_CTRL_WRITE = (1<<1), > +}; > + > +enum { > + CTRL_EN = (1<<0), > +}; > + > +struct MilkymistAC97State { > + SysBusDevice busdev; > + > + QEMUSoundCard card; > + SWVoiceIn *voice_in; > + SWVoiceOut *voice_out; > + > + uint32_t regs[R_MAX]; > + > + qemu_irq crrequest_irq; > + qemu_irq crreply_irq; > + qemu_irq dmar_irq; > + qemu_irq dmaw_irq; > +}; > +typedef struct MilkymistAC97State MilkymistAC97State; > + > +static void update_voices(MilkymistAC97State *s) > +{ > + if (s->regs[R_D_CTRL]& CTRL_EN) { > + AUD_set_active_out(s->voice_out, 1); > + } else { > + AUD_set_active_out(s->voice_out, 0); > + } > + > + if (s->regs[R_U_CTRL]& CTRL_EN) { > + AUD_set_active_in(s->voice_in, 1); > + } else { > + AUD_set_active_in(s->voice_in, 0); > + } > +} > + > +static uint32_t ac97_read(void *opaque, target_phys_addr_t addr) > +{ > + MilkymistAC97State *s = opaque; > + uint32_t r = 0; > + > + addr>>= 2; > + switch (addr) { > + case R_AC97_CTRL: > + case R_AC97_ADDR: > + case R_AC97_DATAOUT: > + case R_AC97_DATAIN: > + case R_D_CTRL: > + case R_D_ADDR: > + case R_D_REMAINING: > + case R_U_CTRL: > + case R_U_ADDR: > + case R_U_REMAINING: > + r = s->regs[addr]; > + break; > + > + default: > + error_report("milkymist_ac97: read access to unkown register 0x" > + TARGET_FMT_plx, addr<< 2); > + break; > + } > + > + trace_milkymist_ac97_memory_read(addr<< 2, r); > + > + return r; > +} > + > +static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value) > +{ > + MilkymistAC97State *s = opaque; > + > + trace_milkymist_ac97_memory_write(addr, value); > + > + addr>>= 2; > + switch (addr) { > + case R_AC97_CTRL: > + /* always raise an IRQ according to the direction */ > + if (value& AC97_CTRL_RQEN) { > + if (value& AC97_CTRL_WRITE) { > + trace_milkymist_ac97_pulse_irq_crrequest(); > + qemu_irq_pulse(s->crrequest_irq); > + } else { > + trace_milkymist_ac97_pulse_irq_crreply(); > + qemu_irq_pulse(s->crreply_irq); > + } > + } > + > + /* RQEN is self clearing */ > + s->regs[addr] = value& ~AC97_CTRL_RQEN; > + break; > + case R_D_CTRL: > + case R_U_CTRL: > + s->regs[addr] = value; > + update_voices(s); > + break; > + case R_AC97_ADDR: > + case R_AC97_DATAOUT: > + case R_AC97_DATAIN: > + case R_D_ADDR: > + case R_D_REMAINING: > + case R_U_ADDR: > + case R_U_REMAINING: > + s->regs[addr] = value; > + break; > + > + default: > + error_report("milkymist_ac97: write access to unkown register 0x" > + TARGET_FMT_plx, addr); > + break; > + } > + > +} > + > +static CPUReadMemoryFunc * const ac97_read_fn[] = { > + NULL, > + NULL, > +&ac97_read, > +}; > + > +static CPUWriteMemoryFunc * const ac97_write_fn[] = { > + NULL, > + NULL, > +&ac97_write, > +}; > + > +static void ac97_in_cb(void *opaque, int avail_b) > +{ > + MilkymistAC97State *s = opaque; > + uint8_t buf[4096]; > + uint32_t remaining = s->regs[R_U_REMAINING]; > + int temp = audio_MIN(remaining, avail_b); > + uint32_t addr = s->regs[R_U_ADDR]; > + int transferred = 0; > + > + trace_milkymist_ac97_in_cb(avail_b, remaining); > + > + /* prevent from raising an IRQ */ > + if (temp == 0) { > + return; > + } > + > + while (temp) { > + int acquired, to_copy; > + > + to_copy = audio_MIN(temp, sizeof(buf)); > + acquired = AUD_read(s->voice_in, buf, to_copy); > + if (!acquired) { > + break; > + } > + > + cpu_physical_memory_write(addr, buf, acquired); > + > + temp -= acquired; > + addr += acquired; > + transferred += acquired; > + } > + > + trace_milkymist_ac97_in_cb_transferred(transferred); > + > + s->regs[R_U_ADDR] = addr; > + s->regs[R_U_REMAINING] -= transferred; > + > + if ((s->regs[R_U_CTRL]& CTRL_EN)&& (s->regs[R_U_REMAINING] == 0)) { > + trace_milkymist_ac97_pulse_irq_dmaw(); > + qemu_irq_pulse(s->dmaw_irq); > + } > +} > + > +static void ac97_out_cb(void *opaque, int free_b) > +{ > + MilkymistAC97State *s = opaque; > + uint8_t buf[4096]; > + uint32_t remaining = s->regs[R_D_REMAINING]; > + int temp = audio_MIN(remaining, free_b); > + uint32_t addr = s->regs[R_D_ADDR]; > + int transferred = 0; > + > + trace_milkymist_ac97_out_cb(free_b, remaining); > + > + /* prevent from raising an IRQ */ > + if (temp == 0) { > + return; > + } > + > + while (temp) { > + int copied, to_copy; > + > + to_copy = audio_MIN(temp, sizeof(buf)); > + cpu_physical_memory_read(addr, buf, to_copy); > + copied = AUD_write(s->voice_out, buf, to_copy); > + if (!copied) { > + break; > + } > + temp -= copied; > + addr += copied; > + transferred += copied; > + } > + > + trace_milkymist_ac97_out_cb_transferred(transferred); > + > + s->regs[R_D_ADDR] = addr; > + s->regs[R_D_REMAINING] -= transferred; > + > + if ((s->regs[R_D_CTRL]& CTRL_EN)&& (s->regs[R_D_REMAINING] == 0)) { > + trace_milkymist_ac97_pulse_irq_dmar(); > + qemu_irq_pulse(s->dmar_irq); > + } > +} > + > +static void milkymist_ac97_reset(DeviceState *d) > +{ > + MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev); > + int i; > + > + for (i = 0; i< R_MAX; i++) { > + s->regs[i] = 0; > + } > + > + AUD_set_active_in(s->voice_in, 0); > + AUD_set_active_out(s->voice_out, 0); > +} > + > +static int ac97_post_load(void *opaque, int version_id) > +{ > + MilkymistAC97State *s = opaque; > + > + update_voices(s); > + > + return 0; > +} > + > +static int milkymist_ac97_init(SysBusDevice *dev) > +{ > + MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev); > + int ac97_regs; > + > + struct audsettings as; > + sysbus_init_irq(dev,&s->crrequest_irq); > + sysbus_init_irq(dev,&s->crreply_irq); > + sysbus_init_irq(dev,&s->dmar_irq); > + sysbus_init_irq(dev,&s->dmaw_irq); > + > + AUD_register_card("Milkymist AC'97",&s->card); > + > + as.freq = 48000; > + as.nchannels = 2; > + as.fmt = AUD_FMT_S16; > + as.endianness = 1; > + > + s->voice_in = AUD_open_in(&s->card, s->voice_in, > + "mm_ac97.in", s, ac97_in_cb,&as); > + s->voice_out = AUD_open_out(&s->card, s->voice_out, > + "mm_ac97.out", s, ac97_out_cb,&as); > + > + ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s, > + DEVICE_NATIVE_ENDIAN); > + sysbus_init_mmio(dev, R_MAX * 4, ac97_regs); > + > + return 0; > +} > + > +static const VMStateDescription vmstate_milkymist_ac97 = { > + .name = "milkymist-ac97", > + .version_id = 1, > + .minimum_version_id = 1, > + .minimum_version_id_old = 1, > + .post_load = ac97_post_load, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static SysBusDeviceInfo milkymist_ac97_info = { > + .init = milkymist_ac97_init, > + .qdev.name = "milkymist-ac97", > + .qdev.size = sizeof(MilkymistAC97State), > + .qdev.vmsd =&vmstate_milkymist_ac97, > + .qdev.reset = milkymist_ac97_reset, > +}; > + > +static void milkymist_ac97_register(void) > +{ > + sysbus_register_withprop(&milkymist_ac97_info); > +} > + > +device_init(milkymist_ac97_register) > diff --git a/trace-events b/trace-events > index c791719..9241ac9 100644 > --- a/trace-events > +++ b/trace-events > @@ -283,3 +283,15 @@ disable lm32_uart_irq_state(int level) "irq state %d" > > # hw/lm32_sys.c > disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" > + > +# hw/milkymist-ac97.c > +disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" > +disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" > +disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" > +disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" > +disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" > +disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" > +disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u" > +disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" > +disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" > +disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
On Wed, 16 Mar 2011, Alexander Graf wrote: > On 03/07/2011 11:32 PM, Michael Walle wrote: > > This patch adds support for the Milkymist AC97 compatible sound output and > > input core. > > Malc, could you please take a look at this? :) Okay... > > > Signed-off-by: Michael Walle<michael@walle.cc> > > --- > > Makefile.target | 1 + > > configure | 3 + > > hw/milkymist-ac97.c | 335 > > +++++++++++++++++++++++++++++++++++++++++++++++++++ > > trace-events | 12 ++ > > 4 files changed, 351 insertions(+), 0 deletions(-) > > create mode 100644 hw/milkymist-ac97.c > > > > diff --git a/Makefile.target b/Makefile.target > > index f0df98e..3be7868 100644 > > --- a/Makefile.target > > +++ b/Makefile.target > > @@ -256,6 +256,7 @@ obj-lm32-y += lm32_juart.o > > obj-lm32-y += lm32_timer.o > > obj-lm32-y += lm32_uart.o > > obj-lm32-y += lm32_sys.o > > +obj-lm32-y += milkymist-ac97.o > > > > obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o > > obj-mips-y += mips_addr.o mips_timer.o mips_int.o > > diff --git a/configure b/configure > > index 5513d3e..e75e1a2 100755 > > --- a/configure > > +++ b/configure > > @@ -3281,6 +3281,9 @@ if test "$target_softmmu" = "yes" ; then > > arm) > > cflags="-DHAS_AUDIO $cflags" > > ;; > > + lm32) > > + cflags="-DHAS_AUDIO $cflags" > > + ;; > > i386|mips|ppc) > > cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags" > > ;; > > diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c > > new file mode 100644 > > index 0000000..6c9e318 > > --- /dev/null > > +++ b/hw/milkymist-ac97.c > > @@ -0,0 +1,335 @@ > > +/* > > + * QEMU model of the Milkymist System Controller. > > + * > > + * Copyright (c) 2010 Michael Walle<michael@walle.cc> > > + * > > + * This library is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU Lesser General Public > > + * License as published by the Free Software Foundation; either > > + * version 2 of the License, or (at your option) any later version. > > + * > > + * This library is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + * Lesser General Public License for more details. > > + * > > + * You should have received a copy of the GNU Lesser General Public > > + * License along with this library; if not, > > see<http://www.gnu.org/licenses/>. > > + * > > + * > > + * Specification available at: > > + * http://www.milkymist.org/socdoc/ac97.pdf > > + */ > > + > > +#include "hw.h" > > +#include "sysbus.h" > > +#include "trace.h" > > +#include "audio/audio.h" > > +#include "qemu-error.h" > > + > > +enum { > > + R_AC97_CTRL = 0, Unneeded.. > > + R_AC97_ADDR, > > + R_AC97_DATAOUT, > > + R_AC97_DATAIN, > > + R_D_CTRL, > > + R_D_ADDR, > > + R_D_REMAINING, > > + R_RESERVED, > > + R_U_CTRL, > > + R_U_ADDR, > > + R_U_REMAINING, > > + R_MAX > > +}; > > + > > +enum { > > + AC97_CTRL_RQEN = (1<<0), Oookay.. > > + AC97_CTRL_WRITE = (1<<1), Incinsistent(with previous enum formatting) comma (and C99 only at that) > > +}; > > + > > +enum { > > + CTRL_EN = (1<<0), Ditto x2 > > +}; > > + > > +struct MilkymistAC97State { > > + SysBusDevice busdev; > > + > > + QEMUSoundCard card; > > + SWVoiceIn *voice_in; > > + SWVoiceOut *voice_out; > > + > > + uint32_t regs[R_MAX]; > > + > > + qemu_irq crrequest_irq; > > + qemu_irq crreply_irq; > > + qemu_irq dmar_irq; > > + qemu_irq dmaw_irq; > > +}; > > +typedef struct MilkymistAC97State MilkymistAC97State; > > + > > +static void update_voices(MilkymistAC97State *s) > > +{ > > + if (s->regs[R_D_CTRL]& CTRL_EN) { Space before ampersand would be nice. > > + AUD_set_active_out(s->voice_out, 1); > > + } else { > > + AUD_set_active_out(s->voice_out, 0); > > + } > > + > > + if (s->regs[R_U_CTRL]& CTRL_EN) { > > + AUD_set_active_in(s->voice_in, 1); > > + } else { > > + AUD_set_active_in(s->voice_in, 0); > > + } > > +} > > + > > +static uint32_t ac97_read(void *opaque, target_phys_addr_t addr) > > +{ > > + MilkymistAC97State *s = opaque; > > + uint32_t r = 0; > > + > > + addr>>= 2; Again space here and elsewhere. > > + switch (addr) { > > + case R_AC97_CTRL: > > + case R_AC97_ADDR: > > + case R_AC97_DATAOUT: > > + case R_AC97_DATAIN: > > + case R_D_CTRL: > > + case R_D_ADDR: > > + case R_D_REMAINING: > > + case R_U_CTRL: > > + case R_U_ADDR: > > + case R_U_REMAINING: > > + r = s->regs[addr]; > > + break; > > + > > + default: > > + error_report("milkymist_ac97: read access to unkown register 0x" > > + TARGET_FMT_plx, addr<< 2); > > + break; > > + } > > + > > + trace_milkymist_ac97_memory_read(addr<< 2, r); > > + > > + return r; > > +} > > + > > +static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t > > value) > > +{ > > + MilkymistAC97State *s = opaque; > > + > > + trace_milkymist_ac97_memory_write(addr, value); > > + > > + addr>>= 2; > > + switch (addr) { > > + case R_AC97_CTRL: > > + /* always raise an IRQ according to the direction */ > > + if (value& AC97_CTRL_RQEN) { > > + if (value& AC97_CTRL_WRITE) { > > + trace_milkymist_ac97_pulse_irq_crrequest(); > > + qemu_irq_pulse(s->crrequest_irq); > > + } else { > > + trace_milkymist_ac97_pulse_irq_crreply(); > > + qemu_irq_pulse(s->crreply_irq); > > + } > > + } > > + > > + /* RQEN is self clearing */ > > + s->regs[addr] = value& ~AC97_CTRL_RQEN; > > + break; > > + case R_D_CTRL: > > + case R_U_CTRL: > > + s->regs[addr] = value; > > + update_voices(s); > > + break; > > + case R_AC97_ADDR: > > + case R_AC97_DATAOUT: > > + case R_AC97_DATAIN: > > + case R_D_ADDR: > > + case R_D_REMAINING: > > + case R_U_ADDR: > > + case R_U_REMAINING: > > + s->regs[addr] = value; > > + break; > > + > > + default: > > + error_report("milkymist_ac97: write access to unkown register 0x" > > + TARGET_FMT_plx, addr); > > + break; > > + } > > + > > +} > > + > > +static CPUReadMemoryFunc * const ac97_read_fn[] = { > > + NULL, > > + NULL, > > +&ac97_read, > > +}; > > + > > +static CPUWriteMemoryFunc * const ac97_write_fn[] = { > > + NULL, > > + NULL, > > +&ac97_write, > > +}; > > + > > +static void ac97_in_cb(void *opaque, int avail_b) > > +{ > > + MilkymistAC97State *s = opaque; > > + uint8_t buf[4096]; > > + uint32_t remaining = s->regs[R_U_REMAINING]; > > + int temp = audio_MIN(remaining, avail_b); > > + uint32_t addr = s->regs[R_U_ADDR]; > > + int transferred = 0; > > + > > + trace_milkymist_ac97_in_cb(avail_b, remaining); > > + > > + /* prevent from raising an IRQ */ > > + if (temp == 0) { > > + return; > > + } > > + > > + while (temp) { > > + int acquired, to_copy; > > + > > + to_copy = audio_MIN(temp, sizeof(buf)); > > + acquired = AUD_read(s->voice_in, buf, to_copy); > > + if (!acquired) { > > + break; > > + } > > + > > + cpu_physical_memory_write(addr, buf, acquired); > > + > > + temp -= acquired; > > + addr += acquired; > > + transferred += acquired; > > + } > > + > > + trace_milkymist_ac97_in_cb_transferred(transferred); > > + > > + s->regs[R_U_ADDR] = addr; > > + s->regs[R_U_REMAINING] -= transferred; > > + > > + if ((s->regs[R_U_CTRL]& CTRL_EN)&& (s->regs[R_U_REMAINING] == 0)) { > > + trace_milkymist_ac97_pulse_irq_dmaw(); > > + qemu_irq_pulse(s->dmaw_irq); > > + } > > +} > > + > > +static void ac97_out_cb(void *opaque, int free_b) > > +{ > > + MilkymistAC97State *s = opaque; > > + uint8_t buf[4096]; > > + uint32_t remaining = s->regs[R_D_REMAINING]; > > + int temp = audio_MIN(remaining, free_b); > > + uint32_t addr = s->regs[R_D_ADDR]; > > + int transferred = 0; > > + > > + trace_milkymist_ac97_out_cb(free_b, remaining); > > + > > + /* prevent from raising an IRQ */ > > + if (temp == 0) { > > + return; > > + } > > + > > + while (temp) { > > + int copied, to_copy; > > + > > + to_copy = audio_MIN(temp, sizeof(buf)); > > + cpu_physical_memory_read(addr, buf, to_copy); > > + copied = AUD_write(s->voice_out, buf, to_copy); > > + if (!copied) { > > + break; > > + } > > + temp -= copied; > > + addr += copied; > > + transferred += copied; > > + } > > + > > + trace_milkymist_ac97_out_cb_transferred(transferred); > > + > > + s->regs[R_D_ADDR] = addr; > > + s->regs[R_D_REMAINING] -= transferred; > > + > > + if ((s->regs[R_D_CTRL]& CTRL_EN)&& (s->regs[R_D_REMAINING] == 0)) { > > + trace_milkymist_ac97_pulse_irq_dmar(); > > + qemu_irq_pulse(s->dmar_irq); > > + } > > +} > > + > > +static void milkymist_ac97_reset(DeviceState *d) > > +{ > > + MilkymistAC97State *s = container_of(d, MilkymistAC97State, > > busdev.qdev); > > + int i; > > + > > + for (i = 0; i< R_MAX; i++) { > > + s->regs[i] = 0; > > + } > > + > > + AUD_set_active_in(s->voice_in, 0); > > + AUD_set_active_out(s->voice_out, 0); > > +} > > + > > +static int ac97_post_load(void *opaque, int version_id) > > +{ > > + MilkymistAC97State *s = opaque; > > + > > + update_voices(s); > > + > > + return 0; > > +} > > + > > +static int milkymist_ac97_init(SysBusDevice *dev) > > +{ > > + MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev); > > + int ac97_regs; > > + > > + struct audsettings as; > > + sysbus_init_irq(dev,&s->crrequest_irq); > > + sysbus_init_irq(dev,&s->crreply_irq); > > + sysbus_init_irq(dev,&s->dmar_irq); > > + sysbus_init_irq(dev,&s->dmaw_irq); > > + > > + AUD_register_card("Milkymist AC'97",&s->card); > > + > > + as.freq = 48000; > > + as.nchannels = 2; > > + as.fmt = AUD_FMT_S16; > > + as.endianness = 1; > > + > > + s->voice_in = AUD_open_in(&s->card, s->voice_in, > > + "mm_ac97.in", s, ac97_in_cb,&as); > > + s->voice_out = AUD_open_out(&s->card, s->voice_out, > > + "mm_ac97.out", s, ac97_out_cb,&as); > > + > > + ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s, > > + DEVICE_NATIVE_ENDIAN); > > + sysbus_init_mmio(dev, R_MAX * 4, ac97_regs); > > + > > + return 0; > > +} > > + > > +static const VMStateDescription vmstate_milkymist_ac97 = { > > + .name = "milkymist-ac97", > > + .version_id = 1, > > + .minimum_version_id = 1, > > + .minimum_version_id_old = 1, > > + .post_load = ac97_post_load, > > + .fields = (VMStateField[]) { > > + VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX), > > + VMSTATE_END_OF_LIST() > > + } > > +}; > > + > > +static SysBusDeviceInfo milkymist_ac97_info = { > > + .init = milkymist_ac97_init, > > + .qdev.name = "milkymist-ac97", > > + .qdev.size = sizeof(MilkymistAC97State), > > + .qdev.vmsd =&vmstate_milkymist_ac97, > > + .qdev.reset = milkymist_ac97_reset, > > +}; > > + > > +static void milkymist_ac97_register(void) > > +{ > > + sysbus_register_withprop(&milkymist_ac97_info); > > +} > > + > > +device_init(milkymist_ac97_register) > > diff --git a/trace-events b/trace-events > > index c791719..9241ac9 100644 > > --- a/trace-events > > +++ b/trace-events > > @@ -283,3 +283,15 @@ disable lm32_uart_irq_state(int level) "irq state %d" > > > > # hw/lm32_sys.c > > disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x > > value 0x%08x" > > + > > +# hw/milkymist-ac97.c > > +disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr > > %08x value %08x" > > +disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr > > %08x value %08x" > > +disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" > > +disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" > > +disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" > > +disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" > > +disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d > > remaining %u" > > +disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" > > +disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d > > remaining %u" > > +disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d" > IOW looks good to me.
Am Mittwoch 16 März 2011, 19:12:44 schrieb malc: > > > diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c > > > new file mode 100644 > > > index 0000000..6c9e318 > > > --- /dev/null > > > +++ b/hw/milkymist-ac97.c > > > @@ -0,0 +1,335 @@ > > > +/* > > > + * QEMU model of the Milkymist System Controller. > > > + * > > > + * Copyright (c) 2010 Michael Walle<michael@walle.cc> > > > + * > > > + * This library is free software; you can redistribute it and/or > > > + * modify it under the terms of the GNU Lesser General Public > > > + * License as published by the Free Software Foundation; either > > > + * version 2 of the License, or (at your option) any later version. > > > + * > > > + * This library is distributed in the hope that it will be useful, > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > + * Lesser General Public License for more details. > > > + * > > > + * You should have received a copy of the GNU Lesser General Public > > > + * License along with this library; if not, > > > see<http://www.gnu.org/licenses/>. > > > + * > > > + * > > > + * Specification available at: > > > + * http://www.milkymist.org/socdoc/ac97.pdf > > > + */ > > > + > > > +#include "hw.h" > > > +#include "sysbus.h" > > > +#include "trace.h" > > > +#include "audio/audio.h" > > > +#include "qemu-error.h" > > > + > > > +enum { > > > + R_AC97_CTRL = 0, > > Unneeded.. I wanted to point out, that the registers begin at offset 0. If i change this, i'll need to change all other models, too. Including the ones that have been committed. > > > + R_AC97_ADDR, > > > + R_AC97_DATAOUT, > > > + R_AC97_DATAIN, > > > + R_D_CTRL, > > > + R_D_ADDR, > > > + R_D_REMAINING, > > > + R_RESERVED, > > > + R_U_CTRL, > > > + R_U_ADDR, > > > + R_U_REMAINING, > > > + R_MAX > > > +}; > > > + > > > +enum { > > > + AC97_CTRL_RQEN = (1<<0), > > Oookay.. > > > > + AC97_CTRL_WRITE = (1<<1), > > Incinsistent(with previous enum formatting) comma (and C99 only at that) > > > > +}; > > > + > > > +enum { > > > + CTRL_EN = (1<<0), > > Ditto x2 Ok, but it has a hidden agenda. R_MAX must always be the last entry, therefore i omitted the comma. Whereas the bit flags could still be extended. Again if this is a concern for you, i'll change that and all other models too. > > > +}; > > > + > > > +struct MilkymistAC97State { > > > + SysBusDevice busdev; > > > + > > > + QEMUSoundCard card; > > > + SWVoiceIn *voice_in; > > > + SWVoiceOut *voice_out; > > > + > > > + uint32_t regs[R_MAX]; > > > + > > > + qemu_irq crrequest_irq; > > > + qemu_irq crreply_irq; > > > + qemu_irq dmar_irq; > > > + qemu_irq dmaw_irq; > > > +}; > > > +typedef struct MilkymistAC97State MilkymistAC97State; > > > + > > > +static void update_voices(MilkymistAC97State *s) > > > +{ > > > + if (s->regs[R_D_CTRL]& CTRL_EN) { > > Space before ampersand would be nice. mh i think Alex email client messed this up. At least for me, there is one space before and one space after the ampersand in my original email.
On 17.03.2011, at 00:02, Michael Walle <michael@walle.cc> wrote: > Am Mittwoch 16 März 2011, 19:12:44 schrieb malc: >>>> diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c >>>> new file mode 100644 >>>> index 0000000..6c9e318 >>>> --- /dev/null >>>> +++ b/hw/milkymist-ac97.c >>>> @@ -0,0 +1,335 @@ >>>> +/* >>>> + * QEMU model of the Milkymist System Controller. >>>> + * >>>> + * Copyright (c) 2010 Michael Walle<michael@walle.cc> >>>> + * >>>> + * This library is free software; you can redistribute it and/or >>>> + * modify it under the terms of the GNU Lesser General Public >>>> + * License as published by the Free Software Foundation; either >>>> + * version 2 of the License, or (at your option) any later version. >>>> + * >>>> + * This library is distributed in the hope that it will be useful, >>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>>> + * Lesser General Public License for more details. >>>> + * >>>> + * You should have received a copy of the GNU Lesser General Public >>>> + * License along with this library; if not, >>>> see<http://www.gnu.org/licenses/>. >>>> + * >>>> + * >>>> + * Specification available at: >>>> + * http://www.milkymist.org/socdoc/ac97.pdf >>>> + */ >>>> + >>>> +#include "hw.h" >>>> +#include "sysbus.h" >>>> +#include "trace.h" >>>> +#include "audio/audio.h" >>>> +#include "qemu-error.h" >>>> + >>>> +enum { >>>> + R_AC97_CTRL = 0, >> >> Unneeded.. > I wanted to point out, that the registers begin at offset 0. If i change this, > i'll need to change all other models, too. Including the ones that have been > committed. > >>>> + R_AC97_ADDR, >>>> + R_AC97_DATAOUT, >>>> + R_AC97_DATAIN, >>>> + R_D_CTRL, >>>> + R_D_ADDR, >>>> + R_D_REMAINING, >>>> + R_RESERVED, >>>> + R_U_CTRL, >>>> + R_U_ADDR, >>>> + R_U_REMAINING, >>>> + R_MAX >>>> +}; >>>> + >>>> +enum { >>>> + AC97_CTRL_RQEN = (1<<0), >> >> Oookay.. >> >>>> + AC97_CTRL_WRITE = (1<<1), >> >> Incinsistent(with previous enum formatting) comma (and C99 only at that) >> >>>> +}; >>>> + >>>> +enum { >>>> + CTRL_EN = (1<<0), >> >> Ditto x2 > Ok, but it has a hidden agenda. R_MAX must always be the last entry, therefore > i omitted the comma. Whereas the bit flags could still be extended. Again if > this is a concern for you, i'll change that and all other models too. > >>>> +}; >>>> + >>>> +struct MilkymistAC97State { >>>> + SysBusDevice busdev; >>>> + >>>> + QEMUSoundCard card; >>>> + SWVoiceIn *voice_in; >>>> + SWVoiceOut *voice_out; >>>> + >>>> + uint32_t regs[R_MAX]; >>>> + >>>> + qemu_irq crrequest_irq; >>>> + qemu_irq crreply_irq; >>>> + qemu_irq dmar_irq; >>>> + qemu_irq dmaw_irq; >>>> +}; >>>> +typedef struct MilkymistAC97State MilkymistAC97State; >>>> + >>>> +static void update_voices(MilkymistAC97State *s) >>>> +{ >>>> + if (s->regs[R_D_CTRL]& CTRL_EN) { >> >> Space before ampersand would be nice. > mh i think Alex email client messed this up. At least for me, there is one > space before and one space after the ampersand in my original email. Yes, thunderbird breaks those. Sorry :). Alex > > -- > Michael
On Thu, 17 Mar 2011, Michael Walle wrote: > Am Mittwoch 16 M?rz 2011, 19:12:44 schrieb malc: > > > > diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c > > > > new file mode 100644 > > > > index 0000000..6c9e318 > > > > --- /dev/null > > > > +++ b/hw/milkymist-ac97.c > > > > @@ -0,0 +1,335 @@ > > > > +/* > > > > + * QEMU model of the Milkymist System Controller. > > > > + * > > > > + * Copyright (c) 2010 Michael Walle<michael@walle.cc> > > > > + * > > > > + * This library is free software; you can redistribute it and/or > > > > + * modify it under the terms of the GNU Lesser General Public > > > > + * License as published by the Free Software Foundation; either > > > > + * version 2 of the License, or (at your option) any later version. > > > > + * > > > > + * This library is distributed in the hope that it will be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > > + * Lesser General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU Lesser General Public > > > > + * License along with this library; if not, > > > > see<http://www.gnu.org/licenses/>. > > > > + * > > > > + * > > > > + * Specification available at: > > > > + * http://www.milkymist.org/socdoc/ac97.pdf > > > > + */ > > > > + > > > > +#include "hw.h" > > > > +#include "sysbus.h" > > > > +#include "trace.h" > > > > +#include "audio/audio.h" > > > > +#include "qemu-error.h" > > > > + > > > > +enum { > > > > + R_AC97_CTRL = 0, > > > > Unneeded.. > I wanted to point out, that the registers begin at offset 0. If i change > this, i'll need to change all other models, too. Including the ones that > have been committed. And i just wanted to nitpick that it would be zero even without '= 0' part (6.7.2.2#3 of ISO/IEC 9899:201x) > > > > > + R_AC97_ADDR, > > > > + R_AC97_DATAOUT, > > > > + R_AC97_DATAIN, > > > > + R_D_CTRL, > > > > + R_D_ADDR, > > > > + R_D_REMAINING, > > > > + R_RESERVED, > > > > + R_U_CTRL, > > > > + R_U_ADDR, > > > > + R_U_REMAINING, > > > > + R_MAX > > > > +}; > > > > + > > > > +enum { > > > > + AC97_CTRL_RQEN = (1<<0), > > > > Oookay.. > > > > > > + AC97_CTRL_WRITE = (1<<1), > > > > Incinsistent(with previous enum formatting) comma (and C99 only at that) > > > > > > +}; > > > > + > > > > +enum { > > > > + CTRL_EN = (1<<0), > > > > Ditto x2 > Ok, but it has a hidden agenda. R_MAX must always be the last entry, therefore > i omitted the comma. Whereas the bit flags could still be extended. Again if > this is a concern for you, i'll change that and all other models too. > > > > > +}; > > > > + > > > > +struct MilkymistAC97State { > > > > + SysBusDevice busdev; > > > > + > > > > + QEMUSoundCard card; > > > > + SWVoiceIn *voice_in; > > > > + SWVoiceOut *voice_out; > > > > + > > > > + uint32_t regs[R_MAX]; > > > > + > > > > + qemu_irq crrequest_irq; > > > > + qemu_irq crreply_irq; > > > > + qemu_irq dmar_irq; > > > > + qemu_irq dmaw_irq; > > > > +}; > > > > +typedef struct MilkymistAC97State MilkymistAC97State; > > > > + > > > > +static void update_voices(MilkymistAC97State *s) > > > > +{ > > > > + if (s->regs[R_D_CTRL]& CTRL_EN) { > > > > Space before ampersand would be nice. > mh i think Alex email client messed this up. At least for me, there is one > space before and one space after the ampersand in my original email. > Sorry for the noise then. (to Alexander: real men don't use crap MUA you use)
diff --git a/Makefile.target b/Makefile.target index f0df98e..3be7868 100644 --- a/Makefile.target +++ b/Makefile.target @@ -256,6 +256,7 @@ obj-lm32-y += lm32_juart.o obj-lm32-y += lm32_timer.o obj-lm32-y += lm32_uart.o obj-lm32-y += lm32_sys.o +obj-lm32-y += milkymist-ac97.o obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o obj-mips-y += mips_addr.o mips_timer.o mips_int.o diff --git a/configure b/configure index 5513d3e..e75e1a2 100755 --- a/configure +++ b/configure @@ -3281,6 +3281,9 @@ if test "$target_softmmu" = "yes" ; then arm) cflags="-DHAS_AUDIO $cflags" ;; + lm32) + cflags="-DHAS_AUDIO $cflags" + ;; i386|mips|ppc) cflags="-DHAS_AUDIO -DHAS_AUDIO_CHOICE $cflags" ;; diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c new file mode 100644 index 0000000..6c9e318 --- /dev/null +++ b/hw/milkymist-ac97.c @@ -0,0 +1,335 @@ +/* + * QEMU model of the Milkymist System Controller. + * + * Copyright (c) 2010 Michael Walle <michael@walle.cc> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * + * Specification available at: + * http://www.milkymist.org/socdoc/ac97.pdf + */ + +#include "hw.h" +#include "sysbus.h" +#include "trace.h" +#include "audio/audio.h" +#include "qemu-error.h" + +enum { + R_AC97_CTRL = 0, + R_AC97_ADDR, + R_AC97_DATAOUT, + R_AC97_DATAIN, + R_D_CTRL, + R_D_ADDR, + R_D_REMAINING, + R_RESERVED, + R_U_CTRL, + R_U_ADDR, + R_U_REMAINING, + R_MAX +}; + +enum { + AC97_CTRL_RQEN = (1<<0), + AC97_CTRL_WRITE = (1<<1), +}; + +enum { + CTRL_EN = (1<<0), +}; + +struct MilkymistAC97State { + SysBusDevice busdev; + + QEMUSoundCard card; + SWVoiceIn *voice_in; + SWVoiceOut *voice_out; + + uint32_t regs[R_MAX]; + + qemu_irq crrequest_irq; + qemu_irq crreply_irq; + qemu_irq dmar_irq; + qemu_irq dmaw_irq; +}; +typedef struct MilkymistAC97State MilkymistAC97State; + +static void update_voices(MilkymistAC97State *s) +{ + if (s->regs[R_D_CTRL] & CTRL_EN) { + AUD_set_active_out(s->voice_out, 1); + } else { + AUD_set_active_out(s->voice_out, 0); + } + + if (s->regs[R_U_CTRL] & CTRL_EN) { + AUD_set_active_in(s->voice_in, 1); + } else { + AUD_set_active_in(s->voice_in, 0); + } +} + +static uint32_t ac97_read(void *opaque, target_phys_addr_t addr) +{ + MilkymistAC97State *s = opaque; + uint32_t r = 0; + + addr >>= 2; + switch (addr) { + case R_AC97_CTRL: + case R_AC97_ADDR: + case R_AC97_DATAOUT: + case R_AC97_DATAIN: + case R_D_CTRL: + case R_D_ADDR: + case R_D_REMAINING: + case R_U_CTRL: + case R_U_ADDR: + case R_U_REMAINING: + r = s->regs[addr]; + break; + + default: + error_report("milkymist_ac97: read access to unkown register 0x" + TARGET_FMT_plx, addr << 2); + break; + } + + trace_milkymist_ac97_memory_read(addr << 2, r); + + return r; +} + +static void ac97_write(void *opaque, target_phys_addr_t addr, uint32_t value) +{ + MilkymistAC97State *s = opaque; + + trace_milkymist_ac97_memory_write(addr, value); + + addr >>= 2; + switch (addr) { + case R_AC97_CTRL: + /* always raise an IRQ according to the direction */ + if (value & AC97_CTRL_RQEN) { + if (value & AC97_CTRL_WRITE) { + trace_milkymist_ac97_pulse_irq_crrequest(); + qemu_irq_pulse(s->crrequest_irq); + } else { + trace_milkymist_ac97_pulse_irq_crreply(); + qemu_irq_pulse(s->crreply_irq); + } + } + + /* RQEN is self clearing */ + s->regs[addr] = value & ~AC97_CTRL_RQEN; + break; + case R_D_CTRL: + case R_U_CTRL: + s->regs[addr] = value; + update_voices(s); + break; + case R_AC97_ADDR: + case R_AC97_DATAOUT: + case R_AC97_DATAIN: + case R_D_ADDR: + case R_D_REMAINING: + case R_U_ADDR: + case R_U_REMAINING: + s->regs[addr] = value; + break; + + default: + error_report("milkymist_ac97: write access to unkown register 0x" + TARGET_FMT_plx, addr); + break; + } + +} + +static CPUReadMemoryFunc * const ac97_read_fn[] = { + NULL, + NULL, + &ac97_read, +}; + +static CPUWriteMemoryFunc * const ac97_write_fn[] = { + NULL, + NULL, + &ac97_write, +}; + +static void ac97_in_cb(void *opaque, int avail_b) +{ + MilkymistAC97State *s = opaque; + uint8_t buf[4096]; + uint32_t remaining = s->regs[R_U_REMAINING]; + int temp = audio_MIN(remaining, avail_b); + uint32_t addr = s->regs[R_U_ADDR]; + int transferred = 0; + + trace_milkymist_ac97_in_cb(avail_b, remaining); + + /* prevent from raising an IRQ */ + if (temp == 0) { + return; + } + + while (temp) { + int acquired, to_copy; + + to_copy = audio_MIN(temp, sizeof(buf)); + acquired = AUD_read(s->voice_in, buf, to_copy); + if (!acquired) { + break; + } + + cpu_physical_memory_write(addr, buf, acquired); + + temp -= acquired; + addr += acquired; + transferred += acquired; + } + + trace_milkymist_ac97_in_cb_transferred(transferred); + + s->regs[R_U_ADDR] = addr; + s->regs[R_U_REMAINING] -= transferred; + + if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) { + trace_milkymist_ac97_pulse_irq_dmaw(); + qemu_irq_pulse(s->dmaw_irq); + } +} + +static void ac97_out_cb(void *opaque, int free_b) +{ + MilkymistAC97State *s = opaque; + uint8_t buf[4096]; + uint32_t remaining = s->regs[R_D_REMAINING]; + int temp = audio_MIN(remaining, free_b); + uint32_t addr = s->regs[R_D_ADDR]; + int transferred = 0; + + trace_milkymist_ac97_out_cb(free_b, remaining); + + /* prevent from raising an IRQ */ + if (temp == 0) { + return; + } + + while (temp) { + int copied, to_copy; + + to_copy = audio_MIN(temp, sizeof(buf)); + cpu_physical_memory_read(addr, buf, to_copy); + copied = AUD_write(s->voice_out, buf, to_copy); + if (!copied) { + break; + } + temp -= copied; + addr += copied; + transferred += copied; + } + + trace_milkymist_ac97_out_cb_transferred(transferred); + + s->regs[R_D_ADDR] = addr; + s->regs[R_D_REMAINING] -= transferred; + + if ((s->regs[R_D_CTRL] & CTRL_EN) && (s->regs[R_D_REMAINING] == 0)) { + trace_milkymist_ac97_pulse_irq_dmar(); + qemu_irq_pulse(s->dmar_irq); + } +} + +static void milkymist_ac97_reset(DeviceState *d) +{ + MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev); + int i; + + for (i = 0; i < R_MAX; i++) { + s->regs[i] = 0; + } + + AUD_set_active_in(s->voice_in, 0); + AUD_set_active_out(s->voice_out, 0); +} + +static int ac97_post_load(void *opaque, int version_id) +{ + MilkymistAC97State *s = opaque; + + update_voices(s); + + return 0; +} + +static int milkymist_ac97_init(SysBusDevice *dev) +{ + MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev); + int ac97_regs; + + struct audsettings as; + sysbus_init_irq(dev, &s->crrequest_irq); + sysbus_init_irq(dev, &s->crreply_irq); + sysbus_init_irq(dev, &s->dmar_irq); + sysbus_init_irq(dev, &s->dmaw_irq); + + AUD_register_card("Milkymist AC'97", &s->card); + + as.freq = 48000; + as.nchannels = 2; + as.fmt = AUD_FMT_S16; + as.endianness = 1; + + s->voice_in = AUD_open_in(&s->card, s->voice_in, + "mm_ac97.in", s, ac97_in_cb, &as); + s->voice_out = AUD_open_out(&s->card, s->voice_out, + "mm_ac97.out", s, ac97_out_cb, &as); + + ac97_regs = cpu_register_io_memory(ac97_read_fn, ac97_write_fn, s, + DEVICE_NATIVE_ENDIAN); + sysbus_init_mmio(dev, R_MAX * 4, ac97_regs); + + return 0; +} + +static const VMStateDescription vmstate_milkymist_ac97 = { + .name = "milkymist-ac97", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = ac97_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX), + VMSTATE_END_OF_LIST() + } +}; + +static SysBusDeviceInfo milkymist_ac97_info = { + .init = milkymist_ac97_init, + .qdev.name = "milkymist-ac97", + .qdev.size = sizeof(MilkymistAC97State), + .qdev.vmsd = &vmstate_milkymist_ac97, + .qdev.reset = milkymist_ac97_reset, +}; + +static void milkymist_ac97_register(void) +{ + sysbus_register_withprop(&milkymist_ac97_info); +} + +device_init(milkymist_ac97_register) diff --git a/trace-events b/trace-events index c791719..9241ac9 100644 --- a/trace-events +++ b/trace-events @@ -283,3 +283,15 @@ disable lm32_uart_irq_state(int level) "irq state %d" # hw/lm32_sys.c disable lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" + +# hw/milkymist-ac97.c +disable milkymist_ac97_memory_read(uint32_t addr, uint32_t value) "addr %08x value %08x" +disable milkymist_ac97_memory_write(uint32_t addr, uint32_t value) "addr %08x value %08x" +disable milkymist_ac97_pulse_irq_crrequest(void) "Pulse IRQ CR request" +disable milkymist_ac97_pulse_irq_crreply(void) "Pulse IRQ CR reply" +disable milkymist_ac97_pulse_irq_dmaw(void) "Pulse IRQ DMA write" +disable milkymist_ac97_pulse_irq_dmar(void) "Pulse IRQ DMA read" +disable milkymist_ac97_in_cb(int avail, uint32_t remaining) "avail %d remaining %u" +disable milkymist_ac97_in_cb_transferred(int transferred) "transferred %d" +disable milkymist_ac97_out_cb(int free, uint32_t remaining) "free %d remaining %u" +disable milkymist_ac97_out_cb_transferred(int transferred) "transferred %d"
This patch adds support for the Milkymist AC97 compatible sound output and input core. Signed-off-by: Michael Walle <michael@walle.cc> --- Makefile.target | 1 + configure | 3 + hw/milkymist-ac97.c | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++ trace-events | 12 ++ 4 files changed, 351 insertions(+), 0 deletions(-) create mode 100644 hw/milkymist-ac97.c