Sparc32/64 CPU selection
[qemu] / hw / sb16.c
index e79d192..04325ac 100644 (file)
--- a/hw/sb16.c
+++ b/hw/sb16.c
@@ -53,6 +53,7 @@ static struct {
 } conf = {5, 4, 5, 1, 5, 0x220};
 
 typedef struct SB16State {
+    QEMUSoundCard card;
     int irq;
     int dma;
     int hdma;
@@ -108,9 +109,6 @@ typedef struct SB16State {
     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)
@@ -195,6 +193,31 @@ static void aux_timer (void *opaque)
 #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;
@@ -203,7 +226,8 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
     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);
@@ -241,20 +265,7 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
             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);
 }
 
@@ -330,15 +341,22 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
     }
 
     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
             );
     }
 
@@ -349,7 +367,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
 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;
     }
 }
@@ -425,7 +443,7 @@ static void command (SB16State *s, uint8_t cmd)
             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 */
@@ -519,7 +537,9 @@ static void command (SB16State *s, uint8_t cmd)
             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 */
@@ -753,7 +773,7 @@ static void complete (SB16State *s)
                             );
                     }
                 }
-                ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
+                ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
             }
             break;
 
@@ -806,6 +826,33 @@ static void complete (SB16State *s)
     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);
@@ -829,6 +876,7 @@ static void reset (SB16State *s)
     dsp_out_data(s, 0xaa);
     speaker (s, 0);
     control (s, 0);
+    legacy_reset (s);
 }
 
 static IO_WRITE_PROTO (dsp_write)
@@ -1018,6 +1066,7 @@ static void reset_mixer (SB16State *s)
 static IO_WRITE_PROTO(mixer_write_indexb)
 {
     SB16State *s = opaque;
+    (void) nport;
     s->mixer_nreg = val;
 }
 
@@ -1025,10 +1074,8 @@ static IO_WRITE_PROTO(mixer_write_datab)
 {
     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:
@@ -1088,6 +1135,8 @@ static IO_WRITE_PROTO(mixer_write_indexw)
 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",
@@ -1111,11 +1160,12 @@ static int write_audio (SB16State *s, int nchan, int dma_pos,
 
     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);
@@ -1308,21 +1358,28 @@ static int SB_load (QEMUFile *f, void *opaque, int version_id)
     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
                 );
         }
 
@@ -1332,13 +1389,25 @@ static int SB_load (QEMUFile *f, void *opaque, int version_id)
     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;
@@ -1356,7 +1425,7 @@ void SB16_init (void)
     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++) {
@@ -1377,4 +1446,6 @@ void SB16_init (void)
     s->can_write = 1;
 
     register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
+    AUD_register_card (audio, "sb16", &s->card);
+    return 0;
 }