Statistics
| Branch: | Revision:

root / hw / sb16.c @ 1ea879e5

History | View | Annotate | Download (35.9 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 "hw.h"
25
#include "audiodev.h"
26
#include "audio/audio.h"
27
#include "isa.h"
28
#include "qemu-timer.h"
29

    
30
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
31

    
32
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
33

    
34
/* #define DEBUG */
35
/* #define DEBUG_SB16_MOST */
36

    
37
#ifdef DEBUG
38
#define ldebug(...) dolog (__VA_ARGS__)
39
#else
40
#define ldebug(...)
41
#endif
42

    
43
#define IO_READ_PROTO(name)                             \
44
    uint32_t name (void *opaque, uint32_t nport)
45
#define IO_WRITE_PROTO(name)                                    \
46
    void name (void *opaque, uint32_t nport, uint32_t val)
47

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

    
50
static struct {
51
    int ver_lo;
52
    int ver_hi;
53
    int irq;
54
    int dma;
55
    int hdma;
56
    int port;
57
} conf = {5, 4, 5, 1, 5, 0x220};
58

    
59
typedef struct SB16State {
60
    QEMUSoundCard card;
61
    qemu_irq *pic;
62
    int irq;
63
    int dma;
64
    int hdma;
65
    int port;
66
    int ver;
67

    
68
    int in_index;
69
    int out_data_len;
70
    int fmt_stereo;
71
    int fmt_signed;
72
    int fmt_bits;
73
    audfmt_e 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
} SB16State;
116

    
117
static void SB_audio_callback (void *opaque, int free);
118

    
119
static 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
        dolog ("bad irq %d\n", irq);
132
        return 2;
133
    }
134
}
135

    
136
static 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
        dolog ("bad irq magic %d\n", magic);
149
        return -1;
150
    }
151
}
152

    
153
#if 0
154
static 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

    
168
static void speaker (SB16State *s, int on)
169
{
170
    s->speaker = on;
171
    /* AUD_enable (s->voice, on); */
172
}
173

    
174
static void control (SB16State *s, int hold)
175
{
176
    int dma = s->use_hdma ? s->hdma : s->dma;
177
    s->dma_running = hold;
178

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

    
181
    if (hold) {
182
        DMA_hold_DREQ (dma);
183
        AUD_set_active_out (s->voice, 1);
184
    }
185
    else {
186
        DMA_release_DREQ (dma);
187
        AUD_set_active_out (s->voice, 0);
188
    }
189
}
190

    
191
static void aux_timer (void *opaque)
192
{
193
    SB16State *s = opaque;
194
    s->can_write = 1;
195
    qemu_irq_raise (s->pic[s->irq]);
196
}
197

    
198
#define DMA8_AUTO 1
199
#define DMA8_HIGH 2
200

    
201
static void continue_dma8 (SB16State *s)
202
{
203
    if (s->freq > 0) {
204
        struct audsettings as;
205

    
206
        s->audio_free = 0;
207

    
208
        as.freq = s->freq;
209
        as.nchannels = 1 << s->fmt_stereo;
210
        as.fmt = s->fmt;
211
        as.endianness = 0;
212

    
213
        s->voice = AUD_open_out (
214
            &s->card,
215
            s->voice,
216
            "sb16",
217
            s,
218
            SB_audio_callback,
219
            &as
220
            );
221
    }
222

    
223
    control (s, 1);
224
}
225

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

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

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

    
256
    s->freq >>= s->fmt_stereo;
257
    s->left_till_irq = s->block_size;
258
    s->bytes_per_second = (s->freq << s->fmt_stereo);
259
    /* s->highspeed = (mask & DMA8_HIGH) != 0; */
260
    s->dma_auto = (mask & DMA8_AUTO) != 0;
261
    s->align = (1 << s->fmt_stereo) - 1;
