debuggers.hg

view tools/ioemu/hw/sb16.c @ 16974:3daab9b636c1

ioemu: Better fix for SB16 infinite looping.

Qemu upstream solves "Fix an infinite loop in the emulated SB16
device" issue differently as stated in [2]

[1] http://xenbits.xensource.com/xen-3.1-testing.hg?rev/4b22d472bda6
[2] http://lists.gnu.org/archive/html/qemu-devel/2008-01/msg00709.html

Signed-off-by: S. Caglar Onur <caglar@pardus.org.tr>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 30 09:33:26 2008 +0000 (2008-01-30)
parents 0b873d909ad3
children
line source
1 /*
2 * QEMU Soundblaster 16 emulation
3 *
4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
24 #include "vl.h"
26 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
28 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
30 /* #define DEBUG */
31 /* #define DEBUG_SB16_MOST */
33 #ifdef DEBUG
34 #define ldebug(...) dolog (__VA_ARGS__)
35 #else
36 #define ldebug(...)
37 #endif
39 #define IO_READ_PROTO(name) \
40 uint32_t name (void *opaque, uint32_t nport)
41 #define IO_WRITE_PROTO(name) \
42 void name (void *opaque, uint32_t nport, uint32_t val)
44 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
46 static struct {
47 int ver_lo;
48 int ver_hi;
49 int irq;
50 int dma;
51 int hdma;
52 int port;
53 } conf = {5, 4, 5, 1, 5, 0x220};
55 typedef struct SB16State {
56 QEMUSoundCard card;
57 int irq;
58 int dma;
59 int hdma;
60 int port;
61 int ver;
63 int in_index;
64 int out_data_len;
65 int fmt_stereo;
66 int fmt_signed;
67 int fmt_bits;
68 audfmt_e fmt;
69 int dma_auto;
70 int block_size;
71 int fifo;
72 int freq;
73 int time_const;
74 int speaker;
75 int needed_bytes;
76 int cmd;
77 int use_hdma;
78 int highspeed;
79 int can_write;
81 int v2x6;
83 uint8_t csp_param;
84 uint8_t csp_value;
85 uint8_t csp_mode;
86 uint8_t csp_regs[256];
87 uint8_t csp_index;
88 uint8_t csp_reg83[4];
89 int csp_reg83r;
90 int csp_reg83w;
92 uint8_t in2_data[10];
93 uint8_t out_data[50];
94 uint8_t test_reg;
95 uint8_t last_read_byte;
96 int nzero;
98 int left_till_irq;
100 int dma_running;
101 int bytes_per_second;
102 int align;
103 int audio_free;
104 SWVoiceOut *voice;
106 QEMUTimer *aux_ts;
107 /* mixer state */
108 int mixer_nreg;
109 uint8_t mixer_regs[256];
110 } SB16State;
112 static void SB_audio_callback (void *opaque, int free);
114 static int magic_of_irq (int irq)
115 {
116 switch (irq) {
117 case 5:
118 return 2;
119 case 7:
120 return 4;
121 case 9:
122 return 1;
123 case 10:
124 return 8;
125 default:
126 dolog ("bad irq %d\n", irq);
127 return 2;
128 }
129 }
131 static int irq_of_magic (int magic)
132 {
133 switch (magic) {
134 case 1:
135 return 9;
136 case 2:
137 return 5;
138 case 4:
139 return 7;
140 case 8:
141 return 10;
142 default:
143 dolog ("bad irq magic %d\n", magic);
144 return -1;
145 }
146 }
148 #if 0
149 static void log_dsp (SB16State *dsp)
150 {
151 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
152 dsp->fmt_stereo ? "Stereo" : "Mono",
153 dsp->fmt_signed ? "Signed" : "Unsigned",
154 dsp->fmt_bits,
155 dsp->dma_auto ? "Auto" : "Single",
156 dsp->block_size,
157 dsp->freq,
158 dsp->time_const,
159 dsp->speaker);
160 }
161 #endif
163 static void speaker (SB16State *s, int on)
164 {
165 s->speaker = on;
166 /* AUD_enable (s->voice, on); */
167 }
169 static void control (SB16State *s, int hold)
170 {
171 int dma = s->use_hdma ? s->hdma : s->dma;
172 s->dma_running = hold;
174 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
176 if (hold) {
177 DMA_hold_DREQ (dma);
178 AUD_set_active_out (s->voice, 1);
179 }
180 else {
181 DMA_release_DREQ (dma);
182 AUD_set_active_out (s->voice, 0);
183 }
184 }
186 static void aux_timer (void *opaque)
187 {
188 SB16State *s = opaque;
189 s->can_write = 1;
190 pic_set_irq (s->irq, 1);
191 }
193 #define DMA8_AUTO 1
194 #define DMA8_HIGH 2
196 static void continue_dma8 (SB16State *s)
197 {
198 if (s->freq > 0) {
199 audsettings_t as;
201 s->audio_free = 0;
203 as.freq = s->freq;
204 as.nchannels = 1 << s->fmt_stereo;
205 as.fmt = s->fmt;
206 as.endianness = 0;
208 s->voice = AUD_open_out (
209 &s->card,
210 s->voice,
211 "sb16",
212 s,
213 SB_audio_callback,
214 &as
215 );
216 }
218 control (s, 1);
219 }
221 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
222 {
223 s->fmt = AUD_FMT_U8;
224 s->use_hdma = 0;
225 s->fmt_bits = 8;
226 s->fmt_signed = 0;
227 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
228 if (-1 == s->time_const) {
229 if (s->freq <= 0)
230 s->freq = 11025;
231 }
232 else {
233 int tmp = (256 - s->time_const);
234 s->freq = (1000000 + (tmp / 2)) / tmp;
235 }
237 if (dma_len != -1) {
238 s->block_size = dma_len << s->fmt_stereo;
239 }
240 else {
241 /* This is apparently the only way to make both Act1/PL
242 and SecondReality/FC work
244 Act1 sets block size via command 0x48 and it's an odd number
245 SR does the same with even number
246 Both use stereo, and Creatives own documentation states that
247 0x48 sets block size in bytes less one.. go figure */
248 s->block_size &= ~s->fmt_stereo;
249 }
251 s->freq >>= s->fmt_stereo;
252 s->left_till_irq = s->block_size;
253 s->bytes_per_second = (s->freq << s->fmt_stereo);
254 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
255 s->dma_auto = (mask & DMA8_AUTO) != 0;
256 s->align = (1 << s->fmt_stereo) - 1;
258 if (s->block_size & s->align) {
259 dolog ("warning: misaligned block size %d, alignment %d\n",
260 s->block_size, s->align + 1);
261 }
263 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
264 "dma %d, auto %d, fifo %d, high %d\n",
265 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
266 s->block_size, s->dma_auto, s->fifo, s->highspeed);
268 continue_dma8 (s);
269 speaker (s, 1);
270 }
272 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
273 {
274 s->use_hdma = cmd < 0xc0;
275 s->fifo = (cmd >> 1) & 1;
276 s->dma_auto = (cmd >> 2) & 1;
277 s->fmt_signed = (d0 >> 4) & 1;
278 s->fmt_stereo = (d0 >> 5) & 1;
280 switch (cmd >> 4) {
281 case 11:
282 s->fmt_bits = 16;
283 break;
285 case 12:
286 s->fmt_bits = 8;
287 break;
288 }
290 if (-1 != s->time_const) {
291 #if 1
292 int tmp = 256 - s->time_const;
293 s->freq = (1000000 + (tmp / 2)) / tmp;
294 #else
295 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
296 s->freq = 1000000 / ((255 - s->time_const));
297 #endif
298 s->time_const = -1;
299 }
301 s->block_size = dma_len + 1;
302 s->block_size <<= (s->fmt_bits == 16);
303 if (!s->dma_auto) {
304 /* It is clear that for DOOM and auto-init this value
305 shouldn't take stereo into account, while Miles Sound Systems
306 setsound.exe with single transfer mode wouldn't work without it
307 wonders of SB16 yet again */
308 s->block_size <<= s->fmt_stereo;
309 }
311 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
312 "dma %d, auto %d, fifo %d, high %d\n",
313 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
314 s->block_size, s->dma_auto, s->fifo, s->highspeed);
316 if (16 == s->fmt_bits) {
317 if (s->fmt_signed) {
318 s->fmt = AUD_FMT_S16;
319 }
320 else {
321 s->fmt = AUD_FMT_U16;
322 }
323 }
324 else {
325 if (s->fmt_signed) {
326 s->fmt = AUD_FMT_S8;
327 }
328 else {
329 s->fmt = AUD_FMT_U8;
330 }
331 }
333 s->left_till_irq = s->block_size;
335 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
336 s->highspeed = 0;
337 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
338 if (s->block_size & s->align) {
339 dolog ("warning: misaligned block size %d, alignment %d\n",
340 s->block_size, s->align + 1);
341 }
343 if (s->freq) {
344 audsettings_t as;
346 s->audio_free = 0;
348 as.freq = s->freq;
349 as.nchannels = 1 << s->fmt_stereo;
350 as.fmt = s->fmt;
351 as.endianness = 0;
353 s->voice = AUD_open_out (
354 &s->card,
355 s->voice,
356 "sb16",
357 s,
358 SB_audio_callback,
359 &as
360 );
361 }
363 control (s, 1);
364 speaker (s, 1);
365 }
367 static inline void dsp_out_data (SB16State *s, uint8_t val)
368 {
369 ldebug ("outdata %#x\n", val);
370 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
371 s->out_data[s->out_data_len++] = val;
372 }
373 }
375 static inline uint8_t dsp_get_data (SB16State *s)
376 {
377 if (s->in_index) {
378 return s->in2_data[--s->in_index];
379 }
380 else {
381 dolog ("buffer underflow\n");
382 return 0;
383 }
384 }
386 static void command (SB16State *s, uint8_t cmd)
387 {
388 ldebug ("command %#x\n", cmd);
390 if (cmd > 0xaf && cmd < 0xd0) {
391 if (cmd & 8) {
392 dolog ("ADC not yet supported (command %#x)\n", cmd);
393 }
395 switch (cmd >> 4) {
396 case 11:
397 case 12:
398 break;
399 default:
400 dolog ("%#x wrong bits\n", cmd);
401 }
402 s->needed_bytes = 3;
403 }
404 else {
405 s->needed_bytes = 0;
407 switch (cmd) {
408 case 0x03:
409 dsp_out_data (s, 0x10); /* s->csp_param); */
410 goto warn;
412 case 0x04:
413 s->needed_bytes = 1;
414 goto warn;
416 case 0x05:
417 s->needed_bytes = 2;
418 goto warn;
420 case 0x08:
421 /* __asm__ ("int3"); */
422 goto warn;
424 case 0x0e:
425 s->needed_bytes = 2;
426 goto warn;
428 case 0x09:
429 dsp_out_data (s, 0xf8);
430 goto warn;
432 case 0x0f:
433 s->needed_bytes = 1;
434 goto warn;
436 case 0x10:
437 s->needed_bytes = 1;
438 goto warn;
440 case 0x14:
441 s->needed_bytes = 2;
442 s->block_size = 0;
443 break;
445 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
446 dma_cmd8 (s, DMA8_AUTO, -1);
447 break;
449 case 0x20: /* Direct ADC, Juice/PL */
450 dsp_out_data (s, 0xff);
451 goto warn;
453 case 0x35:
454 dolog ("0x35 - MIDI command not implemented\n");
455 break;
457 case 0x40:
458 s->freq = -1;
459 s->time_const = -1;
460 s->needed_bytes = 1;
461 break;
463 case 0x41:
464 s->freq = -1;
465 s->time_const = -1;
466 s->needed_bytes = 2;
467 break;
469 case 0x42:
470 s->freq = -1;
471 s->time_const = -1;
472 s->needed_bytes = 2;
473 goto warn;
475 case 0x45:
476 dsp_out_data (s, 0xaa);
477 goto warn;
479 case 0x47: /* Continue Auto-Initialize DMA 16bit */
480 break;
482 case 0x48:
483 s->needed_bytes = 2;
484 break;
486 case 0x74:
487 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
488 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
489 break;
491 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
492 s->needed_bytes = 2;
493 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
494 break;
496 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
497 s->needed_bytes = 2;
498 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
499 break;
501 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
502 s->needed_bytes = 2;
503 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
504 break;
506 case 0x7d:
507 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
508 dolog ("not implemented\n");
509 break;
511 case 0x7f:
512 dolog (
513 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
514 );
515 dolog ("not implemented\n");
516 break;
518 case 0x80:
519 s->needed_bytes = 2;
520 break;
522 case 0x90:
523 case 0x91:
524 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
525 break;
527 case 0xd0: /* halt DMA operation. 8bit */
528 control (s, 0);
529 break;
531 case 0xd1: /* speaker on */
532 speaker (s, 1);
533 break;
535 case 0xd3: /* speaker off */
536 speaker (s, 0);
537 break;
539 case 0xd4: /* continue DMA operation. 8bit */
540 /* KQ6 (or maybe Sierras audblst.drv in general) resets
541 the frequency between halt/continue */
542 continue_dma8 (s);
543 break;
545 case 0xd5: /* halt DMA operation. 16bit */
546 control (s, 0);
547 break;
549 case 0xd6: /* continue DMA operation. 16bit */
550 control (s, 1);
551 break;
553 case 0xd9: /* exit auto-init DMA after this block. 16bit */
554 s->dma_auto = 0;
555 break;
557 case 0xda: /* exit auto-init DMA after this block. 8bit */
558 s->dma_auto = 0;
559 break;
561 case 0xe0: /* DSP identification */
562 s->needed_bytes = 1;
563 break;
565 case 0xe1:
566 dsp_out_data (s, s->ver & 0xff);
567 dsp_out_data (s, s->ver >> 8);
568 break;
570 case 0xe2:
571 s->needed_bytes = 1;
572 goto warn;
574 case 0xe3:
575 {
576 int i;
577 for (i = sizeof (e3) - 1; i >= 0; --i)
578 dsp_out_data (s, e3[i]);
579 }
580 break;
582 case 0xe4: /* write test reg */
583 s->needed_bytes = 1;
584 break;
586 case 0xe7:
587 dolog ("Attempt to probe for ESS (0xe7)?\n");
588 break;
590 case 0xe8: /* read test reg */
591 dsp_out_data (s, s->test_reg);
592 break;
594 case 0xf2:
595 case 0xf3:
596 dsp_out_data (s, 0xaa);
597 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
598 pic_set_irq (s->irq, 1);
599 break;
601 case 0xf9:
602 s->needed_bytes = 1;
603 goto warn;
605 case 0xfa:
606 dsp_out_data (s, 0);
607 goto warn;
609 case 0xfc: /* FIXME */
610 dsp_out_data (s, 0);
611 goto warn;
613 default:
614 dolog ("Unrecognized command %#x\n", cmd);
615 break;
616 }
617 }
619 if (!s->needed_bytes) {
620 ldebug ("\n");
621 }
623 exit:
624 if (!s->needed_bytes) {
625 s->cmd = -1;
626 }
627 else {
628 s->cmd = cmd;
629 }
630 return;
632 warn:
633 dolog ("warning: command %#x,%d is not truly understood yet\n",
634 cmd, s->needed_bytes);
635 goto exit;
637 }
639 static uint16_t dsp_get_lohi (SB16State *s)
640 {
641 uint8_t hi = dsp_get_data (s);
642 uint8_t lo = dsp_get_data (s);
643 return (hi << 8) | lo;
644 }
646 static uint16_t dsp_get_hilo (SB16State *s)
647 {
648 uint8_t lo = dsp_get_data (s);
649 uint8_t hi = dsp_get_data (s);
650 return (hi << 8) | lo;
651 }
653 static void complete (SB16State *s)
654 {
655 int d0, d1, d2;
656 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
657 s->cmd, s->in_index, s->needed_bytes);
659 if (s->cmd > 0xaf && s->cmd < 0xd0) {
660 d2 = dsp_get_data (s);
661 d1 = dsp_get_data (s);
662 d0 = dsp_get_data (s);
664 if (s->cmd & 8) {
665 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
666 s->cmd, d0, d1, d2);
667 }
668 else {
669 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
670 s->cmd, d0, d1, d2);
671 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
672 }
673 }
674 else {
675 switch (s->cmd) {
676 case 0x04:
677 s->csp_mode = dsp_get_data (s);
678 s->csp_reg83r = 0;
679 s->csp_reg83w = 0;
680 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
681 break;
683 case 0x05:
684 s->csp_param = dsp_get_data (s);
685 s->csp_value = dsp_get_data (s);
686 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
687 s->csp_param,
688 s->csp_value);
689 break;
691 case 0x0e:
692 d0 = dsp_get_data (s);
693 d1 = dsp_get_data (s);
694 ldebug ("write CSP register %d <- %#x\n", d1, d0);
695 if (d1 == 0x83) {
696 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
697 s->csp_reg83[s->csp_reg83r % 4] = d0;
698 s->csp_reg83r += 1;
699 }
700 else {
701 s->csp_regs[d1] = d0;
702 }
703 break;
705 case 0x0f:
706 d0 = dsp_get_data (s);
707 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
708 d0, s->csp_regs[d0], s->csp_mode);
709 if (d0 == 0x83) {
710 ldebug ("0x83[%d] -> %#x\n",
711 s->csp_reg83w,
712 s->csp_reg83[s->csp_reg83w % 4]);
713 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
714 s->csp_reg83w += 1;
715 }
716 else {
717 dsp_out_data (s, s->csp_regs[d0]);
718 }
719 break;
721 case 0x10:
722 d0 = dsp_get_data (s);
723 dolog ("cmd 0x10 d0=%#x\n", d0);
724 break;
726 case 0x14:
727 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
728 break;
730 case 0x40:
731 s->time_const = dsp_get_data (s);
732 ldebug ("set time const %d\n", s->time_const);
733 break;
735 case 0x42: /* FT2 sets output freq with this, go figure */
736 #if 0
737 dolog ("cmd 0x42 might not do what it think it should\n");
738 #endif
739 case 0x41:
740 s->freq = dsp_get_hilo (s);
741 ldebug ("set freq %d\n", s->freq);
742 break;
744 case 0x48:
745 s->block_size = dsp_get_lohi (s) + 1;
746 ldebug ("set dma block len %d\n", s->block_size);
747 break;
749 case 0x74:
750 case 0x75:
751 case 0x76:
752 case 0x77:
753 /* ADPCM stuff, ignore */
754 break;
756 case 0x80:
757 {
758 int freq, samples, bytes;
759 int64_t ticks;
761 freq = s->freq > 0 ? s->freq : 11025;
762 samples = dsp_get_lohi (s) + 1;
763 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
764 ticks = (bytes * ticks_per_sec) / freq;
765 if (ticks < ticks_per_sec / 1024) {
766 pic_set_irq (s->irq, 1);
767 }
768 else {
769 if (s->aux_ts) {
770 qemu_mod_timer (
771 s->aux_ts,
772 qemu_get_clock (vm_clock) + ticks
773 );
774 }
775 }
776 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
777 }
778 break;
780 case 0xe0:
781 d0 = dsp_get_data (s);
782 s->out_data_len = 0;
783 ldebug ("E0 data = %#x\n", d0);
784 dsp_out_data (s, ~d0);
785 break;
787 case 0xe2:
788 d0 = dsp_get_data (s);
789 ldebug ("E2 = %#x\n", d0);
790 break;
792 case 0xe4:
793 s->test_reg = dsp_get_data (s);
794 break;
796 case 0xf9:
797 d0 = dsp_get_data (s);
798 ldebug ("command 0xf9 with %#x\n", d0);
799 switch (d0) {
800 case 0x0e:
801 dsp_out_data (s, 0xff);
802 break;
804 case 0x0f:
805 dsp_out_data (s, 0x07);
806 break;
808 case 0x37:
809 dsp_out_data (s, 0x38);
810 break;
812 default:
813 dsp_out_data (s, 0x00);
814 break;
815 }
816 break;
818 default:
819 dolog ("complete: unrecognized command %#x\n", s->cmd);
820 return;
821 }
822 }
824 ldebug ("\n");
825 s->cmd = -1;
826 return;
827 }
829 static void legacy_reset (SB16State *s)
830 {
831 audsettings_t as;
833 s->freq = 11025;
834 s->fmt_signed = 0;
835 s->fmt_bits = 8;
836 s->fmt_stereo = 0;
838 as.freq = s->freq;
839 as.nchannels = 1;
840 as.fmt = AUD_FMT_U8;
841 as.endianness = 0;
843 s->voice = AUD_open_out (
844 &s->card,
845 s->voice,
846 "sb16",
847 s,
848 SB_audio_callback,
849 &as
850 );
852 /* Not sure about that... */
853 /* AUD_set_active_out (s->voice, 1); */
854 }
856 static void reset (SB16State *s)
857 {
858 pic_set_irq (s->irq, 0);
859 if (s->dma_auto) {
860 pic_set_irq (s->irq, 1);
861 pic_set_irq (s->irq, 0);
862 }
864 s->mixer_regs[0x82] = 0;
865 s->dma_auto = 0;
866 s->in_index = 0;
867 s->out_data_len = 0;
868 s->left_till_irq = 0;
869 s->needed_bytes = 0;
870 s->block_size = -1;
871 s->nzero = 0;
872 s->highspeed = 0;
873 s->v2x6 = 0;
874 s->cmd = -1;
876 dsp_out_data(s, 0xaa);
877 speaker (s, 0);
878 control (s, 0);
879 legacy_reset (s);
880 }
882 static IO_WRITE_PROTO (dsp_write)
883 {
884 SB16State *s = opaque;
885 int iport;
887 iport = nport - s->port;
889 ldebug ("write %#x <- %#x\n", nport, val);
890 switch (iport) {
891 case 0x06:
892 switch (val) {
893 case 0x00:
894 if (s->v2x6 == 1) {
895 if (0 && s->highspeed) {
896 s->highspeed = 0;
897 pic_set_irq (s->irq, 0);
898 control (s, 0);
899 }
900 else {
901 reset (s);
902 }
903 }
904 s->v2x6 = 0;
905 break;
907 case 0x01:
908 case 0x03: /* FreeBSD kludge */
909 s->v2x6 = 1;
910 break;
912 case 0xc6:
913 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
914 break;
916 case 0xb8: /* Panic */
917 reset (s);
918 break;
920 case 0x39:
921 dsp_out_data (s, 0x38);
922 reset (s);
923 s->v2x6 = 0x39;
924 break;
926 default:
927 s->v2x6 = val;
928 break;
929 }
930 break;
932 case 0x0c: /* write data or command | write status */
933 /* if (s->highspeed) */
934 /* break; */
936 if (0 == s->needed_bytes) {
937 command (s, val);
938 #if 0
939 if (0 == s->needed_bytes) {
940 log_dsp (s);
941 }
942 #endif
943 }
944 else {
945 if (s->in_index == sizeof (s->in2_data)) {
946 dolog ("in data overrun\n");
947 }
948 else {
949 s->in2_data[s->in_index++] = val;
950 if (s->in_index == s->needed_bytes) {
951 s->needed_bytes = 0;
952 complete (s);
953 #if 0
954 log_dsp (s);
955 #endif
956 }
957 }
958 }
959 break;
961 default:
962 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
963 break;
964 }
965 }
967 static IO_READ_PROTO (dsp_read)
968 {
969 SB16State *s = opaque;
970 int iport, retval, ack = 0;
972 iport = nport - s->port;
974 switch (iport) {
975 case 0x06: /* reset */
976 retval = 0xff;
977 break;
979 case 0x0a: /* read data */
980 if (s->out_data_len) {
981 retval = s->out_data[--s->out_data_len];
982 s->last_read_byte = retval;
983 }
984 else {
985 if (s->cmd != -1) {
986 dolog ("empty output buffer for command %#x\n",
987 s->cmd);
988 }
989 retval = s->last_read_byte;
990 /* goto error; */
991 }
992 break;
994 case 0x0c: /* 0 can write */
995 retval = s->can_write ? 0 : 0x80;
996 break;
998 case 0x0d: /* timer interrupt clear */
999 /* dolog ("timer interrupt clear\n"); */
1000 retval = 0;
1001 break;
1003 case 0x0e: /* data available status | irq 8 ack */
1004 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1005 if (s->mixer_regs[0x82] & 1) {
1006 ack = 1;
1007 s->mixer_regs[0x82] &= 1;
1008 pic_set_irq (s->irq, 0);
1010 break;
1012 case 0x0f: /* irq 16 ack */
1013 retval = 0xff;
1014 if (s->mixer_regs[0x82] & 2) {
1015 ack = 1;
1016 s->mixer_regs[0x82] &= 2;
1017 pic_set_irq (s->irq, 0);
1019 break;
1021 default:
1022 goto error;
1025 if (!ack) {
1026 ldebug ("read %#x -> %#x\n", nport, retval);
1029 return retval;
1031 error:
1032 dolog ("warning: dsp_read %#x error\n", nport);
1033 return 0xff;
1036 static void reset_mixer (SB16State *s)
1038 int i;
1040 memset (s->mixer_regs, 0xff, 0x7f);
1041 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1043 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1044 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1045 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1046 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1048 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1049 s->mixer_regs[0x0c] = 0;
1051 /* d5=output filt, d1=stereo switch */
1052 s->mixer_regs[0x0e] = 0;
1054 /* voice volume L d5,d7, R d1,d3 */
1055 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1056 /* master ... */
1057 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1058 /* MIDI ... */
1059 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1061 for (i = 0x30; i < 0x48; i++) {
1062 s->mixer_regs[i] = 0x20;
1066 static IO_WRITE_PROTO(mixer_write_indexb)
1068 SB16State *s = opaque;
1069 (void) nport;
1070 s->mixer_nreg = val;
1073 static IO_WRITE_PROTO(mixer_write_datab)
1075 SB16State *s = opaque;
1077 (void) nport;
1078 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1080 switch (s->mixer_nreg) {
1081 case 0x00:
1082 reset_mixer (s);
1083 break;
1085 case 0x80:
1087 int irq = irq_of_magic (val);
1088 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1089 if (irq > 0) {
1090 s->irq = irq;
1093 break;
1095 case 0x81:
1097 int dma, hdma;
1099 dma = lsbindex (val & 0xf);
1100 hdma = lsbindex (val & 0xf0);
1101 if (dma != s->dma || hdma != s->hdma) {
1102 dolog (
1103 "attempt to change DMA "
1104 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1105 dma, s->dma, hdma, s->hdma, val);
1107 #if 0
1108 s->dma = dma;
1109 s->hdma = hdma;
1110 #endif
1112 break;
1114 case 0x82:
1115 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1116 val);
1117 return;
1119 default:
1120 if (s->mixer_nreg >= 0x80) {
1121 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1123 break;
1126 s->mixer_regs[s->mixer_nreg] = val;
1129 static IO_WRITE_PROTO(mixer_write_indexw)
1131 mixer_write_indexb (opaque, nport, val & 0xff);
1132 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1135 static IO_READ_PROTO(mixer_read)
1137 SB16State *s = opaque;
1139 (void) nport;
1140 #ifndef DEBUG_SB16_MOST
1141 if (s->mixer_nreg != 0x82) {
1142 ldebug ("mixer_read[%#x] -> %#x\n",
1143 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1145 #else
1146 ldebug ("mixer_read[%#x] -> %#x\n",
1147 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1148 #endif
1149 return s->mixer_regs[s->mixer_nreg];
1152 static int write_audio (SB16State *s, int nchan, int dma_pos,
1153 int dma_len, int len)
1155 int temp, net;
1156 uint8_t tmpbuf[4096];
1158 temp = len;
1159 net = 0;
1161 while (temp) {
1162 int left = dma_len - dma_pos;
1163 int copied;
1164 size_t to_copy;
1166 to_copy = audio_MIN (temp, left);
1167 if (to_copy > sizeof (tmpbuf)) {
1168 to_copy = sizeof (tmpbuf);
1171 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1172 copied = AUD_write (s->voice, tmpbuf, copied);
1174 temp -= copied;
1175 dma_pos = (dma_pos + copied) % dma_len;
1176 net += copied;
1178 if (!copied) {
1179 break;
1183 return net;
1186 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1188 SB16State *s = opaque;
1189 int till, copy, written, free;
1191 if (s->block_size <= 0) {
1192 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1193 s->block_size, nchan, dma_pos, dma_len);
1194 return dma_pos;
1197 if (s->left_till_irq < 0) {
1198 s->left_till_irq = s->block_size;
1201 if (s->voice) {
1202 free = s->audio_free & ~s->align;
1203 if ((free <= 0) || !dma_len) {
1204 return dma_pos;
1207 else {
1208 free = dma_len;
1211 copy = free;
1212 till = s->left_till_irq;
1214 #ifdef DEBUG_SB16_MOST
1215 dolog ("pos:%06d %d till:%d len:%d\n",
1216 dma_pos, free, till, dma_len);
1217 #endif
1219 if (till <= copy) {
1220 if (0 == s->dma_auto) {
1221 copy = till;
1225 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1226 dma_pos = (dma_pos + written) % dma_len;
1227 s->left_till_irq -= written;
1229 if (s->left_till_irq <= 0) {
1230 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1231 pic_set_irq (s->irq, 1);
1232 if (0 == s->dma_auto) {
1233 control (s, 0);
1234 speaker (s, 0);
1238 #ifdef DEBUG_SB16_MOST
1239 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1240 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1241 s->block_size);
1242 #endif
1244 while (s->left_till_irq <= 0) {
1245 s->left_till_irq = s->block_size + s->left_till_irq;
1248 return dma_pos;
1251 static void SB_audio_callback (void *opaque, int free)
1253 SB16State *s = opaque;
1254 s->audio_free = free;
1257 static void SB_save (QEMUFile *f, void *opaque)
1259 SB16State *s = opaque;
1261 qemu_put_be32s (f, &s->irq);
1262 qemu_put_be32s (f, &s->dma);
1263 qemu_put_be32s (f, &s->hdma);
1264 qemu_put_be32s (f, &s->port);
1265 qemu_put_be32s (f, &s->ver);
1266 qemu_put_be32s (f, &s->in_index);
1267 qemu_put_be32s (f, &s->out_data_len);
1268 qemu_put_be32s (f, &s->fmt_stereo);
1269 qemu_put_be32s (f, &s->fmt_signed);
1270 qemu_put_be32s (f, &s->fmt_bits);
1271 qemu_put_be32s (f, &s->fmt);
1272 qemu_put_be32s (f, &s->dma_auto);
1273 qemu_put_be32s (f, &s->block_size);
1274 qemu_put_be32s (f, &s->fifo);
1275 qemu_put_be32s (f, &s->freq);
1276 qemu_put_be32s (f, &s->time_const);
1277 qemu_put_be32s (f, &s->speaker);
1278 qemu_put_be32s (f, &s->needed_bytes);
1279 qemu_put_be32s (f, &s->cmd);
1280 qemu_put_be32s (f, &s->use_hdma);
1281 qemu_put_be32s (f, &s->highspeed);
1282 qemu_put_be32s (f, &s->can_write);
1283 qemu_put_be32s (f, &s->v2x6);
1285 qemu_put_8s (f, &s->csp_param);
1286 qemu_put_8s (f, &s->csp_value);
1287 qemu_put_8s (f, &s->csp_mode);
1288 qemu_put_8s (f, &s->csp_param);
1289 qemu_put_buffer (f, s->csp_regs, 256);
1290 qemu_put_8s (f, &s->csp_index);
1291 qemu_put_buffer (f, s->csp_reg83, 4);
1292 qemu_put_be32s (f, &s->csp_reg83r);
1293 qemu_put_be32s (f, &s->csp_reg83w);
1295 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1296 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1297 qemu_put_8s (f, &s->test_reg);
1298 qemu_put_8s (f, &s->last_read_byte);
1300 qemu_put_be32s (f, &s->nzero);
1301 qemu_put_be32s (f, &s->left_till_irq);
1302 qemu_put_be32s (f, &s->dma_running);
1303 qemu_put_be32s (f, &s->bytes_per_second);
1304 qemu_put_be32s (f, &s->align);
1306 qemu_put_be32s (f, &s->mixer_nreg);
1307 qemu_put_buffer (f, s->mixer_regs, 256);
1310 static int SB_load (QEMUFile *f, void *opaque, int version_id)
1312 SB16State *s = opaque;
1314 if (version_id != 1) {
1315 return -EINVAL;
1318 qemu_get_be32s (f, &s->irq);
1319 qemu_get_be32s (f, &s->dma);
1320 qemu_get_be32s (f, &s->hdma);
1321 qemu_get_be32s (f, &s->port);
1322 qemu_get_be32s (f, &s->ver);
1323 qemu_get_be32s (f, &s->in_index);
1324 qemu_get_be32s (f, &s->out_data_len);
1325 qemu_get_be32s (f, &s->fmt_stereo);
1326 qemu_get_be32s (f, &s->fmt_signed);
1327 qemu_get_be32s (f, &s->fmt_bits);
1328 qemu_get_be32s (f, &s->fmt);
1329 qemu_get_be32s (f, &s->dma_auto);
1330 qemu_get_be32s (f, &s->block_size);
1331 qemu_get_be32s (f, &s->fifo);
1332 qemu_get_be32s (f, &s->freq);
1333 qemu_get_be32s (f, &s->time_const);
1334 qemu_get_be32s (f, &s->speaker);
1335 qemu_get_be32s (f, &s->needed_bytes);
1336 qemu_get_be32s (f, &s->cmd);
1337 qemu_get_be32s (f, &s->use_hdma);
1338 qemu_get_be32s (f, &s->highspeed);
1339 qemu_get_be32s (f, &s->can_write);
1340 qemu_get_be32s (f, &s->v2x6);
1342 qemu_get_8s (f, &s->csp_param);
1343 qemu_get_8s (f, &s->csp_value);
1344 qemu_get_8s (f, &s->csp_mode);
1345 qemu_get_8s (f, &s->csp_param);
1346 qemu_get_buffer (f, s->csp_regs, 256);
1347 qemu_get_8s (f, &s->csp_index);
1348 qemu_get_buffer (f, s->csp_reg83, 4);
1349 qemu_get_be32s (f, &s->csp_reg83r);
1350 qemu_get_be32s (f, &s->csp_reg83w);
1352 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1353 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1354 qemu_get_8s (f, &s->test_reg);
1355 qemu_get_8s (f, &s->last_read_byte);
1357 qemu_get_be32s (f, &s->nzero);
1358 qemu_get_be32s (f, &s->left_till_irq);
1359 qemu_get_be32s (f, &s->dma_running);
1360 qemu_get_be32s (f, &s->bytes_per_second);
1361 qemu_get_be32s (f, &s->align);
1363 qemu_get_be32s (f, &s->mixer_nreg);
1364 qemu_get_buffer (f, s->mixer_regs, 256);
1366 if (s->voice) {
1367 AUD_close_out (&s->card, s->voice);
1368 s->voice = NULL;
1371 if (s->dma_running) {
1372 if (s->freq) {
1373 audsettings_t as;
1375 s->audio_free = 0;
1377 as.freq = s->freq;
1378 as.nchannels = 1 << s->fmt_stereo;
1379 as.fmt = s->fmt;
1380 as.endianness = 0;
1382 s->voice = AUD_open_out (
1383 &s->card,
1384 s->voice,
1385 "sb16",
1386 s,
1387 SB_audio_callback,
1388 &as
1389 );
1392 control (s, 1);
1393 speaker (s, s->speaker);
1395 return 0;
1398 int SB16_init (AudioState *audio)
1400 SB16State *s;
1401 int i;
1402 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1403 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1405 if (!audio) {
1406 dolog ("No audio state\n");
1407 return -1;
1410 s = qemu_mallocz (sizeof (*s));
1411 if (!s) {
1412 dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1413 sizeof (*s));
1414 return -1;
1417 s->cmd = -1;
1418 s->irq = conf.irq;
1419 s->dma = conf.dma;
1420 s->hdma = conf.hdma;
1421 s->port = conf.port;
1422 s->ver = conf.ver_lo | (conf.ver_hi << 8);
1424 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1425 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1426 s->mixer_regs[0x82] = 2 << 5;
1428 s->csp_regs[5] = 1;
1429 s->csp_regs[9] = 0xf8;
1431 reset_mixer (s);
1432 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1433 if (!s->aux_ts) {
1434 dolog ("warning: Could not create auxiliary timer\n");
1437 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1438 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1441 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1442 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1445 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1446 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1447 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1448 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1450 DMA_register_channel (s->hdma, SB_read_DMA, s);
1451 DMA_register_channel (s->dma, SB_read_DMA, s);
1452 s->can_write = 1;
1454 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1455 AUD_register_card (audio, "sb16", &s->card);
1456 return 0;