} conf = {5, 4, 5, 1, 5, 0x220};
typedef struct SB16State {
+ QEMUSoundCard card;
int irq;
int dma;
int hdma;
uint8_t mixer_regs[256];
} SB16State;
-/* XXX: suppress that and use a context */
-static struct SB16State dsp;
-
static void SB_audio_callback (void *opaque, int free);
static int magic_of_irq (int irq)
#define DMA8_AUTO 1
#define DMA8_HIGH 2
+static void continue_dma8 (SB16State *s)
+{
+ if (s->freq > 0) {
+ audsettings_t as;
+
+ s->audio_free = 0;
+
+ as.freq = s->freq;
+ as.nchannels = 1 << s->fmt_stereo;
+ as.fmt = s->fmt;
+ as.endianness = 0;
+
+ s->voice = AUD_open_out (
+ &s->card,
+ s->voice,
+ "sb16",
+ s,
+ SB_audio_callback,
+ &as
+ );
+ }
+
+ control (s, 1);
+}
+
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
{
s->fmt = AUD_FMT_U8;
s->fmt_signed = 0;
s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
if (-1 == s->time_const) {
- s->freq = 11025;
+ if (s->freq <= 0)
+ s->freq = 11025;
}
else {
int tmp = (256 - s->time_const);
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
s->block_size, s->dma_auto, s->fifo, s->highspeed);
- if (s->freq) {
- s->audio_free = 0;
- s->voice = AUD_open_out (
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- s->freq,
- 1 << s->fmt_stereo,
- s->fmt
- );
- }
-
- control (s, 1);
+ continue_dma8 (s);
speaker (s, 1);
}
}
if (s->freq) {
+ audsettings_t as;
+
s->audio_free = 0;
+
+ as.freq = s->freq;
+ as.nchannels = 1 << s->fmt_stereo;
+ as.fmt = s->fmt;
+ as.endianness = 0;
+
s->voice = AUD_open_out (
+ &s->card,
s->voice,
"sb16",
s,
SB_audio_callback,
- s->freq,
- 1 << s->fmt_stereo,
- s->fmt
+ &as
);
}
static inline void dsp_out_data (SB16State *s, uint8_t val)
{
ldebug ("outdata %#x\n", val);
- if (s->out_data_len < sizeof (s->out_data)) {
+ if ((size_t) s->out_data_len < sizeof (s->out_data)) {
s->out_data[s->out_data_len++] = val;
}
}
break;
case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
- control (s, 1);
+ dma_cmd8 (s, DMA8_AUTO, -1);
break;
case 0x20: /* Direct ADC, Juice/PL */
break;
case 0xd4: /* continue DMA operation. 8bit */
- control (s, 1);
+ /* KQ6 (or maybe Sierras audblst.drv in general) resets
+ the frequency between halt/continue */
+ continue_dma8 (s);
break;
case 0xd5: /* halt DMA operation. 16bit */
);
}
}
- ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
+ ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
}
break;
return;
}
+static void legacy_reset (SB16State *s)
+{
+ audsettings_t as;
+
+ s->freq = 11025;
+ s->fmt_signed = 0;
+ s->fmt_bits = 8;
+ s->fmt_stereo = 0;
+
+ as.freq = s->freq;
+ as.nchannels = 1;
+ as.fmt = AUD_FMT_U8;
+ as.endianness = 0;
+
+ s->voice = AUD_open_out (
+ &s->card,
+ s->voice,
+ "sb16",
+ s,
+ SB_audio_callback,
+ &as
+ );
+
+ /* Not sure about that... */
+ /* AUD_set_active_out (s->voice, 1); */
+}
+
static void reset (SB16State *s)
{
pic_set_irq (s->irq, 0);
dsp_out_data(s, 0xaa);
speaker (s, 0);
control (s, 0);
+ legacy_reset (s);
}
static IO_WRITE_PROTO (dsp_write)
static IO_WRITE_PROTO(mixer_write_indexb)
{
SB16State *s = opaque;
+ (void) nport;
s->mixer_nreg = val;
}
{
SB16State *s = opaque;
+ (void) nport;
ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
- if (s->mixer_nreg > sizeof (s->mixer_regs)) {
- return;
- }
switch (s->mixer_nreg) {
case 0x00:
static IO_READ_PROTO(mixer_read)
{
SB16State *s = opaque;
+
+ (void) nport;
#ifndef DEBUG_SB16_MOST
if (s->mixer_nreg != 0x82) {
ldebug ("mixer_read[%#x] -> %#x\n",
while (temp) {
int left = dma_len - dma_pos;
- int to_copy, copied;
+ int copied;
+ size_t to_copy;
to_copy = audio_MIN (temp, left);
- if (to_copy > sizeof(tmpbuf)) {
- to_copy = sizeof(tmpbuf);
+ if (to_copy > sizeof (tmpbuf)) {
+ to_copy = sizeof (tmpbuf);
}
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
qemu_get_buffer (f, s->mixer_regs, 256);
if (s->voice) {
- AUD_close_out (s->voice);
+ AUD_close_out (&s->card, s->voice);
s->voice = NULL;
}
if (s->dma_running) {
if (s->freq) {
+ audsettings_t as;
+
s->audio_free = 0;
+
+ as.freq = s->freq;
+ as.nchannels = 1 << s->fmt_stereo;
+ as.fmt = s->fmt;
+ as.endianness = 0;
+
s->voice = AUD_open_out (
+ &s->card,
s->voice,
"sb16",
s,
SB_audio_callback,
- s->freq,
- 1 << s->fmt_stereo,
- s->fmt
+ &as
);
}
return 0;
}
-void SB16_init (void)
+int SB16_init (AudioState *audio)
{
- SB16State *s = &dsp;
+ SB16State *s;
int i;
static const uint8_t dsp_write_ports[] = {0x6, 0xc};
static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
+ if (!audio) {
+ dolog ("No audio state\n");
+ return -1;
+ }
+
+ s = qemu_mallocz (sizeof (*s));
+ if (!s) {
+ dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
+ sizeof (*s));
+ return -1;
+ }
+
s->cmd = -1;
s->irq = conf.irq;
s->dma = conf.dma;
reset_mixer (s);
s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
if (!s->aux_ts) {
- dolog ("Can not create auxiliary timer\n");
+ dolog ("warning: Could not create auxiliary timer\n");
}
for (i = 0; i < LENOFA (dsp_write_ports); i++) {
s->can_write = 1;
register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
+ AUD_register_card (audio, "sb16", &s->card);
+ return 0;
}