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