262

    
263
    if (s->block_size & s->align) {
264
        dolog ("warning: misaligned block size %d, alignment %d\n",
265
               s->block_size, s->align + 1);
266
    }
267

    
268
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
269
            "dma %d, auto %d, fifo %d, high %d\n",
270
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
271
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
272

    
273
    continue_dma8 (s);
274
    speaker (s, 1);
275
}
276

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

    
285
    switch (cmd >> 4) {
286
    case 11:
287
        s->fmt_bits = 16;
288
        break;
289

    
290
    case 12:
291
        s->fmt_bits = 8;
292
        break;
293
    }
294

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

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

    
316
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
317
            "dma %d, auto %d, fifo %d, high %d\n",
318
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
319
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
320

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

    
338
    s->left_till_irq = s->block_size;
339

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

    
348
    if (s->freq) {
349
        struct audsettings as;
350

    
351
        s->audio_free = 0;
352

    
353
        as.freq = s->freq;
354
        as.nchannels = 1 << s->fmt_stereo;
355
        as.fmt = s->fmt;
356
        as.endianness = 0;
357

    
358
        s->voice = AUD_open_out (
359
            &s->card,
360
            s->voice,
361
            "sb16",
362
            s,
363
            SB_audio_callback,
364
            &as
365
            );
366
    }
367

    
368
    control (s, 1);
369
    speaker (s, 1);
