1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "hw.h"
25#include "audiodev.h"
26#include "audio/audio.h"
27#include "isa.h"
28#include "qemu-timer.h"
29
30#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
31
32
33
34
35#ifdef DEBUG
36#define ldebug(...) dolog (__VA_ARGS__)
37#else
38#define ldebug(...)
39#endif
40
41#define IO_READ_PROTO(name) \
42 uint32_t name (void *opaque, uint32_t nport)
43#define IO_WRITE_PROTO(name) \
44 void name (void *opaque, uint32_t nport, uint32_t val)
45
46static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
47
48static struct {
49 int ver_lo;
50 int ver_hi;
51 int irq;
52 int dma;
53 int hdma;
54 int port;
55} conf = {5, 4, 5, 1, 5, 0x220};
56
57typedef struct SB16State {
58 QEMUSoundCard card;
59 qemu_irq *pic;
60 int irq;
61 int dma;
62 int hdma;
63 int port;
64 int ver;
65
66 int in_index;
67 int out_data_len;
68 int fmt_stereo;
69 int fmt_signed;
70 int fmt_bits;
71 audfmt_e fmt;
72 int dma_auto;
73 int block_size;
74 int fifo;
75 int freq;
76 int time_const;
77 int speaker;
78 int needed_bytes;
79 int cmd;
80 int use_hdma;
81 int highspeed;
82 int can_write;
83
84 int v2x6;
85
86 uint8_t csp_param;
87 uint8_t csp_value;
88 uint8_t csp_mode;
89 uint8_t csp_regs[256];
90 uint8_t csp_index;
91 uint8_t csp_reg83[4];
92 int csp_reg83r;
93 int csp_reg83w;
94
95 uint8_t in2_data[10];
96 uint8_t out_data[50];
97 uint8_t test_reg;
98 uint8_t last_read_byte;
99 int nzero;
100
101 int left_till_irq;
102
103 int dma_running;
104 int bytes_per_second;
105 int align;
106 int audio_free;
107 SWVoiceOut *voice;
108
109 QEMUTimer *aux_ts;
110
111 int mixer_nreg;
112 uint8_t mixer_regs[256];
113} SB16State;
114
115static void SB_audio_callback (void *opaque, int free);
116
117static int magic_of_irq (int irq)
118{
119 switch (irq) {
120 case 5:
121 return 2;
122 case 7:
123 return 4;
124 case 9:
125 return 1;
126 case 10:
127 return 8;
128 default:
129 dolog ("bad irq %d\n", irq);
130 return 2;
131 }
132}
133
134static int irq_of_magic (int magic)
135{
136 switch (magic) {
137 case 1:
138 return 9;
139 case 2:
140 return 5;
141 case 4:
142 return 7;
143 case 8:
144 return 10;
145 default:
146 dolog ("bad irq magic %d\n", magic);
147 return -1;
148 }
149}
150
151#if 0
152static void log_dsp (SB16State *dsp)
153{
154 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
155 dsp->fmt_stereo ? "Stereo" : "Mono",
156 dsp->fmt_signed ? "Signed" : "Unsigned",
157 dsp->fmt_bits,
158 dsp->dma_auto ? "Auto" : "Single",
159 dsp->block_size,
160 dsp->freq,
161 dsp->time_const,
162 dsp->speaker);
163}
164#endif
165
166static void speaker (SB16State *s, int on)
167{
168 s->speaker = on;
169
170}
171
172static void control (SB16State *s, int hold)
173{
174 int dma = s->use_hdma ? s->hdma : s->dma;
175 s->dma_running = hold;
176
177 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
178
179 if (hold) {
180 DMA_hold_DREQ (dma);
181 AUD_set_active_out (s->voice, 1);
182 }
183 else {
184 DMA_release_DREQ (dma);
185 AUD_set_active_out (s->voice, 0);
186 }
187}
188
189static void aux_timer (void *opaque)
190{
191 SB16State *s = opaque;
192 s->can_write = 1;
193 qemu_irq_raise (s->pic[s->irq]);
194}
195
196#define DMA8_AUTO 1
197#define DMA8_HIGH 2
198
199static void continue_dma8 (SB16State *s)
200{
201 if (s->freq > 0) {
202 struct audsettings as;
203
204 s->audio_free = 0;
205
206 as.freq = s->freq;
207 as.nchannels = 1 << s->fmt_stereo;
208 as.fmt = s->fmt;
209 as.endianness = 0;
210
211 s->voice = AUD_open_out (
212 &s->card,
213 s->voice,
214 "sb16",
215 s,
216 SB_audio_callback,
217 &as
218 );
219 }
220
221 control (s, 1);
222}
223
224static void dma_cmd8 (SB16State *s, int mask, int dma_len)
225{
226 s->fmt = AUD_FMT_U8;
227 s->use_hdma = 0;
228 s->fmt_bits = 8;
229 s->fmt_signed = 0;
230 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
231 if (-1 == s->time_const) {
232 if (s->freq <= 0)
233 s->freq = 11025;
234 }
235 else {
236 int tmp = (256 - s->time_const);
237 s->freq = (1000000 + (tmp / 2)) / tmp;
238 }
239
240 if (dma_len != -1) {
241 s->block_size = dma_len << s->fmt_stereo;
242 }
243 else {
244
245
246
247
248
249
250
251 s->block_size &= ~s->fmt_stereo;
252 }
253
254 s->freq >>= s->fmt_stereo;
255 s->left_till_irq = s->block_size;
256 s->bytes_per_second = (s->freq << s->fmt_stereo);
257
258 s->dma_auto = (mask & DMA8_AUTO) != 0;
259 s->align = (1 << s->fmt_stereo) - 1;
260
261 if (s->block_size & s->align) {
262 dolog ("warning: misaligned block size %d, alignment %d\n",
263 s->block_size, s->align + 1);
264 }
265
266 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
267 "dma %d, auto %d, fifo %d, high %d\n",
268 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
269 s->block_size, s->dma_auto, s->fifo, s->highspeed);
270
271 continue_dma8 (s);
272 speaker (s, 1);
273}
274
275static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
276{
277 s->use_hdma = cmd < 0xc0;
278 s->fifo = (cmd >> 1) & 1;
279 s->dma_auto = (cmd >> 2) & 1;
280 s->fmt_signed = (d0 >> 4) & 1;
281 s->fmt_stereo = (d0 >> 5) & 1;
282
283 switch (cmd >> 4) {
284 case 11:
285 s->fmt_bits = 16;
286 break;
287
288 case 12:
289 s->fmt_bits = 8;
290 break;
291 }
292
293 if (-1 != s->time_const) {
294#if 1
295 int tmp = 256 - s->time_const;
296 s->freq = (1000000 + (tmp / 2)) / tmp;
297#else
298
299 s->freq = 1000000 / ((255 - s->time_const));
300#endif
301 s->time_const = -1;
302 }
303
304 s->block_size = dma_len + 1;
305 s->block_size <<= (s->fmt_bits == 16);
306 if (!s->dma_auto) {
307
308
309
310
311 s->block_size <<= s->fmt_stereo;
312 }
313
314 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
315 "dma %d, auto %d, fifo %d, high %d\n",
316 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
317 s->block_size, s->dma_auto, s->fifo, s->highspeed);
318
319 if (16 == s->fmt_bits) {
320 if (s->fmt_signed) {
321 s->fmt = AUD_FMT_S16;
322 }
323 else {
324 s->fmt = AUD_FMT_U16;
325 }
326 }
327 else {
328 if (s->fmt_signed) {
329 s->fmt = AUD_FMT_S8;
330 }
331 else {
332 s->fmt = AUD_FMT_U8;
333 }
334 }
335
336 s->left_till_irq = s->block_size;
337
338 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
339 s->highspeed = 0;
340 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
341 if (s->block_size & s->align) {
342 dolog ("warning: misaligned block size %d, alignment %d\n",
343 s->block_size, s->align + 1);
344 }
345
346 if (s->freq) {
347 struct audsettings as;
348
349 s->audio_free = 0;
350
351 as.freq = s->freq;
352 as.nchannels = 1 << s->fmt_stereo;
353 as.fmt = s->fmt;
354 as.endianness = 0;
355
356 s->voice = AUD_open_out (
357 &s->card,
358 s->voice,
359 "sb16",
360 s,
361 SB_audio_callback,
362 &as
363 );
364 }
365
366 control (s, 1);
367 speaker (s, 1);
368}
369
370static inline void dsp_out_data (SB16State *s, uint8_t val)
371{
372 ldebug ("outdata %#x\n", val);
373 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
374 s->out_data[s->out_data_len++] = val;
375 }
376}
377
378static inline uint8_t dsp_get_data (SB16State *s)
379{
380 if (s->in_index) {
381 return s->in2_data[--s->in_index];
382 }
383 else {
384 dolog ("buffer underflow\n");
385 return 0;
386 }
387}
388
389static void command (SB16State *s, uint8_t cmd)
390{
391 ldebug ("command %#x\n", cmd);
392
393 if (cmd > 0xaf && cmd < 0xd0) {
394 if (cmd & 8) {
395 dolog ("ADC not yet supported (command %#x)\n", cmd);
396 }
397
398 switch (cmd >> 4) {
399 case 11:
400 case 12:
401 break;
402 default:
403 dolog ("%#x wrong bits\n", cmd);
404 }
405 s->needed_bytes = 3;
406 }
407 else {
408 s->needed_bytes = 0;
409
410 switch (cmd) {
411 case 0x03:
412 dsp_out_data (s, 0x10);
413 goto warn;
414
415 case 0x04:
416 s->needed_bytes = 1;
417 goto warn;
418
419 case 0x05:
420 s->needed_bytes = 2;
421 goto warn;
422
423 case 0x08:
424
425 goto warn;
426
427 case 0x0e:
428 s->needed_bytes = 2;
429 goto warn;
430
431 case 0x09:
432 dsp_out_data (s, 0xf8);
433 goto warn;
434
435 case 0x0f:
436 s->needed_bytes = 1;
437 goto warn;
438
439 case 0x10:
440 s->needed_bytes = 1;
441 goto warn;
442
443 case 0x14:
444 s->needed_bytes = 2;
445 s->block_size = 0;
446 break;
447
448 case 0x1c:
449 dma_cmd8 (s, DMA8_AUTO, -1);
450 break;
451
452 case 0x20:
453 dsp_out_data (s, 0xff);
454 goto warn;
455
456 case 0x35:
457 dolog ("0x35 - MIDI command not implemented\n");
458 break;
459
460 case 0x40:
461 s->freq = -1;
462 s->time_const = -1;
463 s->needed_bytes = 1;
464 break;
465
466 case 0x41:
467 s->freq = -1;
468 s->time_const = -1;
469 s->needed_bytes = 2;
470 break;
471
472 case 0x42:
473 s->freq = -1;
474 s->time_const = -1;
475 s->needed_bytes = 2;
476 goto warn;
477
478 case 0x45:
479 dsp_out_data (s, 0xaa);
480 goto warn;
481
482 case 0x47:
483 break;
484
485 case 0x48:
486 s->needed_bytes = 2;
487 break;
488
489 case 0x74:
490 s->needed_bytes = 2;
491 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
492 break;
493
494 case 0x75:
495 s->needed_bytes = 2;
496 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
497 break;
498
499 case 0x76:
500 s->needed_bytes = 2;
501 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
502 break;
503
504 case 0x77:
505 s->needed_bytes = 2;
506 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
507 break;
508
509 case 0x7d:
510 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
511 dolog ("not implemented\n");
512 break;
513
514 case 0x7f:
515 dolog (
516 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
517 );
518 dolog ("not implemented\n");
519 break;
520
521 case 0x80:
522 s->needed_bytes = 2;
523 break;
524
525 case 0x90:
526 case 0x91:
527 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
528 break;
529
530 case 0xd0:
531 control (s, 0);
532 break;
533
534 case 0xd1:
535 speaker (s, 1);
536 break;
537
538 case 0xd3:
539 speaker (s, 0);
540 break;
541
542 case 0xd4:
543
544
545 continue_dma8 (s);
546 break;
547
548 case 0xd5:
549 control (s, 0);
550 break;
551
552 case 0xd6:
553 control (s, 1);
554 break;
555
556 case 0xd9:
557 s->dma_auto = 0;
558 break;
559
560 case 0xda:
561 s->dma_auto = 0;
562 break;
563
564 case 0xe0:
565 s->needed_bytes = 1;
566 break;
567
568 case 0xe1:
569 dsp_out_data (s, s->ver & 0xff);
570 dsp_out_data (s, s->ver >> 8);
571 break;
572
573 case 0xe2:
574 s->needed_bytes = 1;
575 goto warn;
576
577 case 0xe3:
578 {
579 int i;
580 for (i = sizeof (e3) - 1; i >= 0; --i)
581 dsp_out_data (s, e3[i]);
582 }
583 break;
584
585 case 0xe4:
586 s->needed_bytes = 1;
587 break;
588
589 case 0xe7:
590 dolog ("Attempt to probe for ESS (0xe7)?\n");
591 break;
592
593 case 0xe8:
594 dsp_out_data (s, s->test_reg);
595 break;
596
597 case 0xf2:
598 case 0xf3:
599 dsp_out_data (s, 0xaa);
600 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
601 qemu_irq_raise (s->pic[s->irq]);
602 break;
603
604 case 0xf9:
605 s->needed_bytes = 1;
606 goto warn;
607
608 case 0xfa:
609 dsp_out_data (s, 0);
610 goto warn;
611
612 case 0xfc:
613 dsp_out_data (s, 0);
614 goto warn;
615
616 default:
617 dolog ("Unrecognized command %#x\n", cmd);
618 break;
619 }
620 }
621
622 if (!s->needed_bytes) {
623 ldebug ("\n");
624 }
625
626 exit:
627 if (!s->needed_bytes) {
628 s->cmd = -1;
629 }
630 else {
631 s->cmd = cmd;
632 }
633 return;
634
635 warn:
636 dolog ("warning: command %#x,%d is not truly understood yet\n",
637 cmd, s->needed_bytes);
638 goto exit;
639
640}
641
642static uint16_t dsp_get_lohi (SB16State *s)
643{
644 uint8_t hi = dsp_get_data (s);
645 uint8_t lo = dsp_get_data (s);
646 return (hi << 8) | lo;
647}
648
649static uint16_t dsp_get_hilo (SB16State *s)
650{
651 uint8_t lo = dsp_get_data (s);
652 uint8_t hi = dsp_get_data (s);
653 return (hi << 8) | lo;
654}
655
656static void complete (SB16State *s)
657{
658 int d0, d1, d2;
659 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
660 s->cmd, s->in_index, s->needed_bytes);
661
662 if (s->cmd > 0xaf && s->cmd < 0xd0) {
663 d2 = dsp_get_data (s);
664 d1 = dsp_get_data (s);
665 d0 = dsp_get_data (s);
666
667 if (s->cmd & 8) {
668 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
669 s->cmd, d0, d1, d2);
670 }
671 else {
672 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
673 s->cmd, d0, d1, d2);
674 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
675 }
676 }
677 else {
678 switch (s->cmd) {
679 case 0x04:
680 s->csp_mode = dsp_get_data (s);
681 s->csp_reg83r = 0;
682 s->csp_reg83w = 0;
683 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
684 break;
685
686 case 0x05:
687 s->csp_param = dsp_get_data (s);
688 s->csp_value = dsp_get_data (s);
689 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
690 s->csp_param,
691 s->csp_value);
692 break;
693
694 case 0x0e:
695 d0 = dsp_get_data (s);
696 d1 = dsp_get_data (s);
697 ldebug ("write CSP register %d <- %#x\n", d1, d0);
698 if (d1 == 0x83) {
699 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
700 s->csp_reg83[s->csp_reg83r % 4] = d0;
701 s->csp_reg83r += 1;
702 }
703 else {
704 s->csp_regs[d1] = d0;
705 }
706 break;
707
708 case 0x0f:
709 d0 = dsp_get_data (s);
710 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
711 d0, s->csp_regs[d0], s->csp_mode);
712 if (d0 == 0x83) {
713 ldebug ("0x83[%d] -> %#x\n",
714 s->csp_reg83w,
715 s->csp_reg83[s->csp_reg83w % 4]);
716 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
717 s->csp_reg83w += 1;
718 }
719 else {
720 dsp_out_data (s, s->csp_regs[d0]);
721 }
722 break;
723
724 case 0x10:
725 d0 = dsp_get_data (s);
726 dolog ("cmd 0x10 d0=%#x\n", d0);
727 break;
728
729 case 0x14:
730 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
731 break;
732
733 case 0x40:
734 s->time_const = dsp_get_data (s);
735 ldebug ("set time const %d\n", s->time_const);
736 break;
737
738 case 0x42:
739#if 0
740 dolog ("cmd 0x42 might not do what it think it should\n");
741#endif
742 case 0x41:
743 s->freq = dsp_get_hilo (s);
744 ldebug ("set freq %d\n", s->freq);
745 break;
746
747 case 0x48:
748 s->block_size = dsp_get_lohi (s) + 1;
749 ldebug ("set dma block len %d\n", s->block_size);
750 break;
751
752 case 0x74:
753 case 0x75:
754 case 0x76:
755 case 0x77:
756
757 break;
758
759 case 0x80:
760 {
761 int freq, samples, bytes;
762 int64_t ticks;
763
764 freq = s->freq > 0 ? s->freq : 11025;
765 samples = dsp_get_lohi (s) + 1;
766 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
767 ticks = (bytes * ticks_per_sec) / freq;
768 if (ticks < ticks_per_sec / 1024) {
769 qemu_irq_raise (s->pic[s->irq]);
770 }
771 else {
772 if (s->aux_ts) {
773 qemu_mod_timer (
774 s->aux_ts,
775 qemu_get_clock (vm_clock) + ticks
776 );
777 }
778 }
779 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
780 }
781 break;
782
783 case 0xe0:
784 d0 = dsp_get_data (s);
785 s->out_data_len = 0;
786 ldebug ("E0 data = %#x\n", d0);
787 dsp_out_data (s, ~d0);
788 break;
789
790 case 0xe2:
791 d0 = dsp_get_data (s);
792 ldebug ("E2 = %#x\n", d0);
793 break;
794
795 case 0xe4:
796 s->test_reg = dsp_get_data (s);
797 break;
798
799 case 0xf9:
800 d0 = dsp_get_data (s);
801 ldebug ("command 0xf9 with %#x\n", d0);
802 switch (d0) {
803 case 0x0e:
804 dsp_out_data (s, 0xff);
805 break;
806
807 case 0x0f:
808 dsp_out_data (s, 0x07);
809 break;
810
811 case 0x37:
812 dsp_out_data (s, 0x38);
813 break;
814
815 default:
816 dsp_out_data (s, 0x00);
817 break;
818 }
819 break;
820
821 default:
822 dolog ("complete: unrecognized command %#x\n", s->cmd);
823 return;
824 }
825 }
826
827 ldebug ("\n");
828 s->cmd = -1;
829 return;
830}
831
832static void legacy_reset (SB16State *s)
833{
834 struct audsettings as;
835
836 s->freq = 11025;
837 s->fmt_signed = 0;
838 s->fmt_bits = 8;
839 s->fmt_stereo = 0;
840
841 as.freq = s->freq;
842 as.nchannels = 1;
843 as.fmt = AUD_FMT_U8;
844 as.endianness = 0;
845
846 s->voice = AUD_open_out (
847 &s->card,
848 s->voice,
849 "sb16",
850 s,
851 SB_audio_callback,
852 &as
853 );
854
855
856
857}
858
859static void reset (SB16State *s)
860{
861 qemu_irq_lower (s->pic[s->irq]);
862 if (s->dma_auto) {
863 qemu_irq_raise (s->pic[s->irq]);
864 qemu_irq_lower (s->pic[s->irq]);
865 }
866
867 s->mixer_regs[0x82] = 0;
868 s->dma_auto = 0;
869 s->in_index = 0;
870 s->out_data_len = 0;
871 s->left_till_irq = 0;
872 s->needed_bytes = 0;
873 s->block_size = -1;
874 s->nzero = 0;
875 s->highspeed = 0;
876 s->v2x6 = 0;
877 s->cmd = -1;
878
879 dsp_out_data(s, 0xaa);
880 speaker (s, 0);
881 control (s, 0);
882 legacy_reset (s);
883}
884
885static IO_WRITE_PROTO (dsp_write)
886{
887 SB16State *s = opaque;
888 int iport;
889
890 iport = nport - s->port;
891
892 ldebug ("write %#x <- %#x\n", nport, val);
893 switch (iport) {
894 case 0x06:
895 switch (val) {
896 case 0x00:
897 if (s->v2x6 == 1) {
898 if (0 && s->highspeed) {
899 s->highspeed = 0;
900 qemu_irq_lower (s->pic[s->irq]);
901 control (s, 0);
902 }
903 else {
904 reset (s);
905 }
906 }
907 s->v2x6 = 0;
908 break;
909
910 case 0x01:
911 case 0x03:
912 s->v2x6 = 1;
913 break;
914
915 case 0xc6:
916 s->v2x6 = 0;
917 break;
918
919 case 0xb8:
920 reset (s);
921 break;
922
923 case 0x39:
924 dsp_out_data (s, 0x38);
925 reset (s);
926 s->v2x6 = 0x39;
927 break;
928
929 default:
930 s->v2x6 = val;
931 break;
932 }
933 break;
934
935 case 0x0c:
936
937
938
939 if (0 == s->needed_bytes) {
940 command (s, val);
941#if 0
942 if (0 == s->needed_bytes) {
943 log_dsp (s);
944 }
945#endif
946 }
947 else {
948 if (s->in_index == sizeof (s->in2_data)) {
949 dolog ("in data overrun\n");
950 }
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
959 }
960 }
961 }
962 break;
963
964 default:
965 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
966 break;
967 }
968}
969
970static IO_READ_PROTO (dsp_read)
971{
972 SB16State *s = opaque;
973 int iport, retval, ack = 0;
974
975 iport = nport - s->port;
976
977 switch (iport) {
978 case 0x06:
979 retval = 0xff;
980 break;
981
982 case 0x0a:
983 if (s->out_data_len) {
984 retval = s->out_data[--s->out_data_len];
985 s->last_read_byte = retval;
986 }
987 else {
988 if (s->cmd != -1) {
989 dolog ("empty output buffer for command %#x\n",
990 s->cmd);
991 }
992 retval = s->last_read_byte;
993
994 }
995 break;
996
997 case 0x0c:
998 retval = s->can_write ? 0 : 0x80;
999 break;
1000
1001 case 0x0d:
1002
1003 retval = 0;
1004 break;
1005
1006 case 0x0e:
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[s->irq]);
1012 }
1013 break;
1014
1015 case 0x0f:
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[s->irq]);
1021 }
1022 break;
1023
1024 default:
1025 goto error;
1026 }
1027
1028 if (!ack) {
1029 ldebug ("read %#x -> %#x\n", nport, retval);
1030 }
1031
1032 return retval;
1033
1034 error:
1035 dolog ("warning: dsp_read %#x error\n", nport);
1036 return 0xff;
1037}
1038
1039static void reset_mixer (SB16State *s)
1040{
1041 int i;
1042
1043 memset (s->mixer_regs, 0xff, 0x7f);
1044 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1045
1046 s->mixer_regs[0x02] = 4;
1047 s->mixer_regs[0x06] = 4;
1048 s->mixer_regs[0x08] = 0;
1049 s->mixer_regs[0x0a] = 0;
1050
1051
1052 s->mixer_regs[0x0c] = 0;
1053
1054
1055 s->mixer_regs[0x0e] = 0;
1056
1057
1058 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1059
1060 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1061
1062 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1063
1064 for (i = 0x30; i < 0x48; i++) {
1065 s->mixer_regs[i] = 0x20;
1066 }
1067}
1068
1069static IO_WRITE_PROTO (mixer_write_indexb)
1070{
1071 SB16State *s = opaque;
1072 (void) nport;
1073 s->mixer_nreg = val;
1074}
1075
1076static IO_WRITE_PROTO (mixer_write_datab)
1077{
1078 SB16State *s = opaque;
1079
1080 (void) nport;
1081 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1082
1083 switch (s->mixer_nreg) {
1084 case 0x00:
1085 reset_mixer (s);
1086 break;
1087
1088 case 0x80:
1089 {
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;
1094 }
1095 }
1096 break;
1097
1098 case 0x81:
1099 {
1100 int dma, hdma;
1101
1102 dma = lsbindex (val & 0xf);
1103 hdma = lsbindex (val & 0xf0);
1104 if (dma != s->dma || hdma != s->hdma) {
1105 dolog (
1106 "attempt to change DMA "
1107 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1108 dma, s->dma, hdma, s->hdma, val);
1109 }
1110#if 0
1111 s->dma = dma;
1112 s->hdma = hdma;
1113#endif
1114 }
1115 break;
1116
1117 case 0x82:
1118 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1119 val);
1120 return;
1121
1122 default:
1123 if (s->mixer_nreg >= 0x80) {
1124 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1125 }
1126 break;
1127 }
1128
1129 s->mixer_regs[s->mixer_nreg] = val;
1130}
1131
1132static IO_WRITE_PROTO (mixer_write_indexw)
1133{
1134 mixer_write_indexb (opaque, nport, val & 0xff);
1135 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1136}
1137
1138static IO_READ_PROTO (mixer_read)
1139{
1140 SB16State *s = opaque;
1141
1142 (void) nport;
1143#ifndef DEBUG_SB16_MOST
1144 if (s->mixer_nreg != 0x82) {
1145 ldebug ("mixer_read[%#x] -> %#x\n",
1146 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1147 }
1148#else
1149 ldebug ("mixer_read[%#x] -> %#x\n",
1150 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1151#endif
1152 return s->mixer_regs[s->mixer_nreg];
1153}
1154
1155static int write_audio (SB16State *s, int nchan, int dma_pos,
1156 int dma_len, int len)
1157{
1158 int temp, net;
1159 uint8_t tmpbuf[4096];
1160
1161 temp = len;
1162 net = 0;
1163
1164 while (temp) {
1165 int left = dma_len - dma_pos;
1166 int copied;
1167 size_t to_copy;
1168
1169 to_copy = audio_MIN (temp, left);
1170 if (to_copy > sizeof (tmpbuf)) {
1171 to_copy = sizeof (tmpbuf);
1172 }
1173
1174 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1175 copied = AUD_write (s->voice, tmpbuf, copied);
1176
1177 temp -= copied;
1178 dma_pos = (dma_pos + copied) % dma_len;
1179 net += copied;
1180
1181 if (!copied) {
1182 break;
1183 }
1184 }
1185
1186 return net;
1187}
1188
1189static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1190{
1191 SB16State *s = opaque;
1192 int till, copy, written, free;
1193
1194 if (s->block_size <= 0) {
1195 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1196 s->block_size, nchan, dma_pos, dma_len);
1197 return dma_pos;
1198 }
1199
1200 if (s->left_till_irq < 0) {
1201 s->left_till_irq = s->block_size;
1202 }
1203
1204 if (s->voice) {
1205 free = s->audio_free & ~s->align;
1206 if ((free <= 0) || !dma_len) {
1207 return dma_pos;
1208 }
1209 }
1210 else {
1211 free = dma_len;
1212 }
1213
1214 copy = free;
1215 till = s->left_till_irq;
1216
1217#ifdef DEBUG_SB16_MOST
1218 dolog ("pos:%06d %d till:%d len:%d\n",
1219 dma_pos, free, till, dma_len);
1220#endif
1221
1222 if (till <= copy) {
1223 if (0 == s->dma_auto) {
1224 copy = till;
1225 }
1226 }
1227
1228 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1229 dma_pos = (dma_pos + written) % dma_len;
1230 s->left_till_irq -= written;
1231
1232 if (s->left_till_irq <= 0) {
1233 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1234 qemu_irq_raise (s->pic[s->irq]);
1235 if (0 == s->dma_auto) {
1236 control (s, 0);
1237 speaker (s, 0);
1238 }
1239 }
1240
1241#ifdef DEBUG_SB16_MOST
1242 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1243 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1244 s->block_size);
1245#endif
1246
1247 while (s->left_till_irq <= 0) {
1248 s->left_till_irq = s->block_size + s->left_till_irq;
1249 }
1250
1251 return dma_pos;
1252}
1253
1254static void SB_audio_callback (void *opaque, int free)
1255{
1256 SB16State *s = opaque;
1257 s->audio_free = free;
1258}
1259
1260static void SB_save (QEMUFile *f, void *opaque)
1261{
1262 SB16State *s = opaque;
1263
1264 qemu_put_be32 (f, s->irq);
1265 qemu_put_be32 (f, s->dma);
1266 qemu_put_be32 (f, s->hdma);
1267 qemu_put_be32 (f, s->port);
1268 qemu_put_be32 (f, s->ver);
1269 qemu_put_be32 (f, s->in_index);
1270 qemu_put_be32 (f, s->out_data_len);
1271 qemu_put_be32 (f, s->fmt_stereo);
1272 qemu_put_be32 (f, s->fmt_signed);
1273 qemu_put_be32 (f, s->fmt_bits);
1274 qemu_put_be32s (f, &s->fmt);
1275 qemu_put_be32 (f, s->dma_auto);
1276 qemu_put_be32 (f, s->block_size);
1277 qemu_put_be32 (f, s->fifo);
1278 qemu_put_be32 (f, s->freq);
1279 qemu_put_be32 (f, s->time_const);
1280 qemu_put_be32 (f, s->speaker);
1281 qemu_put_be32 (f, s->needed_bytes);
1282 qemu_put_be32 (f, s->cmd);
1283 qemu_put_be32 (f, s->use_hdma);
1284 qemu_put_be32 (f, s->highspeed);
1285 qemu_put_be32 (f, s->can_write);
1286 qemu_put_be32 (f, s->v2x6);
1287
1288 qemu_put_8s (f, &s->csp_param);
1289 qemu_put_8s (f, &s->csp_value);
1290 qemu_put_8s (f, &s->csp_mode);
1291 qemu_put_8s (f, &s->csp_param);
1292 qemu_put_buffer (f, s->csp_regs, 256);
1293 qemu_put_8s (f, &s->csp_index);
1294 qemu_put_buffer (f, s->csp_reg83, 4);
1295 qemu_put_be32 (f, s->csp_reg83r);
1296 qemu_put_be32 (f, s->csp_reg83w);
1297
1298 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1299 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1300 qemu_put_8s (f, &s->test_reg);
1301 qemu_put_8s (f, &s->last_read_byte);
1302
1303 qemu_put_be32 (f, s->nzero);
1304 qemu_put_be32 (f, s->left_till_irq);
1305 qemu_put_be32 (f, s->dma_running);
1306 qemu_put_be32 (f, s->bytes_per_second);
1307 qemu_put_be32 (f, s->align);
1308
1309 qemu_put_be32 (f, s->mixer_nreg);
1310 qemu_put_buffer (f, s->mixer_regs, 256);
1311}
1312
1313static int SB_load (QEMUFile *f, void *opaque, int version_id)
1314{
1315 SB16State *s = opaque;
1316
1317 if (version_id != 1) {
1318 return -EINVAL;
1319 }
1320
1321 s->irq=qemu_get_be32 (f);
1322 s->dma=qemu_get_be32 (f);
1323 s->hdma=qemu_get_be32 (f);
1324 s->port=qemu_get_be32 (f);
1325 s->ver=qemu_get_be32 (f);
1326 s->in_index=qemu_get_be32 (f);
1327 s->out_data_len=qemu_get_be32 (f);
1328 s->fmt_stereo=qemu_get_be32 (f);
1329 s->fmt_signed=qemu_get_be32 (f);
1330 s->fmt_bits=qemu_get_be32 (f);
1331 qemu_get_be32s (f, &s->fmt);
1332 s->dma_auto=qemu_get_be32 (f);
1333 s->block_size=qemu_get_be32 (f);
1334 s->fifo=qemu_get_be32 (f);
1335 s->freq=qemu_get_be32 (f);
1336 s->time_const=qemu_get_be32 (f);
1337 s->speaker=qemu_get_be32 (f);
1338 s->needed_bytes=qemu_get_be32 (f);
1339 s->cmd=qemu_get_be32 (f);
1340 s->use_hdma=qemu_get_be32 (f);
1341 s->highspeed=qemu_get_be32 (f);
1342 s->can_write=qemu_get_be32 (f);
1343 s->v2x6=qemu_get_be32 (f);
1344
1345 qemu_get_8s (f, &s->csp_param);
1346 qemu_get_8s (f, &s->csp_value);
1347 qemu_get_8s (f, &s->csp_mode);
1348 qemu_get_8s (f, &s->csp_param);
1349 qemu_get_buffer (f, s->csp_regs, 256);
1350 qemu_get_8s (f, &s->csp_index);
1351 qemu_get_buffer (f, s->csp_reg83, 4);
1352 s->csp_reg83r=qemu_get_be32 (f);
1353 s->csp_reg83w=qemu_get_be32 (f);
1354
1355 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1356 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1357 qemu_get_8s (f, &s->test_reg);
1358 qemu_get_8s (f, &s->last_read_byte);
1359
1360 s->nzero=qemu_get_be32 (f);
1361 s->left_till_irq=qemu_get_be32 (f);
1362 s->dma_running=qemu_get_be32 (f);
1363 s->bytes_per_second=qemu_get_be32 (f);
1364 s->align=qemu_get_be32 (f);
1365
1366 s->mixer_nreg=qemu_get_be32 (f);
1367 qemu_get_buffer (f, s->mixer_regs, 256);
1368
1369 if (s->voice) {
1370 AUD_close_out (&s->card, s->voice);
1371 s->voice = NULL;
1372 }
1373
1374 if (s->dma_running) {
1375 if (s->freq) {
1376 struct audsettings as;
1377
1378 s->audio_free = 0;
1379
1380 as.freq = s->freq;
1381 as.nchannels = 1 << s->fmt_stereo;
1382 as.fmt = s->fmt;
1383 as.endianness = 0;
1384
1385 s->voice = AUD_open_out (
1386 &s->card,
1387 s->voice,
1388 "sb16",
1389 s,
1390 SB_audio_callback,
1391 &as
1392 );
1393 }
1394
1395 control (s, 1);
1396 speaker (s, s->speaker);
1397 }
1398 return 0;
1399}
1400
1401int SB16_init (qemu_irq *pic)
1402{
1403 SB16State *s;
1404 int i;
1405 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1406 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1407
1408 s = qemu_mallocz (sizeof (*s));
1409
1410 s->cmd = -1;
1411 s->pic = pic;
1412 s->irq = conf.irq;
1413 s->dma = conf.dma;
1414 s->hdma = conf.hdma;
1415 s->port = conf.port;
1416 s->ver = conf.ver_lo | (conf.ver_hi << 8);
1417
1418 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1419 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1420 s->mixer_regs[0x82] = 2 << 5;
1421
1422 s->csp_regs[5] = 1;
1423 s->csp_regs[9] = 0xf8;
1424
1425 reset_mixer (s);
1426 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1427 if (!s->aux_ts) {
1428 dolog ("warning: Could not create auxiliary timer\n");
1429 }
1430
1431 for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) {
1432 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1433 }
1434
1435 for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) {
1436 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1437 }
1438
1439 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1440 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1441 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1442 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1443
1444 DMA_register_channel (s->hdma, SB_read_DMA, s);
1445 DMA_register_channel (s->dma, SB_read_DMA, s);
1446 s->can_write = 1;
1447
1448 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1449 AUD_register_card ("sb16", &s->card);
1450 return 0;
1451}
1452