Statistics
| Branch: | Revision:

root / hw / sb16.c @ 9c02f1a2

History | View | Annotate | Download (35.7 kB)

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
#include "vl.h"
25

    
26
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
27

    
28
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
29

    
30
/* #define DEBUG */
31
/* #define DEBUG_SB16_MOST */
32

    
33
#ifdef DEBUG
34
#define ldebug(...) dolog (__VA_ARGS__)
35
#else
36
#define ldebug(...)
37
#endif
38

    
39
#define IO_READ_PROTO(name)                             \
40
    uint32_t name (void *opaque, uint32_t nport)
41
#define IO_WRITE_PROTO(name)                                    \
42
    void name (void *opaque, uint32_t nport, uint32_t val)
43

    
44
static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
45

    
46
static struct {
47
    int ver_lo;
48
    int ver_hi;
49
    int irq;
50
    int dma;
51
    int hdma;
52
    int port;
53
} conf = {5, 4, 5, 1, 5, 0x220};
54

    
55
typedef struct SB16State {
56
    QEMUSoundCard card;
57
    qemu_irq *pic;
58
    int irq;
59
    int dma;
60
    int hdma;
61
    int port;
62
    int ver;
63

    
64
    int in_index;
65
    int out_data_len;
66
    int fmt_stereo;
67
    int fmt_signed;
68
    int fmt_bits;
69
    audfmt_e fmt;
70
    int dma_auto;
71
    int block_size;
72
    int fifo;
73
    int freq;
74
    int time_const;
75
    int speaker;
76
    int needed_bytes;
77
    int cmd;
78
    int use_hdma;
79
    int highspeed;
80
    int can_write;
81

    
82
    int v2x6;
83

    
84
    uint8_t csp_param;
85
    uint8_t csp_value;
86
    uint8_t csp_mode;
87
    uint8_t csp_regs[256];
88
    uint8_t csp_index;
89
    uint8_t csp_reg83[4];
90
    int csp_reg83r;
91
    int csp_reg83w;
92

    
93
    uint8_t in2_data[10];
94
    uint8_t out_data[50];
95
    uint8_t test_reg;
96
    uint8_t last_read_byte;
97
    int nzero;
98

    
99
    int left_till_irq;
100

    
101
    int dma_running;
102
    int bytes_per_second;
103
    int align;
104
    int audio_free;
105
    SWVoiceOut *voice;
106

    
107
    QEMUTimer *aux_ts;
108
    /* mixer state */
109
    int mixer_nreg;
110
    uint8_t mixer_regs[256];
111
} SB16State;
112

    
113
static void SB_audio_callback (void *opaque, int free);
114

    
115
static int magic_of_irq (int irq)
116
{
117
    switch (irq) {
118
    case 5:
119
        return 2;
120
    case 7:
121
        return 4;
122
    case 9:
123
        return 1;
124
    case 10:
125
        return 8;
126
    default:
127
        dolog ("bad irq %d\n", irq);
128
        return 2;
129
    }
130
}
131

    
132
static int irq_of_magic (int magic)
133
{
134
    switch (magic) {
135
    case 1:
136
        return 9;
137
    case 2:
138
        return 5;
139
    case 4:
140
        return 7;
141
    case 8:
142
        return 10;
143
    default:
144
        dolog ("bad irq magic %d\n", magic);
145
        return -1;
146
    }
147
}
148

    
149
#if 0
150
static void log_dsp (SB16State *dsp)
151
{
152
    ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
153
            dsp->fmt_stereo ? "Stereo" : "Mono",
154
            dsp->fmt_signed ? "Signed" : "Unsigned",
155
            dsp->fmt_bits,
156
            dsp->dma_auto ? "Auto" : "Single",
157
            dsp->block_size,
158
            dsp->freq,
159
            dsp->time_const,
160
            dsp->speaker);
