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