370
}
371

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

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

    
391
static void command (SB16State *s, uint8_t cmd)
392
{
393
    ldebug ("command %#x\n", cmd);
394

    
395
    if (cmd > 0xaf && cmd < 0xd0) {
396
        if (cmd & 8) {
397
            dolog ("ADC not yet supported (command %#x)\n", cmd);
398
        }
399

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

    
412
        switch (cmd) {
413
        case 0x03:
414
            dsp_out_data (s, 0x10); /* s->csp_param); */
415
            goto warn;
416

    
417
        case 0x04:
418
            s->needed_bytes = 1;
419
            goto warn;
420

    
421
        case 0x05:
422
            s->needed_bytes = 2;
423
            goto warn;
424

    
425
        case 0x08:
426
            /* __asm__ ("int3"); */
427
            goto warn;
428

    
429
        case 0x0e:
430
            s->needed_bytes = 2;
431
            goto warn;
432

    
433
        case 0x09:
434
            dsp_out_data (s, 0xf8);
435
            goto warn;
436

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

    
441
        case 0x10:
442
            s->needed_bytes = 1;
443
            goto warn;
444

    
445
        case 0x14:
446
            s->needed_bytes = 2;
447
            s->block_size = 0;
448
            break;
449

    
450
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
451
            dma_cmd8 (s, DMA8_AUTO, -1);
452
            break;
453

    
454
        case 0x20:              /* Direct ADC, Juice/PL */
455
            dsp_out_data (s, 0xff);
456
            goto warn;
457

    
458
        case 0x35:
459
            dolog ("0x35 - MIDI command not implemented\n");
460
            break;
461

    
462
        case 0x40:
463
            s->freq = -1;
464
            s->time_const = -1;
465
            s->needed_bytes = 1;
466
            break;
467

    
468
        case 0x41:
469
            s->freq = -1;
470
            s->time_const = -1;
471
            s->needed_bytes = 2;
472
            break;
473

    
474
        case 0x42:
475
            s->freq = -1;
476
            s->time_const = -1;
477
            s->needed_bytes = 2;
478
            goto warn;
479

    
480
        case 0x45:
481
            dsp_out_data (s, 0xaa);
482
            goto warn;
483

    
484
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
485
            break;
486

    
487
        case 0x48:
488
            s->needed_bytes = 2;
489
            break;
490

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

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

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

    
506
        case 0x77:              /* DMA DAC, 2.6-bit ADPCM Reference */
507
            s->needed_bytes = 2;
508
            dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
509
            break;
510

    
511
        case 0x7d:
512
            dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
513
            dolog ("not implemented\n");
514
            break;
515

    
516
        case 0x7f:
517
            dolog (
518
                "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
519
                );
520
            dolog ("not implemented\n");
521
            break;
522

    
523
        case 0x80:
524
            s->needed_bytes = 2;
525
            break;
526

    
527
        case 0x90:
528
        case 0x91:
529
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
530
            break;
531

    
532
        case 0xd0:              /* halt DMA operation. 8bit */
533
            control (s, 0);
534
            break;
535

    
536
        case 0xd1:              /* speaker on */
537
            speaker (s, 1);
538
            break;
539

    
540
        case 0xd3:              /* speaker off */
541
            speaker (s, 0);
542
            break;
543

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

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

    
554
        case 0xd6:              /* continue DMA operation. 16bit */
555
            control (s, 1);
556
            break;
557

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

    
562
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
563
            s->dma_auto = 0;
564
            break;
565

    
566
        case 0xe0:              /* DSP identification */
567
            s->needed_bytes = 1;
568
            break;
569

    
570
        case 0xe1:
571
            dsp_out_data (s, s->ver & 0xff);
572
            dsp_out_data (s, s->ver >> 8);
573
            break;
574

    
575
        case 0xe2:
576
            s->needed_bytes = 1;
577
            goto warn;
578

    
579
        case 0xe3:
580
            {
581
                int i;
582
                for (i = sizeof (e3) - 1; i >= 0; --i)
583
                    dsp_out_data (s, e3[i]);
584
            }
585
            break;
586

    
587
        case 0xe4:              /* write test reg */
588
            s->needed_bytes = 1;
589
            break;
590

    
591
        case 0xe7:
592
            dolog ("Attempt to probe for ESS (0xe7)?\n");
593
            break;
594

    
595
        case 0xe8:              /* read test reg */
596
            dsp_out_data (s, s->test_reg);
597
            break;
598

    
599
        case 0xf2:
600
        case 0xf3:
601
            dsp_out_data (s, 0xaa);
602
            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
603
            qemu_irq_raise (s->pic[s->irq]);
604
            break;
605

    
606
        case 0xf9:
607
            s->needed_bytes = 1;
608
            goto warn;
609

    
610
        case 0xfa:
611
            dsp_out_data (s, 0);
612
            goto warn;
613

    
614
        case 0xfc:              /* FIXME */
615
            dsp_out_data (s, 0);
616
            goto warn;
617

    
618
        default:
619
            dolog ("Unrecognized command %#x\n", cmd);
620
            break;
621
        }
622
    }
623

    
624
    if (!s->needed_bytes) {
625
        ldebug ("\n");
626
    }
627

    
628
 exit:
629
    if (!s->needed_bytes) {
630
        s->cmd = -1;
631
    }
632
    else {
633
        s->cmd = cmd;
634
    }
635
    return;
636

    
637
 warn:
638
    dolog ("warning: command %#x,%d is not truly understood yet\n",
639
           cmd, s->needed_bytes);
640
    goto exit;
641

    
642
}
643

    
644
static uint16_t dsp_get_lohi (SB16State *s)
645
{
646
    uint8_t hi = dsp_get_data (s);
647
    uint8_t lo = dsp_get_data (s);
648
    return (hi << 8) | lo;
649
}
650

    
651
static uint16_t dsp_get_hilo (SB16State *s)
652
{
653
    uint8_t lo = dsp_get_data (s);
654
    uint8_t hi = dsp_get_data (s);
655
    return (hi << 8) | lo;
656
}
657

    
658
static void complete (SB16State *s)
659
{
660
    int d0, d1, d2;
661
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
662
            s->cmd, s->in_index, s->needed_bytes);
663

    
664
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
665
        d2 = dsp_get_data (s);
666
        d1 = dsp_get_data (s);
667
        d0 = dsp_get_data (s);
668

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

    
688
        case 0x05:
689
            s->csp_param = dsp_get_data (s);