161
}
162
#endif
163

    
164
static void speaker (SB16State *s, int on)
165
{
166
    s->speaker = on;
167
    /* AUD_enable (s->voice, on); */
168
}
169

    
170
static void control (SB16State *s, int hold)
171
{
172
    int dma = s->use_hdma ? s->hdma : s->dma;
173
    s->dma_running = hold;
174

    
175
    ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
176

    
177
    if (hold) {
178
        DMA_hold_DREQ (dma);
179
        AUD_set_active_out (s->voice, 1);
180
    }
181
    else {
182
        DMA_release_DREQ (dma);
183
        AUD_set_active_out (s->voice, 0);
184
    }
185
}
186

    
187
static void aux_timer (void *opaque)
188
{
189
    SB16State *s = opaque;
190
    s->can_write = 1;
191
    qemu_irq_raise (s->pic[s->irq]);
192
}
193

    
194
#define DMA8_AUTO 1
195
#define DMA8_HIGH 2
196

    
197
static void continue_dma8 (SB16State *s)
198
{
199
    if (s->freq > 0) {
200
        audsettings_t as;
201

    
202
        s->audio_free = 0;
203

    
204
        as.freq = s->freq;
205
        as.nchannels = 1 << s->fmt_stereo;
206
        as.fmt = s->fmt;
207
        as.endianness = 0;
208

    
209
        s->voice = AUD_open_out (
210
            &s->card,
211
            s->voice,
212
            "sb16",
213
            s,
214
            SB_audio_callback,
215
            &as
216
            );
217
    }
218

    
219
    control (s, 1);
220
}
221

    
222
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
223
{
224
    s->fmt = AUD_FMT_U8;
225
    s->use_hdma = 0;
226
    s->fmt_bits = 8;
227
    s->fmt_signed = 0;
228
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
229
    if (-1 == s->time_const) {
230
        if (s->freq <= 0)
231
            s->freq = 11025;
232
    }
233
    else {
234
        int tmp = (256 - s->time_const);
235
        s->freq = (1000000 + (tmp / 2)) / tmp;
236
    }
237

    
238
    if (dma_len != -1) {
239
        s->block_size = dma_len << s->fmt_stereo;
240
    }
241
    else {
242
        /* This is apparently the only way to make both Act1/PL
243
           and SecondReality/FC work
244

245
           Act1 sets block size via command 0x48 and it's an odd number
246
           SR does the same with even number
247
           Both use stereo, and Creatives own documentation states that
248
           0x48 sets block size in bytes less one.. go figure */
249
        s->block_size &= ~s->fmt_stereo;
250
    }
251

    
252
    s->freq >>= s->fmt_stereo;
253
    s->left_till_irq = s->block_size;
254
    s->bytes_per_second = (s->freq << s->fmt_stereo);
255
    /* s->highspeed = (mask & DMA8_HIGH) != 0; */
256
    s->dma_auto = (mask & DMA8_AUTO) != 0;
257
    s->align = (1 << s->fmt_stereo) - 1;
258

    
259
    if (s->block_size & s->align) {
260
        dolog ("warning: misaligned block size %d, alignment %d\n",
261
               s->block_size, s->align + 1);
262
    }
263

    
264
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
265
            "dma %d, auto %d, fifo %d, high %d\n",
266
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
267
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
268

    
269
    continue_dma8 (s);
270
    speaker (s, 1);
271
}
272

    
273
static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
274
{
275
    s->use_hdma = cmd < 0xc0;
276
    s->fifo = (cmd >> 1) & 1;
277
    s->dma_auto = (cmd >> 2) & 1;
278
    s->fmt_signed = (d0 >> 4) & 1;
279
    s->fmt_stereo = (d0 >> 5) & 1;
280

    
281
    switch (cmd >> 4) {
282
    case 11:
283
        s->fmt_bits = 16;
284
        break;
285

    
286
    case 12:
287
        s->fmt_bits = 8;
288
        break;
289
    }
290

    
291
    if (-1 != s->time_const) {
292
#if 1
293
        int tmp = 256 - s->time_const;
294
        s->freq = (1000000 + (tmp / 2)) / tmp;
295
#else
296
        /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
297
        s->freq = 1000000 / ((255 - s->time_const));
298
#endif
299
        s->time_const = -1;
300
    }
301

    
302
    s->block_size = dma_len + 1;
303
    s->block_size <<= (s->fmt_bits == 16);
304
    if (!s->dma_auto) {
305
        /* It is clear that for DOOM and auto-init this value
306
           shouldn't take stereo into account, while Miles Sound Systems
307
           setsound.exe with single transfer mode wouldn't work without it
308
           wonders of SB16 yet again */
309
        s->block_size <<= s->fmt_stereo;
310
    }
311

    
312
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
313
            "dma %d, auto %d, fifo %d, high %d\n",
314
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
315
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
316

    
317
    if (16 == s->fmt_bits) {
318
        if (s->fmt_signed) {
319
            s->fmt = AUD_FMT_S16;
320
        }
321
        else {
322
            s->fmt = AUD_FMT_U16;
323
        }
324
    }
325
    else {
326
        if (s->fmt_signed) {
327
            s->fmt = AUD_FMT_S8;
328
        }
329
        else {
330
            s->fmt = AUD_FMT_U8;
331
        }
332
    }
333

    
334
    s->left_till_irq = s->block_size;
335

    
336
    s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
337
    s->highspeed = 0;
338
    s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
339
    if (s->block_size & s->align) {
340
        dolog ("warning: misaligned block size %d, alignment %d\n",
341
               s->block_size, s->align + 1);
342
    }
343

    
344
    if (s->freq) {
345
        audsettings_t as;
346

    
347
        s->audio_free = 0;
348

    
349
        as.freq = s->freq;
350
        as.nchannels = 1 << s->fmt_stereo;
351
        as.fmt = s->fmt;
352
        as.endianness = 0;
353

    
354
        s->voice = AUD_open_out (
355
            &s->card,
356
            s->voice,
357
            "sb16",
358
            s,
359
            SB_audio_callback,
360
            &as
361
            );
362
    }
363

    
364
    control (s, 1);
365
    speaker (s, 1);
366
}
367

    
368
static inline void dsp_out_data (SB16State *s, uint8_t val)
369
{
370
    ldebug ("outdata %#x\n", val);
371
    if ((size_t) s->out_data_len < sizeof (s->out_data)) {
372
        s->out_data[s->out_data_len++] = val;
373
    }
374
}
375

    
376
static inline uint8_t dsp_get_data (SB16State *s)
377
{
378
    if (s->in_index) {
379
        return s->in2_data[--s->in_index];
380
    }
381
    else {
382
        dolog ("buffer underflow\n");
383
        return 0;
384
    }
385
}
386

    
387
static void command (SB16State *s, uint8_t cmd)
388
{
389
    ldebug ("command %#x\n", cmd);
390

    
391
    if (cmd > 0xaf && cmd < 0xd0) {
392
        if (cmd & 8) {
393
            dolog ("ADC not yet supported (command %#x)\n", cmd);
394
        }
395

    
396
        switch (cmd >> 4) {
397
        case 11:
398
        case 12:
399
            break;
400
        default:
401
            dolog ("%#x wrong bits\n", cmd);
402
        }
403
        s->needed_bytes = 3;
404
    }
405
    else {
406
        s->needed_bytes = 0;
407

    
408
        switch (cmd) {
409
        case 0x03:
410
            dsp_out_data (s, 0x10); /* s->csp_param); */
411
            goto warn;
412

    
413
        case 0x04:
414
            s->needed_bytes = 1;
415
            goto warn;
416

    
417
        case 0x05:
418
            s->needed_bytes = 2;
419
            goto warn;
420

    
421
        case 0x08:
422
            /* __asm__ ("int3"); */
423
            goto warn;
424

    
425
        case 0x0e:
426
            s->needed_bytes = 2;
427
            goto warn;
428

    
429
        case 0x09:
430
            dsp_out_data (s, 0xf8);
431
            goto warn;
432

    
433
        case 0x0f:
434
            s->needed_bytes = 1;
435
            goto warn;
436

    
437
        case 0x10:
438
            s->needed_bytes = 1;
439
            goto warn;
440

    
441
        case 0x14:
442
            s->needed_bytes = 2;
443
            s->block_size = 0;
444
            break;
445

    
446
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
447
            dma_cmd8 (s, DMA8_AUTO, -1);
448
            break;
449

    
450
        case 0x20:              /* Direct ADC, Juice/PL */
451
            dsp_out_data (s, 0xff);
452
            goto warn;
453

    
454
        case 0x35:
455
            dolog ("0x35 - MIDI command not implemented\n");
456
            break;
457

    
458
        case 0x40:
459
            s->freq = -1;
460
            s->time_const = -1;
461
            s->needed_bytes = 1;
462
            break;
463

    
464
        case 0x41:
465
            s->freq = -1;
466
            s->time_const = -1;
467
            s->needed_bytes = 2;
468
            break;
469

    
470
        case 0x42:
471
            s->freq = -1;
472
            s->time_const = -1;
473
            s->needed_bytes = 2;
474
            goto warn;
475

    
476
        case 0x45:
477
            dsp_out_data (s, 0xaa);
478
            goto warn;
479

    
480
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
481
            break;
482

    
483
        case 0x48:
484
            s->needed_bytes = 2;
485
            break;
486

    
487
        case 0x74:
488
            s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
489
            dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
490
            break;
491

    
492
        case 0x75:              /* DMA DAC, 4-bit ADPCM Reference */
493
            s->needed_bytes = 2;
494
            dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
495
            break;
496

    
497
        case 0x76:              /* DMA DAC, 2.6-bit ADPCM */
498
            s->needed_bytes = 2;
499
            dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
500
            break;
501

    
502
        case 0x77:              /* DMA DAC, 2.6-bit ADPCM Reference */
503
            s->needed_bytes = 2;
504
            dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
505
            break;
506

    
507
        case 0x7d:
508
            dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
509
            dolog ("not implemented\n");
510
            break;
511

    
512
        case 0x7f:
513
            dolog (
514
                "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
515
                );
516
            dolog ("not implemented\n");
517
            break;
518

    
519
        case 0x80:
520
            s->needed_bytes = 2;
521
            break;
522

    
523
        case 0x90:
524
        case 0x91:
525
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
526
            break;
527

    
528
        case 0xd0:              /* halt DMA operation. 8bit */
529
            control (s, 0);
530
            break;
531

    
532
        case 0xd1:              /* speaker on */
533
            speaker (s, 1);
534
            break;
535

    
536
        case 0xd3:              /* speaker off */
537
            speaker (s, 0);
538
            break;
539

    
540
        case 0xd4:              /* continue DMA operation. 8bit */
541
            /* KQ6 (or maybe Sierras audblst.drv in general) resets
542
               the frequency between halt/continue */
543
            continue_dma8 (s);
544
            break;
545

    
546
        case 0xd5:              /* halt DMA operation. 16bit */
547
            control (s, 0);
548
            break;
549

    
550
        case 0xd6:              /* continue DMA operation. 16bit */
551
            control (s, 1);
552
            break;
553

    
554
        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
555
            s->dma_auto = 0;
556
            break;
557

    
558
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
559
            s->dma_auto = 0;
560
            break;
561

    
562
        case 0xe0:              /* DSP identification */
563
            s->needed_bytes = 1;
564
            break;
565

    
566
        case 0xe1:
567
            dsp_out_data (s, s->ver & 0xff);
568
            dsp_out_data (s, s->ver >> 8);
569
            break;
570

    
571
        case 0xe2:
572
            s->needed_bytes = 1;
573
            goto warn;
574

    
575
        case 0xe3:
576
            {
577
                int i;
578
                for (i = sizeof (e3) - 1; i >= 0; --i)
579
                    dsp_out_data (s, e3[i]);
580
            }
581
            break;
582

    
583
        case 0xe4:              /* write test reg */
584
            s->needed_bytes = 1;
585
            break;
586

    
587
        case 0xe7:
588
            dolog ("Attempt to probe for ESS (0xe7)?\n");
589
            break;
590

    
591
        case 0xe8:              /* read test reg */
592
            dsp_out_data (s, s->test_reg);
593
            break;
594

    
595
        case 0xf2:
596
        case 0xf3:
597
            dsp_out_data (s, 0xaa);
598
            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
599
            qemu_irq_raise (s->pic[s->irq]);
600
            break;
601

    
602
        case 0xf9:
603
            s->needed_bytes = 1;
604
            goto warn;
605

    
606
        case 0xfa:
607
            dsp_out_data (s, 0);
608
            goto warn;
609

    
610
        case 0xfc:              /* FIXME */
611
            dsp_out_data (s, 0);
612
            goto warn;
613

    
614
        default:
615
            dolog ("Unrecognized command %#x\n", cmd);
616
            break;
617
        }
618
    }
619

    
620
    if (!s->needed_bytes) {
621
        ldebug ("\n");
622
    }
623

    
624
 exit:
625
    if (!s->needed_bytes) {
626
        s->cmd = -1;
627
    }
628
    else {
629
        s->cmd = cmd;
630
    }
631
    return;
632

    
633
 warn:
634
    dolog ("warning: command %#x,%d is not truly understood yet\n",
635
           cmd, s->needed_bytes);
636
    goto exit;
637

    
638
}
639

    
640
static uint16_t dsp_get_lohi (SB16State *s)
641
{
642
    uint8_t hi = dsp_get_data (s);
643
    uint8_t lo = dsp_get_data (s);
644
    return (hi << 8) | lo;
645
}
646

    
647
static uint16_t dsp_get_hilo (SB16State *s)
648
{
649
    uint8_t lo = dsp_get_data (s);
650
    uint8_t hi = dsp_get_data (s);
651
    return (hi << 8) | lo;
652
}
653

    
654
static void complete (SB16State *s)
655
{
656
    int d0, d1, d2;
657
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
658
            s->cmd, s->in_index, s->needed_bytes);
