memory: unify loops to sync dirty log bitmap
[qemu/ar7.git] / hw / audio / sb16.c
blob31de264ab7bc37d02c128d84f479bd45beba5314
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 "qemu/osdep.h"
25 #include "hw/hw.h"
26 #include "hw/audio/soundhw.h"
27 #include "audio/audio.h"
28 #include "hw/isa/isa.h"
29 #include "hw/qdev.h"
30 #include "qemu/timer.h"
31 #include "qemu/host-utils.h"
32 #include "qemu/log.h"
33 #include "qapi/error.h"
35 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
37 /* #define DEBUG */
38 /* #define DEBUG_SB16_MOST */
40 #ifdef DEBUG
41 #define ldebug(...) dolog (__VA_ARGS__)
42 #else
43 #define ldebug(...)
44 #endif
46 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
48 #define TYPE_SB16 "sb16"
49 #define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
51 typedef struct SB16State {
52 ISADevice parent_obj;
54 QEMUSoundCard card;
55 qemu_irq pic;
56 uint32_t irq;
57 uint32_t dma;
58 uint32_t hdma;
59 uint32_t port;
60 uint32_t ver;
61 IsaDma *isa_dma;
62 IsaDma *isa_hdma;
64 int in_index;
65 int out_data_len;
66 int fmt_stereo;
67 int fmt_signed;
68 int fmt_bits;
69 audfmt_e fmt;
70 int dma_auto;
71 int block_size;
72 int fifo;
73 int freq;
74 int time_const;
75 int speaker;
76 int needed_bytes;
77 int cmd;
78 int use_hdma;
79 int highspeed;
80 int can_write;
82 int v2x6;
84 uint8_t csp_param;
85 uint8_t csp_value;
86 uint8_t csp_mode;
87 uint8_t csp_regs[256];
88 uint8_t csp_index;
89 uint8_t csp_reg83[4];
90 int csp_reg83r;
91 int csp_reg83w;
93 uint8_t in2_data[10];
94 uint8_t out_data[50];
95 uint8_t test_reg;
96 uint8_t last_read_byte;
97 int nzero;
99 int left_till_irq;
101 int dma_running;
102 int bytes_per_second;
103 int align;
104 int audio_free;
105 SWVoiceOut *voice;
107 QEMUTimer *aux_ts;
108 /* mixer state */
109 int mixer_nreg;
110 uint8_t mixer_regs[256];
111 PortioList portio_list;
112 } SB16State;
114 static void SB_audio_callback (void *opaque, int free);
116 static int magic_of_irq (int irq)
118 switch (irq) {
119 case 5:
120 return 2;
121 case 7:
122 return 4;
123 case 9:
124 return 1;
125 case 10:
126 return 8;
127 default:
128 qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
129 return 2;
133 static int irq_of_magic (int magic)
135 switch (magic) {
136 case 1:
137 return 9;
138 case 2:
139 return 5;
140 case 4:
141 return 7;
142 case 8:
143 return 10;
144 default:
145 qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
146 return -1;
150 #if 0
151 static void log_dsp (SB16State *dsp)
153 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
154 dsp->fmt_stereo ? "Stereo" : "Mono",
155 dsp->fmt_signed ? "Signed" : "Unsigned",
156 dsp->fmt_bits,
157 dsp->dma_auto ? "Auto" : "Single",
158 dsp->block_size,
159 dsp->freq,
160 dsp->time_const,
161 dsp->speaker);
163 #endif
165 static void speaker (SB16State *s, int on)
167 s->speaker = on;
168 /* AUD_enable (s->voice, on); */
171 static void control (SB16State *s, int hold)
173 int dma = s->use_hdma ? s->hdma : s->dma;
174 IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
175 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
176 s->dma_running = hold;
178 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
180 if (hold) {
181 k->hold_DREQ(isa_dma, dma);
182 AUD_set_active_out (s->voice, 1);
184 else {
185 k->release_DREQ(isa_dma, dma);
186 AUD_set_active_out (s->voice, 0);
190 static void aux_timer (void *opaque)
192 SB16State *s = opaque;
193 s->can_write = 1;
194 qemu_irq_raise (s->pic);
197 #define DMA8_AUTO 1
198 #define DMA8_HIGH 2
200 static void continue_dma8 (SB16State *s)
202 if (s->freq > 0) {
203 struct audsettings as;
205 s->audio_free = 0;
207 as.freq = s->freq;
208 as.nchannels = 1 << s->fmt_stereo;
209 as.fmt = s->fmt;
210 as.endianness = 0;
212 s->voice = AUD_open_out (
213 &s->card,
214 s->voice,
215 "sb16",
217 SB_audio_callback,
222 control (s, 1);
225 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
227 s->fmt = AUD_FMT_U8;
228 s->use_hdma = 0;
229 s->fmt_bits = 8;
230 s->fmt_signed = 0;
231 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
232 if (-1 == s->time_const) {
233 if (s->freq <= 0)
234 s->freq = 11025;
236 else {
237 int tmp = (256 - s->time_const);
238 s->freq = (1000000 + (tmp / 2)) / tmp;
241 if (dma_len != -1) {
242 s->block_size = dma_len << s->fmt_stereo;
244 else {
245 /* This is apparently the only way to make both Act1/PL
246 and SecondReality/FC work
248 Act1 sets block size via command 0x48 and it's an odd number
249 SR does the same with even number
250 Both use stereo, and Creatives own documentation states that
251 0x48 sets block size in bytes less one.. go figure */
252 s->block_size &= ~s->fmt_stereo;
255 s->freq >>= s->fmt_stereo;
256 s->left_till_irq = s->block_size;
257 s->bytes_per_second = (s->freq << s->fmt_stereo);
258 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
259 s->dma_auto = (mask & DMA8_AUTO) != 0;
260 s->align = (1 << s->fmt_stereo) - 1;
262 if (s->block_size & s->align) {
263 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
264 " alignment %d\n", s->block_size, s->align + 1);
267 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
268 "dma %d, auto %d, fifo %d, high %d\n",
269 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
270 s->block_size, s->dma_auto, s->fifo, s->highspeed);
272 continue_dma8 (s);
273 speaker (s, 1);
276 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
278 s->use_hdma = cmd < 0xc0;
279 s->fifo = (cmd >> 1) & 1;
280 s->dma_auto = (cmd >> 2) & 1;
281 s->fmt_signed = (d0 >> 4) & 1;
282 s->fmt_stereo = (d0 >> 5) & 1;
284 switch (cmd >> 4) {
285 case 11:
286 s->fmt_bits = 16;
287 break;
289 case 12:
290 s->fmt_bits = 8;
291 break;
294 if (-1 != s->time_const) {
295 #if 1
296 int tmp = 256 - s->time_const;
297 s->freq = (1000000 + (tmp / 2)) / tmp;
298 #else
299 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
300 s->freq = 1000000 / ((255 - s->time_const));
301 #endif
302 s->time_const = -1;
305 s->block_size = dma_len + 1;
306 s->block_size <<= (s->fmt_bits == 16);
307 if (!s->dma_auto) {
308 /* It is clear that for DOOM and auto-init this value
309 shouldn't take stereo into account, while Miles Sound Systems
310 setsound.exe with single transfer mode wouldn't work without it
311 wonders of SB16 yet again */
312 s->block_size <<= s->fmt_stereo;
315 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
316 "dma %d, auto %d, fifo %d, high %d\n",
317 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
318 s->block_size, s->dma_auto, s->fifo, s->highspeed);
320 if (16 == s->fmt_bits) {
321 if (s->fmt_signed) {
322 s->fmt = AUD_FMT_S16;
324 else {
325 s->fmt = AUD_FMT_U16;
328 else {
329 if (s->fmt_signed) {
330 s->fmt = AUD_FMT_S8;
332 else {
333 s->fmt = AUD_FMT_U8;
337 s->left_till_irq = s->block_size;
339 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
340 s->highspeed = 0;
341 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
342 if (s->block_size & s->align) {
343 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
344 " alignment %d\n", s->block_size, s->align + 1);
347 if (s->freq) {
348 struct audsettings as;
350 s->audio_free = 0;
352 as.freq = s->freq;
353 as.nchannels = 1 << s->fmt_stereo;
354 as.fmt = s->fmt;
355 as.endianness = 0;
357 s->voice = AUD_open_out (
358 &s->card,
359 s->voice,
360 "sb16",
362 SB_audio_callback,
367 control (s, 1);
368 speaker (s, 1);
371 static inline void dsp_out_data (SB16State *s, uint8_t val)
373 ldebug ("outdata %#x\n", val);
374 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
375 s->out_data[s->out_data_len++] = val;
379 static inline uint8_t dsp_get_data (SB16State *s)
381 if (s->in_index) {
382 return s->in2_data[--s->in_index];
384 else {
385 dolog ("buffer underflow\n");
386 return 0;
390 static void command (SB16State *s, uint8_t cmd)
392 ldebug ("command %#x\n", cmd);
394 if (cmd > 0xaf && cmd < 0xd0) {
395 if (cmd & 8) {
396 qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
397 cmd);
400 switch (cmd >> 4) {
401 case 11:
402 case 12:
403 break;
404 default:
405 qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
407 s->needed_bytes = 3;
409 else {
410 s->needed_bytes = 0;
412 switch (cmd) {
413 case 0x03:
414 dsp_out_data (s, 0x10); /* s->csp_param); */
415 goto warn;
417 case 0x04:
418 s->needed_bytes = 1;
419 goto warn;
421 case 0x05:
422 s->needed_bytes = 2;
423 goto warn;
425 case 0x08:
426 /* __asm__ ("int3"); */
427 goto warn;
429 case 0x0e:
430 s->needed_bytes = 2;
431 goto warn;
433 case 0x09:
434 dsp_out_data (s, 0xf8);
435 goto warn;
437 case 0x0f:
438 s->needed_bytes = 1;
439 goto warn;
441 case 0x10:
442 s->needed_bytes = 1;
443 goto warn;
445 case 0x14:
446 s->needed_bytes = 2;
447 s->block_size = 0;
448 break;
450 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
451 dma_cmd8 (s, DMA8_AUTO, -1);
452 break;
454 case 0x20: /* Direct ADC, Juice/PL */
455 dsp_out_data (s, 0xff);
456 goto warn;
458 case 0x35:
459 qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
460 break;
462 case 0x40:
463 s->freq = -1;
464 s->time_const = -1;
465 s->needed_bytes = 1;
466 break;
468 case 0x41:
469 s->freq = -1;
470 s->time_const = -1;
471 s->needed_bytes = 2;
472 break;
474 case 0x42:
475 s->freq = -1;
476 s->time_const = -1;
477 s->needed_bytes = 2;
478 goto warn;
480 case 0x45:
481 dsp_out_data (s, 0xaa);
482 goto warn;
484 case 0x47: /* Continue Auto-Initialize DMA 16bit */
485 break;
487 case 0x48:
488 s->needed_bytes = 2;
489 break;
491 case 0x74:
492 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
493 qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
494 " implemented\n");
495 break;
497 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
498 s->needed_bytes = 2;
499 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
500 " implemented\n");
501 break;
503 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
504 s->needed_bytes = 2;
505 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
506 " implemented\n");
507 break;
509 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
510 s->needed_bytes = 2;
511 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
512 " not implemented\n");
513 break;
515 case 0x7d:
516 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
517 " ADPCM Reference\n");
518 qemu_log_mask(LOG_UNIMP, "not implemented\n");
519 break;
521 case 0x7f:
522 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
523 " ADPCM Reference\n");
524 qemu_log_mask(LOG_UNIMP, "not implemented\n");
525 break;
527 case 0x80:
528 s->needed_bytes = 2;
529 break;
531 case 0x90:
532 case 0x91:
533 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
534 break;
536 case 0xd0: /* halt DMA operation. 8bit */
537 control (s, 0);
538 break;
540 case 0xd1: /* speaker on */
541 speaker (s, 1);
542 break;
544 case 0xd3: /* speaker off */
545 speaker (s, 0);
546 break;
548 case 0xd4: /* continue DMA operation. 8bit */
549 /* KQ6 (or maybe Sierras audblst.drv in general) resets
550 the frequency between halt/continue */
551 continue_dma8 (s);
552 break;
554 case 0xd5: /* halt DMA operation. 16bit */
555 control (s, 0);
556 break;
558 case 0xd6: /* continue DMA operation. 16bit */
559 control (s, 1);
560 break;
562 case 0xd9: /* exit auto-init DMA after this block. 16bit */
563 s->dma_auto = 0;
564 break;
566 case 0xda: /* exit auto-init DMA after this block. 8bit */
567 s->dma_auto = 0;
568 break;
570 case 0xe0: /* DSP identification */
571 s->needed_bytes = 1;
572 break;
574 case 0xe1:
575 dsp_out_data (s, s->ver & 0xff);
576 dsp_out_data (s, s->ver >> 8);
577 break;
579 case 0xe2:
580 s->needed_bytes = 1;
581 goto warn;
583 case 0xe3:
585 int i;
586 for (i = sizeof (e3) - 1; i >= 0; --i)
587 dsp_out_data (s, e3[i]);
589 break;
591 case 0xe4: /* write test reg */
592 s->needed_bytes = 1;
593 break;
595 case 0xe7:
596 qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
597 break;
599 case 0xe8: /* read test reg */
600 dsp_out_data (s, s->test_reg);
601 break;
603 case 0xf2:
604 case 0xf3:
605 dsp_out_data (s, 0xaa);
606 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
607 qemu_irq_raise (s->pic);
608 break;
610 case 0xf9:
611 s->needed_bytes = 1;
612 goto warn;
614 case 0xfa:
615 dsp_out_data (s, 0);
616 goto warn;
618 case 0xfc: /* FIXME */
619 dsp_out_data (s, 0);
620 goto warn;
622 default:
623 qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
624 break;
628 if (!s->needed_bytes) {
629 ldebug ("\n");
632 exit:
633 if (!s->needed_bytes) {
634 s->cmd = -1;
636 else {
637 s->cmd = cmd;
639 return;
641 warn:
642 qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
643 " yet\n", cmd, s->needed_bytes);
644 goto exit;
648 static uint16_t dsp_get_lohi (SB16State *s)
650 uint8_t hi = dsp_get_data (s);
651 uint8_t lo = dsp_get_data (s);
652 return (hi << 8) | lo;
655 static uint16_t dsp_get_hilo (SB16State *s)
657 uint8_t lo = dsp_get_data (s);
658 uint8_t hi = dsp_get_data (s);
659 return (hi << 8) | lo;
662 static void complete (SB16State *s)
664 int d0, d1, d2;
665 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
666 s->cmd, s->in_index, s->needed_bytes);
668 if (s->cmd > 0xaf && s->cmd < 0xd0) {
669 d2 = dsp_get_data (s);
670 d1 = dsp_get_data (s);
671 d0 = dsp_get_data (s);
673 if (s->cmd & 8) {
674 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
675 s->cmd, d0, d1, d2);
677 else {
678 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
679 s->cmd, d0, d1, d2);
680 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
683 else {
684 switch (s->cmd) {
685 case 0x04:
686 s->csp_mode = dsp_get_data (s);
687 s->csp_reg83r = 0;
688 s->csp_reg83w = 0;
689 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
690 break;
692 case 0x05:
693 s->csp_param = dsp_get_data (s);
694 s->csp_value = dsp_get_data (s);
695 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
696 s->csp_param,
697 s->csp_value);
698 break;
700 case 0x0e:
701 d0 = dsp_get_data (s);
702 d1 = dsp_get_data (s);
703 ldebug ("write CSP register %d <- %#x\n", d1, d0);
704 if (d1 == 0x83) {
705 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
706 s->csp_reg83[s->csp_reg83r % 4] = d0;
707 s->csp_reg83r += 1;
709 else {
710 s->csp_regs[d1] = d0;
712 break;
714 case 0x0f:
715 d0 = dsp_get_data (s);
716 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
717 d0, s->csp_regs[d0], s->csp_mode);
718 if (d0 == 0x83) {
719 ldebug ("0x83[%d] -> %#x\n",
720 s->csp_reg83w,
721 s->csp_reg83[s->csp_reg83w % 4]);
722 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
723 s->csp_reg83w += 1;
725 else {
726 dsp_out_data (s, s->csp_regs[d0]);
728 break;
730 case 0x10:
731 d0 = dsp_get_data (s);
732 dolog ("cmd 0x10 d0=%#x\n", d0);
733 break;
735 case 0x14:
736 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
737 break;
739 case 0x40:
740 s->time_const = dsp_get_data (s);
741 ldebug ("set time const %d\n", s->time_const);
742 break;
744 case 0x42: /* FT2 sets output freq with this, go figure */
745 qemu_log_mask(LOG_UNIMP, "cmd 0x42 might not do what it think it"
746 " should\n");
747 case 0x41:
748 s->freq = dsp_get_hilo (s);
749 ldebug ("set freq %d\n", s->freq);
750 break;
752 case 0x48:
753 s->block_size = dsp_get_lohi (s) + 1;
754 ldebug ("set dma block len %d\n", s->block_size);
755 break;
757 case 0x74:
758 case 0x75:
759 case 0x76:
760 case 0x77:
761 /* ADPCM stuff, ignore */
762 break;
764 case 0x80:
766 int freq, samples, bytes;
767 int64_t ticks;
769 freq = s->freq > 0 ? s->freq : 11025;
770 samples = dsp_get_lohi (s) + 1;
771 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
772 ticks = muldiv64(bytes, NANOSECONDS_PER_SECOND, freq);
773 if (ticks < NANOSECONDS_PER_SECOND / 1024) {
774 qemu_irq_raise (s->pic);
776 else {
777 if (s->aux_ts) {
778 timer_mod (
779 s->aux_ts,
780 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks
784 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
786 break;
788 case 0xe0:
789 d0 = dsp_get_data (s);
790 s->out_data_len = 0;
791 ldebug ("E0 data = %#x\n", d0);
792 dsp_out_data (s, ~d0);
793 break;
795 case 0xe2:
796 #ifdef DEBUG
797 d0 = dsp_get_data (s);
798 dolog ("E2 = %#x\n", d0);
799 #endif
800 break;
802 case 0xe4:
803 s->test_reg = dsp_get_data (s);
804 break;
806 case 0xf9:
807 d0 = dsp_get_data (s);
808 ldebug ("command 0xf9 with %#x\n", d0);
809 switch (d0) {
810 case 0x0e:
811 dsp_out_data (s, 0xff);
812 break;
814 case 0x0f:
815 dsp_out_data (s, 0x07);
816 break;
818 case 0x37:
819 dsp_out_data (s, 0x38);
820 break;
822 default:
823 dsp_out_data (s, 0x00);
824 break;
826 break;
828 default:
829 qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
830 s->cmd);
831 return;
835 ldebug ("\n");
836 s->cmd = -1;
839 static void legacy_reset (SB16State *s)
841 struct audsettings as;
843 s->freq = 11025;
844 s->fmt_signed = 0;
845 s->fmt_bits = 8;
846 s->fmt_stereo = 0;
848 as.freq = s->freq;
849 as.nchannels = 1;
850 as.fmt = AUD_FMT_U8;
851 as.endianness = 0;
853 s->voice = AUD_open_out (
854 &s->card,
855 s->voice,
856 "sb16",
858 SB_audio_callback,
862 /* Not sure about that... */
863 /* AUD_set_active_out (s->voice, 1); */
866 static void reset (SB16State *s)
868 qemu_irq_lower (s->pic);
869 if (s->dma_auto) {
870 qemu_irq_raise (s->pic);
871 qemu_irq_lower (s->pic);
874 s->mixer_regs[0x82] = 0;
875 s->dma_auto = 0;
876 s->in_index = 0;
877 s->out_data_len = 0;
878 s->left_till_irq = 0;
879 s->needed_bytes = 0;
880 s->block_size = -1;
881 s->nzero = 0;
882 s->highspeed = 0;
883 s->v2x6 = 0;
884 s->cmd = -1;
886 dsp_out_data (s, 0xaa);
887 speaker (s, 0);
888 control (s, 0);
889 legacy_reset (s);
892 static void dsp_write(void *opaque, uint32_t nport, uint32_t val)
894 SB16State *s = opaque;
895 int iport;
897 iport = nport - s->port;
899 ldebug ("write %#x <- %#x\n", nport, val);
900 switch (iport) {
901 case 0x06:
902 switch (val) {
903 case 0x00:
904 if (s->v2x6 == 1) {
905 reset (s);
907 s->v2x6 = 0;
908 break;
910 case 0x01:
911 case 0x03: /* FreeBSD kludge */
912 s->v2x6 = 1;
913 break;
915 case 0xc6:
916 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
917 break;
919 case 0xb8: /* Panic */
920 reset (s);
921 break;
923 case 0x39:
924 dsp_out_data (s, 0x38);
925 reset (s);
926 s->v2x6 = 0x39;
927 break;
929 default:
930 s->v2x6 = val;
931 break;
933 break;
935 case 0x0c: /* write data or command | write status */
936 /* if (s->highspeed) */
937 /* break; */
939 if (s->needed_bytes == 0) {
940 command (s, val);
941 #if 0
942 if (0 == s->needed_bytes) {
943 log_dsp (s);
945 #endif
947 else {
948 if (s->in_index == sizeof (s->in2_data)) {
949 dolog ("in data overrun\n");
951 else {
952 s->in2_data[s->in_index++] = val;
953 if (s->in_index == s->needed_bytes) {
954 s->needed_bytes = 0;
955 complete (s);
956 #if 0
957 log_dsp (s);
958 #endif
962 break;
964 default:
965 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
966 break;
970 static uint32_t dsp_read(void *opaque, uint32_t nport)
972 SB16State *s = opaque;
973 int iport, retval, ack = 0;
975 iport = nport - s->port;
977 switch (iport) {
978 case 0x06: /* reset */
979 retval = 0xff;
980 break;
982 case 0x0a: /* read data */
983 if (s->out_data_len) {
984 retval = s->out_data[--s->out_data_len];
985 s->last_read_byte = retval;
987 else {
988 if (s->cmd != -1) {
989 dolog ("empty output buffer for command %#x\n",
990 s->cmd);
992 retval = s->last_read_byte;
993 /* goto error; */
995 break;
997 case 0x0c: /* 0 can write */
998 retval = s->can_write ? 0 : 0x80;
999 break;
1001 case 0x0d: /* timer interrupt clear */
1002 /* dolog ("timer interrupt clear\n"); */
1003 retval = 0;
1004 break;
1006 case 0x0e: /* data available status | irq 8 ack */
1007 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1008 if (s->mixer_regs[0x82] & 1) {
1009 ack = 1;
1010 s->mixer_regs[0x82] &= ~1;
1011 qemu_irq_lower (s->pic);
1013 break;
1015 case 0x0f: /* irq 16 ack */
1016 retval = 0xff;
1017 if (s->mixer_regs[0x82] & 2) {
1018 ack = 1;
1019 s->mixer_regs[0x82] &= ~2;
1020 qemu_irq_lower (s->pic);
1022 break;
1024 default:
1025 goto error;
1028 if (!ack) {
1029 ldebug ("read %#x -> %#x\n", nport, retval);
1032 return retval;
1034 error:
1035 dolog ("warning: dsp_read %#x error\n", nport);
1036 return 0xff;
1039 static void reset_mixer (SB16State *s)
1041 int i;
1043 memset (s->mixer_regs, 0xff, 0x7f);
1044 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1046 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1047 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1048 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1049 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1051 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1052 s->mixer_regs[0x0c] = 0;
1054 /* d5=output filt, d1=stereo switch */
1055 s->mixer_regs[0x0e] = 0;
1057 /* voice volume L d5,d7, R d1,d3 */
1058 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1059 /* master ... */
1060 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1061 /* MIDI ... */
1062 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1064 for (i = 0x30; i < 0x48; i++) {
1065 s->mixer_regs[i] = 0x20;
1069 static void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1071 SB16State *s = opaque;
1072 (void) nport;
1073 s->mixer_nreg = val;
1076 static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
1078 SB16State *s = opaque;
1080 (void) nport;
1081 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1083 switch (s->mixer_nreg) {
1084 case 0x00:
1085 reset_mixer (s);
1086 break;
1088 case 0x80:
1090 int irq = irq_of_magic (val);
1091 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1092 if (irq > 0) {
1093 s->irq = irq;
1096 break;
1098 case 0x81:
1100 int dma, hdma;
1102 dma = ctz32 (val & 0xf);
1103 hdma = ctz32 (val & 0xf0);
1104 if (dma != s->dma || hdma != s->hdma) {
1105 qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
1106 " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
1107 hdma, s->hdma, val);
1109 #if 0
1110 s->dma = dma;
1111 s->hdma = hdma;
1112 #endif
1114 break;
1116 case 0x82:
1117 qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
1118 " register (val=%#x)\n", val);
1119 return;
1121 default:
1122 if (s->mixer_nreg >= 0x80) {
1123 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1125 break;
1128 s->mixer_regs[s->mixer_nreg] = val;
1131 static uint32_t mixer_read(void *opaque, uint32_t nport)
1133 SB16State *s = opaque;
1135 (void) nport;
1136 #ifndef DEBUG_SB16_MOST
1137 if (s->mixer_nreg != 0x82) {
1138 ldebug ("mixer_read[%#x] -> %#x\n",
1139 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1141 #else
1142 ldebug ("mixer_read[%#x] -> %#x\n",
1143 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1144 #endif
1145 return s->mixer_regs[s->mixer_nreg];
1148 static int write_audio (SB16State *s, int nchan, int dma_pos,
1149 int dma_len, int len)
1151 IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
1152 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
1153 int temp, net;
1154 uint8_t tmpbuf[4096];
1156 temp = len;
1157 net = 0;
1159 while (temp) {
1160 int left = dma_len - dma_pos;
1161 int copied;
1162 size_t to_copy;
1164 to_copy = audio_MIN (temp, left);
1165 if (to_copy > sizeof (tmpbuf)) {
1166 to_copy = sizeof (tmpbuf);
1169 copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
1170 copied = AUD_write (s->voice, tmpbuf, copied);
1172 temp -= copied;
1173 dma_pos = (dma_pos + copied) % dma_len;
1174 net += copied;
1176 if (!copied) {
1177 break;
1181 return net;
1184 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1186 SB16State *s = opaque;
1187 int till, copy, written, free;
1189 if (s->block_size <= 0) {
1190 qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
1191 " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
1192 dma_pos, dma_len);
1193 return dma_pos;
1196 if (s->left_till_irq < 0) {
1197 s->left_till_irq = s->block_size;
1200 if (s->voice) {
1201 free = s->audio_free & ~s->align;
1202 if ((free <= 0) || !dma_len) {
1203 return dma_pos;
1206 else {
1207 free = dma_len;
1210 copy = free;
1211 till = s->left_till_irq;
1213 #ifdef DEBUG_SB16_MOST
1214 dolog ("pos:%06d %d till:%d len:%d\n",
1215 dma_pos, free, till, dma_len);
1216 #endif
1218 if (till <= copy) {
1219 if (s->dma_auto == 0) {
1220 copy = till;
1224 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1225 dma_pos = (dma_pos + written) % dma_len;
1226 s->left_till_irq -= written;
1228 if (s->left_till_irq <= 0) {
1229 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1230 qemu_irq_raise (s->pic);
1231 if (s->dma_auto == 0) {
1232 control (s, 0);
1233 speaker (s, 0);
1237 #ifdef DEBUG_SB16_MOST
1238 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1239 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1240 s->block_size);
1241 #endif
1243 while (s->left_till_irq <= 0) {
1244 s->left_till_irq = s->block_size + s->left_till_irq;
1247 return dma_pos;
1250 static void SB_audio_callback (void *opaque, int free)
1252 SB16State *s = opaque;
1253 s->audio_free = free;
1256 static int sb16_post_load (void *opaque, int version_id)
1258 SB16State *s = opaque;
1260 if (s->voice) {
1261 AUD_close_out (&s->card, s->voice);
1262 s->voice = NULL;
1265 if (s->dma_running) {
1266 if (s->freq) {
1267 struct audsettings as;
1269 s->audio_free = 0;
1271 as.freq = s->freq;
1272 as.nchannels = 1 << s->fmt_stereo;
1273 as.fmt = s->fmt;
1274 as.endianness = 0;
1276 s->voice = AUD_open_out (
1277 &s->card,
1278 s->voice,
1279 "sb16",
1281 SB_audio_callback,
1286 control (s, 1);
1287 speaker (s, s->speaker);
1289 return 0;
1292 static const VMStateDescription vmstate_sb16 = {
1293 .name = "sb16",
1294 .version_id = 1,
1295 .minimum_version_id = 1,
1296 .post_load = sb16_post_load,
1297 .fields = (VMStateField[]) {
1298 VMSTATE_UINT32 (irq, SB16State),
1299 VMSTATE_UINT32 (dma, SB16State),
1300 VMSTATE_UINT32 (hdma, SB16State),
1301 VMSTATE_UINT32 (port, SB16State),
1302 VMSTATE_UINT32 (ver, SB16State),
1303 VMSTATE_INT32 (in_index, SB16State),
1304 VMSTATE_INT32 (out_data_len, SB16State),
1305 VMSTATE_INT32 (fmt_stereo, SB16State),
1306 VMSTATE_INT32 (fmt_signed, SB16State),
1307 VMSTATE_INT32 (fmt_bits, SB16State),
1308 VMSTATE_UINT32 (fmt, SB16State),
1309 VMSTATE_INT32 (dma_auto, SB16State),
1310 VMSTATE_INT32 (block_size, SB16State),
1311 VMSTATE_INT32 (fifo, SB16State),
1312 VMSTATE_INT32 (freq, SB16State),
1313 VMSTATE_INT32 (time_const, SB16State),
1314 VMSTATE_INT32 (speaker, SB16State),
1315 VMSTATE_INT32 (needed_bytes, SB16State),
1316 VMSTATE_INT32 (cmd, SB16State),
1317 VMSTATE_INT32 (use_hdma, SB16State),
1318 VMSTATE_INT32 (highspeed, SB16State),
1319 VMSTATE_INT32 (can_write, SB16State),
1320 VMSTATE_INT32 (v2x6, SB16State),
1322 VMSTATE_UINT8 (csp_param, SB16State),
1323 VMSTATE_UINT8 (csp_value, SB16State),
1324 VMSTATE_UINT8 (csp_mode, SB16State),
1325 VMSTATE_UINT8 (csp_param, SB16State),
1326 VMSTATE_BUFFER (csp_regs, SB16State),
1327 VMSTATE_UINT8 (csp_index, SB16State),
1328 VMSTATE_BUFFER (csp_reg83, SB16State),
1329 VMSTATE_INT32 (csp_reg83r, SB16State),
1330 VMSTATE_INT32 (csp_reg83w, SB16State),
1332 VMSTATE_BUFFER (in2_data, SB16State),
1333 VMSTATE_BUFFER (out_data, SB16State),
1334 VMSTATE_UINT8 (test_reg, SB16State),
1335 VMSTATE_UINT8 (last_read_byte, SB16State),
1337 VMSTATE_INT32 (nzero, SB16State),
1338 VMSTATE_INT32 (left_till_irq, SB16State),
1339 VMSTATE_INT32 (dma_running, SB16State),
1340 VMSTATE_INT32 (bytes_per_second, SB16State),
1341 VMSTATE_INT32 (align, SB16State),
1343 VMSTATE_INT32 (mixer_nreg, SB16State),
1344 VMSTATE_BUFFER (mixer_regs, SB16State),
1346 VMSTATE_END_OF_LIST ()
1350 static const MemoryRegionPortio sb16_ioport_list[] = {
1351 { 4, 1, 1, .write = mixer_write_indexb },
1352 { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1353 { 6, 1, 1, .read = dsp_read, .write = dsp_write },
1354 { 10, 1, 1, .read = dsp_read },
1355 { 12, 1, 1, .write = dsp_write },
1356 { 12, 4, 1, .read = dsp_read },
1357 PORTIO_END_OF_LIST (),
1361 static void sb16_initfn (Object *obj)
1363 SB16State *s = SB16 (obj);
1365 s->cmd = -1;
1368 static void sb16_realizefn (DeviceState *dev, Error **errp)
1370 ISADevice *isadev = ISA_DEVICE (dev);
1371 SB16State *s = SB16 (dev);
1372 IsaDmaClass *k;
1374 isa_init_irq (isadev, &s->pic, s->irq);
1376 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1377 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1378 s->mixer_regs[0x82] = 2 << 5;
1380 s->csp_regs[5] = 1;
1381 s->csp_regs[9] = 0xf8;
1383 reset_mixer (s);
1384 s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1385 if (!s->aux_ts) {
1386 error_setg(errp, "warning: Could not create auxiliary timer");
1389 isa_register_portio_list(isadev, &s->portio_list, s->port,
1390 sb16_ioport_list, s, "sb16");
1392 s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
1393 k = ISADMA_GET_CLASS(s->isa_hdma);
1394 k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1396 s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
1397 k = ISADMA_GET_CLASS(s->isa_dma);
1398 k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1400 s->can_write = 1;
1402 AUD_register_card ("sb16", &s->card);
1405 static int SB16_init (ISABus *bus)
1407 isa_create_simple (bus, TYPE_SB16);
1408 return 0;
1411 static Property sb16_properties[] = {
1412 DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1413 DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
1414 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1415 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1416 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1417 DEFINE_PROP_END_OF_LIST (),
1420 static void sb16_class_initfn (ObjectClass *klass, void *data)
1422 DeviceClass *dc = DEVICE_CLASS (klass);
1424 dc->realize = sb16_realizefn;
1425 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1426 dc->desc = "Creative Sound Blaster 16";
1427 dc->vmsd = &vmstate_sb16;
1428 dc->props = sb16_properties;
1431 static const TypeInfo sb16_info = {
1432 .name = TYPE_SB16,
1433 .parent = TYPE_ISA_DEVICE,
1434 .instance_size = sizeof (SB16State),
1435 .instance_init = sb16_initfn,
1436 .class_init = sb16_class_initfn,
1439 static void sb16_register_types (void)
1441 type_register_static (&sb16_info);
1442 isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init);
1445 type_init (sb16_register_types)