690
            s->csp_value = dsp_get_data (s);
691
            ldebug ("CSP command 0x05: param=%#x value=%#x\n",
692
                    s->csp_param,
693
                    s->csp_value);
694
            break;
695

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

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

    
726
        case 0x10:
727
            d0 = dsp_get_data (s);
728
            dolog ("cmd 0x10 d0=%#x\n", d0);
729
            break;
730

    
731
        case 0x14:
732
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
733
            break;
734

    
735
        case 0x40:
736
            s->time_const = dsp_get_data (s);
737
            ldebug ("set time const %d\n", s->time_const);
738
            break;
739

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

    
749
        case 0x48:
750
            s->block_size = dsp_get_lohi (s) + 1;
751
            ldebug ("set dma block len %d\n", s->block_size);
752
            break;
753

    
754
        case 0x74:
755
        case 0x75:
756
        case 0x76:
757
        case 0x77:
758
            /* ADPCM stuff, ignore */
759
            break;
760

    
761
        case 0x80:
762
            {
763
                int freq, samples, bytes;
764
                int64_t ticks;
765

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

    
785
        case 0xe0:
786
            d0 = dsp_get_data (s);
787
            s->out_data_len = 0;
788
            ldebug ("E0 data = %#x\n", d0);
789
            dsp_out_data (s, ~d0);
790
            break;
791

    
792
        case 0xe2:
793
            d0 = dsp_get_data (s);
794
            ldebug ("E2 = %#x\n", d0);
795
            break;
796

    
797
        case 0xe4:
798
            s->test_reg = dsp_get_data (s);
799
            break;
800

    
801
        case 0xf9:
802
            d0 = dsp_get_data (s);
803
            ldebug ("command 0xf9 with %#x\n", d0);
804
            switch (d0) {
805
            case 0x0e:
806
                dsp_out_data (s, 0xff);
807
                break;
808

    
809
            case 0x0f:
810
                dsp_out_data (s, 0x07);
811
                break;
812

    
813
            case 0x37:
814
                dsp_out_data (s, 0x38);
815
                break;
816

    
817
            default:
818
                dsp_out_data (s, 0x00);
819
                break;
820
            }
821
            break;
822

    
823
        default:
824
            dolog ("complete: unrecognized command %#x\n", s->cmd);
825
            return;
826
        }
827
    }
828

    
829
    ldebug ("\n");
830
    s->cmd = -1;
831
    return;
832
}
833

    
834
static void legacy_reset (SB16State *s)
835
{
836
    struct audsettings as;
837

    
838
    s->freq = 11025;
839
    s->fmt_signed = 0;
840
    s->fmt_bits = 8;
841
    s->fmt_stereo = 0;
842

    
843
    as.freq = s->freq;
844
    as.nchannels = 1;
845
    as.fmt = AUD_FMT_U8;
846
    as.endianness = 0;
847

    
848
    s->voice = AUD_open_out (
849
        &s->card,
850
        s->voice,
851
        "sb16",
852
        s,
853
        SB_audio_callback,
854
        &as
855
        );
856

    
857
    /* Not sure about that... */
858
    /* AUD_set_active_out (s->voice, 1); */
859
}
860

    
861
static void reset (SB16State *s)
862
{
863
    qemu_irq_lower (s->pic[s->irq]);
864
    if (s->dma_auto) {
865
        qemu_irq_raise (s->pic[s->irq]);
866
        qemu_irq_lower (s->pic[s->irq]);
867
    }
868

    
869
    s->mixer_regs[0x82] = 0;
870
    s->dma_auto = 0;
871
    s->in_index = 0;
872
    s->out_data_len = 0;
873
    s->left_till_irq = 0;
874
    s->needed_bytes = 0;
875
    s->block_size = -1;
876
    s->nzero = 0;
877
    s->highspeed = 0;
878
    s->v2x6 = 0;
879
    s->cmd = -1;
880

    
881
    dsp_out_data(s, 0xaa);
882
    speaker (s, 0);
883
    control (s, 0);
884
    legacy_reset (s);
885
}
886

    
887
static IO_WRITE_PROTO (dsp_write)
888
{
889
    SB16State *s = opaque;
890
    int iport;
891

    
892
    iport = nport - s->port;
893

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

    
912
        case 0x01:
913
        case 0x03:              /* FreeBSD kludge */
914
            s->v2x6 = 1;
915
            break;
916

    
917
        case 0xc6:
918
            s->v2x6 = 0;        /* Prince of Persia, csp.sys, diagnose.exe */
919
            break;
920

    
921
        case 0xb8:              /* Panic */
922
            reset (s);
923
            break;
924

    
925
        case 0x39:
926
            dsp_out_data (s, 0x38);
927
            reset (s);
928
            s->v2x6 = 0x39;
929
            break;
930

    
931
        default:
932
            s->v2x6 = val;
933
            break;
934
        }
