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