659

    
660
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
661
        d2 = dsp_get_data (s);
662
        d1 = dsp_get_data (s);
663
        d0 = dsp_get_data (s);
664

    
665
        if (s->cmd & 8) {
666
            dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
667
                   s->cmd, d0, d1, d2);
668
        }
669
        else {
670
            ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
671
                    s->cmd, d0, d1, d2);
672
            dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
673
        }
674
    }
675
    else {
676
        switch (s->cmd) {
677
        case 0x04:
678
            s->csp_mode = dsp_get_data (s);
679
            s->csp_reg83r = 0;
680
            s->csp_reg83w = 0;
681
            ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
682
            break;
683

    
684
        case 0x05:
685
            s->csp_param = dsp_get_data (s);
686
            s->csp_value = dsp_get_data (s);
687
            ldebug ("CSP command 0x05: param=%#x value=%#x\n",
688
                    s->csp_param,
689
                    s->csp_value);
690
            break;
691

    
692
        case 0x0e:
693
            d0 = dsp_get_data (s);
694
            d1 = dsp_get_data (s);
695
            ldebug ("write CSP register %d <- %#x\n", d1, d0);
696
            if (d1 == 0x83) {
697
                ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
698
                s->csp_reg83[s->csp_reg83r % 4] = d0;
699
                s->csp_reg83r += 1;
700
            }
701
            else {
702
                s->csp_regs[d1] = d0;
703
            }
704
            break;
705

    
706
        case 0x0f:
707
            d0 = dsp_get_data (s);
708
            ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
709
                    d0, s->csp_regs[d0], s->csp_mode);
710
            if (d0 == 0x83) {
711
                ldebug ("0x83[%d] -> %#x\n",
712
                        s->csp_reg83w,
713
                        s->csp_reg83[s->csp_reg83w % 4]);
714
                dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
715
                s->csp_reg83w += 1;
716
            }
717
            else {
718
                dsp_out_data (s, s->csp_regs[d0]);
719
            }
720
            break;
721

    
722
        case 0x10:
723
            d0 = dsp_get_data (s);
724
            dolog ("cmd 0x10 d0=%#x\n", d0);
725
            break;
726

    
727
        case 0x14:
728
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
729
            break;
730

    
731
        case 0x40:
732
            s->time_const = dsp_get_data (s);
733
            ldebug ("set time const %d\n", s->time_const);
734
            break;
735

    
736
        case 0x42:              /* FT2 sets output freq with this, go figure */
737
#if 0
738
            dolog ("cmd 0x42 might not do what it think it should\n");
739
#endif
740
        case 0x41:
741
            s->freq = dsp_get_hilo (s);
742
            ldebug ("set freq %d\n", s->freq);
743
            break;
744

    
745
        case 0x48:
746
            s->block_size = dsp_get_lohi (s) + 1;
747
            ldebug ("set dma block len %d\n", s->block_size);
748
            break;
749

    
750
        case 0x74:
751
        case 0x75:
752
        case 0x76:
753
        case 0x77:
754
            /* ADPCM stuff, ignore */
755
            break;
756

    
757
        case 0x80:
758
            {
759
                int freq, samples, bytes;
760
                int64_t ticks;
761

    
762
                freq = s->freq > 0 ? s->freq : 11025;
763
                samples = dsp_get_lohi (s) + 1;
764
                bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
765
                ticks = (bytes * ticks_per_sec) / freq;
766
                if (ticks < ticks_per_sec / 1024) {
767
                    qemu_irq_raise (s->pic[s->irq]);
768
                }
769
                else {
770
                    if (s->aux_ts) {
771
                        qemu_mod_timer (
772
                            s->aux_ts,
773
                            qemu_get_clock (vm_clock) + ticks
774
                            );
775
                    }
776
                }
777
                ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
778
            }
779
            break;
780

    
781
        case 0xe0:
782
            d0 = dsp_get_data (s);
783
            s->out_data_len = 0;
784
            ldebug ("E0 data = %#x\n", d0);
785
            dsp_out_data (s, ~d0);
786
            break;
787

    
788
        case 0xe2:
789
            d0 = dsp_get_data (s);
790
            ldebug ("E2 = %#x\n", d0);
791
            break;
792

    
793
        case 0xe4:
794
            s->test_reg = dsp_get_data (s);
795
            break;
796

    
797
        case 0xf9:
798
            d0 = dsp_get_data (s);
799
            ldebug ("command 0xf9 with %#x\n", d0);
800
            switch (d0) {
801
            case 0x0e:
802
                dsp_out_data (s, 0xff);
803
                break;
804

    
805
            case 0x0f:
806
                dsp_out_data (s, 0x07);
807
                break;
808

    
809
            case 0x37:
810
                dsp_out_data (s, 0x38);
811
                break;
812

    
813
            default:
814
                dsp_out_data (s, 0x00);
815
                break;
816
            }
817
            break;
818

    
819
        default:
820
            dolog ("complete: unrecognized command %#x\n", s->cmd);
821
            return;
822
        }