935
        break;
936

    
937
    case 0x0c:                  /* write data or command | write status */
938
/*         if (s->highspeed) */
939
/*             break; */
940

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

    
966
    default:
967
        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
968
        break;
969
    }
970
}
971

    
972
static IO_READ_PROTO (dsp_read)
973
{
974
    SB16State *s = opaque;
975
    int iport, retval, ack = 0;
976

    
977
    iport = nport - s->port;
978

    
979
    switch (iport) {
980
    case 0x06:                  /* reset */
981
        retval = 0xff;
982
        break;
983

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

    
999
    case 0x0c:                  /* 0 can write */
1000
        retval = s->can_write ? 0 : 0x80;
1001
        break;
1002

    
1003
    case 0x0d:                  /* timer interrupt clear */
1004
        /* dolog ("timer interrupt clear\n"); */
1005
        retval = 0;
1006
        break;
1007

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

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

    
1026
    default:
1027
        goto error;
1028
    }
1029

    
1030
    if (!ack) {
1031
        ldebug ("read %#x -> %#x\n", nport, retval);
1032
    }
1033

    
1034
    return retval;
1035

    
1036
 error:
1037
    dolog ("warning: dsp_read %#x error\n", nport);
1038
    return 0xff;
1039
}
1040

    
1041
static void reset_mixer (SB16State *s)
1042
{
1043
    int i;
1044

    
1045
    memset (s->mixer_regs, 0xff, 0x7f);
1046
    memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1047

    
1048
    s->mixer_regs[0x02] = 4;    /* master volume 3bits */
1049
    s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */
1050
    s->mixer_regs[0x08] = 0;    /* CD volume 3bits */
1051
    s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */
1052

    
1053
    /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1054
    s->mixer_regs[0x0c] = 0;
1055

    
1056
    /* d5=output filt, d1=stereo switch */
1057
    s->mixer_regs[0x0e] = 0;
1058

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

    
1066
    for (i = 0x30; i < 0x48; i++) {
1067
        s->mixer_regs[i] = 0x20;
1068
    }
1069
}
1070

    
1071
static IO_WRITE_PROTO(mixer_write_indexb)
1072
{
1073
    SB16State *s = opaque;
1074
    (void) nport;
1075
    s->mixer_nreg = val;
1076
}
1077

    
1078
static IO_WRITE_PROTO(mixer_write_datab)
1079
{
1080
    SB16State *s = opaque;
1081

    
1082
    (void) nport;
1083
    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1084

    
1085
    switch (s->mixer_nreg) {
1086
    case 0x00:
1087
        reset_mixer (s);
1088
        break;
1089

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

    
1100
    case 0x81:
1101
        {
1102
            int dma, hdma;
1103

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

    
1119
    case 0x82:
1120
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
1121
               val);
1122
        return;
1123

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

    
1131
    s->mixer_regs[s->mixer_nreg] = val;
1132
}
1133

    
1134
static IO_WRITE_PROTO(mixer_write_indexw)
1135
{
1136
    mixer_write_indexb (opaque, nport, val & 0xff);
1137
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1138
}
1139

    
1140
static IO_READ_PROTO(mixer_read)
1141
{
1142
    SB16State *s = opaque;
1143

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

    
1157
static int write_audio (SB16State *s, int nchan, int dma_pos,
1158
                        int dma_len, int len)
1159
{
1160
    int temp, net;
1161
    uint8_t tmpbuf[4096];
1162

    
1163
    temp = len;
1164
    net = 0;
1165

    
1166
    while (temp) {
1167
        int left = dma_len - dma_pos;
1168
        int copied;
1169
        size_t to_copy;
1170

    
1171
        to_copy = audio_MIN (temp, left);
1172
        if (to_copy > sizeof (tmpbuf)) {
1173
            to_copy = sizeof (tmpbuf);
1174
        }
1175

    
1176
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1177
        copied = AUD_write (s->voice, tmpbuf, copied);
1178

    
1179
        temp -= copied;
1180
        dma_pos = (dma_pos + copied) % dma_len;
1181
        net += copied;
1182

    
1183
        if (!copied) {
1184
            break;
1185
        }
1186
    }
1187

    
1188
    return net;
1189
}
1190

    
1191
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1192
{
1193
    SB16State *s = opaque;
1194
    int till, copy, written, free;
1195

    
1196
    if (s->block_size <= 0) {
1197
        dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1198
               s->block_size, nchan, dma_pos, dma_len);
1199
        return dma_pos;
1200
    }
1201

    
1202
    if (s->left_till_irq < 0) {
1203
        s->left_till_irq = s->block_size;
1204
    }
1205

    
1206
    if (s->voice) {
1207
        free = s->audio_free & ~s->align;
1208
        if ((free <= 0) || !dma_len) {
1209
            return dma_pos;
1210
        }
1211
    }
1212
    else {
1213
        free = dma_len;
1214
    }
1215

    
1216
    copy = free;
1217
    till = s->left_till_irq;
1218

    
1219
#ifdef DEBUG_SB16_MOST
1220
    dolog ("pos:%06d %d till:%d len:%d\n",
1221
           dma_pos, free, till, dma_len);
1222
#endif
1223

    
1224
    if (till <= copy) {
1225
        if (0 == s->dma_auto) {
1226
            copy = till;
1227
        }
1228
    }
1229

    
1230
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
1231
    dma_pos = (dma_pos + written) % dma_len;
1232
    s->left_till_irq -= written;
1233

    
1234
    if (s->left_till_irq <= 0) {
1235
        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1236
        qemu_irq_raise (s->pic[s->irq]);
1237
        if (0 == s->dma_auto) {
1238
            control (s, 0);
1239
            speaker (s, 0);
1240
        }
1241
    }
1242

    
1243
#ifdef DEBUG_SB16_MOST
1244
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1245
            dma_pos, free, dma_len, s->left_till_irq, copy, written,
1246
            s->block_size);
1247
#endif
1248

    
1249
    while (s->left_till_irq <= 0) {
1250
        s->left_till_irq = s->block_size + s->left_till_irq;
1251
    }
1252

    
1253
    return dma_pos;
1254
}
1255

    
1256
static void SB_audio_callback (void *opaque, int free)
1257
{
1258
    SB16State *s = opaque;
1259
    s->audio_free = free;
1260
}
1261

    
1262
static void SB_save (QEMUFile *f, void *opaque)
1263
{
1264
    SB16State *s = opaque;
1265

    
1266
    qemu_put_be32 (f, s->irq);
1267
    qemu_put_be32 (f, s->dma);
1268
    qemu_put_be32 (f, s->hdma);
1269
    qemu_put_be32 (f, s->port);
1270
    qemu_put_be32 (f, s->ver);
1271
    qemu_put_be32 (f, s->in_index);
1272
    qemu_put_be32 (f, s->out_data_len);
1273
    qemu_put_be32 (f, s->fmt_stereo);
1274
    qemu_put_be32 (f, s->fmt_signed);
1275
    qemu_put_be32 (f, s->fmt_bits);
1276
    qemu_put_be32s (f, &s->fmt);
1277
    qemu_put_be32 (f, s->dma_auto);
1278
    qemu_put_be32 (f, s->block_size);
1279
    qemu_put_be32 (f, s->fifo);
1280
    qemu_put_be32 (f, s->freq);
1281
    qemu_put_be32 (f, s->time_const);
1282
    qemu_put_be32 (f, s->speaker);
1283
    qemu_put_be32 (f, s->needed_bytes);
1284
    qemu_put_be32 (f, s->cmd);
1285
    qemu_put_be32 (f, s->use_hdma);
1286
    qemu_put_be32 (f, s->highspeed);
1287
    qemu_put_be32 (f, s->can_write);
1288
    qemu_put_be32 (f, s->v2x6);
1289

    
1290
    qemu_put_8s (f, &s->csp_param);
1291
    qemu_put_8s (f, &s->csp_value);
1292
    qemu_put_8s (f, &s->csp_mode);
1293
    qemu_put_8s (f, &s->csp_param);
1294
    qemu_put_buffer (f, s->csp_regs, 256);
1295
    qemu_put_8s (f, &s->csp_index);
1296
    qemu_put_buffer (f, s->csp_reg83, 4);
1297
    qemu_put_be32 (f, s->csp_reg83r);
1298
    qemu_put_be32 (f, s->csp_reg83w);
1299

    
1300
    qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1301
    qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1302
    qemu_put_8s (f, &s->test_reg);
1303
    qemu_put_8s (f, &s->last_read_byte);
1304

    
1305
    qemu_put_be32 (f, s->nzero);
1306
    qemu_put_be32 (f, s->left_till_irq);
1307
    qemu_put_be32 (f, s->dma_running);
1308
    qemu_put_be32 (f, s->bytes_per_second);
1309
    qemu_put_be32 (f, s->align);
1310

    
1311
    qemu_put_be32 (f, s->mixer_nreg);
1312
    qemu_put_buffer (f, s->mixer_regs, 256);
1313
}
1314

    
1315
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1316
{
1317
    SB16State *s = opaque;
1318

    
1319
    if (version_id != 1) {
1320
        return -EINVAL;
1321
    }
1322

    
1323
    s->irq=qemu_get_be32 (f);
1324
    s->dma=qemu_get_be32 (f);
1325
    s->hdma=qemu_get_be32 (f);
1326
    s->port=qemu_get_be32 (f);
1327
    s->ver=qemu_get_be32 (f);
1328
    s->in_index=qemu_get_be32 (f);
1329
    s->out_data_len=qemu_get_be32 (f);
1330
    s->fmt_stereo=qemu_get_be32 (f);
1331
    s->fmt_signed=qemu_get_be32 (f);
1332
    s->fmt_bits=qemu_get_be32 (f);
1333
    qemu_get_be32s (f, &s->fmt);
1334
    s->dma_auto=qemu_get_be32 (f);
1335
    s->block_size=qemu_get_be32 (f);
1336
    s->fifo=qemu_get_be32 (f);
1337
    s->freq=qemu_get_be32 (f);
1338
    s->time_const=qemu_get_be32 (f);
1339
    s->speaker=qemu_get_be32 (f);
1340
    s->needed_bytes=qemu_get_be32 (f);
1341
    s->cmd=qemu_get_be32 (f);
1342
    s->use_hdma=qemu_get_be32 (f);
1343
    s->highspeed=qemu_get_be32 (f);
1344
    s->can_write=qemu_get_be32 (f);
1345
    s->v2x6=qemu_get_be32 (f);
1346

    
1347
    qemu_get_8s (f, &s->csp_param);
1348
    qemu_get_8s (f, &s->csp_value);
1349
    qemu_get_8s (f, &s->csp_mode);
1350
    qemu_get_8s (f, &s->csp_param);
1351
    qemu_get_buffer (f, s->csp_regs, 256);
1352
    qemu_get_8s (f, &s->csp_index);
1353
    qemu_get_buffer (f, s->csp_reg83, 4);
1354
    s->csp_reg83r=qemu_get_be32 (f);
1355
    s->csp_reg83w=qemu_get_be32 (f);
1356

    
1357
    qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1358
    qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1359
    qemu_get_8s (f, &s->test_reg);
1360
    qemu_get_8s (f, &s->last_read_byte);
1361

    
1362
    s->nzero=qemu_get_be32 (f);
1363
    s->left_till_irq=qemu_get_be32 (f);
1364
    s->dma_running=qemu_get_be32 (f);
1365
    s->bytes_per_second=qemu_get_be32 (f);
1366
    s->align=qemu_get_be32 (f);
1367

    
1368
    s->mixer_nreg=qemu_get_be32 (f);
1369
    qemu_get_buffer (f, s->mixer_regs, 256);
1370

    
1371
    if (s->voice) {
1372
        AUD_close_out (&s->card, s->voice);
1373
        s->voice = NULL;
1374
    }
1375

    
1376
    if (s->dma_running) {
1377
        if (s->freq) {
1378
            struct audsettings as;
1379

    
1380
            s->audio_free = 0;
1381

    
1382
            as.freq = s->freq;
1383
            as.nchannels = 1 << s->fmt_stereo;
1384
            as.fmt = s->fmt;
1385
            as.endianness = 0;
1386

    
1387
            s->voice = AUD_open_out (
1388
                &s->card,
1389
                s->voice,
1390
                "sb16",
1391
                s,
1392
                SB_audio_callback,
1393
                &as
1394
                );
1395
        }
1396

    
1397
        control (s, 1);
1398
        speaker (s, s->speaker);
1399
    }
1400
    return 0;
1401
}
1402

    
1403
int SB16_init (AudioState *audio, qemu_irq *pic)
1404
{
1405
    SB16State *s;
1406
    int i;
1407
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1408
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1409

    
1410
    if (!audio) {
1411
        dolog ("No audio state\n");
1412
        return -1;
1413
    }
1414

    
1415
    s = qemu_mallocz (sizeof (*s));
1416
    if (!s) {
1417
        dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1418
               sizeof (*s));
1419
        return -1;
1420
    }
