vmxnet3: Introduce 'x-old-msi-offsets' back-compat property
[qemu.git] / hw / audio / sb16.c
blob995435f2404b5762ace4a09ae252471d6bcc1609
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/hw.h"
25 #include "hw/audio/audio.h"
26 #include "audio/audio.h"
27 #include "hw/isa/isa.h"
28 #include "hw/qdev.h"
29 #include "qemu/timer.h"
30 #include "qemu/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 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
45 #define TYPE_SB16 "sb16"
46 #define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
48 typedef struct SB16State {
49 ISADevice parent_obj;
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 = muldiv64 (bytes, get_ticks_per_sec (), freq);
761 if (ticks < get_ticks_per_sec () / 1024) {
762 qemu_irq_raise (s->pic);
764 else {
765 if (s->aux_ts) {
766 timer_mod (
767 s->aux_ts,
768 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 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 #ifdef DEBUG
785 d0 = dsp_get_data (s);
786 dolog ("E2 = %#x\n", d0);
787 #endif
788 break;
790 case 0xe4:
791 s->test_reg = dsp_get_data (s);
792 break;
794 case 0xf9:
795 d0 = dsp_get_data (s);
796 ldebug ("command 0xf9 with %#x\n", d0);
797 switch (d0) {
798 case 0x0e:
799 dsp_out_data (s, 0xff);
800 break;
802 case 0x0f:
803 dsp_out_data (s, 0x07);
804 break;
806 case 0x37:
807 dsp_out_data (s, 0x38);
808 break;
810 default:
811 dsp_out_data (s, 0x00);
812 break;
814 break;
816 default:
817 dolog ("complete: unrecognized command %#x\n", s->cmd);
818 return;
822 ldebug ("\n");
823 s->cmd = -1;
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 void dsp_write(void *opaque, uint32_t nport, uint32_t val)
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 reset (s);
894 s->v2x6 = 0;
895 break;
897 case 0x01:
898 case 0x03: /* FreeBSD kludge */
899 s->v2x6 = 1;
900 break;
902 case 0xc6:
903 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
904 break;
906 case 0xb8: /* Panic */
907 reset (s);
908 break;
910 case 0x39:
911 dsp_out_data (s, 0x38);
912 reset (s);
913 s->v2x6 = 0x39;
914 break;
916 default:
917 s->v2x6 = val;
918 break;
920 break;
922 case 0x0c: /* write data or command | write status */
923 /* if (s->highspeed) */
924 /* break; */
926 if (s->needed_bytes == 0) {
927 command (s, val);
928 #if 0
929 if (0 == s->needed_bytes) {
930 log_dsp (s);
932 #endif
934 else {
935 if (s->in_index == sizeof (s->in2_data)) {
936 dolog ("in data overrun\n");
938 else {
939 s->in2_data[s->in_index++] = val;
940 if (s->in_index == s->needed_bytes) {
941 s->needed_bytes = 0;
942 complete (s);
943 #if 0
944 log_dsp (s);
945 #endif
949 break;
951 default:
952 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
953 break;
957 static uint32_t dsp_read(void *opaque, uint32_t nport)
959 SB16State *s = opaque;
960 int iport, retval, ack = 0;
962 iport = nport - s->port;
964 switch (iport) {
965 case 0x06: /* reset */
966 retval = 0xff;
967 break;
969 case 0x0a: /* read data */
970 if (s->out_data_len) {
971 retval = s->out_data[--s->out_data_len];
972 s->last_read_byte = retval;
974 else {
975 if (s->cmd != -1) {
976 dolog ("empty output buffer for command %#x\n",
977 s->cmd);
979 retval = s->last_read_byte;
980 /* goto error; */
982 break;
984 case 0x0c: /* 0 can write */
985 retval = s->can_write ? 0 : 0x80;
986 break;
988 case 0x0d: /* timer interrupt clear */
989 /* dolog ("timer interrupt clear\n"); */
990 retval = 0;
991 break;
993 case 0x0e: /* data available status | irq 8 ack */
994 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
995 if (s->mixer_regs[0x82] & 1) {
996 ack = 1;
997 s->mixer_regs[0x82] &= ~1;
998 qemu_irq_lower (s->pic);
1000 break;
1002 case 0x0f: /* irq 16 ack */
1003 retval = 0xff;
1004 if (s->mixer_regs[0x82] & 2) {
1005 ack = 1;
1006 s->mixer_regs[0x82] &= ~2;
1007 qemu_irq_lower (s->pic);
1009 break;
1011 default:
1012 goto error;
1015 if (!ack) {
1016 ldebug ("read %#x -> %#x\n", nport, retval);
1019 return retval;
1021 error:
1022 dolog ("warning: dsp_read %#x error\n", nport);
1023 return 0xff;
1026 static void reset_mixer (SB16State *s)
1028 int i;
1030 memset (s->mixer_regs, 0xff, 0x7f);
1031 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1033 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1034 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1035 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1036 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1038 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1039 s->mixer_regs[0x0c] = 0;
1041 /* d5=output filt, d1=stereo switch */
1042 s->mixer_regs[0x0e] = 0;
1044 /* voice volume L d5,d7, R d1,d3 */
1045 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1046 /* master ... */
1047 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1048 /* MIDI ... */
1049 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1051 for (i = 0x30; i < 0x48; i++) {
1052 s->mixer_regs[i] = 0x20;
1056 static void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1058 SB16State *s = opaque;
1059 (void) nport;
1060 s->mixer_nreg = val;
1063 static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
1065 SB16State *s = opaque;
1067 (void) nport;
1068 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1070 switch (s->mixer_nreg) {
1071 case 0x00:
1072 reset_mixer (s);
1073 break;
1075 case 0x80:
1077 int irq = irq_of_magic (val);
1078 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1079 if (irq > 0) {
1080 s->irq = irq;
1083 break;
1085 case 0x81:
1087 int dma, hdma;
1089 dma = ctz32 (val & 0xf);
1090 hdma = ctz32 (val & 0xf0);
1091 if (dma != s->dma || hdma != s->hdma) {
1092 dolog (
1093 "attempt to change DMA "
1094 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1095 dma, s->dma, hdma, s->hdma, val);
1097 #if 0
1098 s->dma = dma;
1099 s->hdma = hdma;
1100 #endif
1102 break;
1104 case 0x82:
1105 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1106 val);
1107 return;
1109 default:
1110 if (s->mixer_nreg >= 0x80) {
1111 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1113 break;
1116 s->mixer_regs[s->mixer_nreg] = val;
1119 static uint32_t mixer_read(void *opaque, uint32_t nport)
1121 SB16State *s = opaque;
1123 (void) nport;
1124 #ifndef DEBUG_SB16_MOST
1125 if (s->mixer_nreg != 0x82) {
1126 ldebug ("mixer_read[%#x] -> %#x\n",
1127 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1129 #else
1130 ldebug ("mixer_read[%#x] -> %#x\n",
1131 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1132 #endif
1133 return s->mixer_regs[s->mixer_nreg];
1136 static int write_audio (SB16State *s, int nchan, int dma_pos,
1137 int dma_len, int len)
1139 int temp, net;
1140 uint8_t tmpbuf[4096];
1142 temp = len;
1143 net = 0;
1145 while (temp) {
1146 int left = dma_len - dma_pos;
1147 int copied;
1148 size_t to_copy;
1150 to_copy = audio_MIN (temp, left);
1151 if (to_copy > sizeof (tmpbuf)) {
1152 to_copy = sizeof (tmpbuf);
1155 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1156 copied = AUD_write (s->voice, tmpbuf, copied);
1158 temp -= copied;
1159 dma_pos = (dma_pos + copied) % dma_len;
1160 net += copied;
1162 if (!copied) {
1163 break;
1167 return net;
1170 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1172 SB16State *s = opaque;
1173 int till, copy, written, free;
1175 if (s->block_size <= 0) {
1176 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1177 s->block_size, nchan, dma_pos, dma_len);
1178 return dma_pos;
1181 if (s->left_till_irq < 0) {
1182 s->left_till_irq = s->block_size;
1185 if (s->voice) {
1186 free = s->audio_free & ~s->align;
1187 if ((free <= 0) || !dma_len) {
1188 return dma_pos;
1191 else {
1192 free = dma_len;
1195 copy = free;
1196 till = s->left_till_irq;
1198 #ifdef DEBUG_SB16_MOST
1199 dolog ("pos:%06d %d till:%d len:%d\n",
1200 dma_pos, free, till, dma_len);
1201 #endif
1203 if (till <= copy) {
1204 if (s->dma_auto == 0) {
1205 copy = till;
1209 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1210 dma_pos = (dma_pos + written) % dma_len;
1211 s->left_till_irq -= written;
1213 if (s->left_till_irq <= 0) {
1214 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1215 qemu_irq_raise (s->pic);
1216 if (s->dma_auto == 0) {
1217 control (s, 0);
1218 speaker (s, 0);
1222 #ifdef DEBUG_SB16_MOST
1223 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1224 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1225 s->block_size);
1226 #endif
1228 while (s->left_till_irq <= 0) {
1229 s->left_till_irq = s->block_size + s->left_till_irq;
1232 return dma_pos;
1235 static void SB_audio_callback (void *opaque, int free)
1237 SB16State *s = opaque;
1238 s->audio_free = free;
1241 static int sb16_post_load (void *opaque, int version_id)
1243 SB16State *s = opaque;
1245 if (s->voice) {
1246 AUD_close_out (&s->card, s->voice);
1247 s->voice = NULL;
1250 if (s->dma_running) {
1251 if (s->freq) {
1252 struct audsettings as;
1254 s->audio_free = 0;
1256 as.freq = s->freq;
1257 as.nchannels = 1 << s->fmt_stereo;
1258 as.fmt = s->fmt;
1259 as.endianness = 0;
1261 s->voice = AUD_open_out (
1262 &s->card,
1263 s->voice,
1264 "sb16",
1266 SB_audio_callback,
1271 control (s, 1);
1272 speaker (s, s->speaker);
1274 return 0;
1277 static const VMStateDescription vmstate_sb16 = {
1278 .name = "sb16",
1279 .version_id = 1,
1280 .minimum_version_id = 1,
1281 .post_load = sb16_post_load,
1282 .fields = (VMStateField[]) {
1283 VMSTATE_UINT32 (irq, SB16State),
1284 VMSTATE_UINT32 (dma, SB16State),
1285 VMSTATE_UINT32 (hdma, SB16State),
1286 VMSTATE_UINT32 (port, SB16State),
1287 VMSTATE_UINT32 (ver, SB16State),
1288 VMSTATE_INT32 (in_index, SB16State),
1289 VMSTATE_INT32 (out_data_len, SB16State),
1290 VMSTATE_INT32 (fmt_stereo, SB16State),
1291 VMSTATE_INT32 (fmt_signed, SB16State),
1292 VMSTATE_INT32 (fmt_bits, SB16State),
1293 VMSTATE_UINT32 (fmt, SB16State),
1294 VMSTATE_INT32 (dma_auto, SB16State),
1295 VMSTATE_INT32 (block_size, SB16State),
1296 VMSTATE_INT32 (fifo, SB16State),
1297 VMSTATE_INT32 (freq, SB16State),
1298 VMSTATE_INT32 (time_const, SB16State),
1299 VMSTATE_INT32 (speaker, SB16State),
1300 VMSTATE_INT32 (needed_bytes, SB16State),
1301 VMSTATE_INT32 (cmd, SB16State),
1302 VMSTATE_INT32 (use_hdma, SB16State),
1303 VMSTATE_INT32 (highspeed, SB16State),
1304 VMSTATE_INT32 (can_write, SB16State),
1305 VMSTATE_INT32 (v2x6, SB16State),
1307 VMSTATE_UINT8 (csp_param, SB16State),
1308 VMSTATE_UINT8 (csp_value, SB16State),
1309 VMSTATE_UINT8 (csp_mode, SB16State),
1310 VMSTATE_UINT8 (csp_param, SB16State),
1311 VMSTATE_BUFFER (csp_regs, SB16State),
1312 VMSTATE_UINT8 (csp_index, SB16State),
1313 VMSTATE_BUFFER (csp_reg83, SB16State),
1314 VMSTATE_INT32 (csp_reg83r, SB16State),
1315 VMSTATE_INT32 (csp_reg83w, SB16State),
1317 VMSTATE_BUFFER (in2_data, SB16State),
1318 VMSTATE_BUFFER (out_data, SB16State),
1319 VMSTATE_UINT8 (test_reg, SB16State),
1320 VMSTATE_UINT8 (last_read_byte, SB16State),
1322 VMSTATE_INT32 (nzero, SB16State),
1323 VMSTATE_INT32 (left_till_irq, SB16State),
1324 VMSTATE_INT32 (dma_running, SB16State),
1325 VMSTATE_INT32 (bytes_per_second, SB16State),
1326 VMSTATE_INT32 (align, SB16State),
1328 VMSTATE_INT32 (mixer_nreg, SB16State),
1329 VMSTATE_BUFFER (mixer_regs, SB16State),
1331 VMSTATE_END_OF_LIST ()
1335 static const MemoryRegionPortio sb16_ioport_list[] = {
1336 { 4, 1, 1, .write = mixer_write_indexb },
1337 { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1338 { 6, 1, 1, .read = dsp_read, .write = dsp_write },
1339 { 10, 1, 1, .read = dsp_read },
1340 { 12, 1, 1, .write = dsp_write },
1341 { 12, 4, 1, .read = dsp_read },
1342 PORTIO_END_OF_LIST (),
1346 static void sb16_initfn (Object *obj)
1348 SB16State *s = SB16 (obj);
1350 s->cmd = -1;
1353 static void sb16_realizefn (DeviceState *dev, Error **errp)
1355 ISADevice *isadev = ISA_DEVICE (dev);
1356 SB16State *s = SB16 (dev);
1358 isa_init_irq (isadev, &s->pic, s->irq);
1360 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1361 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1362 s->mixer_regs[0x82] = 2 << 5;
1364 s->csp_regs[5] = 1;
1365 s->csp_regs[9] = 0xf8;
1367 reset_mixer (s);
1368 s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1369 if (!s->aux_ts) {
1370 dolog ("warning: Could not create auxiliary timer\n");
1373 isa_register_portio_list (isadev, s->port, sb16_ioport_list, s, "sb16");
1375 DMA_register_channel (s->hdma, SB_read_DMA, s);
1376 DMA_register_channel (s->dma, SB_read_DMA, s);
1377 s->can_write = 1;
1379 AUD_register_card ("sb16", &s->card);
1382 static int SB16_init (ISABus *bus)
1384 isa_create_simple (bus, TYPE_SB16);
1385 return 0;
1388 static Property sb16_properties[] = {
1389 DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1390 DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
1391 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1392 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1393 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1394 DEFINE_PROP_END_OF_LIST (),
1397 static void sb16_class_initfn (ObjectClass *klass, void *data)
1399 DeviceClass *dc = DEVICE_CLASS (klass);
1401 dc->realize = sb16_realizefn;
1402 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1403 dc->desc = "Creative Sound Blaster 16";
1404 dc->vmsd = &vmstate_sb16;
1405 dc->props = sb16_properties;
1408 static const TypeInfo sb16_info = {
1409 .name = TYPE_SB16,
1410 .parent = TYPE_ISA_DEVICE,
1411 .instance_size = sizeof (SB16State),
1412 .instance_init = sb16_initfn,
1413 .class_init = sb16_class_initfn,
1416 static void sb16_register_types (void)
1418 type_register_static (&sb16_info);
1419 isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init);
1422 type_init (sb16_register_types)