823
    }
824

    
825
    ldebug ("\n");
826
    s->cmd = -1;
827
    return;
828
}
829

    
830
static void legacy_reset (SB16State *s)
831
{
832
    audsettings_t as;
833

    
834
    s->freq = 11025;
835
    s->fmt_signed = 0;
836
    s->fmt_bits = 8;
837
    s->fmt_stereo = 0;
838

    
839
    as.freq = s->freq;
840
    as.nchannels = 1;
841
    as.fmt = AUD_FMT_U8;
842
    as.endianness = 0;
843

    
844
    s->voice = AUD_open_out (
845
        &s->card,
846
        s->voice,
847
        "sb16",
848
        s,
849
        SB_audio_callback,
850
        &as
851
        );
852

    
853
    /* Not sure about that... */
854
    /* AUD_set_active_out (s->voice, 1); */
855
}
856

    
857
static void reset (SB16State *s)
858
{
859
    qemu_irq_lower (s->pic[s->irq]);
860
    if (s->dma_auto) {
861
        qemu_irq_raise (s->pic[s->irq]);
862
        qemu_irq_lower (s->pic[s->irq]);
863
    }
864

    
865
    s->mixer_regs[0x82] = 0;
866
    s->dma_auto = 0;
867
    s->in_index = 0;
868
    s->out_data_len = 0;
869
    s->left_till_irq = 0;
870
    s->needed_bytes = 0;
871
    s->block_size = -1;
872
    s->nzero = 0;
873
    s->highspeed = 0;
874
    s->v2x6 = 0;
875
    s->cmd = -1;
876

    
877
    dsp_out_data(s, 0xaa);
878
    speaker (s, 0);
879
    control (s, 0);
880
    legacy_reset (s);
881
}
882

    
883
static IO_WRITE_PROTO (dsp_write)
884
{
885
    SB16State *s = opaque;
886
    int iport;
887

    
888
    iport = nport - s->port;
889

    
890
    ldebug ("write %#x <- %#x\n", nport, val);
891
    switch (iport) {
892
    case 0x06:
893
        switch (val) {
894
        case 0x00:
895
            if (s->v2x6 == 1) {
896
                if (0 && s->highspeed) {
897
                    s->highspeed = 0;
898
                    qemu_irq_lower (s->pic[s->irq]);
899
                    control (s, 0);
900
                }
901
                else {
902
                    reset (s);
903
                }
904
            }
905
            s->v2x6 = 0;
906
            break;
907

    
908
        case 0x01:
909
        case 0x03:              /* FreeBSD kludge */
910
            s->v2x6 = 1;
911
            break;
912

    
913
        case 0xc6:
914
            s->v2x6 = 0;        /* Prince of Persia, csp.sys, diagnose.exe */
915
            break;
916

    
917
        case 0xb8:              /* Panic */
918
            reset (s);
919
            break;
920

    
921
        case 0x39:
922
            dsp_out_data (s, 0x38);
923
            reset (s);
924
            s->v2x6 = 0x39;
925
            break;
926

    
927
        default:
928
            s->v2x6 = val;
929
            break;
930
        }
931
        break;
932

    
933
    case 0x0c:                  /* write data or command | write status */
934
/*         if (s->highspeed) */
935
/*             break; */
936

    
937
        if (0 == s->needed_bytes) {
938
            command (s, val);
939
#if 0
940
            if (0 == s->needed_bytes) {
941
                log_dsp (s);
942
            }
943
#endif
944
        }
945
        else {
946
            if (s->in_index == sizeof (s->in2_data)) {
947
                dolog ("in data overrun\n");
948
            }
949
            else {
950
                s->in2_data[s->in_index++] = val;
951
                if (s->in_index == s->needed_bytes) {
952
                    s->needed_bytes = 0;
953
                    complete (s);
954
#if 0
955
                    log_dsp (s);
956
#endif
957
                }
958
            }
959
        }
960
        break;
961

    
962
    default:
963
        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
964
        break;
965
    }
966
}
967

    
968
static IO_READ_PROTO (dsp_read)
969
{
970
    SB16State *s = opaque;
971
    int iport, retval, ack = 0;
972

    
973
    iport = nport - s->port;
974

    
975
    switch (iport) {
976
    case 0x06:                  /* reset */
977
        retval = 0xff;
978
        break;
979

    
980
    case 0x0a:                  /* read data */
981
        if (s->out_data_len) {
982
            retval = s->out_data[--s->out_data_len];
983
            s->last_read_byte = retval;
984
        }
985
        else {
986
            if (s->cmd != -1) {
987
                dolog ("empty output buffer for command %#x\n",
988
                       s->cmd);
989
            }
990
            retval = s->last_read_byte;
991
            /* goto error; */
992
        }
993
        break;
994

    
995
    case 0x0c:                  /* 0 can write */
996
        retval = s->can_write ? 0 : 0x80;
997
        break;
998

    
999
    case 0x0d:                  /* timer interrupt clear */
1000
        /* dolog ("timer interrupt clear\n"); */
1001
        retval = 0;
1002
        break;
1003

    
1004
    case 0x0e:                  /* data available status | irq 8 ack */
1005
        retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1006
        if (s->mixer_regs[0x82] & 1) {
1007
            ack = 1;
1008
            s->mixer_regs[0x82] &= 1;
1009
            qemu_irq_lower (s->pic[s->irq]);
1010
        }
1011
        break;
1012

    
1013
    case 0x0f:                  /* irq 16 ack */
1014
        retval = 0xff;
1015
        if (s->mixer_regs[0x82] & 2) {
1016
            ack = 1;
1017
            s->mixer_regs[0x82] &= 2;
1018
            qemu_irq_lower (s->pic[s->irq]);
1019
        }
1020
        break;
1021

    
1022
    default:
1023
        goto error;
1024
    }
1025

    
1026
    if (!ack) {
1027
        ldebug ("read %#x -> %#x\n", nport, retval);
1028
    }
1029

    
1030
    return retval;
1031

    
1032
 error:
1033
    dolog ("warning: dsp_read %#x error\n", nport);
1034
    return 0xff;
1035
}
1036

    
1037
static void reset_mixer (SB16State *s)
1038
{
1039
    int i;
1040

    
1041
    memset (s->mixer_regs, 0xff, 0x7f);
1042
    memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1043

    
1044
    s->mixer_regs[0x02] = 4;    /* master volume 3bits */
1045
    s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */
1046
    s->mixer_regs[0x08] = 0;    /* CD volume 3bits */
1047
    s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */
1048

    
1049
    /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1050
    s->mixer_regs[0x0c] = 0;
1051

    
1052
    /* d5=output filt, d1=stereo switch */
1053
    s->mixer_regs[0x0e] = 0;
1054

    
1055
    /* voice volume L d5,d7, R d1,d3 */
1056
    s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1057
    /* master ... */
1058
    s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1059
    /* MIDI ... */
1060
    s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1061

    
1062
    for (i = 0x30; i < 0x48; i++) {
1063
        s->mixer_regs[i] = 0x20;
1064
    }
1065
}
1066

    
1067
static IO_WRITE_PROTO(mixer_write_indexb)
1068
{
1069
    SB16State *s = opaque;
1070
    (void) nport;
1071
    s->mixer_nreg = val;
1072
}
1073

    
1074
static IO_WRITE_PROTO(mixer_write_datab)
1075
{
1076
    SB16State *s = opaque;
1077

    
1078
    (void) nport;
1079
    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1080

    
1081
    switch (s->mixer_nreg) {
1082
    case 0x00:
1083
        reset_mixer (s);
1084
        break;
1085

    
1086
    case 0x80:
1087
        {
1088
            int irq = irq_of_magic (val);
1089
            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1090
            if (irq > 0) {
1091
                s->irq = irq;
1092
            }
1093
        }
1094
        break;
1095

    
1096
    case 0x81:
1097
        {
1098
            int dma, hdma;
1099

    
1100
            dma = lsbindex (val & 0xf);
1101
            hdma = lsbindex (val & 0xf0);
1102
            if (dma != s->dma || hdma != s->hdma) {
1103
                dolog (
1104
                    "attempt to change DMA "
1105
                    "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1106
                    dma, s->dma, hdma, s->hdma, val);
1107
            }
1108
#if 0
1109
            s->dma = dma;
1110
            s->hdma = hdma;
1111
#endif
1112
        }
1113
        break;
1114

    
1115
    case 0x82:
1116
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
1117
               val);
1118
        return;
1119

    
1120
    default:
1121
        if (s->mixer_nreg >= 0x80) {
1122
            ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1123
        }
1124
        break;
1125
    }
