* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "vl.h"
-
-#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
+#include "hw.h"
+#include "audiodev.h"
+#include "audio/audio.h"
+#include "isa.h"
+#include "qemu-timer.h"
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
typedef struct SB16State {
QEMUSoundCard card;
+ qemu_irq *pic;
int irq;
int dma;
int hdma;
{
SB16State *s = opaque;
s->can_write = 1;
- pic_set_irq (s->irq, 1);
+ qemu_irq_raise (s->pic[s->irq]);
}
#define DMA8_AUTO 1
#define DMA8_HIGH 2
+static void continue_dma8 (SB16State *s)
+{
+ if (s->freq > 0) {
+ struct audsettings 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) {
- audsettings_t as;
-
- s->audio_free = 0;
-
- as.freq = s->freq;
- as.nchannels = 1 << s->fmt_stereo;
- as.fmt = s->fmt;
-
- s->voice = AUD_open_out (
- &s->card,
- s->voice,
- "sb16",
- s,
- SB_audio_callback,
- &as,
- 0 /* little endian */
- );
- }
-
- control (s, 1);
+ continue_dma8 (s);
speaker (s, 1);
}
}
if (s->freq) {
- audsettings_t as;
+ struct audsettings 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,
"sb16",
s,
SB_audio_callback,
- &as,
- 0 /* little endian */
+ &as
);
}
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 */
case 0xf3:
dsp_out_data (s, 0xaa);
s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
- pic_set_irq (s->irq, 1);
+ qemu_irq_raise (s->pic[s->irq]);
break;
case 0xf9:
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
ticks = (bytes * ticks_per_sec) / freq;
if (ticks < ticks_per_sec / 1024) {
- pic_set_irq (s->irq, 1);
+ qemu_irq_raise (s->pic[s->irq]);
}
else {
if (s->aux_ts) {
);
}
}
- 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)
+{
+ struct audsettings 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);
+ qemu_irq_lower (s->pic[s->irq]);
if (s->dma_auto) {
- pic_set_irq (s->irq, 1);
- pic_set_irq (s->irq, 0);
+ qemu_irq_raise (s->pic[s->irq]);
+ qemu_irq_lower (s->pic[s->irq]);
}
s->mixer_regs[0x82] = 0;
dsp_out_data(s, 0xaa);
speaker (s, 0);
control (s, 0);
+ legacy_reset (s);
}
static IO_WRITE_PROTO (dsp_write)
if (s->v2x6 == 1) {
if (0 && s->highspeed) {
s->highspeed = 0;
- pic_set_irq (s->irq, 0);
+ qemu_irq_lower (s->pic[s->irq]);
control (s, 0);
}
else {
if (s->mixer_regs[0x82] & 1) {
ack = 1;
s->mixer_regs[0x82] &= 1;
- pic_set_irq (s->irq, 0);
+ qemu_irq_lower (s->pic[s->irq]);
}
break;
if (s->mixer_regs[0x82] & 2) {
ack = 1;
s->mixer_regs[0x82] &= 2;
- pic_set_irq (s->irq, 0);
+ qemu_irq_lower (s->pic[s->irq]);
}
break;
SB16State *s = opaque;
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);
+ return dma_pos;
+ }
+
if (s->left_till_irq < 0) {
s->left_till_irq = s->block_size;
}
if (s->left_till_irq <= 0) {
s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
- pic_set_irq (s->irq, 1);
+ qemu_irq_raise (s->pic[s->irq]);
if (0 == s->dma_auto) {
control (s, 0);
speaker (s, 0);
{
SB16State *s = opaque;
- qemu_put_be32s (f, &s->irq);
- qemu_put_be32s (f, &s->dma);
- qemu_put_be32s (f, &s->hdma);
- qemu_put_be32s (f, &s->port);
- qemu_put_be32s (f, &s->ver);
- qemu_put_be32s (f, &s->in_index);
- qemu_put_be32s (f, &s->out_data_len);
- qemu_put_be32s (f, &s->fmt_stereo);
- qemu_put_be32s (f, &s->fmt_signed);
- qemu_put_be32s (f, &s->fmt_bits);
+ qemu_put_be32 (f, s->irq);
+ qemu_put_be32 (f, s->dma);
+ qemu_put_be32 (f, s->hdma);
+ qemu_put_be32 (f, s->port);
+ qemu_put_be32 (f, s->ver);
+ qemu_put_be32 (f, s->in_index);
+ qemu_put_be32 (f, s->out_data_len);
+ qemu_put_be32 (f, s->fmt_stereo);
+ qemu_put_be32 (f, s->fmt_signed);
+ qemu_put_be32 (f, s->fmt_bits);
qemu_put_be32s (f, &s->fmt);
- qemu_put_be32s (f, &s->dma_auto);
- qemu_put_be32s (f, &s->block_size);
- qemu_put_be32s (f, &s->fifo);
- qemu_put_be32s (f, &s->freq);
- qemu_put_be32s (f, &s->time_const);
- qemu_put_be32s (f, &s->speaker);
- qemu_put_be32s (f, &s->needed_bytes);
- qemu_put_be32s (f, &s->cmd);
- qemu_put_be32s (f, &s->use_hdma);
- qemu_put_be32s (f, &s->highspeed);
- qemu_put_be32s (f, &s->can_write);
- qemu_put_be32s (f, &s->v2x6);
+ qemu_put_be32 (f, s->dma_auto);
+ qemu_put_be32 (f, s->block_size);
+ qemu_put_be32 (f, s->fifo);
+ qemu_put_be32 (f, s->freq);
+ qemu_put_be32 (f, s->time_const);
+ qemu_put_be32 (f, s->speaker);
+ qemu_put_be32 (f, s->needed_bytes);
+ qemu_put_be32 (f, s->cmd);
+ qemu_put_be32 (f, s->use_hdma);
+ qemu_put_be32 (f, s->highspeed);
+ qemu_put_be32 (f, s->can_write);
+ qemu_put_be32 (f, s->v2x6);
qemu_put_8s (f, &s->csp_param);
qemu_put_8s (f, &s->csp_value);
qemu_put_buffer (f, s->csp_regs, 256);
qemu_put_8s (f, &s->csp_index);
qemu_put_buffer (f, s->csp_reg83, 4);
- qemu_put_be32s (f, &s->csp_reg83r);
- qemu_put_be32s (f, &s->csp_reg83w);
+ qemu_put_be32 (f, s->csp_reg83r);
+ qemu_put_be32 (f, s->csp_reg83w);
qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
qemu_put_8s (f, &s->test_reg);
qemu_put_8s (f, &s->last_read_byte);
- qemu_put_be32s (f, &s->nzero);
- qemu_put_be32s (f, &s->left_till_irq);
- qemu_put_be32s (f, &s->dma_running);
- qemu_put_be32s (f, &s->bytes_per_second);
- qemu_put_be32s (f, &s->align);
+ qemu_put_be32 (f, s->nzero);
+ qemu_put_be32 (f, s->left_till_irq);
+ qemu_put_be32 (f, s->dma_running);
+ qemu_put_be32 (f, s->bytes_per_second);
+ qemu_put_be32 (f, s->align);
- qemu_put_be32s (f, &s->mixer_nreg);
+ qemu_put_be32 (f, s->mixer_nreg);
qemu_put_buffer (f, s->mixer_regs, 256);
}
return -EINVAL;
}
- qemu_get_be32s (f, &s->irq);
- qemu_get_be32s (f, &s->dma);
- qemu_get_be32s (f, &s->hdma);
- qemu_get_be32s (f, &s->port);
- qemu_get_be32s (f, &s->ver);
- qemu_get_be32s (f, &s->in_index);
- qemu_get_be32s (f, &s->out_data_len);
- qemu_get_be32s (f, &s->fmt_stereo);
- qemu_get_be32s (f, &s->fmt_signed);
- qemu_get_be32s (f, &s->fmt_bits);
+ s->irq=qemu_get_be32 (f);
+ s->dma=qemu_get_be32 (f);
+ s->hdma=qemu_get_be32 (f);
+ s->port=qemu_get_be32 (f);
+ s->ver=qemu_get_be32 (f);
+ s->in_index=qemu_get_be32 (f);
+ s->out_data_len=qemu_get_be32 (f);
+ s->fmt_stereo=qemu_get_be32 (f);
+ s->fmt_signed=qemu_get_be32 (f);
+ s->fmt_bits=qemu_get_be32 (f);
qemu_get_be32s (f, &s->fmt);
- qemu_get_be32s (f, &s->dma_auto);
- qemu_get_be32s (f, &s->block_size);
- qemu_get_be32s (f, &s->fifo);
- qemu_get_be32s (f, &s->freq);
- qemu_get_be32s (f, &s->time_const);
- qemu_get_be32s (f, &s->speaker);
- qemu_get_be32s (f, &s->needed_bytes);
- qemu_get_be32s (f, &s->cmd);
- qemu_get_be32s (f, &s->use_hdma);
- qemu_get_be32s (f, &s->highspeed);
- qemu_get_be32s (f, &s->can_write);
- qemu_get_be32s (f, &s->v2x6);
+ s->dma_auto=qemu_get_be32 (f);
+ s->block_size=qemu_get_be32 (f);
+ s->fifo=qemu_get_be32 (f);
+ s->freq=qemu_get_be32 (f);
+ s->time_const=qemu_get_be32 (f);
+ s->speaker=qemu_get_be32 (f);
+ s->needed_bytes=qemu_get_be32 (f);
+ s->cmd=qemu_get_be32 (f);
+ s->use_hdma=qemu_get_be32 (f);
+ s->highspeed=qemu_get_be32 (f);
+ s->can_write=qemu_get_be32 (f);
+ s->v2x6=qemu_get_be32 (f);
qemu_get_8s (f, &s->csp_param);
qemu_get_8s (f, &s->csp_value);
qemu_get_buffer (f, s->csp_regs, 256);
qemu_get_8s (f, &s->csp_index);
qemu_get_buffer (f, s->csp_reg83, 4);
- qemu_get_be32s (f, &s->csp_reg83r);
- qemu_get_be32s (f, &s->csp_reg83w);
+ s->csp_reg83r=qemu_get_be32 (f);
+ s->csp_reg83w=qemu_get_be32 (f);
qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
qemu_get_8s (f, &s->test_reg);
qemu_get_8s (f, &s->last_read_byte);
- qemu_get_be32s (f, &s->nzero);
- qemu_get_be32s (f, &s->left_till_irq);
- qemu_get_be32s (f, &s->dma_running);
- qemu_get_be32s (f, &s->bytes_per_second);
- qemu_get_be32s (f, &s->align);
+ s->nzero=qemu_get_be32 (f);
+ s->left_till_irq=qemu_get_be32 (f);
+ s->dma_running=qemu_get_be32 (f);
+ s->bytes_per_second=qemu_get_be32 (f);
+ s->align=qemu_get_be32 (f);
- qemu_get_be32s (f, &s->mixer_nreg);
+ s->mixer_nreg=qemu_get_be32 (f);
qemu_get_buffer (f, s->mixer_regs, 256);
if (s->voice) {
if (s->dma_running) {
if (s->freq) {
- audsettings_t as;
+ struct audsettings 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,
"sb16",
s,
SB_audio_callback,
- &as,
- 0 /* little endian */
+ &as
);
}
return 0;
}
-int SB16_init (AudioState *audio)
+int SB16_init (qemu_irq *pic)
{
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->pic = pic;
s->irq = conf.irq;
s->dma = conf.dma;
s->hdma = conf.hdma;
dolog ("warning: Could not create auxiliary timer\n");
}
- for (i = 0; i < LENOFA (dsp_write_ports); i++) {
+ for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
}
- for (i = 0; i < LENOFA (dsp_read_ports); i++) {
+ for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
}
s->can_write = 1;
register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
- AUD_register_card (audio, "sb16", &s->card);
+ AUD_register_card ("sb16", &s->card);
return 0;
}