hw/riscv: spike: Remove compile time XLEN checks
[qemu/ar7.git] / hw / audio / sb16.c
blob8b207004102548cd2f9e29bf840ad0c24ce9e740
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.
25 #include "qemu/osdep.h"
26 #include "hw/audio/soundhw.h"
27 #include "audio/audio.h"
28 #include "hw/irq.h"
29 #include "hw/isa/isa.h"
30 #include "hw/qdev-properties.h"
31 #include "migration/vmstate.h"
32 #include "qemu/timer.h"
33 #include "qemu/host-utils.h"
34 #include "qemu/log.h"
35 #include "qemu/module.h"
36 #include "qapi/error.h"
37 #include "qom/object.h"
39 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
41 /* #define DEBUG */
42 /* #define DEBUG_SB16_MOST */
44 #ifdef DEBUG
45 #define ldebug(...) dolog (__VA_ARGS__)
46 #else
47 #define ldebug(...)
48 #endif
50 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
52 #define TYPE_SB16 "sb16"
53 OBJECT_DECLARE_SIMPLE_TYPE(SB16State, SB16)
55 struct SB16State {
56 ISADevice parent_obj;
58 QEMUSoundCard card;
59 qemu_irq pic;
60 uint32_t irq;
61 uint32_t dma;
62 uint32_t hdma;
63 uint32_t port;
64 uint32_t ver;
65 IsaDma *isa_dma;
66 IsaDma *isa_hdma;
68 int in_index;
69 int out_data_len;
70 int fmt_stereo;
71 int fmt_signed;
72 int fmt_bits;
73 AudioFormat fmt;
74 int dma_auto;
75 int block_size;
76 int fifo;
77 int freq;
78 int time_const;
79 int speaker;
80 int needed_bytes;
81 int cmd;
82 int use_hdma;
83 int highspeed;
84 int can_write;
86 int v2x6;
88 uint8_t csp_param;
89 uint8_t csp_value;
90 uint8_t csp_mode;
91 uint8_t csp_regs[256];
92 uint8_t csp_index;
93 uint8_t csp_reg83[4];
94 int csp_reg83r;
95 int csp_reg83w;
97 uint8_t in2_data[10];
98 uint8_t out_data[50];
99 uint8_t test_reg;
100 uint8_t last_read_byte;
101 int nzero;
103 int left_till_irq;
105 int dma_running;
106 int bytes_per_second;
107 int align;
108 int audio_free;
109 SWVoiceOut *voice;
111 QEMUTimer *aux_ts;
112 /* mixer state */
113 int mixer_nreg;
114 uint8_t mixer_regs[256];
115 PortioList portio_list;
118 static void SB_audio_callback (void *opaque, int free);
120 static int magic_of_irq (int irq)
122 switch (irq) {
123 case 5:
124 return 2;
125 case 7:
126 return 4;
127 case 9:
128 return 1;
129 case 10:
130 return 8;
131 default:
132 qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
133 return 2;
137 static int irq_of_magic (int magic)
139 switch (magic) {
140 case 1:
141 return 9;
142 case 2:
143 return 5;
144 case 4:
145 return 7;
146 case 8:
147 return 10;
148 default:
149 qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
150 return -1;
154 #if 0
155 static void log_dsp (SB16State *dsp)
157 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
158 dsp->fmt_stereo ? "Stereo" : "Mono",
159 dsp->fmt_signed ? "Signed" : "Unsigned",
160 dsp->fmt_bits,
161 dsp->dma_auto ? "Auto" : "Single",
162 dsp->block_size,
163 dsp->freq,
164 dsp->time_const,
165 dsp->speaker);
167 #endif
169 static void speaker (SB16State *s, int on)
171 s->speaker = on;
172 /* AUD_enable (s->voice, on); */
175 static void control (SB16State *s, int hold)
177 int dma = s->use_hdma ? s->hdma : s->dma;
178 IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
179 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
180 s->dma_running = hold;
182 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
184 if (hold) {
185 k->hold_DREQ(isa_dma, dma);
186 AUD_set_active_out (s->voice, 1);
188 else {
189 k->release_DREQ(isa_dma, dma);
190 AUD_set_active_out (s->voice, 0);
194 static void aux_timer (void *opaque)
196 SB16State *s = opaque;
197 s->can_write = 1;
198 qemu_irq_raise (s->pic);
201 #define DMA8_AUTO 1
202 #define DMA8_HIGH 2
204 static void continue_dma8 (SB16State *s)
206 if (s->freq > 0) {
207 struct audsettings as;
209 s->audio_free = 0;
211 as.freq = s->freq;
212 as.nchannels = 1 << s->fmt_stereo;
213 as.fmt = s->fmt;
214 as.endianness = 0;
216 s->voice = AUD_open_out (
217 &s->card,
218 s->voice,
219 "sb16",
221 SB_audio_callback,
226 control (s, 1);
229 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
231 s->fmt = AUDIO_FORMAT_U8;
232 s->use_hdma = 0;
233 s->fmt_bits = 8;
234 s->fmt_signed = 0;
235 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
236 if (-1 == s->time_const) {
237 if (s->freq <= 0)
238 s->freq = 11025;
240 else {
241 int tmp = (256 - s->time_const);
242 s->freq = (1000000 + (tmp / 2)) / tmp;
245 if (dma_len != -1) {
246 s->block_size = dma_len << s->fmt_stereo;
248 else {
249 /* This is apparently the only way to make both Act1/PL
250 and SecondReality/FC work
252 Act1 sets block size via command 0x48 and it's an odd number
253 SR does the same with even number
254 Both use stereo, and Creatives own documentation states that
255 0x48 sets block size in bytes less one.. go figure */
256 s->block_size &= ~s->fmt_stereo;
259 s->freq >>= s->fmt_stereo;
260 s->left_till_irq = s->block_size;
261 s->bytes_per_second = (s->freq << s->fmt_stereo);
262 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
263 s->dma_auto = (mask & DMA8_AUTO) != 0;
264 s->align = (1 << s->fmt_stereo) - 1;
266 if (s->block_size & s->align) {
267 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
268 " alignment %d\n", s->block_size, s->align + 1);
271 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
272 "dma %d, auto %d, fifo %d, high %d\n",
273 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
274 s->block_size, s->dma_auto, s->fifo, s->highspeed);
276 continue_dma8 (s);
277 speaker (s, 1);
280 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
282 s->use_hdma = cmd < 0xc0;
283 s->fifo = (cmd >> 1) & 1;
284 s->dma_auto = (cmd >> 2) & 1;
285 s->fmt_signed = (d0 >> 4) & 1;
286 s->fmt_stereo = (d0 >> 5) & 1;
288 switch (cmd >> 4) {
289 case 11:
290 s->fmt_bits = 16;
291 break;
293 case 12:
294 s->fmt_bits = 8;
295 break;
298 if (-1 != s->time_const) {
299 #if 1
300 int tmp = 256 - s->time_const;
301 s->freq = (1000000 + (tmp / 2)) / tmp;
302 #else
303 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
304 s->freq = 1000000 / ((255 - s->time_const));
305 #endif
306 s->time_const = -1;
309 s->block_size = dma_len + 1;
310 s->block_size <<= (s->fmt_bits == 16);
311 if (!s->dma_auto) {
312 /* It is clear that for DOOM and auto-init this value
313 shouldn't take stereo into account, while Miles Sound Systems
314 setsound.exe with single transfer mode wouldn't work without it
315 wonders of SB16 yet again */
316 s->block_size <<= s->fmt_stereo;
319 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
320 "dma %d, auto %d, fifo %d, high %d\n",
321 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
322 s->block_size, s->dma_auto, s->fifo, s->highspeed);
324 if (16 == s->fmt_bits) {
325 if (s->fmt_signed) {
326 s->fmt = AUDIO_FORMAT_S16;
328 else {
329 s->fmt = AUDIO_FORMAT_U16;
332 else {
333 if (s->fmt_signed) {
334 s->fmt = AUDIO_FORMAT_S8;
336 else {
337 s->fmt = AUDIO_FORMAT_U8;
341 s->left_till_irq = s->block_size;
343 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
344 s->highspeed = 0;
345 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
346 if (s->block_size & s->align) {
347 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
348 " alignment %d\n", s->block_size, s->align + 1);
351 if (s->freq) {
352 struct audsettings as;
354 s->audio_free = 0;
356 as.freq = s->freq;
357 as.nchannels = 1 << s->fmt_stereo;
358 as.fmt = s->fmt;
359 as.endianness = 0;
361 s->voice = AUD_open_out (
362 &s->card,
363 s->voice,
364 "sb16",
366 SB_audio_callback,
371 control (s, 1);
372 speaker (s, 1);
375 static inline void dsp_out_data (SB16State *s, uint8_t val)
377 ldebug ("outdata %#x\n", val);
378 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
379 s->out_data[s->out_data_len++] = val;
383 static inline uint8_t dsp_get_data (SB16State *s)
385 if (s->in_index) {
386 return s->in2_data[--s->in_index];
388 else {
389 dolog ("buffer underflow\n");
390 return 0;
394 static void command (SB16State *s, uint8_t cmd)
396 ldebug ("command %#x\n", cmd);
398 if (cmd > 0xaf && cmd < 0xd0) {
399 if (cmd & 8) {
400 qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
401 cmd);
404 switch (cmd >> 4) {
405 case 11:
406 case 12:
407 break;
408 default:
409 qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
411 s->needed_bytes = 3;
413 else {
414 s->needed_bytes = 0;
416 switch (cmd) {
417 case 0x03:
418 dsp_out_data (s, 0x10); /* s->csp_param); */
419 goto warn;
421 case 0x04:
422 s->needed_bytes = 1;
423 goto warn;
425 case 0x05:
426 s->needed_bytes = 2;
427 goto warn;
429 case 0x08:
430 /* __asm__ ("int3"); */
431 goto warn;
433 case 0x0e:
434 s->needed_bytes = 2;
435 goto warn;
437 case 0x09:
438 dsp_out_data (s, 0xf8);
439 goto warn;
441 case 0x0f:
442 s->needed_bytes = 1;
443 goto warn;
445 case 0x10:
446 s->needed_bytes = 1;
447 goto warn;
449 case 0x14:
450 s->needed_bytes = 2;
451 s->block_size = 0;
452 break;
454 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
455 dma_cmd8 (s, DMA8_AUTO, -1);
456 break;
458 case 0x20: /* Direct ADC, Juice/PL */
459 dsp_out_data (s, 0xff);
460 goto warn;
462 case 0x35:
463 qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
464 break;
466 case 0x40:
467 s->freq = -1;
468 s->time_const = -1;
469 s->needed_bytes = 1;
470 break;
472 case 0x41:
473 s->freq = -1;
474 s->time_const = -1;
475 s->needed_bytes = 2;
476 break;
478 case 0x42:
479 s->freq = -1;
480 s->time_const = -1;
481 s->needed_bytes = 2;
482 goto warn;
484 case 0x45:
485 dsp_out_data (s, 0xaa);
486 goto warn;
488 case 0x47: /* Continue Auto-Initialize DMA 16bit */
489 break;
491 case 0x48:
492 s->needed_bytes = 2;
493 break;
495 case 0x74:
496 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
497 qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
498 " implemented\n");
499 break;
501 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
502 s->needed_bytes = 2;
503 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
504 " implemented\n");
505 break;
507 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
508 s->needed_bytes = 2;
509 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
510 " implemented\n");
511 break;
513 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
514 s->needed_bytes = 2;
515 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
516 " not implemented\n");
517 break;
519 case 0x7d:
520 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
521 " ADPCM Reference\n");
522 qemu_log_mask(LOG_UNIMP, "not implemented\n");
523 break;
525 case 0x7f:
526 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
527 " ADPCM Reference\n");
528 qemu_log_mask(LOG_UNIMP, "not implemented\n");
529 break;
531 case 0x80:
532 s->needed_bytes = 2;
533 break;
535 case 0x90:
536 case 0x91:
537 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
538 break;
540 case 0xd0: /* halt DMA operation. 8bit */
541 control (s, 0);
542 break;
544 case 0xd1: /* speaker on */
545 speaker (s, 1);
546 break;
548 case 0xd3: /* speaker off */
549 speaker (s, 0);
550 break;
552 case 0xd4: /* continue DMA operation. 8bit */
553 /* KQ6 (or maybe Sierras audblst.drv in general) resets
554 the frequency between halt/continue */
555 continue_dma8 (s);
556 break;
558 case 0xd5: /* halt DMA operation. 16bit */
559 control (s, 0);
560 break;
562 case 0xd6: /* continue DMA operation. 16bit */
563 control (s, 1);
564 break;
566 case 0xd9: /* exit auto-init DMA after this block. 16bit */
567 s->dma_auto = 0;
568 break;
570 case 0xda: /* exit auto-init DMA after this block. 8bit */
571 s->dma_auto = 0;
572 break;
574 case 0xe0: /* DSP identification */
575 s->needed_bytes = 1;
576 break;
578 case 0xe1:
579 dsp_out_data (s, s->ver & 0xff);
580 dsp_out_data (s, s->ver >> 8);
581 break;
583 case 0xe2:
584 s->needed_bytes = 1;
585 goto warn;
587 case 0xe3:
589 int i;
590 for (i = sizeof (e3) - 1; i >= 0; --i)
591 dsp_out_data (s, e3[i]);
593 break;
595 case 0xe4: /* write test reg */
596 s->needed_bytes = 1;
597 break;
599 case 0xe7:
600 qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
601 break;
603 case 0xe8: /* read test reg */
604 dsp_out_data (s, s->test_reg);
605 break;
607 case 0xf2:
608 case 0xf3:
609 dsp_out_data (s, 0xaa);
610 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
611 qemu_irq_raise (s->pic);
612 break;
614 case 0xf9:
615 s->needed_bytes = 1;
616 goto warn;
618 case 0xfa:
619 dsp_out_data (s, 0);
620 goto warn;
622 case 0xfc: /* FIXME */
623 dsp_out_data (s, 0);
624 goto warn;
626 default:
627 qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
628 break;
632 if (!s->needed_bytes) {
633 ldebug ("\n");
636 exit:
637 if (!s->needed_bytes) {
638 s->cmd = -1;
640 else {
641 s->cmd = cmd;
643 return;
645 warn:
646 qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
647 " yet\n", cmd, s->needed_bytes);
648 goto exit;
652 static uint16_t dsp_get_lohi (SB16State *s)
654 uint8_t hi = dsp_get_data (s);
655 uint8_t lo = dsp_get_data (s);
656 return (hi << 8) | lo;
659 static uint16_t dsp_get_hilo (SB16State *s)
661 uint8_t lo = dsp_get_data (s);
662 uint8_t hi = dsp_get_data (s);
663 return (hi << 8) | lo;
666 static void complete (SB16State *s)
668 int d0, d1, d2;
669 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
670 s->cmd, s->in_index, s->needed_bytes);
672 if (s->cmd > 0xaf && s->cmd < 0xd0) {
673 d2 = dsp_get_data (s);
674 d1 = dsp_get_data (s);
675 d0 = dsp_get_data (s);
677 if (s->cmd & 8) {
678 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
679 s->cmd, d0, d1, d2);
681 else {
682 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
683 s->cmd, d0, d1, d2);
684 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
687 else {
688 switch (s->cmd) {
689 case 0x04:
690 s->csp_mode = dsp_get_data (s);
691 s->csp_reg83r = 0;
692 s->csp_reg83w = 0;
693 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
694 break;
696 case 0x05:
697 s->csp_param = dsp_get_data (s);
698 s->csp_value = dsp_get_data (s);
699 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
700 s->csp_param,
701 s->csp_value);
702 break;
704 case 0x0e:
705 d0 = dsp_get_data (s);
706 d1 = dsp_get_data (s);
707 ldebug ("write CSP register %d <- %#x\n", d1, d0);
708 if (d1 == 0x83) {
709 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
710 s->csp_reg83[s->csp_reg83r % 4] = d0;
711 s->csp_reg83r += 1;
713 else {
714 s->csp_regs[d1] = d0;
716 break;
718 case 0x0f:
719 d0 = dsp_get_data (s);
720 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
721 d0, s->csp_regs[d0], s->csp_mode);
722 if (d0 == 0x83) {
723 ldebug ("0x83[%d] -> %#x\n",
724 s->csp_reg83w,
725 s->csp_reg83[s->csp_reg83w % 4]);
726 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
727 s->csp_reg83w += 1;
729 else {
730 dsp_out_data (s, s->csp_regs[d0]);
732 break;
734 case 0x10:
735 d0 = dsp_get_data (s);
736 dolog ("cmd 0x10 d0=%#x\n", d0);
737 break;
739 case 0x14:
740 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
741 break;
743 case 0x40:
744 s->time_const = dsp_get_data (s);
745 ldebug ("set time const %d\n", s->time_const);
746 break;
748 case 0x41:
749 case 0x42:
751 * 0x41 is documented as setting the output sample rate,
752 * and 0x42 the input sample rate, but in fact SB16 hardware
753 * seems to have only a single sample rate under the hood,
754 * and FT2 sets output freq with this (go figure). Compare:
755 * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate
757 s->freq = dsp_get_hilo (s);
758 ldebug ("set freq %d\n", s->freq);
759 break;
761 case 0x48:
762 s->block_size = dsp_get_lohi (s) + 1;
763 ldebug ("set dma block len %d\n", s->block_size);
764 break;
766 case 0x74:
767 case 0x75:
768 case 0x76:
769 case 0x77:
770 /* ADPCM stuff, ignore */
771 break;
773 case 0x80:
775 int freq, samples, bytes;
776 int64_t ticks;
778 freq = s->freq > 0 ? s->freq : 11025;
779 samples = dsp_get_lohi (s) + 1;
780 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
781 ticks = muldiv64(bytes, NANOSECONDS_PER_SECOND, freq);
782 if (ticks < NANOSECONDS_PER_SECOND / 1024) {
783 qemu_irq_raise (s->pic);
785 else {
786 if (s->aux_ts) {
787 timer_mod (
788 s->aux_ts,
789 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks
793 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
795 break;
797 case 0xe0:
798 d0 = dsp_get_data (s);
799 s->out_data_len = 0;
800 ldebug ("E0 data = %#x\n", d0);
801 dsp_out_data (s, ~d0);
802 break;
804 case 0xe2:
805 #ifdef DEBUG
806 d0 = dsp_get_data (s);
807 dolog ("E2 = %#x\n", d0);
808 #endif
809 break;
811 case 0xe4:
812 s->test_reg = dsp_get_data (s);
813 break;
815 case 0xf9:
816 d0 = dsp_get_data (s);
817 ldebug ("command 0xf9 with %#x\n", d0);
818 switch (d0) {
819 case 0x0e:
820 dsp_out_data (s, 0xff);
821 break;
823 case 0x0f:
824 dsp_out_data (s, 0x07);
825 break;
827 case 0x37:
828 dsp_out_data (s, 0x38);
829 break;
831 default:
832 dsp_out_data (s, 0x00);
833 break;
835 break;
837 default:
838 qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
839 s->cmd);
840 return;
844 ldebug ("\n");
845 s->cmd = -1;
848 static void legacy_reset (SB16State *s)
850 struct audsettings as;
852 s->freq = 11025;
853 s->fmt_signed = 0;
854 s->fmt_bits = 8;
855 s->fmt_stereo = 0;
857 as.freq = s->freq;
858 as.nchannels = 1;
859 as.fmt = AUDIO_FORMAT_U8;
860 as.endianness = 0;
862 s->voice = AUD_open_out (
863 &s->card,
864 s->voice,
865 "sb16",
867 SB_audio_callback,
871 /* Not sure about that... */
872 /* AUD_set_active_out (s->voice, 1); */
875 static void reset (SB16State *s)
877 qemu_irq_lower (s->pic);
878 if (s->dma_auto) {
879 qemu_irq_raise (s->pic);
880 qemu_irq_lower (s->pic);
883 s->mixer_regs[0x82] = 0;
884 s->dma_auto = 0;
885 s->in_index = 0;
886 s->out_data_len = 0;
887 s->left_till_irq = 0;
888 s->needed_bytes = 0;
889 s->block_size = -1;
890 s->nzero = 0;
891 s->highspeed = 0;
892 s->v2x6 = 0;
893 s->cmd = -1;
895 dsp_out_data (s, 0xaa);
896 speaker (s, 0);
897 control (s, 0);
898 legacy_reset (s);
901 static void dsp_write(void *opaque, uint32_t nport, uint32_t val)
903 SB16State *s = opaque;
904 int iport;
906 iport = nport - s->port;
908 ldebug ("write %#x <- %#x\n", nport, val);
909 switch (iport) {
910 case 0x06:
911 switch (val) {
912 case 0x00:
913 if (s->v2x6 == 1) {
914 reset (s);
916 s->v2x6 = 0;
917 break;
919 case 0x01:
920 case 0x03: /* FreeBSD kludge */
921 s->v2x6 = 1;
922 break;
924 case 0xc6:
925 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
926 break;
928 case 0xb8: /* Panic */
929 reset (s);
930 break;
932 case 0x39:
933 dsp_out_data (s, 0x38);
934 reset (s);
935 s->v2x6 = 0x39;
936 break;
938 default:
939 s->v2x6 = val;
940 break;
942 break;
944 case 0x0c: /* write data or command | write status */
945 /* if (s->highspeed) */
946 /* break; */
948 if (s->needed_bytes == 0) {
949 command (s, val);
950 #if 0
951 if (0 == s->needed_bytes) {
952 log_dsp (s);
954 #endif
956 else {
957 if (s->in_index == sizeof (s->in2_data)) {
958 dolog ("in data overrun\n");
960 else {
961 s->in2_data[s->in_index++] = val;
962 if (s->in_index == s->needed_bytes) {
963 s->needed_bytes = 0;
964 complete (s);
965 #if 0
966 log_dsp (s);
967 #endif
971 break;
973 default:
974 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
975 break;
979 static uint32_t dsp_read(void *opaque, uint32_t nport)
981 SB16State *s = opaque;
982 int iport, retval, ack = 0;
984 iport = nport - s->port;
986 switch (iport) {
987 case 0x06: /* reset */
988 retval = 0xff;
989 break;
991 case 0x0a: /* read data */
992 if (s->out_data_len) {
993 retval = s->out_data[--s->out_data_len];
994 s->last_read_byte = retval;
996 else {
997 if (s->cmd != -1) {
998 dolog ("empty output buffer for command %#x\n",
999 s->cmd);
1001 retval = s->last_read_byte;
1002 /* goto error; */
1004 break;
1006 case 0x0c: /* 0 can write */
1007 retval = s->can_write ? 0 : 0x80;
1008 break;
1010 case 0x0d: /* timer interrupt clear */
1011 /* dolog ("timer interrupt clear\n"); */
1012 retval = 0;
1013 break;
1015 case 0x0e: /* data available status | irq 8 ack */
1016 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1017 if (s->mixer_regs[0x82] & 1) {
1018 ack = 1;
1019 s->mixer_regs[0x82] &= ~1;
1020 qemu_irq_lower (s->pic);
1022 break;
1024 case 0x0f: /* irq 16 ack */
1025 retval = 0xff;
1026 if (s->mixer_regs[0x82] & 2) {
1027 ack = 1;
1028 s->mixer_regs[0x82] &= ~2;
1029 qemu_irq_lower (s->pic);
1031 break;
1033 default:
1034 goto error;
1037 if (!ack) {
1038 ldebug ("read %#x -> %#x\n", nport, retval);
1041 return retval;
1043 error:
1044 dolog ("warning: dsp_read %#x error\n", nport);
1045 return 0xff;
1048 static void reset_mixer (SB16State *s)
1050 int i;
1052 memset (s->mixer_regs, 0xff, 0x7f);
1053 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1055 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1056 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1057 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1058 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1060 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1061 s->mixer_regs[0x0c] = 0;
1063 /* d5=output filt, d1=stereo switch */
1064 s->mixer_regs[0x0e] = 0;
1066 /* voice volume L d5,d7, R d1,d3 */
1067 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1068 /* master ... */
1069 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1070 /* MIDI ... */
1071 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1073 for (i = 0x30; i < 0x48; i++) {
1074 s->mixer_regs[i] = 0x20;
1078 static void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1080 SB16State *s = opaque;
1081 (void) nport;
1082 s->mixer_nreg = val;
1085 static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
1087 SB16State *s = opaque;
1089 (void) nport;
1090 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1092 switch (s->mixer_nreg) {
1093 case 0x00:
1094 reset_mixer (s);
1095 break;
1097 case 0x80:
1099 int irq = irq_of_magic (val);
1100 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1101 if (irq > 0) {
1102 s->irq = irq;
1105 break;
1107 case 0x81:
1109 int dma, hdma;
1111 dma = ctz32 (val & 0xf);
1112 hdma = ctz32 (val & 0xf0);
1113 if (dma != s->dma || hdma != s->hdma) {
1114 qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
1115 " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
1116 hdma, s->hdma, val);
1118 #if 0
1119 s->dma = dma;
1120 s->hdma = hdma;
1121 #endif
1123 break;
1125 case 0x82:
1126 qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
1127 " register (val=%#x)\n", val);
1128 return;
1130 default:
1131 if (s->mixer_nreg >= 0x80) {
1132 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1134 break;
1137 s->mixer_regs[s->mixer_nreg] = val;
1140 static uint32_t mixer_read(void *opaque, uint32_t nport)
1142 SB16State *s = opaque;
1144 (void) nport;
1145 #ifndef DEBUG_SB16_MOST
1146 if (s->mixer_nreg != 0x82) {
1147 ldebug ("mixer_read[%#x] -> %#x\n",
1148 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1150 #else
1151 ldebug ("mixer_read[%#x] -> %#x\n",
1152 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1153 #endif
1154 return s->mixer_regs[s->mixer_nreg];
1157 static int write_audio (SB16State *s, int nchan, int dma_pos,
1158 int dma_len, int len)
1160 IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
1161 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
1162 int temp, net;
1163 uint8_t tmpbuf[4096];
1165 temp = len;
1166 net = 0;
1168 while (temp) {
1169 int left = dma_len - dma_pos;
1170 int copied;
1171 size_t to_copy;
1173 to_copy = MIN (temp, left);
1174 if (to_copy > sizeof (tmpbuf)) {
1175 to_copy = sizeof (tmpbuf);
1178 copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
1179 copied = AUD_write (s->voice, tmpbuf, copied);
1181 temp -= copied;
1182 dma_pos = (dma_pos + copied) % dma_len;
1183 net += copied;
1185 if (!copied) {
1186 break;
1190 return net;
1193 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1195 SB16State *s = opaque;
1196 int till, copy, written, free;
1198 if (s->block_size <= 0) {
1199 qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
1200 " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
1201 dma_pos, dma_len);
1202 return dma_pos;
1205 if (s->left_till_irq < 0) {
1206 s->left_till_irq = s->block_size;
1209 if (s->voice) {
1210 free = s->audio_free & ~s->align;
1211 if ((free <= 0) || !dma_len) {
1212 return dma_pos;
1215 else {
1216 free = dma_len;
1219 copy = free;
1220 till = s->left_till_irq;
1222 #ifdef DEBUG_SB16_MOST
1223 dolog ("pos:%06d %d till:%d len:%d\n",
1224 dma_pos, free, till, dma_len);
1225 #endif
1227 if (till <= copy) {
1228 if (s->dma_auto == 0) {
1229 copy = till;
1233 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1234 dma_pos = (dma_pos + written) % dma_len;
1235 s->left_till_irq -= written;
1237 if (s->left_till_irq <= 0) {
1238 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1239 qemu_irq_raise (s->pic);
1240 if (s->dma_auto == 0) {
1241 control (s, 0);
1242 speaker (s, 0);
1246 #ifdef DEBUG_SB16_MOST
1247 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1248 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1249 s->block_size);
1250 #endif
1252 while (s->left_till_irq <= 0) {
1253 s->left_till_irq = s->block_size + s->left_till_irq;
1256 return dma_pos;
1259 static void SB_audio_callback (void *opaque, int free)
1261 SB16State *s = opaque;
1262 s->audio_free = free;
1265 static int sb16_post_load (void *opaque, int version_id)
1267 SB16State *s = opaque;
1269 if (s->voice) {
1270 AUD_close_out (&s->card, s->voice);
1271 s->voice = NULL;
1274 if (s->dma_running) {
1275 if (s->freq) {
1276 struct audsettings as;
1278 s->audio_free = 0;
1280 as.freq = s->freq;
1281 as.nchannels = 1 << s->fmt_stereo;
1282 as.fmt = s->fmt;
1283 as.endianness = 0;
1285 s->voice = AUD_open_out (
1286 &s->card,
1287 s->voice,
1288 "sb16",
1290 SB_audio_callback,
1295 control (s, 1);
1296 speaker (s, s->speaker);
1298 return 0;
1301 static const VMStateDescription vmstate_sb16 = {
1302 .name = "sb16",
1303 .version_id = 1,
1304 .minimum_version_id = 1,
1305 .post_load = sb16_post_load,
1306 .fields = (VMStateField[]) {
1307 VMSTATE_UINT32 (irq, SB16State),
1308 VMSTATE_UINT32 (dma, SB16State),
1309 VMSTATE_UINT32 (hdma, SB16State),
1310 VMSTATE_UINT32 (port, SB16State),
1311 VMSTATE_UINT32 (ver, SB16State),
1312 VMSTATE_INT32 (in_index, SB16State),
1313 VMSTATE_INT32 (out_data_len, SB16State),
1314 VMSTATE_INT32 (fmt_stereo, SB16State),
1315 VMSTATE_INT32 (fmt_signed, SB16State),
1316 VMSTATE_INT32 (fmt_bits, SB16State),
1317 VMSTATE_UINT32 (fmt, SB16State),
1318 VMSTATE_INT32 (dma_auto, SB16State),
1319 VMSTATE_INT32 (block_size, SB16State),
1320 VMSTATE_INT32 (fifo, SB16State),
1321 VMSTATE_INT32 (freq, SB16State),
1322 VMSTATE_INT32 (time_const, SB16State),
1323 VMSTATE_INT32 (speaker, SB16State),
1324 VMSTATE_INT32 (needed_bytes, SB16State),
1325 VMSTATE_INT32 (cmd, SB16State),
1326 VMSTATE_INT32 (use_hdma, SB16State),
1327 VMSTATE_INT32 (highspeed, SB16State),
1328 VMSTATE_INT32 (can_write, SB16State),
1329 VMSTATE_INT32 (v2x6, SB16State),
1331 VMSTATE_UINT8 (csp_param, SB16State),
1332 VMSTATE_UINT8 (csp_value, SB16State),
1333 VMSTATE_UINT8 (csp_mode, SB16State),
1334 VMSTATE_UINT8 (csp_param, SB16State),
1335 VMSTATE_BUFFER (csp_regs, SB16State),
1336 VMSTATE_UINT8 (csp_index, SB16State),
1337 VMSTATE_BUFFER (csp_reg83, SB16State),
1338 VMSTATE_INT32 (csp_reg83r, SB16State),
1339 VMSTATE_INT32 (csp_reg83w, SB16State),
1341 VMSTATE_BUFFER (in2_data, SB16State),
1342 VMSTATE_BUFFER (out_data, SB16State),
1343 VMSTATE_UINT8 (test_reg, SB16State),
1344 VMSTATE_UINT8 (last_read_byte, SB16State),
1346 VMSTATE_INT32 (nzero, SB16State),
1347 VMSTATE_INT32 (left_till_irq, SB16State),
1348 VMSTATE_INT32 (dma_running, SB16State),
1349 VMSTATE_INT32 (bytes_per_second, SB16State),
1350 VMSTATE_INT32 (align, SB16State),
1352 VMSTATE_INT32 (mixer_nreg, SB16State),
1353 VMSTATE_BUFFER (mixer_regs, SB16State),
1355 VMSTATE_END_OF_LIST ()
1359 static const MemoryRegionPortio sb16_ioport_list[] = {
1360 { 4, 1, 1, .write = mixer_write_indexb },
1361 { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1362 { 6, 1, 1, .read = dsp_read, .write = dsp_write },
1363 { 10, 1, 1, .read = dsp_read },
1364 { 12, 1, 1, .write = dsp_write },
1365 { 12, 4, 1, .read = dsp_read },
1366 PORTIO_END_OF_LIST (),
1370 static void sb16_initfn (Object *obj)
1372 SB16State *s = SB16 (obj);
1374 s->cmd = -1;
1377 static void sb16_realizefn (DeviceState *dev, Error **errp)
1379 ISADevice *isadev = ISA_DEVICE (dev);
1380 SB16State *s = SB16 (dev);
1381 IsaDmaClass *k;
1383 s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
1384 s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
1385 if (!s->isa_dma || !s->isa_hdma) {
1386 error_setg(errp, "ISA controller does not support DMA");
1387 return;
1390 isa_init_irq (isadev, &s->pic, s->irq);
1392 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1393 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1394 s->mixer_regs[0x82] = 2 << 5;
1396 s->csp_regs[5] = 1;
1397 s->csp_regs[9] = 0xf8;
1399 reset_mixer (s);
1400 s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1401 if (!s->aux_ts) {
1402 error_setg(errp, "warning: Could not create auxiliary timer");
1405 isa_register_portio_list(isadev, &s->portio_list, s->port,
1406 sb16_ioport_list, s, "sb16");
1408 k = ISADMA_GET_CLASS(s->isa_hdma);
1409 k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1411 k = ISADMA_GET_CLASS(s->isa_dma);
1412 k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1414 s->can_write = 1;
1416 AUD_register_card ("sb16", &s->card);
1419 static Property sb16_properties[] = {
1420 DEFINE_AUDIO_PROPERTIES(SB16State, card),
1421 DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1422 DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
1423 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1424 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1425 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1426 DEFINE_PROP_END_OF_LIST (),
1429 static void sb16_class_initfn (ObjectClass *klass, void *data)
1431 DeviceClass *dc = DEVICE_CLASS (klass);
1433 dc->realize = sb16_realizefn;
1434 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1435 dc->desc = "Creative Sound Blaster 16";
1436 dc->vmsd = &vmstate_sb16;
1437 device_class_set_props(dc, sb16_properties);
1440 static const TypeInfo sb16_info = {
1441 .name = TYPE_SB16,
1442 .parent = TYPE_ISA_DEVICE,
1443 .instance_size = sizeof (SB16State),
1444 .instance_init = sb16_initfn,
1445 .class_init = sb16_class_initfn,
1448 static void sb16_register_types (void)
1450 type_register_static (&sb16_info);
1451 deprecated_register_soundhw("sb16", "Creative Sound Blaster 16",
1452 1, TYPE_SB16);
1455 type_init (sb16_register_types)