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 "qemu/osdep.h"
25#include "hw/hw.h"
26#include "hw/audio/audio.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
33#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
34
35
36
37
38#ifdef DEBUG
39#define ldebug(...) dolog (__VA_ARGS__)
40#else
41#define ldebug(...)
42#endif
43
44static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
45
46#define TYPE_SB16 "sb16"
47#define SB16(obj) OBJECT_CHECK (SB16State, (obj), TYPE_SB16)
48
49typedef struct SB16State {
50 ISADevice parent_obj;
51
52 QEMUSoundCard card;
53 qemu_irq pic;
54 uint32_t irq;
55 uint32_t dma;
56 uint32_t hdma;
57 uint32_t port;
58 uint32_t ver;
59 IsaDma *isa_dma;
60 IsaDma *isa_hdma;
61
62 int in_index;
63 int out_data_len;
64 int fmt_stereo;
65 int fmt_signed;
66 int fmt_bits;
67 audfmt_e fmt;
68 int dma_auto;
69 int block_size;
70 int fifo;
71 int freq;
72 int time_const;
73 int speaker;
74 int needed_bytes;
75 int cmd;
76 int use_hdma;
77 int highspeed;
78 int can_write;
79
80 int v2x6;
81
82 uint8_t csp_param;
83 uint8_t csp_value;
84 uint8_t csp_mode;
85 uint8_t csp_regs[256];
86 uint8_t csp_index;
87 uint8_t csp_reg83[4];
88 int csp_reg83r;
89 int csp_reg83w;
90
91 uint8_t in2_data[10];
92 uint8_t out_data[50];
93 uint8_t test_reg;
94 uint8_t last_read_byte;
95 int nzero;
96
97 int left_till_irq;
98
99 int dma_running;
100 int bytes_per_second;
101 int align;
102 int audio_free;
103 SWVoiceOut *voice;
104
105 QEMUTimer *aux_ts;
106
107 int mixer_nreg;
108 uint8_t mixer_regs[256];
109} SB16State;
110
111static void SB_audio_callback (void *opaque, int free);
112
113static int magic_of_irq (int irq)
114{
115 switch (irq) {
116 case 5:
117 return 2;
118 case 7:
119 return 4;
120 case 9:
121 return 1;
122 case 10:
123 return 8;
124 default:
125 dolog ("bad irq %d\n", irq);
126 return 2;
127 }
128}
129
130static int irq_of_magic (int magic)
131{
132 switch (magic) {
133 case 1:
134 return 9;
135 case 2:
136 return 5;
137 case 4:
138 return 7;
139 case 8:
140 return 10;
141 default:
142 dolog ("bad irq magic %d\n", magic);
143 return -1;
144 }
145}
146
147#if 0
148static void log_dsp (SB16State *dsp)
149{
150 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
151 dsp->fmt_stereo ? "Stereo" : "Mono",
152 dsp->fmt_signed ? "Signed" : "Unsigned",
153 dsp->fmt_bits,
154 dsp->dma_auto ? "Auto" : "Single",
155 dsp->block_size,
156 dsp->freq,
157 dsp->time_const,
158 dsp->speaker);
159}
160#endif
161
162static void speaker (SB16State *s, int on)
163{
164 s->speaker = on;
165
166}
167
168static void control (SB16State *s, int hold)
169{
170 int dma = s->use_hdma ? s->hdma : s->dma;
171 IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
172 IsaDmaClass *k = ISADMA_GET_CLASS(isa_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 k->hold_DREQ(isa_dma, dma);
179 AUD_set_active_out (s->voice, 1);
180 }
181 else {
182 k->release_DREQ(isa_dma, 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, NANOSECONDS_PER_SECOND, freq);
766 if (ticks < NANOSECONDS_PER_SECOND / 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 void dsp_write(void *opaque, uint32_t nport, uint32_t val)
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 uint32_t dsp_read(void *opaque, uint32_t nport)
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 void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1062{
1063 SB16State *s = opaque;
1064 (void) nport;
1065 s->mixer_nreg = val;
1066}
1067
1068static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
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 uint32_t mixer_read(void *opaque, uint32_t nport)
1125{
1126 SB16State *s = opaque;
1127
1128 (void) nport;
1129#ifndef DEBUG_SB16_MOST
1130 if (s->mixer_nreg != 0x82) {
1131 ldebug ("mixer_read[%#x] -> %#x\n",
1132 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1133 }
1134#else
1135 ldebug ("mixer_read[%#x] -> %#x\n",
1136 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1137#endif
1138 return s->mixer_regs[s->mixer_nreg];
1139}
1140
1141static int write_audio (SB16State *s, int nchan, int dma_pos,
1142 int dma_len, int len)
1143{
1144 IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
1145 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
1146 int temp, net;
1147 uint8_t tmpbuf[4096];
1148
1149 temp = len;
1150 net = 0;
1151
1152 while (temp) {
1153 int left = dma_len - dma_pos;
1154 int copied;
1155 size_t to_copy;
1156
1157 to_copy = audio_MIN (temp, left);
1158 if (to_copy > sizeof (tmpbuf)) {
1159 to_copy = sizeof (tmpbuf);
1160 }
1161
1162 copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
1163 copied = AUD_write (s->voice, tmpbuf, copied);
1164
1165 temp -= copied;
1166 dma_pos = (dma_pos + copied) % dma_len;
1167 net += copied;
1168
1169 if (!copied) {
1170 break;
1171 }
1172 }
1173
1174 return net;
1175}
1176
1177static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1178{
1179 SB16State *s = opaque;
1180 int till, copy, written, free;
1181
1182 if (s->block_size <= 0) {
1183 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1184 s->block_size, nchan, dma_pos, dma_len);
1185 return dma_pos;
1186 }
1187
1188 if (s->left_till_irq < 0) {
1189 s->left_till_irq = s->block_size;
1190 }
1191
1192 if (s->voice) {
1193 free = s->audio_free & ~s->align;
1194 if ((free <= 0) || !dma_len) {
1195 return dma_pos;
1196 }
1197 }
1198 else {
1199 free = dma_len;
1200 }
1201
1202 copy = free;
1203 till = s->left_till_irq;
1204
1205#ifdef DEBUG_SB16_MOST
1206 dolog ("pos:%06d %d till:%d len:%d\n",
1207 dma_pos, free, till, dma_len);
1208#endif
1209
1210 if (till <= copy) {
1211 if (s->dma_auto == 0) {
1212 copy = till;
1213 }
1214 }
1215
1216 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1217 dma_pos = (dma_pos + written) % dma_len;
1218 s->left_till_irq -= written;
1219
1220 if (s->left_till_irq <= 0) {
1221 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1222 qemu_irq_raise (s->pic);
1223 if (s->dma_auto == 0) {
1224 control (s, 0);
1225 speaker (s, 0);
1226 }
1227 }
1228
1229#ifdef DEBUG_SB16_MOST
1230 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1231 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1232 s->block_size);
1233#endif
1234
1235 while (s->left_till_irq <= 0) {
1236 s->left_till_irq = s->block_size + s->left_till_irq;
1237 }
1238
1239 return dma_pos;
1240}
1241
1242static void SB_audio_callback (void *opaque, int free)
1243{
1244 SB16State *s = opaque;
1245 s->audio_free = free;
1246}
1247
1248static int sb16_post_load (void *opaque, int version_id)
1249{
1250 SB16State *s = opaque;
1251
1252 if (s->voice) {
1253 AUD_close_out (&s->card, s->voice);
1254 s->voice = NULL;
1255 }
1256
1257 if (s->dma_running) {
1258 if (s->freq) {
1259 struct audsettings as;
1260
1261 s->audio_free = 0;
1262
1263 as.freq = s->freq;
1264 as.nchannels = 1 << s->fmt_stereo;
1265 as.fmt = s->fmt;
1266 as.endianness = 0;
1267
1268 s->voice = AUD_open_out (
1269 &s->card,
1270 s->voice,
1271 "sb16",
1272 s,
1273 SB_audio_callback,
1274 &as
1275 );
1276 }
1277
1278 control (s, 1);
1279 speaker (s, s->speaker);
1280 }
1281 return 0;
1282}
1283
1284static const VMStateDescription vmstate_sb16 = {
1285 .name = "sb16",
1286 .version_id = 1,
1287 .minimum_version_id = 1,
1288 .post_load = sb16_post_load,
1289 .fields = (VMStateField[]) {
1290 VMSTATE_UINT32 (irq, SB16State),
1291 VMSTATE_UINT32 (dma, SB16State),
1292 VMSTATE_UINT32 (hdma, SB16State),
1293 VMSTATE_UINT32 (port, SB16State),
1294 VMSTATE_UINT32 (ver, SB16State),
1295 VMSTATE_INT32 (in_index, SB16State),
1296 VMSTATE_INT32 (out_data_len, SB16State),
1297 VMSTATE_INT32 (fmt_stereo, SB16State),
1298 VMSTATE_INT32 (fmt_signed, SB16State),
1299 VMSTATE_INT32 (fmt_bits, SB16State),
1300 VMSTATE_UINT32 (fmt, SB16State),
1301 VMSTATE_INT32 (dma_auto, SB16State),
1302 VMSTATE_INT32 (block_size, SB16State),
1303 VMSTATE_INT32 (fifo, SB16State),
1304 VMSTATE_INT32 (freq, SB16State),
1305 VMSTATE_INT32 (time_const, SB16State),
1306 VMSTATE_INT32 (speaker, SB16State),
1307 VMSTATE_INT32 (needed_bytes, SB16State),
1308 VMSTATE_INT32 (cmd, SB16State),
1309 VMSTATE_INT32 (use_hdma, SB16State),
1310 VMSTATE_INT32 (highspeed, SB16State),
1311 VMSTATE_INT32 (can_write, SB16State),
1312 VMSTATE_INT32 (v2x6, SB16State),
1313
1314 VMSTATE_UINT8 (csp_param, SB16State),
1315 VMSTATE_UINT8 (csp_value, SB16State),
1316 VMSTATE_UINT8 (csp_mode, SB16State),
1317 VMSTATE_UINT8 (csp_param, SB16State),
1318 VMSTATE_BUFFER (csp_regs, SB16State),
1319 VMSTATE_UINT8 (csp_index, SB16State),
1320 VMSTATE_BUFFER (csp_reg83, SB16State),
1321 VMSTATE_INT32 (csp_reg83r, SB16State),
1322 VMSTATE_INT32 (csp_reg83w, SB16State),
1323
1324 VMSTATE_BUFFER (in2_data, SB16State),
1325 VMSTATE_BUFFER (out_data, SB16State),
1326 VMSTATE_UINT8 (test_reg, SB16State),
1327 VMSTATE_UINT8 (last_read_byte, SB16State),
1328
1329 VMSTATE_INT32 (nzero, SB16State),
1330 VMSTATE_INT32 (left_till_irq, SB16State),
1331 VMSTATE_INT32 (dma_running, SB16State),
1332 VMSTATE_INT32 (bytes_per_second, SB16State),
1333 VMSTATE_INT32 (align, SB16State),
1334
1335 VMSTATE_INT32 (mixer_nreg, SB16State),
1336 VMSTATE_BUFFER (mixer_regs, SB16State),
1337
1338 VMSTATE_END_OF_LIST ()
1339 }
1340};
1341
1342static const MemoryRegionPortio sb16_ioport_list[] = {
1343 { 4, 1, 1, .write = mixer_write_indexb },
1344 { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1345 { 6, 1, 1, .read = dsp_read, .write = dsp_write },
1346 { 10, 1, 1, .read = dsp_read },
1347 { 12, 1, 1, .write = dsp_write },
1348 { 12, 4, 1, .read = dsp_read },
1349 PORTIO_END_OF_LIST (),
1350};
1351
1352
1353static void sb16_initfn (Object *obj)
1354{
1355 SB16State *s = SB16 (obj);
1356
1357 s->cmd = -1;
1358}
1359
1360static void sb16_realizefn (DeviceState *dev, Error **errp)
1361{
1362 ISADevice *isadev = ISA_DEVICE (dev);
1363 SB16State *s = SB16 (dev);
1364 IsaDmaClass *k;
1365
1366 isa_init_irq (isadev, &s->pic, s->irq);
1367
1368 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1369 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1370 s->mixer_regs[0x82] = 2 << 5;
1371
1372 s->csp_regs[5] = 1;
1373 s->csp_regs[9] = 0xf8;
1374
1375 reset_mixer (s);
1376 s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1377 if (!s->aux_ts) {
1378 dolog ("warning: Could not create auxiliary timer\n");
1379 }
1380
1381 isa_register_portio_list (isadev, s->port, sb16_ioport_list, s, "sb16");
1382
1383 s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
1384 k = ISADMA_GET_CLASS(s->isa_hdma);
1385 k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1386
1387 s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
1388 k = ISADMA_GET_CLASS(s->isa_dma);
1389 k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1390
1391 s->can_write = 1;
1392
1393 AUD_register_card ("sb16", &s->card);
1394}
1395
1396static int SB16_init (ISABus *bus)
1397{
1398 isa_create_simple (bus, TYPE_SB16);
1399 return 0;
1400}
1401
1402static Property sb16_properties[] = {
1403 DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405),
1404 DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
1405 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1406 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1407 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1408 DEFINE_PROP_END_OF_LIST (),
1409};
1410
1411static void sb16_class_initfn (ObjectClass *klass, void *data)
1412{
1413 DeviceClass *dc = DEVICE_CLASS (klass);
1414
1415 dc->realize = sb16_realizefn;
1416 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1417 dc->desc = "Creative Sound Blaster 16";
1418 dc->vmsd = &vmstate_sb16;
1419 dc->props = sb16_properties;
1420}
1421
1422static const TypeInfo sb16_info = {
1423 .name = TYPE_SB16,
1424 .parent = TYPE_ISA_DEVICE,
1425 .instance_size = sizeof (SB16State),
1426 .instance_init = sb16_initfn,
1427 .class_init = sb16_class_initfn,
1428};
1429
1430static void sb16_register_types (void)
1431{
1432 type_register_static (&sb16_info);
1433 isa_register_soundhw("sb16", "Creative Sound Blaster 16", SB16_init);
1434}
1435
1436type_init (sb16_register_types)
1437