Only compile ads7846 when one target uses it
[armpft.git] / hw / sb16.c
blob8654b7d47e752e3cb2023c7c7b03143779e3b826
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"
30 #include "host-utils.h"
32 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
34 /* #define DEBUG */
35 /* #define DEBUG_SB16_MOST */
37 #ifdef DEBUG
38 #define ldebug(...) dolog (__VA_ARGS__)
39 #else
40 #define ldebug(...)
41 #endif
43 #define IO_READ_PROTO(name) \
44 uint32_t name (void *opaque, uint32_t nport)
45 #define IO_WRITE_PROTO(name) \
46 void name (void *opaque, uint32_t nport, uint32_t val)
48 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
50 typedef struct SB16State {
51 ISADevice dev;
52 QEMUSoundCard card;
53 qemu_irq pic;
54 uint32_t irq;
55 uint32_t dma;
56 uint32_t hdma;
57 uint32_t port;
58 uint32_t ver;
60 int in_index;
61 int out_data_len;
62 int fmt_stereo;
63 int fmt_signed;
64 int fmt_bits;
65 audfmt_e fmt;
66 int dma_auto;
67 int block_size;
68 int fifo;
69 int freq;
70 int time_const;
71 int speaker;
72 int needed_bytes;
73 int cmd;
74 int use_hdma;
75 int highspeed;
76 int can_write;
78 int v2x6;
80 uint8_t csp_param;
81 uint8_t csp_value;
82 uint8_t csp_mode;
83 uint8_t csp_regs[256];
84 uint8_t csp_index;
85 uint8_t csp_reg83[4];
86 int csp_reg83r;
87 int csp_reg83w;
89 uint8_t in2_data[10];
90 uint8_t out_data[50];
91 uint8_t test_reg;
92 uint8_t last_read_byte;
93 int nzero;
95 int left_till_irq;
97 int dma_running;
98 int bytes_per_second;
99 int align;
100 int audio_free;
101 SWVoiceOut *voice;
103 QEMUTimer *aux_ts;
104 /* mixer state */
105 int mixer_nreg;
106 uint8_t mixer_regs[256];
107 } SB16State;
109 static void SB_audio_callback (void *opaque, int free);
111 static int magic_of_irq (int irq)
113 switch (irq) {
114 case 5:
115 return 2;
116 case 7:
117 return 4;
118 case 9:
119 return 1;
120 case 10:
121 return 8;
122 default:
123 dolog ("bad irq %d\n", irq);
124 return 2;
128 static int irq_of_magic (int magic)
130 switch (magic) {
131 case 1:
132 return 9;
133 case 2:
134 return 5;
135 case 4:
136 return 7;
137 case 8:
138 return 10;
139 default:
140 dolog ("bad irq magic %d\n", magic);
141 return -1;
145 #if 0
146 static void log_dsp (SB16State *dsp)
148 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
149 dsp->fmt_stereo ? "Stereo" : "Mono",
150 dsp->fmt_signed ? "Signed" : "Unsigned",
151 dsp->fmt_bits,
152 dsp->dma_auto ? "Auto" : "Single",
153 dsp->block_size,
154 dsp->freq,
155 dsp->time_const,
156 dsp->speaker);
158 #endif
160 static void speaker (SB16State *s, int on)
162 s->speaker = on;
163 /* AUD_enable (s->voice, on); */
166 static void control (SB16State *s, int hold)
168 int dma = s->use_hdma ? s->hdma : s->dma;
169 s->dma_running = hold;
171 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
173 if (hold) {
174 DMA_hold_DREQ (dma);
175 AUD_set_active_out (s->voice, 1);
177 else {
178 DMA_release_DREQ (dma);
179 AUD_set_active_out (s->voice, 0);
183 static void aux_timer (void *opaque)
185 SB16State *s = opaque;
186 s->can_write = 1;
187 qemu_irq_raise (s->pic);
190 #define DMA8_AUTO 1
191 #define DMA8_HIGH 2
193 static void continue_dma8 (SB16State *s)
195 if (s->freq > 0) {
196 struct audsettings as;
198 s->audio_free = 0;
200 as.freq = s->freq;
201 as.nchannels = 1 << s->fmt_stereo;
202 as.fmt = s->fmt;
203 as.endianness = 0;
205 s->voice = AUD_open_out (
206 &s->card,
207 s->voice,
208 "sb16",
210 SB_audio_callback,
215 control (s, 1);
218 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
220 s->fmt = AUD_FMT_U8;
221 s->use_hdma = 0;
222 s->fmt_bits = 8;
223 s->fmt_signed = 0;
224 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
225 if (-1 == s->time_const) {
226 if (s->freq <= 0)
227 s->freq = 11025;
229 else {
230 int tmp = (256 - s->time_const);
231 s->freq = (1000000 + (tmp / 2)) / tmp;
234 if (dma_len != -1) {
235 s->block_size = dma_len << s->fmt_stereo;
237 else {
238 /* This is apparently the only way to make both Act1/PL
239 and SecondReality/FC work
241 Act1 sets block size via command 0x48 and it's an odd number
242 SR does the same with even number
243 Both use stereo, and Creatives own documentation states that
244 0x48 sets block size in bytes less one.. go figure */
245 s->block_size &= ~s->fmt_stereo;
248 s->freq >>= s->fmt_stereo;
249 s->left_till_irq = s->block_size;
250 s->bytes_per_second = (s->freq << s->fmt_stereo);
251 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
252 s->dma_auto = (mask & DMA8_AUTO) != 0;
253 s->align = (1 << s->fmt_stereo) - 1;
255 if (s->block_size & s->align) {
256 dolog ("warning: misaligned block size %d, alignment %d\n",
257 s->block_size, s->align + 1);
260 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
261 "dma %d, auto %d, fifo %d, high %d\n",
262 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
263 s->block_size, s->dma_auto, s->fifo, s->highspeed);
265 continue_dma8 (s);
266 speaker (s, 1);
269 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
271 s->use_hdma = cmd < 0xc0;
272 s->fifo = (cmd >> 1) & 1;
273 s->dma_auto = (cmd >> 2) & 1;
274 s->fmt_signed = (d0 >> 4) & 1;
275 s->fmt_stereo = (d0 >> 5) & 1;
277 switch (cmd >> 4) {
278 case 11:
279 s->fmt_bits = 16;
280 break;
282 case 12:
283 s->fmt_bits = 8;
284 break;
287 if (-1 != s->time_const) {
288 #if 1
289 int tmp = 256 - s->time_const;
290 s->freq = (1000000 + (tmp / 2)) / tmp;
291 #else
292 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
293 s->freq = 1000000 / ((255 - s->time_const));
294 #endif
295 s->time_const = -1;
298 s->block_size = dma_len + 1;
299 s->block_size <<= (s->fmt_bits == 16);
300 if (!s->dma_auto) {
301 /* It is clear that for DOOM and auto-init this value
302 shouldn't take stereo into account, while Miles Sound Systems
303 setsound.exe with single transfer mode wouldn't work without it
304 wonders of SB16 yet again */
305 s->block_size <<= s->fmt_stereo;
308 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
309 "dma %d, auto %d, fifo %d, high %d\n",
310 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
311 s->block_size, s->dma_auto, s->fifo, s->highspeed);
313 if (16 == s->fmt_bits) {
314 if (s->fmt_signed) {
315 s->fmt = AUD_FMT_S16;
317 else {
318 s->fmt = AUD_FMT_U16;
321 else {
322 if (s->fmt_signed) {
323 s->fmt = AUD_FMT_S8;
325 else {
326 s->fmt = AUD_FMT_U8;
330 s->left_till_irq = s->block_size;
332 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
333 s->highspeed = 0;
334 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
335 if (s->block_size & s->align) {
336 dolog ("warning: misaligned block size %d, alignment %d\n",
337 s->block_size, s->align + 1);
340 if (s->freq) {
341 struct audsettings as;
343 s->audio_free = 0;
345 as.freq = s->freq;
346 as.nchannels = 1 << s->fmt_stereo;
347 as.fmt = s->fmt;
348 as.endianness = 0;
350 s->voice = AUD_open_out (
351 &s->card,
352 s->voice,
353 "sb16",
355 SB_audio_callback,
360 control (s, 1);
361 speaker (s, 1);
364 static inline void dsp_out_data (SB16State *s, uint8_t val)
366 ldebug ("outdata %#x\n", val);
367 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
368 s->out_data[s->out_data_len++] = val;
372 static inline uint8_t dsp_get_data (SB16State *s)
374 if (s->in_index) {
375 return s->in2_data[--s->in_index];
377 else {
378 dolog ("buffer underflow\n");
379 return 0;
383 static void command (SB16State *s, uint8_t cmd)
385 ldebug ("command %#x\n", cmd);
387 if (cmd > 0xaf && cmd < 0xd0) {
388 if (cmd & 8) {
389 dolog ("ADC not yet supported (command %#x)\n", cmd);
392 switch (cmd >> 4) {
393 case 11:
394 case 12:
395 break;
396 default:
397 dolog ("%#x wrong bits\n", cmd);
399 s->needed_bytes = 3;
401 else {
402 s->needed_bytes = 0;
404 switch (cmd) {
405 case 0x03:
406 dsp_out_data (s, 0x10); /* s->csp_param); */
407 goto warn;
409 case 0x04:
410 s->needed_bytes = 1;
411 goto warn;
413 case 0x05:
414 s->needed_bytes = 2;
415 goto warn;
417 case 0x08:
418 /* __asm__ ("int3"); */
419 goto warn;
421 case 0x0e:
422 s->needed_bytes = 2;
423 goto warn;
425 case 0x09:
426 dsp_out_data (s, 0xf8);
427 goto warn;
429 case 0x0f:
430 s->needed_bytes = 1;
431 goto warn;
433 case 0x10:
434 s->needed_bytes = 1;
435 goto warn;
437 case 0x14:
438 s->needed_bytes = 2;
439 s->block_size = 0;
440 break;
442 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
443 dma_cmd8 (s, DMA8_AUTO, -1);
444 break;
446 case 0x20: /* Direct ADC, Juice/PL */
447 dsp_out_data (s, 0xff);
448 goto warn;
450 case 0x35:
451 dolog ("0x35 - MIDI command not implemented\n");
452 break;
454 case 0x40:
455 s->freq = -1;
456 s->time_const = -1;
457 s->needed_bytes = 1;
458 break;
460 case 0x41:
461 s->freq = -1;
462 s->time_const = -1;
463 s->needed_bytes = 2;
464 break;
466 case 0x42:
467 s->freq = -1;
468 s->time_const = -1;
469 s->needed_bytes = 2;
470 goto warn;
472 case 0x45:
473 dsp_out_data (s, 0xaa);
474 goto warn;
476 case 0x47: /* Continue Auto-Initialize DMA 16bit */
477 break;
479 case 0x48:
480 s->needed_bytes = 2;
481 break;
483 case 0x74:
484 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
485 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
486 break;
488 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
489 s->needed_bytes = 2;
490 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
491 break;
493 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
494 s->needed_bytes = 2;
495 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
496 break;
498 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
499 s->needed_bytes = 2;
500 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
501 break;
503 case 0x7d:
504 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
505 dolog ("not implemented\n");
506 break;
508 case 0x7f:
509 dolog (
510 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
512 dolog ("not implemented\n");
513 break;
515 case 0x80:
516 s->needed_bytes = 2;
517 break;
519 case 0x90:
520 case 0x91:
521 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
522 break;
524 case 0xd0: /* halt DMA operation. 8bit */
525 control (s, 0);
526 break;
528 case 0xd1: /* speaker on */
529 speaker (s, 1);
530 break;
532 case 0xd3: /* speaker off */
533 speaker (s, 0);
534 break;
536 case 0xd4: /* continue DMA operation. 8bit */
537 /* KQ6 (or maybe Sierras audblst.drv in general) resets
538 the frequency between halt/continue */
539 continue_dma8 (s);
540 break;
542 case 0xd5: /* halt DMA operation. 16bit */
543 control (s, 0);
544 break;
546 case 0xd6: /* continue DMA operation. 16bit */
547 control (s, 1);
548 break;
550 case 0xd9: /* exit auto-init DMA after this block. 16bit */
551 s->dma_auto = 0;
552 break;
554 case 0xda: /* exit auto-init DMA after this block. 8bit */
555 s->dma_auto = 0;
556 break;
558 case 0xe0: /* DSP identification */
559 s->needed_bytes = 1;
560 break;
562 case 0xe1:
563 dsp_out_data (s, s->ver & 0xff);
564 dsp_out_data (s, s->ver >> 8);
565 break;
567 case 0xe2:
568 s->needed_bytes = 1;
569 goto warn;
571 case 0xe3:
573 int i;
574 for (i = sizeof (e3) - 1; i >= 0; --i)
575 dsp_out_data (s, e3[i]);
577 break;
579 case 0xe4: /* write test reg */
580 s->needed_bytes = 1;
581 break;
583 case 0xe7:
584 dolog ("Attempt to probe for ESS (0xe7)?\n");
585 break;
587 case 0xe8: /* read test reg */
588 dsp_out_data (s, s->test_reg);
589 break;
591 case 0xf2:
592 case 0xf3:
593 dsp_out_data (s, 0xaa);
594 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
595 qemu_irq_raise (s->pic);
596 break;
598 case 0xf9:
599 s->needed_bytes = 1;
600 goto warn;
602 case 0xfa:
603 dsp_out_data (s, 0);
604 goto warn;
606 case 0xfc: /* FIXME */
607 dsp_out_data (s, 0);
608 goto warn;
610 default:
611 dolog ("Unrecognized command %#x\n", cmd);
612 break;
616 if (!s->needed_bytes) {
617 ldebug ("\n");
620 exit:
621 if (!s->needed_bytes) {
622 s->cmd = -1;
624 else {
625 s->cmd = cmd;
627 return;
629 warn:
630 dolog ("warning: command %#x,%d is not truly understood yet\n",
631 cmd, s->needed_bytes);
632 goto exit;
636 static uint16_t dsp_get_lohi (SB16State *s)
638 uint8_t hi = dsp_get_data (s);
639 uint8_t lo = dsp_get_data (s);
640 return (hi << 8) | lo;
643 static uint16_t dsp_get_hilo (SB16State *s)
645 uint8_t lo = dsp_get_data (s);
646 uint8_t hi = dsp_get_data (s);
647 return (hi << 8) | lo;
650 static void complete (SB16State *s)
652 int d0, d1, d2;
653 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
654 s->cmd, s->in_index, s->needed_bytes);
656 if (s->cmd > 0xaf && s->cmd < 0xd0) {
657 d2 = dsp_get_data (s);
658 d1 = dsp_get_data (s);
659 d0 = dsp_get_data (s);
661 if (s->cmd & 8) {
662 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
663 s->cmd, d0, d1, d2);
665 else {
666 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
667 s->cmd, d0, d1, d2);
668 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
671 else {
672 switch (s->cmd) {
673 case 0x04:
674 s->csp_mode = dsp_get_data (s);
675 s->csp_reg83r = 0;
676 s->csp_reg83w = 0;
677 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
678 break;
680 case 0x05:
681 s->csp_param = dsp_get_data (s);
682 s->csp_value = dsp_get_data (s);
683 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
684 s->csp_param,
685 s->csp_value);
686 break;
688 case 0x0e:
689 d0 = dsp_get_data (s);
690 d1 = dsp_get_data (s);
691 ldebug ("write CSP register %d <- %#x\n", d1, d0);
692 if (d1 == 0x83) {
693 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
694 s->csp_reg83[s->csp_reg83r % 4] = d0;
695 s->csp_reg83r += 1;
697 else {
698 s->csp_regs[d1] = d0;
700 break;
702 case 0x0f:
703 d0 = dsp_get_data (s);
704 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
705 d0, s->csp_regs[d0], s->csp_mode);
706 if (d0 == 0x83) {
707 ldebug ("0x83[%d] -> %#x\n",
708 s->csp_reg83w,
709 s->csp_reg83[s->csp_reg83w % 4]);
710 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
711 s->csp_reg83w += 1;
713 else {
714 dsp_out_data (s, s->csp_regs[d0]);
716 break;
718 case 0x10:
719 d0 = dsp_get_data (s);
720 dolog ("cmd 0x10 d0=%#x\n", d0);
721 break;
723 case 0x14:
724 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
725 break;
727 case 0x40:
728 s->time_const = dsp_get_data (s);
729 ldebug ("set time const %d\n", s->time_const);
730 break;
732 case 0x42: /* FT2 sets output freq with this, go figure */
733 #if 0
734 dolog ("cmd 0x42 might not do what it think it should\n");
735 #endif
736 case 0x41:
737 s->freq = dsp_get_hilo (s);
738 ldebug ("set freq %d\n", s->freq);
739 break;
741 case 0x48:
742 s->block_size = dsp_get_lohi (s) + 1;
743 ldebug ("set dma block len %d\n", s->block_size);
744 break;
746 case 0x74:
747 case 0x75:
748 case 0x76:
749 case 0x77:
750 /* ADPCM stuff, ignore */
751 break;
753 case 0x80:
755 int freq, samples, bytes;
756 int64_t ticks;
758 freq = s->freq > 0 ? s->freq : 11025;
759 samples = dsp_get_lohi (s) + 1;
760 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
761 ticks = muldiv64 (bytes, get_ticks_per_sec (), freq);
762 if (ticks < get_ticks_per_sec () / 1024) {
763 qemu_irq_raise (s->pic);
765 else {
766 if (s->aux_ts) {
767 qemu_mod_timer (
768 s->aux_ts,
769 qemu_get_clock (vm_clock) + ticks
773 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
775 break;
777 case 0xe0:
778 d0 = dsp_get_data (s);
779 s->out_data_len = 0;
780 ldebug ("E0 data = %#x\n", d0);
781 dsp_out_data (s, ~d0);
782 break;
784 case 0xe2:
785 d0 = dsp_get_data (s);
786 ldebug ("E2 = %#x\n", d0);
787 break;
789 case 0xe4:
790 s->test_reg = dsp_get_data (s);
791 break;
793 case 0xf9:
794 d0 = dsp_get_data (s);
795 ldebug ("command 0xf9 with %#x\n", d0);
796 switch (d0) {
797 case 0x0e:
798 dsp_out_data (s, 0xff);
799 break;
801 case 0x0f:
802 dsp_out_data (s, 0x07);
803 break;
805 case 0x37:
806 dsp_out_data (s, 0x38);
807 break;
809 default:
810 dsp_out_data (s, 0x00);
811 break;
813 break;
815 default:
816 dolog ("complete: unrecognized command %#x\n", s->cmd);
817 return;
821 ldebug ("\n");
822 s->cmd = -1;
823 return;
826 static void legacy_reset (SB16State *s)
828 struct audsettings as;
830 s->freq = 11025;
831 s->fmt_signed = 0;
832 s->fmt_bits = 8;
833 s->fmt_stereo = 0;
835 as.freq = s->freq;
836 as.nchannels = 1;
837 as.fmt = AUD_FMT_U8;
838 as.endianness = 0;
840 s->voice = AUD_open_out (
841 &s->card,
842 s->voice,
843 "sb16",
845 SB_audio_callback,
849 /* Not sure about that... */
850 /* AUD_set_active_out (s->voice, 1); */
853 static void reset (SB16State *s)
855 qemu_irq_lower (s->pic);
856 if (s->dma_auto) {
857 qemu_irq_raise (s->pic);
858 qemu_irq_lower (s->pic);
861 s->mixer_regs[0x82] = 0;
862 s->dma_auto = 0;
863 s->in_index = 0;
864 s->out_data_len = 0;
865 s->left_till_irq = 0;
866 s->needed_bytes = 0;
867 s->block_size = -1;
868 s->nzero = 0;
869 s->highspeed = 0;
870 s->v2x6 = 0;
871 s->cmd = -1;
873 dsp_out_data (s, 0xaa);
874 speaker (s, 0);
875 control (s, 0);
876 legacy_reset (s);
879 static IO_WRITE_PROTO (dsp_write)
881 SB16State *s = opaque;
882 int iport;
884 iport = nport - s->port;
886 ldebug ("write %#x <- %#x\n", nport, val);
887 switch (iport) {
888 case 0x06:
889 switch (val) {
890 case 0x00:
891 if (s->v2x6 == 1) {
892 if (0 && s->highspeed) {
893 s->highspeed = 0;
894 qemu_irq_lower (s->pic);
895 control (s, 0);
897 else {
898 reset (s);
901 s->v2x6 = 0;
902 break;
904 case 0x01:
905 case 0x03: /* FreeBSD kludge */
906 s->v2x6 = 1;
907 break;
909 case 0xc6:
910 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
911 break;
913 case 0xb8: /* Panic */
914 reset (s);
915 break;
917 case 0x39:
918 dsp_out_data (s, 0x38);
919 reset (s);
920 s->v2x6 = 0x39;
921 break;
923 default:
924 s->v2x6 = val;
925 break;
927 break;
929 case 0x0c: /* write data or command | write status */
930 /* if (s->highspeed) */
931 /* break; */
933 if (0 == s->needed_bytes) {
934 command (s, val);
935 #if 0
936 if (0 == s->needed_bytes) {
937 log_dsp (s);
939 #endif
941 else {
942 if (s->in_index == sizeof (s->in2_data)) {
943 dolog ("in data overrun\n");
945 else {
946 s->in2_data[s->in_index++] = val;
947 if (s->in_index == s->needed_bytes) {
948 s->needed_bytes = 0;
949 complete (s);
950 #if 0
951 log_dsp (s);
952 #endif
956 break;
958 default:
959 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
960 break;
964 static IO_READ_PROTO (dsp_read)
966 SB16State *s = opaque;
967 int iport, retval, ack = 0;
969 iport = nport - s->port;
971 switch (iport) {
972 case 0x06: /* reset */
973 retval = 0xff;
974 break;
976 case 0x0a: /* read data */
977 if (s->out_data_len) {
978 retval = s->out_data[--s->out_data_len];
979 s->last_read_byte = retval;
981 else {
982 if (s->cmd != -1) {
983 dolog ("empty output buffer for command %#x\n",
984 s->cmd);
986 retval = s->last_read_byte;
987 /* goto error; */
989 break;
991 case 0x0c: /* 0 can write */
992 retval = s->can_write ? 0 : 0x80;
993 break;
995 case 0x0d: /* timer interrupt clear */
996 /* dolog ("timer interrupt clear\n"); */
997 retval = 0;
998 break;
1000 case 0x0e: /* data available status | irq 8 ack */
1001 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1002 if (s->mixer_regs[0x82] & 1) {
1003 ack = 1;
1004 s->mixer_regs[0x82] &= 1;
1005 qemu_irq_lower (s->pic);
1007 break;
1009 case 0x0f: /* irq 16 ack */
1010 retval = 0xff;
1011 if (s->mixer_regs[0x82] & 2) {
1012 ack = 1;
1013 s->mixer_regs[0x82] &= 2;
1014 qemu_irq_lower (s->pic);
1016 break;
1018 default:
1019 goto error;
1022 if (!ack) {
1023 ldebug ("read %#x -> %#x\n", nport, retval);
1026 return retval;
1028 error:
1029 dolog ("warning: dsp_read %#x error\n", nport);
1030 return 0xff;
1033 static void reset_mixer (SB16State *s)
1035 int i;
1037 memset (s->mixer_regs, 0xff, 0x7f);
1038 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1040 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1041 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1042 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1043 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1045 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1046 s->mixer_regs[0x0c] = 0;
1048 /* d5=output filt, d1=stereo switch */
1049 s->mixer_regs[0x0e] = 0;
1051 /* voice volume L d5,d7, R d1,d3 */
1052 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1053 /* master ... */
1054 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1055 /* MIDI ... */
1056 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1058 for (i = 0x30; i < 0x48; i++) {
1059 s->mixer_regs[i] = 0x20;
1063 static IO_WRITE_PROTO (mixer_write_indexb)
1065 SB16State *s = opaque;
1066 (void) nport;
1067 s->mixer_nreg = val;
1070 static IO_WRITE_PROTO (mixer_write_datab)
1072 SB16State *s = opaque;
1074 (void) nport;
1075 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1077 switch (s->mixer_nreg) {
1078 case 0x00:
1079 reset_mixer (s);
1080 break;
1082 case 0x80:
1084 int irq = irq_of_magic (val);
1085 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1086 if (irq > 0) {
1087 s->irq = irq;
1090 break;
1092 case 0x81:
1094 int dma, hdma;
1096 dma = ctz32 (val & 0xf);
1097 hdma = ctz32 (val & 0xf0);
1098 if (dma != s->dma || hdma != s->hdma) {
1099 dolog (
1100 "attempt to change DMA "
1101 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1102 dma, s->dma, hdma, s->hdma, val);
1104 #if 0
1105 s->dma = dma;
1106 s->hdma = hdma;
1107 #endif
1109 break;
1111 case 0x82:
1112 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1113 val);
1114 return;
1116 default:
1117 if (s->mixer_nreg >= 0x80) {
1118 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1120 break;
1123 s->mixer_regs[s->mixer_nreg] = val;
1126 static IO_WRITE_PROTO (mixer_write_indexw)
1128 mixer_write_indexb (opaque, nport, val & 0xff);
1129 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1132 static IO_READ_PROTO (mixer_read)
1134 SB16State *s = opaque;
1136 (void) nport;
1137 #ifndef DEBUG_SB16_MOST
1138 if (s->mixer_nreg != 0x82) {
1139 ldebug ("mixer_read[%#x] -> %#x\n",
1140 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1142 #else
1143 ldebug ("mixer_read[%#x] -> %#x\n",
1144 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1145 #endif
1146 return s->mixer_regs[s->mixer_nreg];
1149 static int write_audio (SB16State *s, int nchan, int dma_pos,
1150 int dma_len, int len)
1152 int temp, net;
1153 uint8_t tmpbuf[4096];
1155 temp = len;
1156 net = 0;
1158 while (temp) {
1159 int left = dma_len - dma_pos;
1160 int copied;
1161 size_t to_copy;
1163 to_copy = audio_MIN (temp, left);
1164 if (to_copy > sizeof (tmpbuf)) {
1165 to_copy = sizeof (tmpbuf);
1168 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1169 copied = AUD_write (s->voice, tmpbuf, copied);
1171 temp -= copied;
1172 dma_pos = (dma_pos + copied) % dma_len;
1173 net += copied;
1175 if (!copied) {
1176 break;
1180 return net;
1183 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1185 SB16State *s = opaque;
1186 int till, copy, written, free;
1188 if (s->block_size <= 0) {
1189 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1190 s->block_size, nchan, dma_pos, dma_len);
1191 return dma_pos;
1194 if (s->left_till_irq < 0) {
1195 s->left_till_irq = s->block_size;
1198 if (s->voice) {
1199 free = s->audio_free & ~s->align;
1200 if ((free <= 0) || !dma_len) {
1201 return dma_pos;
1204 else {
1205 free = dma_len;
1208 copy = free;
1209 till = s->left_till_irq;
1211 #ifdef DEBUG_SB16_MOST
1212 dolog ("pos:%06d %d till:%d len:%d\n",
1213 dma_pos, free, till, dma_len);
1214 #endif
1216 if (till <= copy) {
1217 if (0 == s->dma_auto) {
1218 copy = till;
1222 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1223 dma_pos = (dma_pos + written) % dma_len;
1224 s->left_till_irq -= written;
1226 if (s->left_till_irq <= 0) {
1227 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1228 qemu_irq_raise (s->pic);
1229 if (0 == s->dma_auto) {
1230 control (s, 0);
1231 speaker (s, 0);
1235 #ifdef DEBUG_SB16_MOST
1236 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1237 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1238 s->block_size);
1239 #endif
1241 while (s->left_till_irq <= 0) {
1242 s->left_till_irq = s->block_size + s->left_till_irq;
1245 return dma_pos;
1248 static void SB_audio_callback (void *opaque, int free)
1250 SB16State *s = opaque;
1251 s->audio_free = free;
1254 static void SB_save (QEMUFile *f, void *opaque)
1256 SB16State *s = opaque;
1258 qemu_put_be32 (f, s->irq);
1259 qemu_put_be32 (f, s->dma);
1260 qemu_put_be32 (f, s->hdma);
1261 qemu_put_be32 (f, s->port);
1262 qemu_put_be32 (f, s->ver);
1263 qemu_put_be32 (f, s->in_index);
1264 qemu_put_be32 (f, s->out_data_len);
1265 qemu_put_be32 (f, s->fmt_stereo);
1266 qemu_put_be32 (f, s->fmt_signed);
1267 qemu_put_be32 (f, s->fmt_bits);
1268 qemu_put_be32s (f, &s->fmt);
1269 qemu_put_be32 (f, s->dma_auto);
1270 qemu_put_be32 (f, s->block_size);
1271 qemu_put_be32 (f, s->fifo);
1272 qemu_put_be32 (f, s->freq);
1273 qemu_put_be32 (f, s->time_const);
1274 qemu_put_be32 (f, s->speaker);
1275 qemu_put_be32 (f, s->needed_bytes);
1276 qemu_put_be32 (f, s->cmd);
1277 qemu_put_be32 (f, s->use_hdma);
1278 qemu_put_be32 (f, s->highspeed);
1279 qemu_put_be32 (f, s->can_write);
1280 qemu_put_be32 (f, s->v2x6);
1282 qemu_put_8s (f, &s->csp_param);
1283 qemu_put_8s (f, &s->csp_value);
1284 qemu_put_8s (f, &s->csp_mode);
1285 qemu_put_8s (f, &s->csp_param);
1286 qemu_put_buffer (f, s->csp_regs, 256);
1287 qemu_put_8s (f, &s->csp_index);
1288 qemu_put_buffer (f, s->csp_reg83, 4);
1289 qemu_put_be32 (f, s->csp_reg83r);
1290 qemu_put_be32 (f, s->csp_reg83w);
1292 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1293 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1294 qemu_put_8s (f, &s->test_reg);
1295 qemu_put_8s (f, &s->last_read_byte);
1297 qemu_put_be32 (f, s->nzero);
1298 qemu_put_be32 (f, s->left_till_irq);
1299 qemu_put_be32 (f, s->dma_running);
1300 qemu_put_be32 (f, s->bytes_per_second);
1301 qemu_put_be32 (f, s->align);
1303 qemu_put_be32 (f, s->mixer_nreg);
1304 qemu_put_buffer (f, s->mixer_regs, 256);
1307 static int SB_load (QEMUFile *f, void *opaque, int version_id)
1309 SB16State *s = opaque;
1311 if (version_id != 1) {
1312 return -EINVAL;
1315 s->irq=qemu_get_be32 (f);
1316 s->dma=qemu_get_be32 (f);
1317 s->hdma=qemu_get_be32 (f);
1318 s->port=qemu_get_be32 (f);
1319 s->ver=qemu_get_be32 (f);
1320 s->in_index=qemu_get_be32 (f);
1321 s->out_data_len=qemu_get_be32 (f);
1322 s->fmt_stereo=qemu_get_be32 (f);
1323 s->fmt_signed=qemu_get_be32 (f);
1324 s->fmt_bits=qemu_get_be32 (f);
1325 qemu_get_be32s (f, &s->fmt);
1326 s->dma_auto=qemu_get_be32 (f);
1327 s->block_size=qemu_get_be32 (f);
1328 s->fifo=qemu_get_be32 (f);
1329 s->freq=qemu_get_be32 (f);
1330 s->time_const=qemu_get_be32 (f);
1331 s->speaker=qemu_get_be32 (f);
1332 s->needed_bytes=qemu_get_be32 (f);
1333 s->cmd=qemu_get_be32 (f);
1334 s->use_hdma=qemu_get_be32 (f);
1335 s->highspeed=qemu_get_be32 (f);
1336 s->can_write=qemu_get_be32 (f);
1337 s->v2x6=qemu_get_be32 (f);
1339 qemu_get_8s (f, &s->csp_param);
1340 qemu_get_8s (f, &s->csp_value);
1341 qemu_get_8s (f, &s->csp_mode);
1342 qemu_get_8s (f, &s->csp_param);
1343 qemu_get_buffer (f, s->csp_regs, 256);
1344 qemu_get_8s (f, &s->csp_index);
1345 qemu_get_buffer (f, s->csp_reg83, 4);
1346 s->csp_reg83r=qemu_get_be32 (f);
1347 s->csp_reg83w=qemu_get_be32 (f);
1349 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1350 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1351 qemu_get_8s (f, &s->test_reg);
1352 qemu_get_8s (f, &s->last_read_byte);
1354 s->nzero=qemu_get_be32 (f);
1355 s->left_till_irq=qemu_get_be32 (f);
1356 s->dma_running=qemu_get_be32 (f);
1357 s->bytes_per_second=qemu_get_be32 (f);
1358 s->align=qemu_get_be32 (f);
1360 s->mixer_nreg=qemu_get_be32 (f);
1361 qemu_get_buffer (f, s->mixer_regs, 256);
1363 if (s->voice) {
1364 AUD_close_out (&s->card, s->voice);
1365 s->voice = NULL;
1368 if (s->dma_running) {
1369 if (s->freq) {
1370 struct audsettings as;
1372 s->audio_free = 0;
1374 as.freq = s->freq;
1375 as.nchannels = 1 << s->fmt_stereo;
1376 as.fmt = s->fmt;
1377 as.endianness = 0;
1379 s->voice = AUD_open_out (
1380 &s->card,
1381 s->voice,
1382 "sb16",
1384 SB_audio_callback,
1389 control (s, 1);
1390 speaker (s, s->speaker);
1392 return 0;
1395 static int sb16_initfn (ISADevice *dev)
1397 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1398 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1399 SB16State *s;
1400 int i;
1402 s = DO_UPCAST (SB16State, dev, dev);
1404 s->cmd = -1;
1405 isa_init_irq (dev, &s->pic, s->irq);
1407 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1408 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1409 s->mixer_regs[0x82] = 2 << 5;
1411 s->csp_regs[5] = 1;
1412 s->csp_regs[9] = 0xf8;
1414 reset_mixer (s);
1415 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1416 if (!s->aux_ts) {
1417 dolog ("warning: Could not create auxiliary timer\n");
1420 for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
1421 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1424 for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
1425 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1428 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1429 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1430 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1431 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1433 DMA_register_channel (s->hdma, SB_read_DMA, s);
1434 DMA_register_channel (s->dma, SB_read_DMA, s);
1435 s->can_write = 1;
1437 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1438 AUD_register_card ("sb16", &s->card);
1439 return 0;
1442 int SB16_init (qemu_irq *pic)
1444 isa_create_simple ("sb16");
1445 return 0;
1448 static ISADeviceInfo sb16_info = {
1449 .qdev.name = "sb16",
1450 .qdev.desc = "Creative Sound Blaster 16",
1451 .qdev.size = sizeof (SB16State),
1452 .init = sb16_initfn,
1453 .qdev.props = (Property[]) {
1454 DEFINE_PROP_HEX32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1455 DEFINE_PROP_HEX32 ("iobase", SB16State, port, 0x220),
1456 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1457 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1458 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1459 DEFINE_PROP_END_OF_LIST (),
1463 static void sb16_register (void)
1465 isa_qdev_register (&sb16_info);
1467 device_init (sb16_register)