1126

    
1127
    s->mixer_regs[s->mixer_nreg] = val;
1128
}
1129

    
1130
static IO_WRITE_PROTO(mixer_write_indexw)
1131
{
1132
    mixer_write_indexb (opaque, nport, val & 0xff);
1133
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1134
}
1135

    
1136
static IO_READ_PROTO(mixer_read)
1137
{
1138
    SB16State *s = opaque;
1139

    
1140
    (void) nport;
1141
#ifndef DEBUG_SB16_MOST
1142
    if (s->mixer_nreg != 0x82) {
1143
        ldebug ("mixer_read[%#x] -> %#x\n",
1144
                s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1145
    }
1146
#else
1147
    ldebug ("mixer_read[%#x] -> %#x\n",
1148
            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1149
#endif
1150
    return s->mixer_regs[s->mixer_nreg];
1151
}
1152

    
1153
static int write_audio (SB16State *s, int nchan, int dma_pos,
1154
                        int dma_len, int len)
1155
{
1156
    int temp, net;
1157
    uint8_t tmpbuf[4096];
1158

    
1159
    temp = len;
1160
    net = 0;
1161

    
1162
    while (temp) {
1163
        int left = dma_len - dma_pos;
1164
        int copied;
1165
        size_t to_copy;
1166

    
1167
        to_copy = audio_MIN (temp, left);
1168
        if (to_copy > sizeof (tmpbuf)) {
1169
            to_copy = sizeof (tmpbuf);
1170
        }
1171

    
1172
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1173
        copied = AUD_write (s->voice, tmpbuf, copied);
1174

    
1175
        temp -= copied;
1176
        dma_pos = (dma_pos + copied) % dma_len;
1177
        net += copied;
1178

    
1179
        if (!copied) {
1180
            break;
1181
        }
1182
    }
1183

    
1184
    return net;
1185
}
1186

    
1187
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1188
{
1189
    SB16State *s = opaque;
1190
    int till, copy, written, free;
1191

    
1192
    if (s->left_till_irq < 0) {
1193
        s->left_till_irq = s->block_size;
1194
    }
1195

    
1196
    if (s->voice) {
1197
        free = s->audio_free & ~s->align;
1198
        if ((free <= 0) || !dma_len) {
1199
            return dma_pos;
1200
        }
1201
    }
1202
    else {
1203
        free = dma_len;
1204
    }
1205

    
1206
    copy = free;
1207
    till = s->left_till_irq;
1208

    
1209
#ifdef DEBUG_SB16_MOST
1210
    dolog ("pos:%06d %d till:%d len:%d\n",
1211
           dma_pos, free, till, dma_len);
1212
#endif
1213

    
1214
    if (till <= copy) {
1215
        if (0 == s->dma_auto) {
1216
            copy = till;
1217
        }
1218
    }
1219

    
1220
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
1221
    dma_pos = (dma_pos + written) % dma_len;
1222
    s->left_till_irq -= written;
1223

    
1224
    if (s->left_till_irq <= 0) {
1225
        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1226
        qemu_irq_raise (s->pic[s->irq]);
1227
        if (0 == s->dma_auto) {
1228
            control (s, 0);
1229
            speaker (s, 0);
1230
        }
1231
    }
1232

    
1233
#ifdef DEBUG_SB16_MOST
1234
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1235
            dma_pos, free, dma_len, s->left_till_irq, copy, written,
1236
            s->block_size);
1237
#endif
1238

    
1239
    while (s->left_till_irq <= 0) {
1240
        s->left_till_irq = s->block_size + s->left_till_irq;
1241
    }
1242

    
1243
    return dma_pos;
1244
}
1245

    
1246
static void SB_audio_callback (void *opaque, int free)
1247
{
1248
    SB16State *s = opaque;
1249
    s->audio_free = free;
1250
}
1251

    
1252
static void SB_save (QEMUFile *f, void *opaque)
1253
{
1254
    SB16State *s = opaque;
1255

    
1256
    qemu_put_be32s (f, &s->irq);
1257
    qemu_put_be32s (f, &s->dma);
1258
    qemu_put_be32s (f, &s->hdma);
1259
    qemu_put_be32s (f, &s->port);
1260
    qemu_put_be32s (f, &s->ver);
1261
    qemu_put_be32s (f, &s->in_index);
1262
    qemu_put_be32s (f, &s->out_data_len);
1263
    qemu_put_be32s (f, &s->fmt_stereo);
1264
    qemu_put_be32s (f, &s->fmt_signed);
1265
    qemu_put_be32s (f, &s->fmt_bits);
1266
    qemu_put_be32s (f, &s->fmt);
1267
    qemu_put_be32s (f, &s->dma_auto);
1268
    qemu_put_be32s (f, &s->block_size);
1269
    qemu_put_be32s (f, &s->fifo);
1270
    qemu_put_be32s (f, &s->freq);
1271
    qemu_put_be32s (f, &s->time_const);
1272
    qemu_put_be32s (f, &s->speaker);
1273
    qemu_put_be32s (f, &s->needed_bytes);
1274
    qemu_put_be32s (f, &s->cmd);
1275
    qemu_put_be32s (f, &s->use_hdma);
1276
    qemu_put_be32s (f, &s->highspeed);
1277
    qemu_put_be32s (f, &s->can_write);
1278
    qemu_put_be32s (f, &s->v2x6);
1279

    
1280
    qemu_put_8s (f, &s->csp_param);
1281
    qemu_put_8s (f, &s->csp_value);
1282
    qemu_put_8s (f, &s->csp_mode);
1283
    qemu_put_8s (f, &s->csp_param);
1284
    qemu_put_buffer (f, s->csp_regs, 256);
1285
    qemu_put_8s (f, &s->csp_index);
1286
    qemu_put_buffer (f, s->csp_reg83, 4);
1287
    qemu_put_be32s (f, &s->csp_reg83r);
1288
    qemu_put_be32s (f, &s->csp_reg83w);
1289

    
1290
    qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1291
    qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1292
    qemu_put_8s (f, &s->test_reg);
1293
    qemu_put_8s (f, &s->last_read_byte);
1294

    
1295
    qemu_put_be32s (f, &s->nzero);
1296
    qemu_put_be32s (f, &s->left_till_irq);
1297
    qemu_put_be32s (f, &s->dma_running);
1298
    qemu_put_be32s (f, &s->bytes_per_second);
1299
    qemu_put_be32s (f, &s->align);
1300

    
1301
    qemu_put_be32s (f, &s->mixer_nreg);
1302
    qemu_put_buffer (f, s->mixer_regs, 256);
1303
}
1304

    
1305
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1306
{
1307
    SB16State *s = opaque;
1308

    
1309
    if (version_id != 1) {
1310
        return -EINVAL;
1311
    }
1312

    
1313
    qemu_get_be32s (f, &s->irq);
1314
    qemu_get_be32s (f, &s->dma);
1315
    qemu_get_be32s (f, &s->hdma);
1316
    qemu_get_be32s (f, &s->port);
1317
    qemu_get_be32s (f, &s->ver);
1318
    qemu_get_be32s (f, &s->in_index);
1319
    qemu_get_be32s (f, &s->out_data_len);
1320
    qemu_get_be32s (f, &s->fmt_stereo);
1321
    qemu_get_be32s (f, &s->fmt_signed);
1322
    qemu_get_be32s (f, &s->fmt_bits);
1323
    qemu_get_be32s (f, &s->fmt);
1324
    qemu_get_be32s (f, &s->dma_auto);
1325
    qemu_get_be32s (f, &s->block_size);
1326
    qemu_get_be32s (f, &s->fifo);
1327
    qemu_get_be32s (f, &s->freq);
1328
    qemu_get_be32s (f, &s->time_const);
1329
    qemu_get_be32s (f, &s->speaker);
1330
    qemu_get_be32s (f, &s->needed_bytes);
1331
    qemu_get_be32s (f, &s->cmd);
1332
    qemu_get_be32s (f, &s->use_hdma);
1333
    qemu_get_be32s (f, &s->highspeed);
1334
    qemu_get_be32s (f, &s->can_write);
1335
    qemu_get_be32s (f, &s->v2x6);
1336

    
1337
    qemu_get_8s (f, &s->csp_param);
1338
    qemu_get_8s (f, &s->csp_value);
1339
    qemu_get_8s (f, &s->csp_mode);
1340
    qemu_get_8s (f, &s->csp_param);
1341
    qemu_get_buffer (f, s->csp_regs, 256);
1342
    qemu_get_8s (f, &s->csp_index);
1343
    qemu_get_buffer (f, s->csp_reg83, 4);
1344
    qemu_get_be32s (f, &s->csp_reg83r);
1345
    qemu_get_be32s (f, &s->csp_reg83w);
1346

    
1347
    qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1348
    qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1349
    qemu_get_8s (f, &s->test_reg);
1350
    qemu_get_8s (f, &s->last_read_byte);
1351

    
1352
    qemu_get_be32s (f, &s->nzero);
1353
    qemu_get_be32s (f, &s->left_till_irq);
1354
    qemu_get_be32s (f, &s->dma_running);
1355
    qemu_get_be32s (f, &s->bytes_per_second);
1356
    qemu_get_be32s (f, &s->align);
1357

    
1358
    qemu_get_be32s (f, &s->mixer_nreg);
1359
    qemu_get_buffer (f, s->mixer_regs, 256);
1360

    
1361
    if (s->voice) {
1362
        AUD_close_out (&s->card, s->voice);
1363
        s->voice = NULL;
1364
    }
1365

    
1366
    if (s->dma_running) {
1367
        if (s->freq) {
1368
            audsettings_t as;
1369

    
1370
            s->audio_free = 0;
1371

    
1372
            as.freq = s->freq;
1373
            as.nchannels = 1 << s->fmt_stereo;
1374
            as.fmt = s->fmt;
1375
            as.endianness = 0;
1376

    
1377
            s->voice = AUD_open_out (
1378
                &s->card,
1379
                s->voice,
1380
                "sb16",
1381
                s,
1382
                SB_audio_callback,
1383
                &as
1384
                );
1385
        }
1386

    
1387
        control (s, 1);
1388
        speaker (s, s->speaker);
1389
    }
1390
    return 0;
1391
}
1392

    
1393
int SB16_init (AudioState *audio, qemu_irq *pic)
1394
{
1395
    SB16State *s;
1396
    int i;
1397
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1398
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1399

    
1400
    if (!audio) {
1401
        dolog ("No audio state\n");
1402
        return -1;
1403
    }
1404

    
1405
    s = qemu_mallocz (sizeof (*s));
1406
    if (!s) {
1407
        dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1408
               sizeof (*s));
1409
        return -1;
1410
    }
1411

    
1412
    s->cmd = -1;
1413
    s->pic = pic;
1414
    s->irq = conf.irq;
1415
    s->dma = conf.dma;
1416
    s->hdma = conf.hdma;
1417
    s->port = conf.port;
1418
    s->ver = conf.ver_lo | (conf.ver_hi << 8);
1419

    
1420
    s->mixer_regs[0x80] = magic_of_irq (s->irq);
1421
    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1422
    s->mixer_regs[0x82] = 2 << 5;
1423

    
1424
    s->csp_regs[5] = 1;
1425
    s->csp_regs[9] = 0xf8;
1426

    
1427
    reset_mixer (s);
1428
    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1429
    if (!s->aux_ts) {
1430
        dolog ("warning: Could not create auxiliary timer\n");
1431
    }
1432

    
1433
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1434
        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1435
    }
1436

    
1437
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1438
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1439
    }
1440

    
1441
    register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1442
    register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1443
    register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1444
    register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1445

    
1446
    DMA_register_channel (s->hdma, SB_read_DMA, s);
1447
    DMA_register_channel (s->dma, SB_read_DMA, s);
1448
    s->can_write = 1;
1449

    
1450
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1451
    AUD_register_card (audio, "sb16", &s->card);
1452
    return 0;
1453
}