1 /*
2 * QEMU Soundblaster 16 emulation
3 *
4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 #include "qemu/osdep.h"
26 #include "hw/audio/soundhw.h"
27 #include "audio/audio.h"
28 #include "hw/irq.h"
29 #include "hw/isa/isa.h"
30 #include "hw/qdev-properties.h"
31 #include "migration/vmstate.h"
32 #include "qemu/timer.h"
33 #include "qemu/host-utils.h"
34 #include "qemu/log.h"
35 #include "qemu/module.h"
36 #include "qapi/error.h"
37 #include "qom/object.h"
38
39 #define dolog(...) AUD_log ("sb16", __VA_ARGS__)
40
41 /* #define DEBUG */
42 /* #define DEBUG_SB16_MOST */
43
44 #ifdef DEBUG
45 #define ldebug(...) dolog (__VA_ARGS__)
46 #else
47 #define ldebug(...)
48 #endif
49
50 static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
51
52 #define TYPE_SB16 "sb16"
53 OBJECT_DECLARE_SIMPLE_TYPE(SB16State, SB16)
54
55 struct SB16State {
56 ISADevice parent_obj;
57
58 QEMUSoundCard card;
59 qemu_irq pic;
60 uint32_t irq;
61 uint32_t dma;
62 uint32_t hdma;
63 uint32_t port;
64 uint32_t ver;
65 IsaDma *isa_dma;
66 IsaDma *isa_hdma;
67
68 int in_index;
69 int out_data_len;
70 int fmt_stereo;
71 int fmt_signed;
72 int fmt_bits;
73 AudioFormat fmt;
74 int dma_auto;
75 int block_size;
76 int fifo;
77 int freq;
78 int time_const;
79 int speaker;
80 int needed_bytes;
81 int cmd;
82 int use_hdma;
83 int highspeed;
84 int can_write;
85
86 int v2x6;
87
88 uint8_t csp_param;
89 uint8_t csp_value;
90 uint8_t csp_mode;
91 uint8_t csp_regs[256];
92 uint8_t csp_index;
93 uint8_t csp_reg83[4];
94 int csp_reg83r;
95 int csp_reg83w;
96
97 uint8_t in2_data[10];
98 uint8_t out_data[50];
99 uint8_t test_reg;
100 uint8_t last_read_byte;
101 int nzero;
102
103 int left_till_irq;
104
105 int dma_running;
106 int bytes_per_second;
107 int align;
108 int audio_free;
109 SWVoiceOut *voice;
110
111 QEMUTimer *aux_ts;
112 /* mixer state */
113 int mixer_nreg;
114 uint8_t mixer_regs[256];
115 PortioList portio_list;
116 };
117
118 #define SAMPLE_RATE_MIN 5000
119 #define SAMPLE_RATE_MAX 45000
120
121 static void SB_audio_callback (void *opaque, int free);
122
magic_of_irq(int irq)123 static int magic_of_irq (int irq)
124 {
125 switch (irq) {
126 case 5:
127 return 2;
128 case 7:
129 return 4;
130 case 9:
131 return 1;
132 case 10:
133 return 8;
134 default:
135 qemu_log_mask(LOG_GUEST_ERROR, "bad irq %d\n", irq);
136 return 2;
137 }
138 }
139
irq_of_magic(int magic)140 static int irq_of_magic (int magic)
141 {
142 switch (magic) {
143 case 1:
144 return 9;
145 case 2:
146 return 5;
147 case 4:
148 return 7;
149 case 8:
150 return 10;
151 default:
152 qemu_log_mask(LOG_GUEST_ERROR, "bad irq magic %d\n", magic);
153 return -1;
154 }
155 }
156
157 #if 0
158 static void log_dsp (SB16State *dsp)
159 {
160 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
161 dsp->fmt_stereo ? "Stereo" : "Mono",
162 dsp->fmt_signed ? "Signed" : "Unsigned",
163 dsp->fmt_bits,
164 dsp->dma_auto ? "Auto" : "Single",
165 dsp->block_size,
166 dsp->freq,
167 dsp->time_const,
168 dsp->speaker);
169 }
170 #endif
171
speaker(SB16State * s,int on)172 static void speaker (SB16State *s, int on)
173 {
174 s->speaker = on;
175 /* AUD_enable (s->voice, on); */
176 }
177
control(SB16State * s,int hold)178 static void control (SB16State *s, int hold)
179 {
180 int dma = s->use_hdma ? s->hdma : s->dma;
181 IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
182 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
183 s->dma_running = hold;
184
185 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
186
187 if (hold) {
188 k->hold_DREQ(isa_dma, dma);
189 AUD_set_active_out (s->voice, 1);
190 }
191 else {
192 k->release_DREQ(isa_dma, dma);
193 AUD_set_active_out (s->voice, 0);
194 }
195 }
196
aux_timer(void * opaque)197 static void aux_timer (void *opaque)
198 {
199 SB16State *s = opaque;
200 s->can_write = 1;
201 qemu_irq_raise (s->pic);
202 }
203
204 #define DMA8_AUTO 1
205 #define DMA8_HIGH 2
206
continue_dma8(SB16State * s)207 static void continue_dma8 (SB16State *s)
208 {
209 if (s->freq > 0) {
210 struct audsettings as;
211
212 s->audio_free = 0;
213
214 as.freq = s->freq;
215 as.nchannels = 1 << s->fmt_stereo;
216 as.fmt = s->fmt;
217 as.endianness = 0;
218
219 s->voice = AUD_open_out (
220 &s->card,
221 s->voice,
222 "sb16",
223 s,
224 SB_audio_callback,
225 &as
226 );
227 }
228
229 control (s, 1);
230 }
231
restrict_sampling_rate(int freq)232 static inline int restrict_sampling_rate(int freq)
233 {
234 if (freq < SAMPLE_RATE_MIN) {
235 qemu_log_mask(LOG_GUEST_ERROR,
236 "sampling range too low: %d, increasing to %u\n",
237 freq, SAMPLE_RATE_MIN);
238 return SAMPLE_RATE_MIN;
239 } else if (freq > SAMPLE_RATE_MAX) {
240 qemu_log_mask(LOG_GUEST_ERROR,
241 "sampling range too high: %d, decreasing to %u\n",
242 freq, SAMPLE_RATE_MAX);
243 return SAMPLE_RATE_MAX;
244 } else {
245 return freq;
246 }
247 }
248
dma_cmd8(SB16State * s,int mask,int dma_len)249 static void dma_cmd8 (SB16State *s, int mask, int dma_len)
250 {
251 s->fmt = AUDIO_FORMAT_U8;
252 s->use_hdma = 0;
253 s->fmt_bits = 8;
254 s->fmt_signed = 0;
255 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
256 if (-1 == s->time_const) {
257 if (s->freq <= 0)
258 s->freq = 11025;
259 }
260 else {
261 int tmp = (256 - s->time_const);
262 s->freq = (1000000 + (tmp / 2)) / tmp;
263 }
264 s->freq = restrict_sampling_rate(s->freq);
265
266 if (dma_len != -1) {
267 s->block_size = dma_len << s->fmt_stereo;
268 }
269 else {
270 /* This is apparently the only way to make both Act1/PL
271 and SecondReality/FC work
272
273 Act1 sets block size via command 0x48 and it's an odd number
274 SR does the same with even number
275 Both use stereo, and Creatives own documentation states that
276 0x48 sets block size in bytes less one.. go figure */
277 s->block_size &= ~s->fmt_stereo;
278 }
279
280 s->freq >>= s->fmt_stereo;
281 s->left_till_irq = s->block_size;
282 s->bytes_per_second = (s->freq << s->fmt_stereo);
283 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
284 s->dma_auto = (mask & DMA8_AUTO) != 0;
285 s->align = (1 << s->fmt_stereo) - 1;
286
287 if (s->block_size & s->align) {
288 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
289 " alignment %d\n", s->block_size, s->align + 1);
290 }
291
292 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
293 "dma %d, auto %d, fifo %d, high %d\n",
294 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
295 s->block_size, s->dma_auto, s->fifo, s->highspeed);
296
297 continue_dma8 (s);
298 speaker (s, 1);
299 }
300
dma_cmd(SB16State * s,uint8_t cmd,uint8_t d0,int dma_len)301 static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
302 {
303 s->use_hdma = cmd < 0xc0;
304 s->fifo = (cmd >> 1) & 1;
305 s->dma_auto = (cmd >> 2) & 1;
306 s->fmt_signed = (d0 >> 4) & 1;
307 s->fmt_stereo = (d0 >> 5) & 1;
308
309 switch (cmd >> 4) {
310 case 11:
311 s->fmt_bits = 16;
312 break;
313
314 case 12:
315 s->fmt_bits = 8;
316 break;
317 }
318
319 if (-1 != s->time_const) {
320 #if 1
321 int tmp = 256 - s->time_const;
322 s->freq = (1000000 + (tmp / 2)) / tmp;
323 #else
324 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
325 s->freq = 1000000 / ((255 - s->time_const));
326 #endif
327 s->time_const = -1;
328 }
329
330 s->block_size = dma_len + 1;
331 s->block_size <<= (s->fmt_bits == 16);
332 if (!s->dma_auto) {
333 /* It is clear that for DOOM and auto-init this value
334 shouldn't take stereo into account, while Miles Sound Systems
335 setsound.exe with single transfer mode wouldn't work without it
336 wonders of SB16 yet again */
337 s->block_size <<= s->fmt_stereo;
338 }
339
340 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
341 "dma %d, auto %d, fifo %d, high %d\n",
342 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
343 s->block_size, s->dma_auto, s->fifo, s->highspeed);
344
345 if (16 == s->fmt_bits) {
346 if (s->fmt_signed) {
347 s->fmt = AUDIO_FORMAT_S16;
348 }
349 else {
350 s->fmt = AUDIO_FORMAT_U16;
351 }
352 }
353 else {
354 if (s->fmt_signed) {
355 s->fmt = AUDIO_FORMAT_S8;
356 }
357 else {
358 s->fmt = AUDIO_FORMAT_U8;
359 }
360 }
361
362 s->left_till_irq = s->block_size;
363
364 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
365 s->highspeed = 0;
366 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
367 if (s->block_size & s->align) {
368 qemu_log_mask(LOG_GUEST_ERROR, "warning: misaligned block size %d,"
369 " alignment %d\n", s->block_size, s->align + 1);
370 }
371
372 if (s->freq) {
373 struct audsettings as;
374
375 s->audio_free = 0;
376
377 as.freq = s->freq;
378 as.nchannels = 1 << s->fmt_stereo;
379 as.fmt = s->fmt;
380 as.endianness = 0;
381
382 s->voice = AUD_open_out (
383 &s->card,
384 s->voice,
385 "sb16",
386 s,
387 SB_audio_callback,
388 &as
389 );
390 }
391
392 control (s, 1);
393 speaker (s, 1);
394 }
395
dsp_out_data(SB16State * s,uint8_t val)396 static inline void dsp_out_data (SB16State *s, uint8_t val)
397 {
398 ldebug ("outdata %#x\n", val);
399 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
400 s->out_data[s->out_data_len++] = val;
401 }
402 }
403
dsp_get_data(SB16State * s)404 static inline uint8_t dsp_get_data (SB16State *s)
405 {
406 if (s->in_index) {
407 return s->in2_data[--s->in_index];
408 }
409 else {
410 dolog ("buffer underflow\n");
411 return 0;
412 }
413 }
414
command(SB16State * s,uint8_t cmd)415 static void command (SB16State *s, uint8_t cmd)
416 {
417 ldebug ("command %#x\n", cmd);
418
419 if (cmd > 0xaf && cmd < 0xd0) {
420 if (cmd & 8) {
421 qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n",
422 cmd);
423 }
424
425 switch (cmd >> 4) {
426 case 11:
427 case 12:
428 break;
429 default:
430 qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd);
431 }
432 s->needed_bytes = 3;
433 }
434 else {
435 s->needed_bytes = 0;
436
437 switch (cmd) {
438 case 0x03:
439 dsp_out_data (s, 0x10); /* s->csp_param); */
440 goto warn;
441
442 case 0x04:
443 s->needed_bytes = 1;
444 goto warn;
445
446 case 0x05:
447 s->needed_bytes = 2;
448 goto warn;
449
450 case 0x08:
451 /* __asm__ ("int3"); */
452 goto warn;
453
454 case 0x0e:
455 s->needed_bytes = 2;
456 goto warn;
457
458 case 0x09:
459 dsp_out_data (s, 0xf8);
460 goto warn;
461
462 case 0x0f:
463 s->needed_bytes = 1;
464 goto warn;
465
466 case 0x10:
467 s->needed_bytes = 1;
468 goto warn;
469
470 case 0x14:
471 s->needed_bytes = 2;
472 s->block_size = 0;
473 break;
474
475 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
476 dma_cmd8 (s, DMA8_AUTO, -1);
477 break;
478
479 case 0x20: /* Direct ADC, Juice/PL */
480 dsp_out_data (s, 0xff);
481 goto warn;
482
483 case 0x35:
484 qemu_log_mask(LOG_UNIMP, "0x35 - MIDI command not implemented\n");
485 break;
486
487 case 0x40:
488 s->freq = -1;
489 s->time_const = -1;
490 s->needed_bytes = 1;
491 break;
492
493 case 0x41:
494 s->freq = -1;
495 s->time_const = -1;
496 s->needed_bytes = 2;
497 break;
498
499 case 0x42:
500 s->freq = -1;
501 s->time_const = -1;
502 s->needed_bytes = 2;
503 goto warn;
504
505 case 0x45:
506 dsp_out_data (s, 0xaa);
507 goto warn;
508
509 case 0x47: /* Continue Auto-Initialize DMA 16bit */
510 break;
511
512 case 0x48:
513 s->needed_bytes = 2;
514 break;
515
516 case 0x74:
517 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
518 qemu_log_mask(LOG_UNIMP, "0x75 - DMA DAC, 4-bit ADPCM not"
519 " implemented\n");
520 break;
521
522 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
523 s->needed_bytes = 2;
524 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 4-bit ADPCM Reference not"
525 " implemented\n");
526 break;
527
528 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
529 s->needed_bytes = 2;
530 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM not"
531 " implemented\n");
532 break;
533
534 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
535 s->needed_bytes = 2;
536 qemu_log_mask(LOG_UNIMP, "0x74 - DMA DAC, 2.6-bit ADPCM Reference"
537 " not implemented\n");
538 break;
539
540 case 0x7d:
541 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 4-bit"
542 " ADPCM Reference\n");
543 qemu_log_mask(LOG_UNIMP, "not implemented\n");
544 break;
545
546 case 0x7f:
547 qemu_log_mask(LOG_UNIMP, "0x7d - Autio-Initialize DMA DAC, 2.6-bit"
548 " ADPCM Reference\n");
549 qemu_log_mask(LOG_UNIMP, "not implemented\n");
550 break;
551
552 case 0x80:
553 s->needed_bytes = 2;
554 break;
555
556 case 0x90:
557 case 0x91:
558 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
559 break;
560
561 case 0xd0: /* halt DMA operation. 8bit */
562 control (s, 0);
563 break;
564
565 case 0xd1: /* speaker on */
566 speaker (s, 1);
567 break;
568
569 case 0xd3: /* speaker off */
570 speaker (s, 0);
571 break;
572
573 case 0xd4: /* continue DMA operation. 8bit */
574 /* KQ6 (or maybe Sierras audblst.drv in general) resets
575 the frequency between halt/continue */
576 continue_dma8 (s);
577 break;
578
579 case 0xd5: /* halt DMA operation. 16bit */
580 control (s, 0);
581 break;
582
583 case 0xd6: /* continue DMA operation. 16bit */
584 control (s, 1);
585 break;
586
587 case 0xd9: /* exit auto-init DMA after this block. 16bit */
588 s->dma_auto = 0;
589 break;
590
591 case 0xda: /* exit auto-init DMA after this block. 8bit */
592 s->dma_auto = 0;
593 break;
594
595 case 0xe0: /* DSP identification */
596 s->needed_bytes = 1;
597 break;
598
599 case 0xe1:
600 dsp_out_data (s, s->ver & 0xff);
601 dsp_out_data (s, s->ver >> 8);
602 break;
603
604 case 0xe2:
605 s->needed_bytes = 1;
606 goto warn;
607
608 case 0xe3:
609 {
610 int i;
611 for (i = sizeof (e3) - 1; i >= 0; --i)
612 dsp_out_data (s, e3[i]);
613 }
614 break;
615
616 case 0xe4: /* write test reg */
617 s->needed_bytes = 1;
618 break;
619
620 case 0xe7:
621 qemu_log_mask(LOG_UNIMP, "Attempt to probe for ESS (0xe7)?\n");
622 break;
623
624 case 0xe8: /* read test reg */
625 dsp_out_data (s, s->test_reg);
626 break;
627
628 case 0xf2:
629 case 0xf3:
630 dsp_out_data (s, 0xaa);
631 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
632 qemu_irq_raise (s->pic);
633 break;
634
635 case 0xf9:
636 s->needed_bytes = 1;
637 goto warn;
638
639 case 0xfa:
640 dsp_out_data (s, 0);
641 goto warn;
642
643 case 0xfc: /* FIXME */
644 dsp_out_data (s, 0);
645 goto warn;
646
647 default:
648 qemu_log_mask(LOG_UNIMP, "Unrecognized command %#x\n", cmd);
649 break;
650 }
651 }
652
653 if (!s->needed_bytes) {
654 ldebug ("\n");
655 }
656
657 exit:
658 if (!s->needed_bytes) {
659 s->cmd = -1;
660 }
661 else {
662 s->cmd = cmd;
663 }
664 return;
665
666 warn:
667 qemu_log_mask(LOG_UNIMP, "warning: command %#x,%d is not truly understood"
668 " yet\n", cmd, s->needed_bytes);
669 goto exit;
670
671 }
672
dsp_get_lohi(SB16State * s)673 static uint16_t dsp_get_lohi (SB16State *s)
674 {
675 uint8_t hi = dsp_get_data (s);
676 uint8_t lo = dsp_get_data (s);
677 return (hi << 8) | lo;
678 }
679
dsp_get_hilo(SB16State * s)680 static uint16_t dsp_get_hilo (SB16State *s)
681 {
682 uint8_t lo = dsp_get_data (s);
683 uint8_t hi = dsp_get_data (s);
684 return (hi << 8) | lo;
685 }
686
complete(SB16State * s)687 static void complete (SB16State *s)
688 {
689 int d0, d1, d2;
690 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
691 s->cmd, s->in_index, s->needed_bytes);
692
693 if (s->cmd > 0xaf && s->cmd < 0xd0) {
694 d2 = dsp_get_data (s);
695 d1 = dsp_get_data (s);
696 d0 = dsp_get_data (s);
697
698 if (s->cmd & 8) {
699 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
700 s->cmd, d0, d1, d2);
701 }
702 else {
703 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
704 s->cmd, d0, d1, d2);
705 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
706 }
707 }
708 else {
709 switch (s->cmd) {
710 case 0x04:
711 s->csp_mode = dsp_get_data (s);
712 s->csp_reg83r = 0;
713 s->csp_reg83w = 0;
714 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
715 break;
716
717 case 0x05:
718 s->csp_param = dsp_get_data (s);
719 s->csp_value = dsp_get_data (s);
720 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
721 s->csp_param,
722 s->csp_value);
723 break;
724
725 case 0x0e:
726 d0 = dsp_get_data (s);
727 d1 = dsp_get_data (s);
728 ldebug ("write CSP register %d <- %#x\n", d1, d0);
729 if (d1 == 0x83) {
730 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
731 s->csp_reg83[s->csp_reg83r % 4] = d0;
732 s->csp_reg83r += 1;
733 }
734 else {
735 s->csp_regs[d1] = d0;
736 }
737 break;
738
739 case 0x0f:
740 d0 = dsp_get_data (s);
741 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
742 d0, s->csp_regs[d0], s->csp_mode);
743 if (d0 == 0x83) {
744 ldebug ("0x83[%d] -> %#x\n",
745 s->csp_reg83w,
746 s->csp_reg83[s->csp_reg83w % 4]);
747 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
748 s->csp_reg83w += 1;
749 }
750 else {
751 dsp_out_data (s, s->csp_regs[d0]);
752 }
753 break;
754
755 case 0x10:
756 d0 = dsp_get_data (s);
757 dolog ("cmd 0x10 d0=%#x\n", d0);
758 break;
759
760 case 0x14:
761 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
762 break;
763
764 case 0x40:
765 s->time_const = dsp_get_data (s);
766 ldebug ("set time const %d\n", s->time_const);
767 break;
768
769 case 0x41:
770 case 0x42:
771 /*
772 * 0x41 is documented as setting the output sample rate,
773 * and 0x42 the input sample rate, but in fact SB16 hardware
774 * seems to have only a single sample rate under the hood,
775 * and FT2 sets output freq with this (go figure). Compare:
776 * http://homepages.cae.wisc.edu/~brodskye/sb16doc/sb16doc.html#SamplingRate
777 */
778 s->freq = restrict_sampling_rate(dsp_get_hilo(s));
779 ldebug ("set freq %d\n", s->freq);
780 break;
781
782 case 0x48:
783 s->block_size = dsp_get_lohi (s) + 1;
784 ldebug ("set dma block len %d\n", s->block_size);
785 break;
786
787 case 0x74:
788 case 0x75:
789 case 0x76:
790 case 0x77:
791 /* ADPCM stuff, ignore */
792 break;
793
794 case 0x80:
795 {
796 int freq, samples, bytes;
797 int64_t ticks;
798
799 freq = s->freq > 0 ? s->freq : 11025;
800 samples = dsp_get_lohi (s) + 1;
801 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
802 ticks = muldiv64(bytes, NANOSECONDS_PER_SECOND, freq);
803 if (ticks < NANOSECONDS_PER_SECOND / 1024) {
804 qemu_irq_raise (s->pic);
805 }
806 else {
807 if (s->aux_ts) {
808 timer_mod (
809 s->aux_ts,
810 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks
811 );
812 }
813 }
814 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
815 }
816 break;
817
818 case 0xe0:
819 d0 = dsp_get_data (s);
820 s->out_data_len = 0;
821 ldebug ("E0 data = %#x\n", d0);
822 dsp_out_data (s, ~d0);
823 break;
824
825 case 0xe2:
826 #ifdef DEBUG
827 d0 = dsp_get_data (s);
828 dolog ("E2 = %#x\n", d0);
829 #endif
830 break;
831
832 case 0xe4:
833 s->test_reg = dsp_get_data (s);
834 break;
835
836 case 0xf9:
837 d0 = dsp_get_data (s);
838 ldebug ("command 0xf9 with %#x\n", d0);
839 switch (d0) {
840 case 0x0e:
841 dsp_out_data (s, 0xff);
842 break;
843
844 case 0x0f:
845 dsp_out_data (s, 0x07);
846 break;
847
848 case 0x37:
849 dsp_out_data (s, 0x38);
850 break;
851
852 default:
853 dsp_out_data (s, 0x00);
854 break;
855 }
856 break;
857
858 default:
859 qemu_log_mask(LOG_UNIMP, "complete: unrecognized command %#x\n",
860 s->cmd);
861 return;
862 }
863 }
864
865 ldebug ("\n");
866 s->cmd = -1;
867 }
868
legacy_reset(SB16State * s)869 static void legacy_reset (SB16State *s)
870 {
871 struct audsettings as;
872
873 s->freq = 11025;
874 s->fmt_signed = 0;
875 s->fmt_bits = 8;
876 s->fmt_stereo = 0;
877
878 as.freq = s->freq;
879 as.nchannels = 1;
880 as.fmt = AUDIO_FORMAT_U8;
881 as.endianness = 0;
882
883 s->voice = AUD_open_out (
884 &s->card,
885 s->voice,
886 "sb16",
887 s,
888 SB_audio_callback,
889 &as
890 );
891
892 /* Not sure about that... */
893 /* AUD_set_active_out (s->voice, 1); */
894 }
895
reset(SB16State * s)896 static void reset (SB16State *s)
897 {
898 qemu_irq_lower (s->pic);
899 if (s->dma_auto) {
900 qemu_irq_raise (s->pic);
901 qemu_irq_lower (s->pic);
902 }
903
904 s->mixer_regs[0x82] = 0;
905 s->dma_auto = 0;
906 s->in_index = 0;
907 s->out_data_len = 0;
908 s->left_till_irq = 0;
909 s->needed_bytes = 0;
910 s->block_size = -1;
911 s->nzero = 0;
912 s->highspeed = 0;
913 s->v2x6 = 0;
914 s->cmd = -1;
915
916 dsp_out_data (s, 0xaa);
917 speaker (s, 0);
918 control (s, 0);
919 legacy_reset (s);
920 }
921
dsp_write(void * opaque,uint32_t nport,uint32_t val)922 static void dsp_write(void *opaque, uint32_t nport, uint32_t val)
923 {
924 SB16State *s = opaque;
925 int iport;
926
927 iport = nport - s->port;
928
929 ldebug ("write %#x <- %#x\n", nport, val);
930 switch (iport) {
931 case 0x06:
932 switch (val) {
933 case 0x00:
934 if (s->v2x6 == 1) {
935 reset (s);
936 }
937 s->v2x6 = 0;
938 break;
939
940 case 0x01:
941 case 0x03: /* FreeBSD kludge */
942 s->v2x6 = 1;
943 break;
944
945 case 0xc6:
946 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
947 break;
948
949 case 0xb8: /* Panic */
950 reset (s);
951 break;
952
953 case 0x39:
954 dsp_out_data (s, 0x38);
955 reset (s);
956 s->v2x6 = 0x39;
957 break;
958
959 default:
960 s->v2x6 = val;
961 break;
962 }
963 break;
964
965 case 0x0c: /* write data or command | write status */
966 /* if (s->highspeed) */
967 /* break; */
968
969 if (s->needed_bytes == 0) {
970 command (s, val);
971 #if 0
972 if (0 == s->needed_bytes) {
973 log_dsp (s);
974 }
975 #endif
976 }
977 else {
978 if (s->in_index == sizeof (s->in2_data)) {
979 dolog ("in data overrun\n");
980 }
981 else {
982 s->in2_data[s->in_index++] = val;
983 if (s->in_index == s->needed_bytes) {
984 s->needed_bytes = 0;
985 complete (s);
986 #if 0
987 log_dsp (s);
988 #endif
989 }
990 }
991 }
992 break;
993
994 default:
995 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
996 break;
997 }
998 }
999
dsp_read(void * opaque,uint32_t nport)1000 static uint32_t dsp_read(void *opaque, uint32_t nport)
1001 {
1002 SB16State *s = opaque;
1003 int iport, retval, ack = 0;
1004
1005 iport = nport - s->port;
1006
1007 switch (iport) {
1008 case 0x06: /* reset */
1009 retval = 0xff;
1010 break;
1011
1012 case 0x0a: /* read data */
1013 if (s->out_data_len) {
1014 retval = s->out_data[--s->out_data_len];
1015 s->last_read_byte = retval;
1016 }
1017 else {
1018 if (s->cmd != -1) {
1019 dolog ("empty output buffer for command %#x\n",
1020 s->cmd);
1021 }
1022 retval = s->last_read_byte;
1023 /* goto error; */
1024 }
1025 break;
1026
1027 case 0x0c: /* 0 can write */
1028 retval = s->can_write ? 0 : 0x80;
1029 break;
1030
1031 case 0x0d: /* timer interrupt clear */
1032 /* dolog ("timer interrupt clear\n"); */
1033 retval = 0;
1034 break;
1035
1036 case 0x0e: /* data available status | irq 8 ack */
1037 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1038 if (s->mixer_regs[0x82] & 1) {
1039 ack = 1;
1040 s->mixer_regs[0x82] &= ~1;
1041 qemu_irq_lower (s->pic);
1042 }
1043 break;
1044
1045 case 0x0f: /* irq 16 ack */
1046 retval = 0xff;
1047 if (s->mixer_regs[0x82] & 2) {
1048 ack = 1;
1049 s->mixer_regs[0x82] &= ~2;
1050 qemu_irq_lower (s->pic);
1051 }
1052 break;
1053
1054 default:
1055 goto error;
1056 }
1057
1058 if (!ack) {
1059 ldebug ("read %#x -> %#x\n", nport, retval);
1060 }
1061
1062 return retval;
1063
1064 error:
1065 dolog ("warning: dsp_read %#x error\n", nport);
1066 return 0xff;
1067 }
1068
reset_mixer(SB16State * s)1069 static void reset_mixer (SB16State *s)
1070 {
1071 int i;
1072
1073 memset (s->mixer_regs, 0xff, 0x7f);
1074 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1075
1076 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1077 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1078 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1079 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1080
1081 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1082 s->mixer_regs[0x0c] = 0;
1083
1084 /* d5=output filt, d1=stereo switch */
1085 s->mixer_regs[0x0e] = 0;
1086
1087 /* voice volume L d5,d7, R d1,d3 */
1088 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1089 /* master ... */
1090 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1091 /* MIDI ... */
1092 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1093
1094 for (i = 0x30; i < 0x48; i++) {
1095 s->mixer_regs[i] = 0x20;
1096 }
1097 }
1098
mixer_write_indexb(void * opaque,uint32_t nport,uint32_t val)1099 static void mixer_write_indexb(void *opaque, uint32_t nport, uint32_t val)
1100 {
1101 SB16State *s = opaque;
1102 (void) nport;
1103 s->mixer_nreg = val;
1104 }
1105
mixer_write_datab(void * opaque,uint32_t nport,uint32_t val)1106 static void mixer_write_datab(void *opaque, uint32_t nport, uint32_t val)
1107 {
1108 SB16State *s = opaque;
1109
1110 (void) nport;
1111 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1112
1113 switch (s->mixer_nreg) {
1114 case 0x00:
1115 reset_mixer (s);
1116 break;
1117
1118 case 0x80:
1119 {
1120 int irq = irq_of_magic (val);
1121 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1122 if (irq > 0) {
1123 s->irq = irq;
1124 }
1125 }
1126 break;
1127
1128 case 0x81:
1129 {
1130 int dma, hdma;
1131
1132 dma = ctz32 (val & 0xf);
1133 hdma = ctz32 (val & 0xf0);
1134 if (dma != s->dma || hdma != s->hdma) {
1135 qemu_log_mask(LOG_GUEST_ERROR, "attempt to change DMA 8bit"
1136 " %d(%d), 16bit %d(%d) (val=%#x)\n", dma, s->dma,
1137 hdma, s->hdma, val);
1138 }
1139 #if 0
1140 s->dma = dma;
1141 s->hdma = hdma;
1142 #endif
1143 }
1144 break;
1145
1146 case 0x82:
1147 qemu_log_mask(LOG_GUEST_ERROR, "attempt to write into IRQ status"
1148 " register (val=%#x)\n", val);
1149 return;
1150
1151 default:
1152 if (s->mixer_nreg >= 0x80) {
1153 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1154 }
1155 break;
1156 }
1157
1158 s->mixer_regs[s->mixer_nreg] = val;
1159 }
1160
mixer_read(void * opaque,uint32_t nport)1161 static uint32_t mixer_read(void *opaque, uint32_t nport)
1162 {
1163 SB16State *s = opaque;
1164
1165 (void) nport;
1166 #ifndef DEBUG_SB16_MOST
1167 if (s->mixer_nreg != 0x82) {
1168 ldebug ("mixer_read[%#x] -> %#x\n",
1169 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1170 }
1171 #else
1172 ldebug ("mixer_read[%#x] -> %#x\n",
1173 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1174 #endif
1175 return s->mixer_regs[s->mixer_nreg];
1176 }
1177
write_audio(SB16State * s,int nchan,int dma_pos,int dma_len,int len)1178 static int write_audio (SB16State *s, int nchan, int dma_pos,
1179 int dma_len, int len)
1180 {
1181 IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
1182 IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
1183 int temp, net;
1184 uint8_t tmpbuf[4096];
1185
1186 temp = len;
1187 net = 0;
1188
1189 while (temp) {
1190 int left = dma_len - dma_pos;
1191 int copied;
1192 size_t to_copy;
1193
1194 to_copy = MIN (temp, left);
1195 if (to_copy > sizeof (tmpbuf)) {
1196 to_copy = sizeof (tmpbuf);
1197 }
1198
1199 copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
1200 copied = AUD_write (s->voice, tmpbuf, copied);
1201
1202 temp -= copied;
1203 dma_pos = (dma_pos + copied) % dma_len;
1204 net += copied;
1205
1206 if (!copied) {
1207 break;
1208 }
1209 }
1210
1211 return net;
1212 }
1213
SB_read_DMA(void * opaque,int nchan,int dma_pos,int dma_len)1214 static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1215 {
1216 SB16State *s = opaque;
1217 int till, copy, written, free;
1218
1219 if (s->block_size <= 0) {
1220 qemu_log_mask(LOG_GUEST_ERROR, "invalid block size=%d nchan=%d"
1221 " dma_pos=%d dma_len=%d\n", s->block_size, nchan,
1222 dma_pos, dma_len);
1223 return dma_pos;
1224 }
1225
1226 if (s->left_till_irq < 0) {
1227 s->left_till_irq = s->block_size;
1228 }
1229
1230 if (s->voice) {
1231 free = s->audio_free & ~s->align;
1232 if ((free <= 0) || !dma_len) {
1233 return dma_pos;
1234 }
1235 }
1236 else {
1237 free = dma_len;
1238 }
1239
1240 copy = free;
1241 till = s->left_till_irq;
1242
1243 #ifdef DEBUG_SB16_MOST
1244 dolog ("pos:%06d %d till:%d len:%d\n",
1245 dma_pos, free, till, dma_len);
1246 #endif
1247
1248 if (till <= copy) {
1249 if (s->dma_auto == 0) {
1250 copy = till;
1251 }
1252 }
1253
1254 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1255 dma_pos = (dma_pos + written) % dma_len;
1256 s->left_till_irq -= written;
1257
1258 if (s->left_till_irq <= 0) {
1259 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1260 qemu_irq_raise (s->pic);
1261 if (s->dma_auto == 0) {
1262 control (s, 0);
1263 speaker (s, 0);
1264 }
1265 }
1266
1267 #ifdef DEBUG_SB16_MOST
1268 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1269 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1270 s->block_size);
1271 #endif
1272
1273 while (s->left_till_irq <= 0) {
1274 s->left_till_irq = s->block_size + s->left_till_irq;
1275 }
1276
1277 return dma_pos;
1278 }
1279
SB_audio_callback(void * opaque,int free)1280 static void SB_audio_callback (void *opaque, int free)
1281 {
1282 SB16State *s = opaque;
1283 s->audio_free = free;
1284 }
1285
sb16_post_load(void * opaque,int version_id)1286 static int sb16_post_load (void *opaque, int version_id)
1287 {
1288 SB16State *s = opaque;
1289
1290 if (s->voice) {
1291 AUD_close_out (&s->card, s->voice);
1292 s->voice = NULL;
1293 }
1294
1295 if (s->dma_running) {
1296 if (s->freq) {
1297 struct audsettings as;
1298
1299 s->audio_free = 0;
1300
1301 as.freq = s->freq;
1302 as.nchannels = 1 << s->fmt_stereo;
1303 as.fmt = s->fmt;
1304 as.endianness = 0;
1305
1306 s->voice = AUD_open_out (
1307 &s->card,
1308 s->voice,
1309 "sb16",
1310 s,
1311 SB_audio_callback,
1312 &as
1313 );
1314 }
1315
1316 control (s, 1);
1317 speaker (s, s->speaker);
1318 }
1319 return 0;
1320 }
1321
1322 static const VMStateDescription vmstate_sb16 = {
1323 .name = "sb16",
1324 .version_id = 1,
1325 .minimum_version_id = 1,
1326 .post_load = sb16_post_load,
1327 .fields = (const VMStateField[]) {
1328 VMSTATE_UNUSED( 4 /* irq */
1329 + 4 /* dma */
1330 + 4 /* hdma */
1331 + 4 /* port */
1332 + 4 /* ver */),
1333 VMSTATE_INT32 (in_index, SB16State),
1334 VMSTATE_INT32 (out_data_len, SB16State),
1335 VMSTATE_INT32 (fmt_stereo, SB16State),
1336 VMSTATE_INT32 (fmt_signed, SB16State),
1337 VMSTATE_INT32 (fmt_bits, SB16State),
1338 VMSTATE_UINT32 (fmt, SB16State),
1339 VMSTATE_INT32 (dma_auto, SB16State),
1340 VMSTATE_INT32 (block_size, SB16State),
1341 VMSTATE_INT32 (fifo, SB16State),
1342 VMSTATE_INT32 (freq, SB16State),
1343 VMSTATE_INT32 (time_const, SB16State),
1344 VMSTATE_INT32 (speaker, SB16State),
1345 VMSTATE_INT32 (needed_bytes, SB16State),
1346 VMSTATE_INT32 (cmd, SB16State),
1347 VMSTATE_INT32 (use_hdma, SB16State),
1348 VMSTATE_INT32 (highspeed, SB16State),
1349 VMSTATE_INT32 (can_write, SB16State),
1350 VMSTATE_INT32 (v2x6, SB16State),
1351
1352 VMSTATE_UINT8 (csp_param, SB16State),
1353 VMSTATE_UINT8 (csp_value, SB16State),
1354 VMSTATE_UINT8 (csp_mode, SB16State),
1355 VMSTATE_UINT8 (csp_param, SB16State),
1356 VMSTATE_BUFFER (csp_regs, SB16State),
1357 VMSTATE_UINT8 (csp_index, SB16State),
1358 VMSTATE_BUFFER (csp_reg83, SB16State),
1359 VMSTATE_INT32 (csp_reg83r, SB16State),
1360 VMSTATE_INT32 (csp_reg83w, SB16State),
1361
1362 VMSTATE_BUFFER (in2_data, SB16State),
1363 VMSTATE_BUFFER (out_data, SB16State),
1364 VMSTATE_UINT8 (test_reg, SB16State),
1365 VMSTATE_UINT8 (last_read_byte, SB16State),
1366
1367 VMSTATE_INT32 (nzero, SB16State),
1368 VMSTATE_INT32 (left_till_irq, SB16State),
1369 VMSTATE_INT32 (dma_running, SB16State),
1370 VMSTATE_INT32 (bytes_per_second, SB16State),
1371 VMSTATE_INT32 (align, SB16State),
1372
1373 VMSTATE_INT32 (mixer_nreg, SB16State),
1374 VMSTATE_BUFFER (mixer_regs, SB16State),
1375
1376 VMSTATE_END_OF_LIST ()
1377 }
1378 };
1379
1380 static const MemoryRegionPortio sb16_ioport_list[] = {
1381 { 4, 1, 1, .write = mixer_write_indexb },
1382 { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab },
1383 { 6, 1, 1, .read = dsp_read, .write = dsp_write },
1384 { 10, 1, 1, .read = dsp_read },
1385 { 12, 1, 1, .write = dsp_write },
1386 { 12, 4, 1, .read = dsp_read },
1387 PORTIO_END_OF_LIST (),
1388 };
1389
1390
sb16_initfn(Object * obj)1391 static void sb16_initfn (Object *obj)
1392 {
1393 SB16State *s = SB16 (obj);
1394
1395 s->cmd = -1;
1396 }
1397
sb16_realizefn(DeviceState * dev,Error ** errp)1398 static void sb16_realizefn (DeviceState *dev, Error **errp)
1399 {
1400 ISADevice *isadev = ISA_DEVICE (dev);
1401 ISABus *bus = isa_bus_from_device(isadev);
1402 SB16State *s = SB16 (dev);
1403 IsaDmaClass *k;
1404
1405 if (!AUD_register_card ("sb16", &s->card, errp)) {
1406 return;
1407 }
1408
1409 s->isa_hdma = isa_bus_get_dma(bus, s->hdma);
1410 s->isa_dma = isa_bus_get_dma(bus, s->dma);
1411 if (!s->isa_dma || !s->isa_hdma) {
1412 error_setg(errp, "ISA controller does not support DMA");
1413 return;
1414 }
1415
1416 s->pic = isa_bus_get_irq(bus, s->irq);
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 = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1427 if (!s->aux_ts) {
1428 error_setg(errp, "warning: Could not create auxiliary timer");
1429 }
1430
1431 isa_register_portio_list(isadev, &s->portio_list, s->port,
1432 sb16_ioport_list, s, "sb16");
1433
1434 k = ISADMA_GET_CLASS(s->isa_hdma);
1435 k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1436
1437 k = ISADMA_GET_CLASS(s->isa_dma);
1438 k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1439
1440 s->can_write = 1;
1441 }
1442
1443 static Property sb16_properties[] = {
1444 DEFINE_AUDIO_PROPERTIES(SB16State, card),
1445 DEFINE_PROP_UINT32 ("version", SB16State, ver, 0x0405), /* 4.5 */
1446 DEFINE_PROP_UINT32 ("iobase", SB16State, port, 0x220),
1447 DEFINE_PROP_UINT32 ("irq", SB16State, irq, 5),
1448 DEFINE_PROP_UINT32 ("dma", SB16State, dma, 1),
1449 DEFINE_PROP_UINT32 ("dma16", SB16State, hdma, 5),
1450 DEFINE_PROP_END_OF_LIST (),
1451 };
1452
sb16_class_initfn(ObjectClass * klass,void * data)1453 static void sb16_class_initfn (ObjectClass *klass, void *data)
1454 {
1455 DeviceClass *dc = DEVICE_CLASS (klass);
1456
1457 dc->realize = sb16_realizefn;
1458 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1459 dc->desc = "Creative Sound Blaster 16";
1460 dc->vmsd = &vmstate_sb16;
1461 device_class_set_props(dc, sb16_properties);
1462 }
1463
1464 static const TypeInfo sb16_info = {
1465 .name = TYPE_SB16,
1466 .parent = TYPE_ISA_DEVICE,
1467 .instance_size = sizeof (SB16State),
1468 .instance_init = sb16_initfn,
1469 .class_init = sb16_class_initfn,
1470 };
1471
sb16_register_types(void)1472 static void sb16_register_types (void)
1473 {
1474 type_register_static (&sb16_info);
1475 deprecated_register_soundhw("sb16", "Creative Sound Blaster 16",
1476 1, TYPE_SB16);
1477 }
1478
1479 type_init (sb16_register_types)
1480