*/
#include "qemu/osdep.h"
#include "hw/hw.h"
-#include "hw/audio/audio.h"
+#include "hw/audio/soundhw.h"
#include "audio/audio.h"
#include "hw/isa/isa.h"
#include "hw/qdev.h"
#include "qemu/timer.h"
#include "qemu/host-utils.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
uint32_t hdma;
uint32_t port;
uint32_t ver;
+ IsaDma *isa_dma;
+ IsaDma *isa_hdma;
int in_index;
int out_data_len;
/* mixer state */
int mixer_nreg;
uint8_t mixer_regs[256];
+ PortioList portio_list;
} SB16State;
static void SB_audio_callback (void *opaque, int free);
case 10:
return 8;
default:
- dolog ("bad irq %d\n", irq);
+ qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
return 2;
}
}
case 8:
return 10;
default:
- dolog ("bad irq magic %d\n", magic);
+ qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
return -1;
}
}
static void control (SB16State *s, int hold)
{
int dma = s->use_hdma ? s->hdma : s->dma;
+ IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
+ IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
s->dma_running = hold;
ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
if (hold) {
- DMA_hold_DREQ (dma);
+ k->hold_DREQ(isa_dma, dma);
AUD_set_active_out (s->voice, 1);
}
else {
- DMA_release_DREQ (dma);
+ k->release_DREQ(isa_dma, dma);
AUD_set_active_out (s->voice, 0);
}
}
s->align = (1 << s->fmt_stereo) - 1;
if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
+ qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
+ " alignment %d\n", s->block_size, s->align + 1);
}
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
s->highspeed = 0;
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
if (s->block_size & s->align) {
- dolog ("warning: misaligned block size %d, alignment %d\n",
- s->block_size, s->align + 1);
+ qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
+ " alignment %d\n", s->block_size, s->align + 1);
}
if (s->freq) {
if (cmd > 0xaf && cmd < 0xd0) {
if (cmd & 8) {
- dolog ("ADC not yet supported (command %#x)\n", cmd);
+ qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
+ cmd);
}
switch (cmd >> 4) {
case 12:
break;
default:
- dolog ("%#x wrong bits\n", cmd);
+ qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
}
s->needed_bytes = 3;
}
goto warn;
case 0x35:
- dolog ("0x35 - MIDI command not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
break;
case 0x40:
case 0x74:
s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
- dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
+ " implemented\n");
break;
case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
+ " implemented\n");
break;
case 0x76: /* DMA DAC, 2.6-bit ADPCM */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
+ " implemented\n");
break;
case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
s->needed_bytes = 2;
- dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
+ " not implemented\n");
break;
case 0x7d:
- dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
- dolog ("not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
+ " ADPCM Reference\n");
+ qemu_log_mask(LOG_UNIMP, "not implemented\n");
break;
case 0x7f:
- dolog (
- "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
- );
- dolog ("not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
+ " ADPCM Reference\n");
+ qemu_log_mask(LOG_UNIMP, "not implemented\n");
break;
case 0x80:
break;
case 0xe7:
- dolog ("Attempt to probe for ESS (0xe7)?\n");
+ qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
break;
case 0xe8: /* read test reg */
goto warn;
default:
- dolog ("Unrecognized command %#x\n", cmd);
+ qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
break;
}
}
return;
warn:
- dolog ("warning: command %#x,%d is not truly understood yet\n",
- cmd, s->needed_bytes);
+ qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
+ " yet\n", cmd, s->needed_bytes);
goto exit;
}
ldebug ("set time const %d\n", s->time_const);
break;
- case 0x42: /* FT2 sets output freq with this, go figure */
-#if 0
- dolog ("cmd 0x42 might not do what it think it should\n");
-#endif
case 0x41:
+ case 0x42:
+ /*
+ * 0x41 is documented as setting the output sample rate,
+ * and 0x42 the input sample rate, but in fact SB16 hardware
+ * seems to have only a single sample rate under the hood,
+ * and FT2 sets output freq with this (go figure). Compare:
+ * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate
+ */
s->freq = dsp_get_hilo (s);
ldebug ("set freq %d\n", s->freq);
break;
freq = s->freq > 0 ? s->freq : 11025;
samples = dsp_get_lohi (s) + 1;
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
- ticks = muldiv64 (bytes, get_ticks_per_sec (), freq);
- if (ticks < get_ticks_per_sec () / 1024) {
+ ticks = muldiv64(bytes, NANOSECONDS_PER_SECOND, freq);
+ if (ticks < NANOSECONDS_PER_SECOND / 1024) {
qemu_irq_raise (s->pic);
}
else {
break;
default:
- dolog ("complete: unrecognized command %#x\n", s->cmd);
+ qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
+ s->cmd);
return;
}
}
dma = ctz32 (val & 0xf);
hdma = ctz32 (val & 0xf0);
if (dma != s->dma || hdma != s->hdma) {
- dolog (
- "attempt to change DMA "
- "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
- dma, s->dma, hdma, s->hdma, val);
+ qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
+ " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
+ hdma, s->hdma, val);
}
#if 0
s->dma = dma;
break;
case 0x82:
- dolog ("attempt to write into IRQ status register (val=%#x)\n",
- val);
+ qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
+ " register (val=%#x)\n", val);
return;
default:
static int write_audio (SB16State *s, int nchan, int dma_pos,
int dma_len, int len)
{
+ IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
+ IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
int temp, net;
uint8_t tmpbuf[4096];
to_copy = sizeof (tmpbuf);
}
- copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
+ copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
copied = AUD_write (s->voice, tmpbuf, copied);
temp -= copied;
int till, copy, written, free;
if (s->block_size <= 0) {
- dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
- s->block_size, nchan, dma_pos, dma_len);
+ qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
+ " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
+ dma_pos, dma_len);
return dma_pos;
}
{
ISADevice *isadev = ISA_DEVICE (dev);
SB16State *s = SB16 (dev);
+ IsaDmaClass *k;
+
+ s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
+ s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
+ if (!s->isa_dma || !s->isa_hdma) {
+ error_setg(errp, "ISA controller does not support DMA");
+ return;
+ }
isa_init_irq (isadev, &s->pic, s->irq);
reset_mixer (s);
s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
if (!s->aux_ts) {
- dolog ("warning: Could not create auxiliary timer\n");
+ error_setg(errp, "warning: Could not create auxiliary timer");
}
- isa_register_portio_list (isadev, s->port, sb16_ioport_list, s, "sb16");
+ isa_register_portio_list(isadev, &s->portio_list, s->port,
+ sb16_ioport_list, s, "sb16");
+
+ k = ISADMA_GET_CLASS(s->isa_hdma);
+ k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
+
+ k = ISADMA_GET_CLASS(s->isa_dma);
+ k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
- DMA_register_channel (s->hdma, SB_read_DMA, s);
- DMA_register_channel (s->dma, SB_read_DMA, s);
s->can_write = 1;
AUD_register_card ("sb16", &s->card);