Get hppa-softmmu to compile
[qemu/hppa.git] / hw / sb16.c
blobad246ea3c9c4113250c0cb18fa2bd9e342f8fe24
1 /*
2 * QEMU Soundblaster 16 emulation
4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 #include "hw.h"
25 #include "audiodev.h"
26 #include "audio/audio.h"
27 #include "isa.h"
28 #include "qemu-timer.h"
30 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
32 /* #define DEBUG */
33 /* #define DEBUG_SB16_MOST */
35 #ifdef DEBUG
36 #define ldebug(...) dolog (__VA_ARGS__)
37 #else
38 #define ldebug(...)
39 #endif
41 #define IO_READ_PROTO(name) \
42 uint32_t name (void *opaque, uint32_t nport)
43 #define IO_WRITE_PROTO(name) \
44 void name (void *opaque, uint32_t nport, uint32_t val)
46 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
48 static struct {
49 int ver_lo;
50 int ver_hi;
51 int irq;
52 int dma;
53 int hdma;
54 int port;
55 } conf = {5, 4, 5, 1, 5, 0x220};
57 typedef struct SB16State {
58 QEMUSoundCard card;
59 qemu_irq *pic;
60 int irq;
61 int dma;
62 int hdma;
63 int port;
64 int ver;
66 int in_index;
67 int out_data_len;
68 int fmt_stereo;
69 int fmt_signed;
70 int fmt_bits;
71 audfmt_e fmt;
72 int dma_auto;
73 int block_size;
74 int fifo;
75 int freq;
76 int time_const;
77 int speaker;
78 int needed_bytes;
79 int cmd;
80 int use_hdma;
81 int highspeed;
82 int can_write;
84 int v2x6;
86 uint8_t csp_param;
87 uint8_t csp_value;
88 uint8_t csp_mode;
89 uint8_t csp_regs[256];
90 uint8_t csp_index;
91 uint8_t csp_reg83[4];
92 int csp_reg83r;
93 int csp_reg83w;
95 uint8_t in2_data[10];
96 uint8_t out_data[50];
97 uint8_t test_reg;
98 uint8_t last_read_byte;
99 int nzero;
101 int left_till_irq;
103 int dma_running;
104 int bytes_per_second;
105 int align;
106 int audio_free;
107 SWVoiceOut *voice;
109 QEMUTimer *aux_ts;
110 /* mixer state */
111 int mixer_nreg;
112 uint8_t mixer_regs[256];
113 } SB16State;
115 static void SB_audio_callback (void *opaque, int free);
117 static int magic_of_irq (int irq)
119 switch (irq) {
120 case 5:
121 return 2;
122 case 7:
123 return 4;
124 case 9:
125 return 1;
126 case 10:
127 return 8;
128 default:
129 dolog ("bad irq %d\n", irq);
130 return 2;
134 static int irq_of_magic (int magic)
136 switch (magic) {
137 case 1:
138 return 9;
139 case 2:
140 return 5;
141 case 4:
142 return 7;
143 case 8:
144 return 10;
145 default:
146 dolog ("bad irq magic %d\n", magic);
147 return -1;
151 #if 0
152 static void log_dsp (SB16State *dsp)
154 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
155 dsp->fmt_stereo ? "Stereo" : "Mono",
156 dsp->fmt_signed ? "Signed" : "Unsigned",
157 dsp->fmt_bits,
158 dsp->dma_auto ? "Auto" : "Single",
159 dsp->block_size,
160 dsp->freq,
161 dsp->time_const,
162 dsp->speaker);
164 #endif
166 static void speaker (SB16State *s, int on)
168 s->speaker = on;
169 /* AUD_enable (s->voice, on); */
172 static void control (SB16State *s, int hold)
174 int dma = s->use_hdma ? s->hdma : s->dma;
175 s->dma_running = hold;
177 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
179 if (hold) {
180 DMA_hold_DREQ (dma);
181 AUD_set_active_out (s->voice, 1);
183 else {
184 DMA_release_DREQ (dma);
185 AUD_set_active_out (s->voice, 0);
189 static void aux_timer (void *opaque)
191 SB16State *s = opaque;
192 s->can_write = 1;
193 qemu_irq_raise (s->pic[s->irq]);
196 #define DMA8_AUTO 1
197 #define DMA8_HIGH 2
199 static void continue_dma8 (SB16State *s)
201 if (s->freq > 0) {
202 struct audsettings as;
204 s->audio_free = 0;
206 as.freq = s->freq;
207 as.nchannels = 1 << s->fmt_stereo;
208 as.fmt = s->fmt;
209 as.endianness = 0;
211 s->voice = AUD_open_out (
212 &s->card,
213 s->voice,
214 "sb16",
216 SB_audio_callback,
221 control (s, 1);
224 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
226 s->fmt = AUD_FMT_U8;
227 s->use_hdma = 0;
228 s->fmt_bits = 8;
229 s->fmt_signed = 0;
230 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
231 if (-1 == s->time_const) {
232 if (s->freq <= 0)
233 s->freq = 11025;
235 else {
236 int tmp = (256 - s->time_const);
237 s->freq = (1000000 + (tmp / 2)) / tmp;
240 if (dma_len != -1) {
241 s->block_size = dma_len << s->fmt_stereo;
243 else {
244 /* This is apparently the only way to make both Act1/PL
245 and SecondReality/FC work
247 Act1 sets block size via command 0x48 and it's an odd number
248 SR does the same with even number
249 Both use stereo, and Creatives own documentation states that
250 0x48 sets block size in bytes less one.. go figure */
251 s->block_size &= ~s->fmt_stereo;
254 s->freq >>= s->fmt_stereo;
255 s->left_till_irq = s->block_size;
256 s->bytes_per_second = (s->freq << s->fmt_stereo);
257 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
258 s->dma_auto = (mask & DMA8_AUTO) != 0;
259 s->align = (1 << s->fmt_stereo) - 1;
261 if (s->block_size & s->align) {
262 dolog ("warning: misaligned block size %d, alignment %d\n",
263 s->block_size, s->align + 1);
266 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
267 "dma %d, auto %d, fifo %d, high %d\n",
268 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
269 s->block_size, s->dma_auto, s->fifo, s->highspeed);
271 continue_dma8 (s);
272 speaker (s, 1);
275 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
277 s->use_hdma = cmd < 0xc0;
278 s->fifo = (cmd >> 1) & 1;
279 s->dma_auto = (cmd >> 2) & 1;
280 s->fmt_signed = (d0 >> 4) & 1;
281 s->fmt_stereo = (d0 >> 5) & 1;
283 switch (cmd >> 4) {
284 case 11:
285 s->fmt_bits = 16;
286 break;
288 case 12:
289 s->fmt_bits = 8;
290 break;
293 if (-1 != s->time_const) {
294 #if 1
295 int tmp = 256 - s->time_const;
296 s->freq = (1000000 + (tmp / 2)) / tmp;
297 #else
298 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
299 s->freq = 1000000 / ((255 - s->time_const));
300 #endif
301 s->time_const = -1;
304 s->block_size = dma_len + 1;
305 s->block_size <<= (s->fmt_bits == 16);
306 if (!s->dma_auto) {
307 /* It is clear that for DOOM and auto-init this value
308 shouldn't take stereo into account, while Miles Sound Systems
309 setsound.exe with single transfer mode wouldn't work without it
310 wonders of SB16 yet again */
311 s->block_size <<= s->fmt_stereo;
314 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
315 "dma %d, auto %d, fifo %d, high %d\n",
316 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
317 s->block_size, s->dma_auto, s->fifo, s->highspeed);
319 if (16 == s->fmt_bits) {
320 if (s->fmt_signed) {
321 s->fmt = AUD_FMT_S16;
323 else {
324 s->fmt = AUD_FMT_U16;
327 else {
328 if (s->fmt_signed) {
329 s->fmt = AUD_FMT_S8;
331 else {
332 s->fmt = AUD_FMT_U8;
336 s->left_till_irq = s->block_size;
338 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
339 s->highspeed = 0;
340 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
341 if (s->block_size & s->align) {
342 dolog ("warning: misaligned block size %d, alignment %d\n",
343 s->block_size, s->align + 1);
346 if (s->freq) {
347 struct audsettings as;
349 s->audio_free = 0;
351 as.freq = s->freq;
352 as.nchannels = 1 << s->fmt_stereo;
353 as.fmt = s->fmt;
354 as.endianness = 0;
356 s->voice = AUD_open_out (
357 &s->card,
358 s->voice,
359 "sb16",
361 SB_audio_callback,
366 control (s, 1);
367 speaker (s, 1);
370 static inline void dsp_out_data (SB16State *s, uint8_t val)
372 ldebug ("outdata %#x\n", val);
373 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
374 s->out_data[s->out_data_len++] = val;
378 static inline uint8_t dsp_get_data (SB16State *s)
380 if (s->in_index) {
381 return s->in2_data[--s->in_index];
383 else {
384 dolog ("buffer underflow\n");
385 return 0;
389 static void command (SB16State *s, uint8_t cmd)
391 ldebug ("command %#x\n", cmd);
393 if (cmd > 0xaf && cmd < 0xd0) {
394 if (cmd & 8) {
395 dolog ("ADC not yet supported (command %#x)\n", cmd);
398 switch (cmd >> 4) {
399 case 11:
400 case 12:
401 break;
402 default:
403 dolog ("%#x wrong bits\n", cmd);
405 s->needed_bytes = 3;
407 else {
408 s->needed_bytes = 0;
410 switch (cmd) {
411 case 0x03:
412 dsp_out_data (s, 0x10); /* s->csp_param); */
413 goto warn;
415 case 0x04:
416 s->needed_bytes = 1;
417 goto warn;
419 case 0x05:
420 s->needed_bytes = 2;
421 goto warn;
423 case 0x08:
424 /* __asm__ ("int3"); */
425 goto warn;
427 case 0x0e:
428 s->needed_bytes = 2;
429 goto warn;
431 case 0x09:
432 dsp_out_data (s, 0xf8);
433 goto warn;
435 case 0x0f:
436 s->needed_bytes = 1;
437 goto warn;
439 case 0x10:
440 s->needed_bytes = 1;
441 goto warn;
443 case 0x14:
444 s->needed_bytes = 2;
445 s->block_size = 0;
446 break;
448 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
449 dma_cmd8 (s, DMA8_AUTO, -1);
450 break;
452 case 0x20: /* Direct ADC, Juice/PL */
453 dsp_out_data (s, 0xff);
454 goto warn;
456 case 0x35:
457 dolog ("0x35 - MIDI command not implemented\n");
458 break;
460 case 0x40:
461 s->freq = -1;
462 s->time_const = -1;
463 s->needed_bytes = 1;
464 break;
466 case 0x41:
467 s->freq = -1;
468 s->time_const = -1;
469 s->needed_bytes = 2;
470 break;
472 case 0x42:
473 s->freq = -1;
474 s->time_const = -1;
475 s->needed_bytes = 2;
476 goto warn;
478 case 0x45:
479 dsp_out_data (s, 0xaa);
480 goto warn;
482 case 0x47: /* Continue Auto-Initialize DMA 16bit */
483 break;
485 case 0x48:
486 s->needed_bytes = 2;
487 break;
489 case 0x74:
490 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
491 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
492 break;
494 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
495 s->needed_bytes = 2;
496 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
497 break;
499 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
500 s->needed_bytes = 2;
501 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
502 break;
504 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
505 s->needed_bytes = 2;
506 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
507 break;
509 case 0x7d:
510 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
511 dolog ("not implemented\n");
512 break;
514 case 0x7f:
515 dolog (
516 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
518 dolog ("not implemented\n");
519 break;
521 case 0x80:
522 s->needed_bytes = 2;
523 break;
525 case 0x90:
526 case 0x91:
527 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
528 break;
530 case 0xd0: /* halt DMA operation. 8bit */
531 control (s, 0);
532 break;
534 case 0xd1: /* speaker on */
535 speaker (s, 1);
536 break;
538 case 0xd3: /* speaker off */
539 speaker (s, 0);
540 break;
542 case 0xd4: /* continue DMA operation. 8bit */
543 /* KQ6 (or maybe Sierras audblst.drv in general) resets
544 the frequency between halt/continue */
545 continue_dma8 (s);
546 break;
548 case 0xd5: /* halt DMA operation. 16bit */
549 control (s, 0);
550 break;
552 case 0xd6: /* continue DMA operation. 16bit */
553 control (s, 1);
554 break;
556 case 0xd9: /* exit auto-init DMA after this block. 16bit */
557 s->dma_auto = 0;
558 break;
560 case 0xda: /* exit auto-init DMA after this block. 8bit */
561 s->dma_auto = 0;
562 break;
564 case 0xe0: /* DSP identification */
565 s->needed_bytes = 1;
566 break;
568 case 0xe1:
569 dsp_out_data (s, s->ver & 0xff);
570 dsp_out_data (s, s->ver >> 8);
571 break;
573 case 0xe2:
574 s->needed_bytes = 1;
575 goto warn;
577 case 0xe3:
579 int i;
580 for (i = sizeof (e3) - 1; i >= 0; --i)
581 dsp_out_data (s, e3[i]);
583 break;
585 case 0xe4: /* write test reg */
586 s->needed_bytes = 1;
587 break;
589 case 0xe7:
590 dolog ("Attempt to probe for ESS (0xe7)?\n");
591 break;
593 case 0xe8: /* read test reg */
594 dsp_out_data (s, s->test_reg);
595 break;
597 case 0xf2:
598 case 0xf3:
599 dsp_out_data (s, 0xaa);
600 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
601 qemu_irq_raise (s->pic[s->irq]);
602 break;
604 case 0xf9:
605 s->needed_bytes = 1;
606 goto warn;
608 case 0xfa:
609 dsp_out_data (s, 0);
610 goto warn;
612 case 0xfc: /* FIXME */
613 dsp_out_data (s, 0);
614 goto warn;
616 default:
617 dolog ("Unrecognized command %#x\n", cmd);
618 break;
622 if (!s->needed_bytes) {
623 ldebug ("\n");
626 exit:
627 if (!s->needed_bytes) {
628 s->cmd = -1;
630 else {
631 s->cmd = cmd;
633 return;
635 warn:
636 dolog ("warning: command %#x,%d is not truly understood yet\n",
637 cmd, s->needed_bytes);
638 goto exit;
642 static uint16_t dsp_get_lohi (SB16State *s)
644 uint8_t hi = dsp_get_data (s);
645 uint8_t lo = dsp_get_data (s);
646 return (hi << 8) | lo;
649 static uint16_t dsp_get_hilo (SB16State *s)
651 uint8_t lo = dsp_get_data (s);
652 uint8_t hi = dsp_get_data (s);
653 return (hi << 8) | lo;
656 static void complete (SB16State *s)
658 int d0, d1, d2;
659 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
660 s->cmd, s->in_index, s->needed_bytes);
662 if (s->cmd > 0xaf && s->cmd < 0xd0) {
663 d2 = dsp_get_data (s);
664 d1 = dsp_get_data (s);
665 d0 = dsp_get_data (s);
667 if (s->cmd & 8) {
668 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
669 s->cmd, d0, d1, d2);
671 else {
672 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
673 s->cmd, d0, d1, d2);
674 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
677 else {
678 switch (s->cmd) {
679 case 0x04:
680 s->csp_mode = dsp_get_data (s);
681 s->csp_reg83r = 0;
682 s->csp_reg83w = 0;
683 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
684 break;
686 case 0x05:
687 s->csp_param = dsp_get_data (s);
688 s->csp_value = dsp_get_data (s);
689 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
690 s->csp_param,
691 s->csp_value);
692 break;
694 case 0x0e:
695 d0 = dsp_get_data (s);
696 d1 = dsp_get_data (s);
697 ldebug ("write CSP register %d <- %#x\n", d1, d0);
698 if (d1 == 0x83) {
699 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
700 s->csp_reg83[s->csp_reg83r % 4] = d0;
701 s->csp_reg83r += 1;
703 else {
704 s->csp_regs[d1] = d0;
706 break;
708 case 0x0f:
709 d0 = dsp_get_data (s);
710 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
711 d0, s->csp_regs[d0], s->csp_mode);
712 if (d0 == 0x83) {
713 ldebug ("0x83[%d] -> %#x\n",
714 s->csp_reg83w,
715 s->csp_reg83[s->csp_reg83w % 4]);
716 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
717 s->csp_reg83w += 1;
719 else {
720 dsp_out_data (s, s->csp_regs[d0]);
722 break;
724 case 0x10:
725 d0 = dsp_get_data (s);
726 dolog ("cmd 0x10 d0=%#x\n", d0);
727 break;
729 case 0x14:
730 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
731 break;
733 case 0x40:
734 s->time_const = dsp_get_data (s);
735 ldebug ("set time const %d\n", s->time_const);
736 break;
738 case 0x42: /* FT2 sets output freq with this, go figure */
739 #if 0
740 dolog ("cmd 0x42 might not do what it think it should\n");
741 #endif
742 case 0x41:
743 s->freq = dsp_get_hilo (s);
744 ldebug ("set freq %d\n", s->freq);
745 break;
747 case 0x48:
748 s->block_size = dsp_get_lohi (s) + 1;
749 ldebug ("set dma block len %d\n", s->block_size);
750 break;
752 case 0x74:
753 case 0x75:
754 case 0x76:
755 case 0x77:
756 /* ADPCM stuff, ignore */
757 break;
759 case 0x80:
761 int freq, samples, bytes;
762 int64_t ticks;
764 freq = s->freq > 0 ? s->freq : 11025;
765 samples = dsp_get_lohi (s) + 1;
766 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
767 ticks = (bytes * ticks_per_sec) / freq;
768 if (ticks < ticks_per_sec / 1024) {
769 qemu_irq_raise (s->pic[s->irq]);
771 else {
772 if (s->aux_ts) {
773 qemu_mod_timer (
774 s->aux_ts,
775 qemu_get_clock (vm_clock) + ticks
779 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
781 break;
783 case 0xe0:
784 d0 = dsp_get_data (s);
785 s->out_data_len = 0;
786 ldebug ("E0 data = %#x\n", d0);
787 dsp_out_data (s, ~d0);
788 break;
790 case 0xe2:
791 d0 = dsp_get_data (s);
792 ldebug ("E2 = %#x\n", d0);
793 break;
795 case 0xe4:
796 s->test_reg = dsp_get_data (s);
797 break;
799 case 0xf9:
800 d0 = dsp_get_data (s);
801 ldebug ("command 0xf9 with %#x\n", d0);
802 switch (d0) {
803 case 0x0e:
804 dsp_out_data (s, 0xff);
805 break;
807 case 0x0f:
808 dsp_out_data (s, 0x07);
809 break;
811 case 0x37:
812 dsp_out_data (s, 0x38);
813 break;
815 default:
816 dsp_out_data (s, 0x00);
817 break;
819 break;
821 default:
822 dolog ("complete: unrecognized command %#x\n", s->cmd);
823 return;
827 ldebug ("\n");
828 s->cmd = -1;
829 return;
832 static void legacy_reset (SB16State *s)
834 struct audsettings as;
836 s->freq = 11025;
837 s->fmt_signed = 0;
838 s->fmt_bits = 8;
839 s->fmt_stereo = 0;
841 as.freq = s->freq;
842 as.nchannels = 1;
843 as.fmt = AUD_FMT_U8;
844 as.endianness = 0;
846 s->voice = AUD_open_out (
847 &s->card,
848 s->voice,
849 "sb16",
851 SB_audio_callback,
855 /* Not sure about that... */
856 /* AUD_set_active_out (s->voice, 1); */
859 static void reset (SB16State *s)
861 qemu_irq_lower (s->pic[s->irq]);
862 if (s->dma_auto) {
863 qemu_irq_raise (s->pic[s->irq]);
864 qemu_irq_lower (s->pic[s->irq]);
867 s->mixer_regs[0x82] = 0;
868 s->dma_auto = 0;
869 s->in_index = 0;
870 s->out_data_len = 0;
871 s->left_till_irq = 0;
872 s->needed_bytes = 0;
873 s->block_size = -1;
874 s->nzero = 0;
875 s->highspeed = 0;
876 s->v2x6 = 0;
877 s->cmd = -1;
879 dsp_out_data(s, 0xaa);
880 speaker (s, 0);
881 control (s, 0);
882 legacy_reset (s);
885 static IO_WRITE_PROTO (dsp_write)
887 SB16State *s = opaque;
888 int iport;
890 iport = nport - s->port;
892 ldebug ("write %#x <- %#x\n", nport, val);
893 switch (iport) {
894 case 0x06:
895 switch (val) {
896 case 0x00:
897 if (s->v2x6 == 1) {
898 if (0 && s->highspeed) {
899 s->highspeed = 0;
900 qemu_irq_lower (s->pic[s->irq]);
901 control (s, 0);
903 else {
904 reset (s);
907 s->v2x6 = 0;
908 break;
910 case 0x01:
911 case 0x03: /* FreeBSD kludge */
912 s->v2x6 = 1;
913 break;
915 case 0xc6:
916 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
917 break;
919 case 0xb8: /* Panic */
920 reset (s);
921 break;
923 case 0x39:
924 dsp_out_data (s, 0x38);
925 reset (s);
926 s->v2x6 = 0x39;
927 break;
929 default:
930 s->v2x6 = val;
931 break;
933 break;
935 case 0x0c: /* write data or command | write status */
936 /* if (s->highspeed) */
937 /* break; */
939 if (0 == s->needed_bytes) {
940 command (s, val);
941 #if 0
942 if (0 == s->needed_bytes) {
943 log_dsp (s);
945 #endif
947 else {
948 if (s->in_index == sizeof (s->in2_data)) {
949 dolog ("in data overrun\n");
951 else {
952 s->in2_data[s->in_index++] = val;
953 if (s->in_index == s->needed_bytes) {
954 s->needed_bytes = 0;
955 complete (s);
956 #if 0
957 log_dsp (s);
958 #endif
962 break;
964 default:
965 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
966 break;
970 static IO_READ_PROTO (dsp_read)
972 SB16State *s = opaque;
973 int iport, retval, ack = 0;
975 iport = nport - s->port;
977 switch (iport) {
978 case 0x06: /* reset */
979 retval = 0xff;
980 break;
982 case 0x0a: /* read data */
983 if (s->out_data_len) {
984 retval = s->out_data[--s->out_data_len];
985 s->last_read_byte = retval;
987 else {
988 if (s->cmd != -1) {
989 dolog ("empty output buffer for command %#x\n",
990 s->cmd);
992 retval = s->last_read_byte;
993 /* goto error; */
995 break;
997 case 0x0c: /* 0 can write */
998 retval = s->can_write ? 0 : 0x80;
999 break;
1001 case 0x0d: /* timer interrupt clear */
1002 /* dolog ("timer interrupt clear\n"); */
1003 retval = 0;
1004 break;
1006 case 0x0e: /* data available status | irq 8 ack */
1007 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1008 if (s->mixer_regs[0x82] & 1) {
1009 ack = 1;
1010 s->mixer_regs[0x82] &= 1;
1011 qemu_irq_lower (s->pic[s->irq]);
1013 break;
1015 case 0x0f: /* irq 16 ack */
1016 retval = 0xff;
1017 if (s->mixer_regs[0x82] & 2) {
1018 ack = 1;
1019 s->mixer_regs[0x82] &= 2;
1020 qemu_irq_lower (s->pic[s->irq]);
1022 break;
1024 default:
1025 goto error;
1028 if (!ack) {
1029 ldebug ("read %#x -> %#x\n", nport, retval);
1032 return retval;
1034 error:
1035 dolog ("warning: dsp_read %#x error\n", nport);
1036 return 0xff;
1039 static void reset_mixer (SB16State *s)
1041 int i;
1043 memset (s->mixer_regs, 0xff, 0x7f);
1044 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1046 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1047 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1048 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1049 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1051 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1052 s->mixer_regs[0x0c] = 0;
1054 /* d5=output filt, d1=stereo switch */
1055 s->mixer_regs[0x0e] = 0;
1057 /* voice volume L d5,d7, R d1,d3 */
1058 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1059 /* master ... */
1060 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1061 /* MIDI ... */
1062 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1064 for (i = 0x30; i < 0x48; i++) {
1065 s->mixer_regs[i] = 0x20;
1069 static IO_WRITE_PROTO(mixer_write_indexb)
1071 SB16State *s = opaque;
1072 (void) nport;
1073 s->mixer_nreg = val;
1076 static IO_WRITE_PROTO(mixer_write_datab)
1078 SB16State *s = opaque;
1080 (void) nport;
1081 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1083 switch (s->mixer_nreg) {
1084 case 0x00:
1085 reset_mixer (s);
1086 break;
1088 case 0x80:
1090 int irq = irq_of_magic (val);
1091 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1092 if (irq > 0) {
1093 s->irq = irq;
1096 break;
1098 case 0x81:
1100 int dma, hdma;
1102 dma = lsbindex (val & 0xf);
1103 hdma = lsbindex (val & 0xf0);
1104 if (dma != s->dma || hdma != s->hdma) {
1105 dolog (
1106 "attempt to change DMA "
1107 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1108 dma, s->dma, hdma, s->hdma, val);
1110 #if 0
1111 s->dma = dma;
1112 s->hdma = hdma;
1113 #endif
1115 break;
1117 case 0x82:
1118 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1119 val);
1120 return;
1122 default:
1123 if (s->mixer_nreg >= 0x80) {
1124 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1126 break;
1129 s->mixer_regs[s->mixer_nreg] = val;
1132 static IO_WRITE_PROTO(mixer_write_indexw)
1134 mixer_write_indexb (opaque, nport, val & 0xff);
1135 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1138 static IO_READ_PROTO(mixer_read)
1140 SB16State *s = opaque;
1142 (void) nport;
1143 #ifndef DEBUG_SB16_MOST
1144 if (s->mixer_nreg != 0x82) {
1145 ldebug ("mixer_read[%#x] -> %#x\n",
1146 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1148 #else
1149 ldebug ("mixer_read[%#x] -> %#x\n",
1150 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1151 #endif
1152 return s->mixer_regs[s->mixer_nreg];
1155 static int write_audio (SB16State *s, int nchan, int dma_pos,
1156 int dma_len, int len)
1158 int temp, net;
1159 uint8_t tmpbuf[4096];
1161 temp = len;
1162 net = 0;
1164 while (temp) {
1165 int left = dma_len - dma_pos;
1166 int copied;
1167 size_t to_copy;
1169 to_copy = audio_MIN (temp, left);
1170 if (to_copy > sizeof (tmpbuf)) {
1171 to_copy = sizeof (tmpbuf);
1174 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1175 copied = AUD_write (s->voice, tmpbuf, copied);
1177 temp -= copied;
1178 dma_pos = (dma_pos + copied) % dma_len;
1179 net += copied;
1181 if (!copied) {
1182 break;
1186 return net;
1189 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1191 SB16State *s = opaque;
1192 int till, copy, written, free;
1194 if (s->block_size <= 0) {
1195 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1196 s->block_size, nchan, dma_pos, dma_len);
1197 return dma_pos;
1200 if (s->left_till_irq < 0) {
1201 s->left_till_irq = s->block_size;
1204 if (s->voice) {
1205 free = s->audio_free & ~s->align;
1206 if ((free <= 0) || !dma_len) {
1207 return dma_pos;
1210 else {
1211 free = dma_len;
1214 copy = free;
1215 till = s->left_till_irq;
1217 #ifdef DEBUG_SB16_MOST
1218 dolog ("pos:%06d %d till:%d len:%d\n",
1219 dma_pos, free, till, dma_len);
1220 #endif
1222 if (till <= copy) {
1223 if (0 == s->dma_auto) {
1224 copy = till;
1228 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1229 dma_pos = (dma_pos + written) % dma_len;
1230 s->left_till_irq -= written;
1232 if (s->left_till_irq <= 0) {
1233 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1234 qemu_irq_raise (s->pic[s->irq]);
1235 if (0 == s->dma_auto) {
1236 control (s, 0);
1237 speaker (s, 0);
1241 #ifdef DEBUG_SB16_MOST
1242 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1243 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1244 s->block_size);
1245 #endif
1247 while (s->left_till_irq <= 0) {
1248 s->left_till_irq = s->block_size + s->left_till_irq;
1251 return dma_pos;
1254 static void SB_audio_callback (void *opaque, int free)
1256 SB16State *s = opaque;
1257 s->audio_free = free;
1260 static void SB_save (QEMUFile *f, void *opaque)
1262 SB16State *s = opaque;
1264 qemu_put_be32 (f, s->irq);
1265 qemu_put_be32 (f, s->dma);
1266 qemu_put_be32 (f, s->hdma);
1267 qemu_put_be32 (f, s->port);
1268 qemu_put_be32 (f, s->ver);
1269 qemu_put_be32 (f, s->in_index);
1270 qemu_put_be32 (f, s->out_data_len);
1271 qemu_put_be32 (f, s->fmt_stereo);
1272 qemu_put_be32 (f, s->fmt_signed);
1273 qemu_put_be32 (f, s->fmt_bits);
1274 qemu_put_be32s (f, &s->fmt);
1275 qemu_put_be32 (f, s->dma_auto);
1276 qemu_put_be32 (f, s->block_size);
1277 qemu_put_be32 (f, s->fifo);
1278 qemu_put_be32 (f, s->freq);
1279 qemu_put_be32 (f, s->time_const);
1280 qemu_put_be32 (f, s->speaker);
1281 qemu_put_be32 (f, s->needed_bytes);
1282 qemu_put_be32 (f, s->cmd);
1283 qemu_put_be32 (f, s->use_hdma);
1284 qemu_put_be32 (f, s->highspeed);
1285 qemu_put_be32 (f, s->can_write);
1286 qemu_put_be32 (f, s->v2x6);
1288 qemu_put_8s (f, &s->csp_param);
1289 qemu_put_8s (f, &s->csp_value);
1290 qemu_put_8s (f, &s->csp_mode);
1291 qemu_put_8s (f, &s->csp_param);
1292 qemu_put_buffer (f, s->csp_regs, 256);
1293 qemu_put_8s (f, &s->csp_index);
1294 qemu_put_buffer (f, s->csp_reg83, 4);
1295 qemu_put_be32 (f, s->csp_reg83r);
1296 qemu_put_be32 (f, s->csp_reg83w);
1298 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1299 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1300 qemu_put_8s (f, &s->test_reg);
1301 qemu_put_8s (f, &s->last_read_byte);
1303 qemu_put_be32 (f, s->nzero);
1304 qemu_put_be32 (f, s->left_till_irq);
1305 qemu_put_be32 (f, s->dma_running);
1306 qemu_put_be32 (f, s->bytes_per_second);
1307 qemu_put_be32 (f, s->align);
1309 qemu_put_be32 (f, s->mixer_nreg);
1310 qemu_put_buffer (f, s->mixer_regs, 256);
1313 static int SB_load (QEMUFile *f, void *opaque, int version_id)
1315 SB16State *s = opaque;
1317 if (version_id != 1) {
1318 return -EINVAL;
1321 s->irq=qemu_get_be32 (f);
1322 s->dma=qemu_get_be32 (f);
1323 s->hdma=qemu_get_be32 (f);
1324 s->port=qemu_get_be32 (f);
1325 s->ver=qemu_get_be32 (f);
1326 s->in_index=qemu_get_be32 (f);
1327 s->out_data_len=qemu_get_be32 (f);
1328 s->fmt_stereo=qemu_get_be32 (f);
1329 s->fmt_signed=qemu_get_be32 (f);
1330 s->fmt_bits=qemu_get_be32 (f);
1331 qemu_get_be32s (f, &s->fmt);
1332 s->dma_auto=qemu_get_be32 (f);
1333 s->block_size=qemu_get_be32 (f);
1334 s->fifo=qemu_get_be32 (f);
1335 s->freq=qemu_get_be32 (f);
1336 s->time_const=qemu_get_be32 (f);
1337 s->speaker=qemu_get_be32 (f);
1338 s->needed_bytes=qemu_get_be32 (f);
1339 s->cmd=qemu_get_be32 (f);
1340 s->use_hdma=qemu_get_be32 (f);
1341 s->highspeed=qemu_get_be32 (f);
1342 s->can_write=qemu_get_be32 (f);
1343 s->v2x6=qemu_get_be32 (f);
1345 qemu_get_8s (f, &s->csp_param);
1346 qemu_get_8s (f, &s->csp_value);
1347 qemu_get_8s (f, &s->csp_mode);
1348 qemu_get_8s (f, &s->csp_param);
1349 qemu_get_buffer (f, s->csp_regs, 256);
1350 qemu_get_8s (f, &s->csp_index);
1351 qemu_get_buffer (f, s->csp_reg83, 4);
1352 s->csp_reg83r=qemu_get_be32 (f);
1353 s->csp_reg83w=qemu_get_be32 (f);
1355 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1356 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1357 qemu_get_8s (f, &s->test_reg);
1358 qemu_get_8s (f, &s->last_read_byte);
1360 s->nzero=qemu_get_be32 (f);
1361 s->left_till_irq=qemu_get_be32 (f);
1362 s->dma_running=qemu_get_be32 (f);
1363 s->bytes_per_second=qemu_get_be32 (f);
1364 s->align=qemu_get_be32 (f);
1366 s->mixer_nreg=qemu_get_be32 (f);
1367 qemu_get_buffer (f, s->mixer_regs, 256);
1369 if (s->voice) {
1370 AUD_close_out (&s->card, s->voice);
1371 s->voice = NULL;
1374 if (s->dma_running) {
1375 if (s->freq) {
1376 struct audsettings as;
1378 s->audio_free = 0;
1380 as.freq = s->freq;
1381 as.nchannels = 1 << s->fmt_stereo;
1382 as.fmt = s->fmt;
1383 as.endianness = 0;
1385 s->voice = AUD_open_out (
1386 &s->card,
1387 s->voice,
1388 "sb16",
1390 SB_audio_callback,
1395 control (s, 1);
1396 speaker (s, s->speaker);
1398 return 0;
1401 int SB16_init (AudioState *audio, qemu_irq *pic)
1403 SB16State *s;
1404 int i;
1405 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1406 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1408 if (!audio) {
1409 dolog ("No audio state\n");
1410 return -1;
1413 s = qemu_mallocz (sizeof (*s));
1414 if (!s) {
1415 dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1416 sizeof (*s));
1417 return -1;
1420 s->cmd = -1;
1421 s->pic = pic;
1422 s->irq = conf.irq;
1423 s->dma = conf.dma;
1424 s->hdma = conf.hdma;
1425 s->port = conf.port;
1426 s->ver = conf.ver_lo | (conf.ver_hi << 8);
1428 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1429 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1430 s->mixer_regs[0x82] = 2 << 5;
1432 s->csp_regs[5] = 1;
1433 s->csp_regs[9] = 0xf8;
1435 reset_mixer (s);
1436 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1437 if (!s->aux_ts) {
1438 dolog ("warning: Could not create auxiliary timer\n");
1441 for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
1442 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1445 for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
1446 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1449 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1450 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1451 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1452 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1454 DMA_register_channel (s->hdma, SB_read_DMA, s);
1455 DMA_register_channel (s->dma, SB_read_DMA, s);
1456 s->can_write = 1;
1458 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1459 AUD_register_card (audio, "sb16", &s->card);
1460 return 0;