#include "audiodev.h"
#include "audio/audio.h"
#include "pci.h"
+#include "dma.h"
/* Missing stuff:
SCTRL_P[12](END|ST)INC
};
typedef struct ES1370State {
- PCIDevice *pci_dev;
-
+ PCIDevice dev;
QEMUSoundCard card;
+ MemoryRegion io;
struct chan chan[NB_CHANNELS];
SWVoiceOut *dac_voice[2];
SWVoiceIn *adc_voice;
uint32_t sctl;
} ES1370State;
-typedef struct PCIES1370State {
- PCIDevice dev;
- ES1370State es1370;
-} PCIES1370State;
-
struct chan_bits {
uint32_t ctl_en;
uint32_t stat_int;
else {
s->status = new_status & ~STAT_INTR;
}
- qemu_set_irq (s->pci_dev->irq[0], !!level);
+ qemu_set_irq (s->dev.irq[0], !!level);
}
static void es1370_reset (ES1370State *s)
s->dac_voice[i] = NULL;
}
}
- qemu_irq_lower (s->pci_dev->irq[0]);
+ qemu_irq_lower (s->dev.irq[0]);
}
static void es1370_maybe_lower_irq (ES1370State *s, uint32_t sctl)
if ((old_fmt != new_fmt) || (old_freq != new_freq)) {
d->shift = (new_fmt & 1) + (new_fmt >> 1);
- ldebug ("channel %d, freq = %d, nchannels %d, fmt %d, shift %d\n",
+ ldebug ("channel %zu, freq = %d, nchannels %d, fmt %d, shift %d\n",
i,
new_freq,
1 << (new_fmt & 1),
d++;
case ES1370_REG_DAC1_SCOUNT:
d->scount = (val & 0xffff) | (d->scount & ~0xffff);
- ldebug ("chan %d CURR_SAMP_CT %d, SAMP_CT %d\n",
+ ldebug ("chan %td CURR_SAMP_CT %d, SAMP_CT %d\n",
d - &s->chan[0], val >> 16, (val & 0xffff));
break;
d++;
case ES1370_REG_DAC1_FRAMEADR:
d->frame_addr = val;
- ldebug ("chan %d frame address %#x\n", d - &s->chan[0], val);
+ ldebug ("chan %td frame address %#x\n", d - &s->chan[0], val);
break;
case ES1370_REG_PHANTOM_FRAMECNT:
case ES1370_REG_DAC1_FRAMECNT:
d->frame_cnt = val;
d->leftover = 0;
- ldebug ("chan %d frame count %d, buffer size %d\n",
+ ldebug ("chan %td frame count %d, buffer size %d\n",
d - &s->chan[0], val >> 16, val & 0xffff);
break;
{
uint32_t size = ((d->frame_cnt & 0xffff) + 1) << 2;
uint32_t curr = ((d->frame_cnt >> 16) + 1) << 2;
- if (curr > size)
+ if (curr > size) {
dolog ("read framecnt curr %d, size %d %d\n", curr, size,
curr > size);
+ }
}
#endif
break;
return val;
}
-
static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel,
int max, int *irq)
{
int cnt = d->frame_cnt >> 16;
int size = d->frame_cnt & 0xffff;
int left = ((size - cnt + 1) << 2) + d->leftover;
- int transfered = 0;
+ int transferred = 0;
int temp = audio_MIN (max, audio_MIN (left, csc_bytes));
int index = d - &s->chan[0];
if (!acquired)
break;
- cpu_physical_memory_write (addr, tmpbuf, acquired);
+ pci_dma_write (&s->dev, addr, tmpbuf, acquired);
temp -= acquired;
addr += acquired;
- transfered += acquired;
+ transferred += acquired;
}
}
else {
int copied, to_copy;
to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf));
- cpu_physical_memory_read (addr, tmpbuf, to_copy);
+ pci_dma_read (&s->dev, addr, tmpbuf, to_copy);
copied = AUD_write (voice, tmpbuf, to_copy);
if (!copied)
break;
temp -= copied;
addr += copied;
- transfered += copied;
+ transferred += copied;
}
}
- if (csc_bytes == transfered) {
+ if (csc_bytes == transferred) {
*irq = 1;
d->scount = sc | (sc << 16);
ldebug ("sc = %d, rate = %f\n",
}
else {
*irq = 0;
- d->scount = sc | (((csc_bytes - transfered - 1) >> d->shift) << 16);
+ d->scount = sc | (((csc_bytes - transferred - 1) >> d->shift) << 16);
}
- cnt += (transfered + d->leftover) >> 2;
+ cnt += (transferred + d->leftover) >> 2;
if (s->sctl & loop_sel) {
/* Bah, how stupid is that having a 0 represent true value?
d->frame_cnt |= cnt << 16;
}
- d->leftover = (transfered + d->leftover) & 3;
+ d->leftover = (transferred + d->leftover) & 3;
}
static void es1370_run_channel (ES1370State *s, size_t chan, int free_or_avail)
es1370_run_channel (s, ADC_CHANNEL, avail);
}
-static void es1370_map (PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
-{
- PCIES1370State *d = (PCIES1370State *) pci_dev;
- ES1370State *s = &d->es1370;
-
- (void) region_num;
- (void) size;
- (void) type;
-
- register_ioport_write (addr, 0x40 * 4, 1, es1370_writeb, s);
- register_ioport_write (addr, 0x40 * 2, 2, es1370_writew, s);
- register_ioport_write (addr, 0x40, 4, es1370_writel, s);
-
- register_ioport_read (addr, 0x40 * 4, 1, es1370_readb, s);
- register_ioport_read (addr, 0x40 * 2, 2, es1370_readw, s);
- register_ioport_read (addr, 0x40, 4, es1370_readl, s);
-}
+static const MemoryRegionPortio es1370_portio[] = {
+ { 0, 0x40 * 4, 1, .write = es1370_writeb, },
+ { 0, 0x40 * 2, 2, .write = es1370_writew, },
+ { 0, 0x40, 4, .write = es1370_writel, },
+ { 0, 0x40 * 4, 1, .read = es1370_readb, },
+ { 0, 0x40 * 2, 2, .read = es1370_readw, },
+ { 0, 0x40, 4, .read = es1370_readl, },
+ PORTIO_END_OF_LIST ()
+};
-static void es1370_save (QEMUFile *f, void *opaque)
-{
- ES1370State *s = opaque;
- size_t i;
+static const MemoryRegionOps es1370_io_ops = {
+ .old_portio = es1370_portio,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
- pci_device_save (s->pci_dev, f);
- for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- qemu_put_be32s (f, &d->shift);
- qemu_put_be32s (f, &d->leftover);
- qemu_put_be32s (f, &d->scount);
- qemu_put_be32s (f, &d->frame_addr);
- qemu_put_be32s (f, &d->frame_cnt);
+static const VMStateDescription vmstate_es1370_channel = {
+ .name = "es1370_channel",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32 (shift, struct chan),
+ VMSTATE_UINT32 (leftover, struct chan),
+ VMSTATE_UINT32 (scount, struct chan),
+ VMSTATE_UINT32 (frame_addr, struct chan),
+ VMSTATE_UINT32 (frame_cnt, struct chan),
+ VMSTATE_END_OF_LIST ()
}
- qemu_put_be32s (f, &s->ctl);
- qemu_put_be32s (f, &s->status);
- qemu_put_be32s (f, &s->mempage);
- qemu_put_be32s (f, &s->codec);
- qemu_put_be32s (f, &s->sctl);
-}
+};
-static int es1370_load (QEMUFile *f, void *opaque, int version_id)
+static int es1370_post_load (void *opaque, int version_id)
{
- int ret;
uint32_t ctl, sctl;
ES1370State *s = opaque;
size_t i;
- if (version_id != 2)
- return -EINVAL;
-
- ret = pci_device_load (s->pci_dev, f);
- if (ret)
- return ret;
-
for (i = 0; i < NB_CHANNELS; ++i) {
- struct chan *d = &s->chan[i];
- qemu_get_be32s (f, &d->shift);
- qemu_get_be32s (f, &d->leftover);
- qemu_get_be32s (f, &d->scount);
- qemu_get_be32s (f, &d->frame_addr);
- qemu_get_be32s (f, &d->frame_cnt);
if (i == ADC_CHANNEL) {
if (s->adc_voice) {
AUD_close_in (&s->card, s->adc_voice);
}
}
- qemu_get_be32s (f, &ctl);
- qemu_get_be32s (f, &s->status);
- qemu_get_be32s (f, &s->mempage);
- qemu_get_be32s (f, &s->codec);
- qemu_get_be32s (f, &sctl);
-
+ ctl = s->ctl;
+ sctl = s->sctl;
s->ctl = 0;
s->sctl = 0;
es1370_update_voices (s, ctl, sctl);
return 0;
}
+static const VMStateDescription vmstate_es1370 = {
+ .name = "es1370",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .post_load = es1370_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_PCI_DEVICE (dev, ES1370State),
+ VMSTATE_STRUCT_ARRAY (chan, ES1370State, NB_CHANNELS, 2,
+ vmstate_es1370_channel, struct chan),
+ VMSTATE_UINT32 (ctl, ES1370State),
+ VMSTATE_UINT32 (status, ES1370State),
+ VMSTATE_UINT32 (mempage, ES1370State),
+ VMSTATE_UINT32 (codec, ES1370State),
+ VMSTATE_UINT32 (sctl, ES1370State),
+ VMSTATE_END_OF_LIST ()
+ }
+};
+
static void es1370_on_reset (void *opaque)
{
ES1370State *s = opaque;
es1370_reset (s);
}
-static void es1370_initfn(PCIDevice *dev)
+static int es1370_initfn (PCIDevice *dev)
{
- PCIES1370State *d = DO_UPCAST(PCIES1370State, dev, dev);
- ES1370State *s = &d->es1370;
- uint8_t *c = d->dev.config;
-
- pci_config_set_vendor_id (c, PCI_VENDOR_ID_ENSONIQ);
- pci_config_set_device_id (c, PCI_DEVICE_ID_ENSONIQ_ES1370);
- c[0x07] = 2 << 1;
- pci_config_set_class (c, PCI_CLASS_MULTIMEDIA_AUDIO);
-
-#if 1
- c[0x2c] = 0x42;
- c[0x2d] = 0x49;
- c[0x2e] = 0x4c;
- c[0x2f] = 0x4c;
-#else
- c[0x2c] = 0x74;
- c[0x2d] = 0x12;
- c[0x2e] = 0x71;
- c[0x2f] = 0x13;
- c[0x34] = 0xdc;
- c[0x3c] = 10;
+ ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
+ uint8_t *c = s->dev.config;
+
+ c[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_SLOW >> 8;
+
+#if 0
+ c[PCI_CAPABILITY_LIST] = 0xdc;
+ c[PCI_INTERRUPT_LINE] = 10;
c[0xdc] = 0x00;
#endif
- c[0x3d] = 1;
- c[0x3e] = 0x0c;
- c[0x3f] = 0x80;
+ c[PCI_INTERRUPT_PIN] = 1;
+ c[PCI_MIN_GNT] = 0x0c;
+ c[PCI_MAX_LAT] = 0x80;
- s = &d->es1370;
- s->pci_dev = &d->dev;
-
- pci_register_bar (&d->dev, 0, 256, PCI_ADDRESS_SPACE_IO, es1370_map);
- register_savevm ("es1370", 0, 2, es1370_save, es1370_load, s);
+ memory_region_init_io (&s->io, &es1370_io_ops, s, "es1370", 256);
+ pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
qemu_register_reset (es1370_on_reset, s);
AUD_register_card ("es1370", &s->card);
es1370_reset (s);
+ return 0;
+}
+
+static void es1370_exitfn (PCIDevice *dev)
+{
+ ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
+
+ memory_region_destroy (&s->io);
}
int es1370_init (PCIBus *bus)
{
- pci_create_simple(bus, -1, "ES1370");
+ pci_create_simple (bus, -1, "ES1370");
return 0;
}
-static PCIDeviceInfo es1370_info = {
- .qdev.name = "ES1370",
- .qdev.size = sizeof(PCIES1370State),
- .init = es1370_initfn,
+static void es1370_class_init (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS (klass);
+
+ k->init = es1370_initfn;
+ k->exit = es1370_exitfn;
+ k->vendor_id = PCI_VENDOR_ID_ENSONIQ;
+ k->device_id = PCI_DEVICE_ID_ENSONIQ_ES1370;
+ k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ k->subsystem_vendor_id = 0x4942;
+ k->subsystem_id = 0x4c4c;
+ dc->desc = "ENSONIQ AudioPCI ES1370";
+ dc->vmsd = &vmstate_es1370;
+}
+
+static TypeInfo es1370_info = {
+ .name = "ES1370",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof (ES1370State),
+ .class_init = es1370_class_init,
};
-static void es1370_register(void)
+static void es1370_register_types (void)
{
- pci_qdev_register(&es1370_info);
+ type_register_static (&es1370_info);
}
-device_init(es1370_register);
+
+type_init (es1370_register_types)