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