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
 118#define SAMPLE_RATE_MIN 5000
 119#define SAMPLE_RATE_MAX 45000
 120
 121static void SB_audio_callback (void *opaque, int free);
 122
 123static 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
 140static 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
 158static 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
 172static void speaker (SB16State *s, int on)
 173{
 174    s->speaker = on;
 175    /* AUD_enable (s->voice, on); */
 176}
 177
 178static 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
 197static 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
 207static 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
 232static 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
 249static 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
 301static 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
 396static 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
 404static 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
 415static 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
 673static 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
 680static 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
 687static 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
 869static 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
 896static 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
 922static 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
1000static 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
1069static 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
1099static 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
1106static 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
1161static 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
1178static 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
1214static 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
1280static void SB_audio_callback (void *opaque, int free)
1281{
1282    SB16State *s = opaque;
1283    s->audio_free = free;
1284}
1285
1286static 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
1322static const VMStateDescription vmstate_sb16 = {
1323    .name = "sb16",
1324    .version_id = 1,
1325    .minimum_version_id = 1,
1326    .post_load = sb16_post_load,
1327    .fields = (VMStateField[]) {
1328        VMSTATE_UINT32 (irq, SB16State),
1329        VMSTATE_UINT32 (dma, SB16State),
1330        VMSTATE_UINT32 (hdma, SB16State),
1331        VMSTATE_UINT32 (port, SB16State),
1332        VMSTATE_UINT32 (ver, SB16State),
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
1380static 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
1391static void sb16_initfn (Object *obj)
1392{
1393    SB16State *s = SB16 (obj);
1394
1395    s->cmd = -1;
1396}
1397
1398static void sb16_realizefn (DeviceState *dev, Error **errp)
1399{
1400    ISADevice *isadev = ISA_DEVICE (dev);
1401    SB16State *s = SB16 (dev);
1402    IsaDmaClass *k;
1403
1404    s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
1405    s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
1406    if (!s->isa_dma || !s->isa_hdma) {
1407        error_setg(errp, "ISA controller does not support DMA");
1408        return;
1409    }
1410
1411    isa_init_irq (isadev, &s->pic, s->irq);
1412
1413    s->mixer_regs[0x80] = magic_of_irq (s->irq);
1414    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1415    s->mixer_regs[0x82] = 2 << 5;
1416
1417    s->csp_regs[5] = 1;
1418    s->csp_regs[9] = 0xf8;
1419
1420    reset_mixer (s);
1421    s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
1422    if (!s->aux_ts) {
1423        error_setg(errp, "warning: Could not create auxiliary timer");
1424    }
1425
1426    isa_register_portio_list(isadev, &s->portio_list, s->port,
1427                             sb16_ioport_list, s, "sb16");
1428
1429    k = ISADMA_GET_CLASS(s->isa_hdma);
1430    k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
1431
1432    k = ISADMA_GET_CLASS(s->isa_dma);
1433    k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
1434
1435    s->can_write = 1;
1436
1437    AUD_register_card ("sb16", &s->card);
1438}
1439
1440static Property sb16_properties[] = {
1441    DEFINE_AUDIO_PROPERTIES(SB16State, card),
1442    DEFINE_PROP_UINT32 ("version", SB16State, ver,  0x0405), /* 4.5 */
1443    DEFINE_PROP_UINT32 ("iobase",  SB16State, port, 0x220),
1444    DEFINE_PROP_UINT32 ("irq",     SB16State, irq,  5),
1445    DEFINE_PROP_UINT32 ("dma",     SB16State, dma,  1),
1446    DEFINE_PROP_UINT32 ("dma16",   SB16State, hdma, 5),
1447    DEFINE_PROP_END_OF_LIST (),
1448};
1449
1450static void sb16_class_initfn (ObjectClass *klass, void *data)
1451{
1452    DeviceClass *dc = DEVICE_CLASS (klass);
1453
1454    dc->realize = sb16_realizefn;
1455    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
1456    dc->desc = "Creative Sound Blaster 16";
1457    dc->vmsd = &vmstate_sb16;
1458    device_class_set_props(dc, sb16_properties);
1459}
1460
1461static const TypeInfo sb16_info = {
1462    .name          = TYPE_SB16,
1463    .parent        = TYPE_ISA_DEVICE,
1464    .instance_size = sizeof (SB16State),
1465    .instance_init = sb16_initfn,
1466    .class_init    = sb16_class_initfn,
1467};
1468
1469static void sb16_register_types (void)
1470{
1471    type_register_static (&sb16_info);
1472    deprecated_register_soundhw("sb16", "Creative Sound Blaster 16",
1473                                1, TYPE_SB16);
1474}
1475
1476type_init (sb16_register_types)
1477