1421

    
1422
    s->cmd = -1;
1423
    s->pic = pic;
1424
    s->irq = conf.irq;
1425
    s->dma = conf.dma;
1426
    s->hdma = conf.hdma;
1427
    s->port = conf.port;
1428
    s->ver = conf.ver_lo | (conf.ver_hi << 8);
1429

    
1430
    s->mixer_regs[0x80] = magic_of_irq (s->irq);
1431
    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1432
    s->mixer_regs[0x82] = 2 << 5;
1433

    
1434
    s->csp_regs[5] = 1;
1435
    s->csp_regs[9] = 0xf8;
1436

    
1437
    reset_mixer (s);
1438
    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1439
    if (!s->aux_ts) {
1440
        dolog ("warning: Could not create auxiliary timer\n");
1441
    }
1442

    
1443
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1444
        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1445
    }
1446

    
1447
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1448
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1449
    }
1450

    
1451
    register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1452
    register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1453
    register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1454
    register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1455

    
1456
    DMA_register_channel (s->hdma, SB_read_DMA, s);
1457
    DMA_register_channel (s->dma, SB_read_DMA, s);
1458
    s->can_write = 1;
1459

    
1460
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1461
    AUD_register_card (audio, "sb16", &s->card);
1462
    return 0;
1463
}