Fix formatting
[qemu/kraxel.git] / hw / sb16.c
blob38c5b7277494f53fdcc4b133dd376e4a3484ddb5
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 "qdev.h"
29 #include "qemu-timer.h"
31 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
33 /* #define DEBUG */
34 /* #define DEBUG_SB16_MOST */
36 #ifdef DEBUG
37 #define ldebug(...) dolog (__VA_ARGS__)
38 #else
39 #define ldebug(...)
40 #endif
42 #define IO_READ_PROTO(name) \
43 uint32_t name (void *opaque, uint32_t nport)
44 #define IO_WRITE_PROTO(name) \
45 void name (void *opaque, uint32_t nport, uint32_t val)
47 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
49 typedef struct SB16State {
50 ISADevice dev;
51 QEMUSoundCard card;
52 qemu_irq pic;
53 uint32_t irq;
54 uint32_t dma;
55 uint32_t hdma;
56 uint32_t port;
57 uint32_t ver;
59 int in_index;
60 int out_data_len;
61 int fmt_stereo;
62 int fmt_signed;
63 int fmt_bits;
64 audfmt_e fmt;
65 int dma_auto;
66 int block_size;
67 int fifo;
68 int freq;
69 int time_const;
70 int speaker;
71 int needed_bytes;
72 int cmd;
73 int use_hdma;
74 int highspeed;
75 int can_write;
77 int v2x6;
79 uint8_t csp_param;
80 uint8_t csp_value;
81 uint8_t csp_mode;
82 uint8_t csp_regs[256];
83 uint8_t csp_index;
84 uint8_t csp_reg83[4];
85 int csp_reg83r;
86 int csp_reg83w;
88 uint8_t in2_data[10];
89 uint8_t out_data[50];
90 uint8_t test_reg;
91 uint8_t last_read_byte;
92 int nzero;
94 int left_till_irq;
96 int dma_running;
97 int bytes_per_second;
98 int align;
99 int audio_free;
100 SWVoiceOut *voice;
102 QEMUTimer *aux_ts;
103 /* mixer state */
104 int mixer_nreg;
105 uint8_t mixer_regs[256];
106 } SB16State;
108 static void SB_audio_callback (void *opaque, int free);
110 static int magic_of_irq (int irq)
112 switch (irq) {
113 case 5:
114 return 2;
115 case 7:
116 return 4;
117 case 9:
118 return 1;
119 case 10:
120 return 8;
121 default:
122 dolog ("bad irq %d\n", irq);
123 return 2;
127 static int irq_of_magic (int magic)
129 switch (magic) {
130 case 1:
131 return 9;
132 case 2:
133 return 5;
134 case 4:
135 return 7;
136 case 8:
137 return 10;
138 default:
139 dolog ("bad irq magic %d\n", magic);
140 return -1;
144 #if 0
145 static void log_dsp (SB16State *dsp)
147 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
148 dsp->fmt_stereo ? "Stereo" : "Mono",
149 dsp->fmt_signed ? "Signed" : "Unsigned",
150 dsp->fmt_bits,
151 dsp->dma_auto ? "Auto" : "Single",
152 dsp->block_size,
153 dsp->freq,
154 dsp->time_const,
155 dsp->speaker);
157 #endif
159 static void speaker (SB16State *s, int on)
161 s->speaker = on;
162 /* AUD_enable (s->voice, on); */
165 static void control (SB16State *s, int hold)
167 int dma = s->use_hdma ? s->hdma : s->dma;
168 s->dma_running = hold;
170 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
172 if (hold) {
173 DMA_hold_DREQ (dma);
174 AUD_set_active_out (s->voice, 1);
176 else {
177 DMA_release_DREQ (dma);
178 AUD_set_active_out (s->voice, 0);
182 static void aux_timer (void *opaque)
184 SB16State *s = opaque;
185 s->can_write = 1;
186 qemu_irq_raise (s->pic);
189 #define DMA8_AUTO 1
190 #define DMA8_HIGH 2
192 static void continue_dma8 (SB16State *s)
194 if (s->freq > 0) {
195 struct audsettings as;
197 s->audio_free = 0;
199 as.freq = s->freq;
200 as.nchannels = 1 << s->fmt_stereo;
201 as.fmt = s->fmt;
202 as.endianness = 0;
204 s->voice = AUD_open_out (
205 &s->card,
206 s->voice,
207 "sb16",
209 SB_audio_callback,
214 control (s, 1);
217 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
219 s->fmt = AUD_FMT_U8;
220 s->use_hdma = 0;
221 s->fmt_bits = 8;
222 s->fmt_signed = 0;
223 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
224 if (-1 == s->time_const) {
225 if (s->freq <= 0)
226 s->freq = 11025;
228 else {
229 int tmp = (256 - s->time_const);
230 s->freq = (1000000 + (tmp / 2)) / tmp;
233 if (dma_len != -1) {
234 s->block_size = dma_len << s->fmt_stereo;
236 else {
237 /* This is apparently the only way to make both Act1/PL
238 and SecondReality/FC work
240 Act1 sets block size via command 0x48 and it's an odd number
241 SR does the same with even number
242 Both use stereo, and Creatives own documentation states that
243 0x48 sets block size in bytes less one.. go figure */
244 s->block_size &= ~s->fmt_stereo;
247 s->freq >>= s->fmt_stereo;
248 s->left_till_irq = s->block_size;
249 s->bytes_per_second = (s->freq << s->fmt_stereo);
250 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
251 s->dma_auto = (mask & DMA8_AUTO) != 0;
252 s->align = (1 << s->fmt_stereo) - 1;
254 if (s->block_size & s->align) {
255 dolog ("warning: misaligned block size %d, alignment %d\n",
256 s->block_size, s->align + 1);
259 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
260 "dma %d, auto %d, fifo %d, high %d\n",
261 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
262 s->block_size, s->dma_auto, s->fifo, s->highspeed);
264 continue_dma8 (s);
265 speaker (s, 1);
268 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
270 s->use_hdma = cmd < 0xc0;
271 s->fifo = (cmd >> 1) & 1;
272 s->dma_auto = (cmd >> 2) & 1;
273 s->fmt_signed = (d0 >> 4) & 1;
274 s->fmt_stereo = (d0 >> 5) & 1;
276 switch (cmd >> 4) {
277 case 11:
278 s->fmt_bits = 16;
279 break;
281 case 12:
282 s->fmt_bits = 8;
283 break;
286 if (-1 != s->time_const) {
287 #if 1
288 int tmp = 256 - s->time_const;
289 s->freq = (1000000 + (tmp / 2)) / tmp;
290 #else
291 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
292 s->freq = 1000000 / ((255 - s->time_const));
293 #endif
294 s->time_const = -1;
297 s->block_size = dma_len + 1;
298 s->block_size <<= (s->fmt_bits == 16);
299 if (!s->dma_auto) {
300 /* It is clear that for DOOM and auto-init this value
301 shouldn't take stereo into account, while Miles Sound Systems
302 setsound.exe with single transfer mode wouldn't work without it
303 wonders of SB16 yet again */
304 s->block_size <<= s->fmt_stereo;
307 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
308 "dma %d, auto %d, fifo %d, high %d\n",
309 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
310 s->block_size, s->dma_auto, s->fifo, s->highspeed);
312 if (16 == s->fmt_bits) {
313 if (s->fmt_signed) {
314 s->fmt = AUD_FMT_S16;
316 else {
317 s->fmt = AUD_FMT_U16;
320 else {
321 if (s->fmt_signed) {
322 s->fmt = AUD_FMT_S8;
324 else {
325 s->fmt = AUD_FMT_U8;
329 s->left_till_irq = s->block_size;
331 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
332 s->highspeed = 0;
333 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
334 if (s->block_size & s->align) {
335 dolog ("warning: misaligned block size %d, alignment %d\n",
336 s->block_size, s->align + 1);
339 if (s->freq) {
340 struct audsettings as;
342 s->audio_free = 0;
344 as.freq = s->freq;
345 as.nchannels = 1 << s->fmt_stereo;
346 as.fmt = s->fmt;
347 as.endianness = 0;
349 s->voice = AUD_open_out (
350 &s->card,
351 s->voice,
352 "sb16",
354 SB_audio_callback,
359 control (s, 1);
360 speaker (s, 1);
363 static inline void dsp_out_data (SB16State *s, uint8_t val)
365 ldebug ("outdata %#x\n", val);
366 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
367 s->out_data[s->out_data_len++] = val;
371 static inline uint8_t dsp_get_data (SB16State *s)
373 if (s->in_index) {
374 return s->in2_data[--s->in_index];
376 else {
377 dolog ("buffer underflow\n");
378 return 0;
382 static void command (SB16State *s, uint8_t cmd)
384 ldebug ("command %#x\n", cmd);
386 if (cmd > 0xaf && cmd < 0xd0) {
387 if (cmd & 8) {
388 dolog ("ADC not yet supported (command %#x)\n", cmd);
391 switch (cmd >> 4) {
392 case 11:
393 case 12:
394 break;
395 default:
396 dolog ("%#x wrong bits\n", cmd);
398 s->needed_bytes = 3;
400 else {
401 s->needed_bytes = 0;
403 switch (cmd) {
404 case 0x03:
405 dsp_out_data (s, 0x10); /* s->csp_param); */
406 goto warn;
408 case 0x04:
409 s->needed_bytes = 1;
410 goto warn;
412 case 0x05:
413 s->needed_bytes = 2;
414 goto warn;
416 case 0x08:
417 /* __asm__ ("int3"); */
418 goto warn;
420 case 0x0e:
421 s->needed_bytes = 2;
422 goto warn;
424 case 0x09:
425 dsp_out_data (s, 0xf8);
426 goto warn;
428 case 0x0f:
429 s->needed_bytes = 1;
430 goto warn;
432 case 0x10:
433 s->needed_bytes = 1;
434 goto warn;
436 case 0x14:
437 s->needed_bytes = 2;
438 s->block_size = 0;
439 break;
441 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
442 dma_cmd8 (s, DMA8_AUTO, -1);
443 break;
445 case 0x20: /* Direct ADC, Juice/PL */
446 dsp_out_data (s, 0xff);
447 goto warn;
449 case 0x35:
450 dolog ("0x35 - MIDI command not implemented\n");
451 break;
453 case 0x40:
454 s->freq = -1;
455 s->time_const = -1;
456 s->needed_bytes = 1;
457 break;
459 case 0x41:
460 s->freq = -1;
461 s->time_const = -1;
462 s->needed_bytes = 2;
463 break;
465 case 0x42:
466 s->freq = -1;
467 s->time_const = -1;
468 s->needed_bytes = 2;
469 goto warn;
471 case 0x45:
472 dsp_out_data (s, 0xaa);
473 goto warn;
475 case 0x47: /* Continue Auto-Initialize DMA 16bit */
476 break;
478 case 0x48:
479 s->needed_bytes = 2;
480 break;
482 case 0x74:
483 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
484 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
485 break;
487 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
488 s->needed_bytes = 2;
489 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
490 break;
492 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
493 s->needed_bytes = 2;
494 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
495 break;
497 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
498 s->needed_bytes = 2;
499 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
500 break;
502 case 0x7d:
503 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
504 dolog ("not implemented\n");
505 break;
507 case 0x7f:
508 dolog (
509 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
511 dolog ("not implemented\n");
512 break;
514 case 0x80:
515 s->needed_bytes = 2;
516 break;
518 case 0x90:
519 case 0x91:
520 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
521 break;
523 case 0xd0: /* halt DMA operation. 8bit */
524 control (s, 0);
525 break;
527 case 0xd1: /* speaker on */
528 speaker (s, 1);
529 break;
531 case 0xd3: /* speaker off */
532 speaker (s, 0);
533 break;
535 case 0xd4: /* continue DMA operation. 8bit */
536 /* KQ6 (or maybe Sierras audblst.drv in general) resets
537 the frequency between halt/continue */
538 continue_dma8 (s);
539 break;
541 case 0xd5: /* halt DMA operation. 16bit */
542 control (s, 0);
543 break;
545 case 0xd6: /* continue DMA operation. 16bit */
546 control (s, 1);
547 break;
549 case 0xd9: /* exit auto-init DMA after this block. 16bit */
550 s->dma_auto = 0;
551 break;
553 case 0xda: /* exit auto-init DMA after this block. 8bit */
554 s->dma_auto = 0;
555 break;
557 case 0xe0: /* DSP identification */
558 s->needed_bytes = 1;
559 break;
561 case 0xe1:
562 dsp_out_data (s, s->ver & 0xff);
563 dsp_out_data (s, s->ver >> 8);
564 break;
566 case 0xe2:
567 s->needed_bytes = 1;
568 goto warn;
570 case 0xe3:
572 int i;
573 for (i = sizeof (e3) - 1; i >= 0; --i)
574 dsp_out_data (s, e3[i]);
576 break;
578 case 0xe4: /* write test reg */
579 s->needed_bytes = 1;
580 break;
582 case 0xe7:
583 dolog ("Attempt to probe for ESS (0xe7)?\n");
584 break;
586 case 0xe8: /* read test reg */
587 dsp_out_data (s, s->test_reg);
588 break;
590 case 0xf2:
591 case 0xf3:
592 dsp_out_data (s, 0xaa);
593 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
594 qemu_irq_raise (s->pic);
595 break;
597 case 0xf9:
598 s->needed_bytes = 1;
599 goto warn;
601 case 0xfa:
602 dsp_out_data (s, 0);
603 goto warn;
605 case 0xfc: /* FIXME */
606 dsp_out_data (s, 0);
607 goto warn;
609 default:
610 dolog ("Unrecognized command %#x\n", cmd);
611 break;
615 if (!s->needed_bytes) {
616 ldebug ("\n");
619 exit:
620 if (!s->needed_bytes) {
621 s->cmd = -1;
623 else {
624 s->cmd = cmd;
626 return;
628 warn:
629 dolog ("warning: command %#x,%d is not truly understood yet\n",
630 cmd, s->needed_bytes);
631 goto exit;
635 static uint16_t dsp_get_lohi (SB16State *s)
637 uint8_t hi = dsp_get_data (s);
638 uint8_t lo = dsp_get_data (s);
639 return (hi << 8) | lo;
642 static uint16_t dsp_get_hilo (SB16State *s)
644 uint8_t lo = dsp_get_data (s);
645 uint8_t hi = dsp_get_data (s);
646 return (hi << 8) | lo;
649 static void complete (SB16State *s)
651 int d0, d1, d2;
652 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
653 s->cmd, s->in_index, s->needed_bytes);
655 if (s->cmd > 0xaf && s->cmd < 0xd0) {
656 d2 = dsp_get_data (s);
657 d1 = dsp_get_data (s);
658 d0 = dsp_get_data (s);
660 if (s->cmd & 8) {
661 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
662 s->cmd, d0, d1, d2);
664 else {
665 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
666 s->cmd, d0, d1, d2);
667 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
670 else {
671 switch (s->cmd) {
672 case 0x04:
673 s->csp_mode = dsp_get_data (s);
674 s->csp_reg83r = 0;
675 s->csp_reg83w = 0;
676 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
677 break;
679 case 0x05:
680 s->csp_param = dsp_get_data (s);
681 s->csp_value = dsp_get_data (s);
682 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
683 s->csp_param,
684 s->csp_value);
685 break;
687 case 0x0e:
688 d0 = dsp_get_data (s);
689 d1 = dsp_get_data (s);
690 ldebug ("write CSP register %d <- %#x\n", d1, d0);
691 if (d1 == 0x83) {
692 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
693 s->csp_reg83[s->csp_reg83r % 4] = d0;
694 s->csp_reg83r += 1;
696 else {
697 s->csp_regs[d1] = d0;
699 break;
701 case 0x0f:
702 d0 = dsp_get_data (s);
703 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
704 d0, s->csp_regs[d0], s->csp_mode);
705 if (d0 == 0x83) {
706 ldebug ("0x83[%d] -> %#x\n",
707 s->csp_reg83w,
708 s->csp_reg83[s->csp_reg83w % 4]);
709 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
710 s->csp_reg83w += 1;
712 else {
713 dsp_out_data (s, s->csp_regs[d0]);
715 break;
717 case 0x10:
718 d0 = dsp_get_data (s);
719 dolog ("cmd 0x10 d0=%#x\n", d0);
720 break;
722 case 0x14:
723 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
724 break;
726 case 0x40:
727 s->time_const = dsp_get_data (s);
728 ldebug ("set time const %d\n", s->time_const);
729 break;
731 case 0x42: /* FT2 sets output freq with this, go figure */
732 #if 0
733 dolog ("cmd 0x42 might not do what it think it should\n");
734 #endif
735 case 0x41:
736 s->freq = dsp_get_hilo (s);
737 ldebug ("set freq %d\n", s->freq);
738 break;
740 case 0x48:
741 s->block_size = dsp_get_lohi (s) + 1;
742 ldebug ("set dma block len %d\n", s->block_size);
743 break;
745 case 0x74:
746 case 0x75:
747 case 0x76:
748 case 0x77:
749 /* ADPCM stuff, ignore */
750 break;
752 case 0x80:
754 int freq, samples, bytes;
755 int64_t ticks;
757 freq = s->freq > 0 ? s->freq : 11025;
758 samples = dsp_get_lohi (s) + 1;
759 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
760 ticks = (bytes * ticks_per_sec) / freq;
761 if (ticks < ticks_per_sec / 1024) {
762 qemu_irq_raise (s->pic);
764 else {
765 if (s->aux_ts) {
766 qemu_mod_timer (
767 s->aux_ts,
768 qemu_get_clock (vm_clock) + ticks
772 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
774 break;
776 case 0xe0:
777 d0 = dsp_get_data (s);
778 s->out_data_len = 0;
779 ldebug ("E0 data = %#x\n", d0);
780 dsp_out_data (s, ~d0);
781 break;
783 case 0xe2:
784 d0 = dsp_get_data (s);
785 ldebug ("E2 = %#x\n", d0);
786 break;
788 case 0xe4:
789 s->test_reg = dsp_get_data (s);
790 break;
792 case 0xf9:
793 d0 = dsp_get_data (s);
794 ldebug ("command 0xf9 with %#x\n", d0);
795 switch (d0) {
796 case 0x0e:
797 dsp_out_data (s, 0xff);
798 break;
800 case 0x0f:
801 dsp_out_data (s, 0x07);
802 break;
804 case 0x37:
805 dsp_out_data (s, 0x38);
806 break;
808 default:
809 dsp_out_data (s, 0x00);
810 break;
812 break;
814 default:
815 dolog ("complete: unrecognized command %#x\n", s->cmd);
816 return;
820 ldebug ("\n");
821 s->cmd = -1;
822 return;
825 static void legacy_reset (SB16State *s)
827 struct audsettings as;
829 s->freq = 11025;
830 s->fmt_signed = 0;
831 s->fmt_bits = 8;
832 s->fmt_stereo = 0;
834 as.freq = s->freq;
835 as.nchannels = 1;
836 as.fmt = AUD_FMT_U8;
837 as.endianness = 0;
839 s->voice = AUD_open_out (
840 &s->card,
841 s->voice,
842 "sb16",
844 SB_audio_callback,
848 /* Not sure about that... */
849 /* AUD_set_active_out (s->voice, 1); */
852 static void reset (SB16State *s)
854 qemu_irq_lower (s->pic);
855 if (s->dma_auto) {
856 qemu_irq_raise (s->pic);
857 qemu_irq_lower (s->pic);
860 s->mixer_regs[0x82] = 0;
861 s->dma_auto = 0;
862 s->in_index = 0;
863 s->out_data_len = 0;
864 s->left_till_irq = 0;
865 s->needed_bytes = 0;
866 s->block_size = -1;
867 s->nzero = 0;
868 s->highspeed = 0;
869 s->v2x6 = 0;
870 s->cmd = -1;
872 dsp_out_data (s, 0xaa);
873 speaker (s, 0);
874 control (s, 0);
875 legacy_reset (s);
878 static IO_WRITE_PROTO (dsp_write)
880 SB16State *s = opaque;
881 int iport;
883 iport = nport - s->port;
885 ldebug ("write %#x <- %#x\n", nport, val);
886 switch (iport) {
887 case 0x06:
888 switch (val) {
889 case 0x00:
890 if (s->v2x6 == 1) {
891 if (0 && s->highspeed) {
892 s->highspeed = 0;
893 qemu_irq_lower (s->pic);
894 control (s, 0);
896 else {
897 reset (s);
900 s->v2x6 = 0;
901 break;
903 case 0x01:
904 case 0x03: /* FreeBSD kludge */
905 s->v2x6 = 1;
906 break;
908 case 0xc6:
909 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
910 break;
912 case 0xb8: /* Panic */
913 reset (s);
914 break;
916 case 0x39:
917 dsp_out_data (s, 0x38);
918 reset (s);
919 s->v2x6 = 0x39;
920 break;
922 default:
923 s->v2x6 = val;
924 break;
926 break;
928 case 0x0c: /* write data or command | write status */
929 /* if (s->highspeed) */
930 /* break; */
932 if (0 == s->needed_bytes) {
933 command (s, val);
934 #if 0
935 if (0 == s->needed_bytes) {
936 log_dsp (s);
938 #endif
940 else {
941 if (s->in_index == sizeof (s->in2_data)) {
942 dolog ("in data overrun\n");
944 else {
945 s->in2_data[s->in_index++] = val;
946 if (s->in_index == s->needed_bytes) {
947 s->needed_bytes = 0;
948 complete (s);
949 #if 0
950 log_dsp (s);
951 #endif
955 break;
957 default:
958 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
959 break;
963 static IO_READ_PROTO (dsp_read)
965 SB16State *s = opaque;
966 int iport, retval, ack = 0;
968 iport = nport - s->port;
970 switch (iport) {
971 case 0x06: /* reset */
972 retval = 0xff;
973 break;
975 case 0x0a: /* read data */
976 if (s->out_data_len) {
977 retval = s->out_data[--s->out_data_len];
978 s->last_read_byte = retval;
980 else {
981 if (s->cmd != -1) {
982 dolog ("empty output buffer for command %#x\n",
983 s->cmd);
985 retval = s->last_read_byte;
986 /* goto error; */
988 break;
990 case 0x0c: /* 0 can write */
991 retval = s->can_write ? 0 : 0x80;
992 break;
994 case 0x0d: /* timer interrupt clear */
995 /* dolog ("timer interrupt clear\n"); */
996 retval = 0;
997 break;
999 case 0x0e: /* data available status | irq 8 ack */
1000 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1001 if (s->mixer_regs[0x82] & 1) {
1002 ack = 1;
1003 s->mixer_regs[0x82] &= 1;
1004 qemu_irq_lower (s->pic);
1006 break;
1008 case 0x0f: /* irq 16 ack */
1009 retval = 0xff;
1010 if (s->mixer_regs[0x82] & 2) {
1011 ack = 1;
1012 s->mixer_regs[0x82] &= 2;
1013 qemu_irq_lower (s->pic);
1015 break;
1017 default:
1018 goto error;
1021 if (!ack) {
1022 ldebug ("read %#x -> %#x\n", nport, retval);
1025 return retval;
1027 error:
1028 dolog ("warning: dsp_read %#x error\n", nport);
1029 return 0xff;
1032 static void reset_mixer (SB16State *s)
1034 int i;
1036 memset (s->mixer_regs, 0xff, 0x7f);
1037 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1039 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1040 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1041 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1042 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1044 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1045 s->mixer_regs[0x0c] = 0;
1047 /* d5=output filt, d1=stereo switch */
1048 s->mixer_regs[0x0e] = 0;
1050 /* voice volume L d5,d7, R d1,d3 */
1051 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1052 /* master ... */
1053 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1054 /* MIDI ... */
1055 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1057 for (i = 0x30; i < 0x48; i++) {
1058 s->mixer_regs[i] = 0x20;
1062 static IO_WRITE_PROTO (mixer_write_indexb)
1064 SB16State *s = opaque;
1065 (void) nport;
1066 s->mixer_nreg = val;
1069 static IO_WRITE_PROTO (mixer_write_datab)
1071 SB16State *s = opaque;
1073 (void) nport;
1074 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1076 switch (s->mixer_nreg) {
1077 case 0x00:
1078 reset_mixer (s);
1079 break;
1081 case 0x80:
1083 int irq = irq_of_magic (val);
1084 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1085 if (irq > 0) {
1086 s->irq = irq;
1089 break;
1091 case 0x81:
1093 int dma, hdma;
1095 dma = lsbindex (val & 0xf);
1096 hdma = lsbindex (val & 0xf0);
1097 if (dma != s->dma || hdma != s->hdma) {
1098 dolog (
1099 "attempt to change DMA "
1100 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1101 dma, s->dma, hdma, s->hdma, val);
1103 #if 0
1104 s->dma = dma;
1105 s->hdma = hdma;
1106 #endif
1108 break;
1110 case 0x82:
1111 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1112 val);
1113 return;
1115 default:
1116 if (s->mixer_nreg >= 0x80) {
1117 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1119 break;
1122 s->mixer_regs[s->mixer_nreg] = val;
1125 static IO_WRITE_PROTO (mixer_write_indexw)
1127 mixer_write_indexb (opaque, nport, val & 0xff);
1128 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1131 static IO_READ_PROTO (mixer_read)
1133 SB16State *s = opaque;
1135 (void) nport;
1136 #ifndef DEBUG_SB16_MOST
1137 if (s->mixer_nreg != 0x82) {
1138 ldebug ("mixer_read[%#x] -> %#x\n",
1139 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1141 #else
1142 ldebug ("mixer_read[%#x] -> %#x\n",
1143 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1144 #endif
1145 return s->mixer_regs[s->mixer_nreg];
1148 static int write_audio (SB16State *s, int nchan, int dma_pos,
1149 int dma_len, int len)
1151 int temp, net;
1152 uint8_t tmpbuf[4096];
1154 temp = len;
1155 net = 0;
1157 while (temp) {
1158 int left = dma_len - dma_pos;
1159 int copied;
1160 size_t to_copy;
1162 to_copy = audio_MIN (temp, left);
1163 if (to_copy > sizeof (tmpbuf)) {
1164 to_copy = sizeof (tmpbuf);
1167 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1168 copied = AUD_write (s->voice, tmpbuf, copied);
1170 temp -= copied;
1171 dma_pos = (dma_pos + copied) % dma_len;
1172 net += copied;
1174 if (!copied) {
1175 break;
1179 return net;
1182 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1184 SB16State *s = opaque;
1185 int till, copy, written, free;
1187 if (s->block_size <= 0) {
1188 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1189 s->block_size, nchan, dma_pos, dma_len);
1190 return dma_pos;
1193 if (s->left_till_irq < 0) {
1194 s->left_till_irq = s->block_size;
1197 if (s->voice) {
1198 free = s->audio_free & ~s->align;
1199 if ((free <= 0) || !dma_len) {
1200 return dma_pos;
1203 else {
1204 free = dma_len;
1207 copy = free;
1208 till = s->left_till_irq;
1210 #ifdef DEBUG_SB16_MOST
1211 dolog ("pos:%06d %d till:%d len:%d\n",
1212 dma_pos, free, till, dma_len);
1213 #endif
1215 if (till <= copy) {
1216 if (0 == s->dma_auto) {
1217 copy = till;
1221 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1222 dma_pos = (dma_pos + written) % dma_len;
1223 s->left_till_irq -= written;
1225 if (s->left_till_irq <= 0) {
1226 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1227 qemu_irq_raise (s->pic);
1228 if (0 == s->dma_auto) {
1229 control (s, 0);
1230 speaker (s, 0);
1234 #ifdef DEBUG_SB16_MOST
1235 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1236 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1237 s->block_size);
1238 #endif
1240 while (s->left_till_irq <= 0) {
1241 s->left_till_irq = s->block_size + s->left_till_irq;
1244 return dma_pos;
1247 static void SB_audio_callback (void *opaque, int free)
1249 SB16State *s = opaque;
1250 s->audio_free = free;
1253 static void SB_save (QEMUFile *f, void *opaque)
1255 SB16State *s = opaque;
1257 qemu_put_be32 (f, s->irq);
1258 qemu_put_be32 (f, s->dma);
1259 qemu_put_be32 (f, s->hdma);
1260 qemu_put_be32 (f, s->port);
1261 qemu_put_be32 (f, s->ver);
1262 qemu_put_be32 (f, s->in_index);
1263 qemu_put_be32 (f, s->out_data_len);
1264 qemu_put_be32 (f, s->fmt_stereo);
1265 qemu_put_be32 (f, s->fmt_signed);
1266 qemu_put_be32 (f, s->fmt_bits);
1267 qemu_put_be32s (f, &s->fmt);
1268 qemu_put_be32 (f, s->dma_auto);
1269 qemu_put_be32 (f, s->block_size);
1270 qemu_put_be32 (f, s->fifo);
1271 qemu_put_be32 (f, s->freq);
1272 qemu_put_be32 (f, s->time_const);
1273 qemu_put_be32 (f, s->speaker);
1274 qemu_put_be32 (f, s->needed_bytes);
1275 qemu_put_be32 (f, s->cmd);
1276 qemu_put_be32 (f, s->use_hdma);
1277 qemu_put_be32 (f, s->highspeed);
1278 qemu_put_be32 (f, s->can_write);
1279 qemu_put_be32 (f, s->v2x6);
1281 qemu_put_8s (f, &s->csp_param);
1282 qemu_put_8s (f, &s->csp_value);
1283 qemu_put_8s (f, &s->csp_mode);
1284 qemu_put_8s (f, &s->csp_param);
1285 qemu_put_buffer (f, s->csp_regs, 256);
1286 qemu_put_8s (f, &s->csp_index);
1287 qemu_put_buffer (f, s->csp_reg83, 4);
1288 qemu_put_be32 (f, s->csp_reg83r);
1289 qemu_put_be32 (f, s->csp_reg83w);
1291 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1292 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1293 qemu_put_8s (f, &s->test_reg);
1294 qemu_put_8s (f, &s->last_read_byte);
1296 qemu_put_be32 (f, s->nzero);
1297 qemu_put_be32 (f, s->left_till_irq);
1298 qemu_put_be32 (f, s->dma_running);
1299 qemu_put_be32 (f, s->bytes_per_second);
1300 qemu_put_be32 (f, s->align);
1302 qemu_put_be32 (f, s->mixer_nreg);
1303 qemu_put_buffer (f, s->mixer_regs, 256);
1306 static int SB_load (QEMUFile *f, void *opaque, int version_id)
1308 SB16State *s = opaque;
1310 if (version_id != 1) {
1311 return -EINVAL;
1314 s->irq=qemu_get_be32 (f);
1315 s->dma=qemu_get_be32 (f);
1316 s->hdma=qemu_get_be32 (f);
1317 s->port=qemu_get_be32 (f);
1318 s->ver=qemu_get_be32 (f);
1319 s->in_index=qemu_get_be32 (f);
1320 s->out_data_len=qemu_get_be32 (f);
1321 s->fmt_stereo=qemu_get_be32 (f);
1322 s->fmt_signed=qemu_get_be32 (f);
1323 s->fmt_bits=qemu_get_be32 (f);
1324 qemu_get_be32s (f, &s->fmt);
1325 s->dma_auto=qemu_get_be32 (f);
1326 s->block_size=qemu_get_be32 (f);
1327 s->fifo=qemu_get_be32 (f);
1328 s->freq=qemu_get_be32 (f);
1329 s->time_const=qemu_get_be32 (f);
1330 s->speaker=qemu_get_be32 (f);
1331 s->needed_bytes=qemu_get_be32 (f);
1332 s->cmd=qemu_get_be32 (f);
1333 s->use_hdma=qemu_get_be32 (f);
1334 s->highspeed=qemu_get_be32 (f);
1335 s->can_write=qemu_get_be32 (f);
1336 s->v2x6=qemu_get_be32 (f);
1338 qemu_get_8s (f, &s->csp_param);
1339 qemu_get_8s (f, &s->csp_value);
1340 qemu_get_8s (f, &s->csp_mode);
1341 qemu_get_8s (f, &s->csp_param);
1342 qemu_get_buffer (f, s->csp_regs, 256);
1343 qemu_get_8s (f, &s->csp_index);
1344 qemu_get_buffer (f, s->csp_reg83, 4);
1345 s->csp_reg83r=qemu_get_be32 (f);
1346 s->csp_reg83w=qemu_get_be32 (f);
1348 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1349 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1350 qemu_get_8s (f, &s->test_reg);
1351 qemu_get_8s (f, &s->last_read_byte);
1353 s->nzero=qemu_get_be32 (f);
1354 s->left_till_irq=qemu_get_be32 (f);
1355 s->dma_running=qemu_get_be32 (f);
1356 s->bytes_per_second=qemu_get_be32 (f);
1357 s->align=qemu_get_be32 (f);
1359 s->mixer_nreg=qemu_get_be32 (f);
1360 qemu_get_buffer (f, s->mixer_regs, 256);
1362 if (s->voice) {
1363 AUD_close_out (&s->card, s->voice);
1364 s->voice = NULL;
1367 if (s->dma_running) {
1368 if (s->freq) {
1369 struct audsettings as;
1371 s->audio_free = 0;
1373 as.freq = s->freq;
1374 as.nchannels = 1 << s->fmt_stereo;
1375 as.fmt = s->fmt;
1376 as.endianness = 0;
1378 s->voice = AUD_open_out (
1379 &s->card,
1380 s->voice,
1381 "sb16",
1383 SB_audio_callback,
1388 control (s, 1);
1389 speaker (s, s->speaker);
1391 return 0;
1394 static int sb16_initfn (ISADevice *dev)
1396 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1397 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1398 SB16State *s;
1399 int i;
1401 s = DO_UPCAST (SB16State, dev, dev);
1403 s->cmd = -1;
1404 isa_init_irq (dev, &s->pic, s->irq);
1406 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1407 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1408 s->mixer_regs[0x82] = 2 << 5;
1410 s->csp_regs[5] = 1;
1411 s->csp_regs[9] = 0xf8;
1413 reset_mixer (s);
1414 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1415 if (!s->aux_ts) {
1416 dolog ("warning: Could not create auxiliary timer\n");
1419 for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
1420 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1423 for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
1424 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1427 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1428 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1429 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1430 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1432 DMA_register_channel (s->hdma, SB_read_DMA, s);
1433 DMA_register_channel (s->dma, SB_read_DMA, s);
1434 s->can_write = 1;
1436 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1437 AUD_register_card ("sb16", &s->card);
1438 return 0;
1441 int SB16_init (qemu_irq *pic)
1443 isa_create_simple ("sb16");
1444 return 0;
1447 static ISADeviceInfo sb16_info = {
1448 .qdev.name = "sb16",
1449 .qdev.desc = "Creative Sound Blaster 16",
1450 .qdev.size = sizeof (SB16State),
1451 .init = sb16_initfn,
1452 .qdev.props = (Property[]) {
1453 DEFINE_PROP_HEX32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1454 DEFINE_PROP_HEX32 ("iobase", SB16State, port, 0x220),
1455 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1456 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1457 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1458 DEFINE_PROP_END_OF_LIST (),
1462 static void sb16_register (void)
1464 isa_qdev_register (&sb16_info);
1466 device_init (sb16_register)