Blame view

hw/sb16.c 34.9 KB
1
2
/*
 * QEMU Soundblaster 16 emulation
3
4
5
 *
 * Copyright (c) 2003-2005 Vassili Karpov (malc)
 *
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"
bellard authored
26
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
27
28
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
bellard authored
29
30
31
32

/* #define DEBUG */
/* #define DEBUG_SB16_MOST */
33
34
35
36
37
38
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
bellard authored
39
#define IO_READ_PROTO(name)                             \
bellard authored
40
    uint32_t name (void *opaque, uint32_t nport)
bellard authored
41
#define IO_WRITE_PROTO(name)                                    \
bellard authored
42
    void name (void *opaque, uint32_t nport, uint32_t val)
43
bellard authored
44
static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
bellard authored
45
46
47
48
49
50
51
52
static struct {
    int ver_lo;
    int ver_hi;
    int irq;
    int dma;
    int hdma;
    int port;
bellard authored
53
} conf = {5, 4, 5, 1, 5, 0x220};
54
55
typedef struct SB16State {
bellard authored
56
    QEMUSoundCard card;
bellard authored
57
58
59
60
61
62
    int irq;
    int dma;
    int hdma;
    int port;
    int ver;
63
64
65
66
67
    int in_index;
    int out_data_len;
    int fmt_stereo;
    int fmt_signed;
    int fmt_bits;
bellard authored
68
    audfmt_e fmt;
69
    int dma_auto;
bellard authored
70
    int block_size;
71
72
73
74
75
76
77
    int fifo;
    int freq;
    int time_const;
    int speaker;
    int needed_bytes;
    int cmd;
    int use_hdma;
bellard authored
78
79
    int highspeed;
    int can_write;
80
81
82

    int v2x6;
bellard authored
83
84
85
86
87
88
89
90
91
    uint8_t csp_param;
    uint8_t csp_value;
    uint8_t csp_mode;
    uint8_t csp_regs[256];
    uint8_t csp_index;
    uint8_t csp_reg83[4];
    int csp_reg83r;
    int csp_reg83w;
92
    uint8_t in2_data[10];
bellard authored
93
94
95
96
    uint8_t out_data[50];
    uint8_t test_reg;
    uint8_t last_read_byte;
    int nzero;
97
98
99

    int left_till_irq;
bellard authored
100
101
102
    int dma_running;
    int bytes_per_second;
    int align;
103
104
    int audio_free;
    SWVoiceOut *voice;
bellard authored
105
106
    QEMUTimer *aux_ts;
107
108
    /* mixer state */
    int mixer_nreg;
bellard authored
109
    uint8_t mixer_regs[256];
110
} SB16State;
111
112
113
static void SB_audio_callback (void *opaque, int free);
bellard authored
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
static int magic_of_irq (int irq)
{
    switch (irq) {
    case 5:
        return 2;
    case 7:
        return 4;
    case 9:
        return 1;
    case 10:
        return 8;
    default:
        dolog ("bad irq %d\n", irq);
        return 2;
    }
}

static int irq_of_magic (int magic)
{
    switch (magic) {
    case 1:
        return 9;
    case 2:
        return 5;
    case 4:
        return 7;
    case 8:
        return 10;
    default:
        dolog ("bad irq magic %d\n", magic);
        return -1;
    }
}

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

static void speaker (SB16State *s, int on)
{
    s->speaker = on;
    /* AUD_enable (s->voice, on); */
167
168
}
bellard authored
169
static void control (SB16State *s, int hold)
170
{
bellard authored
171
172
173
174
175
    int dma = s->use_hdma ? s->hdma : s->dma;
    s->dma_running = hold;

    ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
176
    if (hold) {
bellard authored
177
        DMA_hold_DREQ (dma);
178
        AUD_set_active_out (s->voice, 1);
179
180
    }
    else {
bellard authored
181
        DMA_release_DREQ (dma);
182
        AUD_set_active_out (s->voice, 0);
183
184
185
    }
}
bellard authored
186
static void aux_timer (void *opaque)
187
{
bellard authored
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    SB16State *s = opaque;
    s->can_write = 1;
    pic_set_irq (s->irq, 1);
}

#define DMA8_AUTO 1
#define DMA8_HIGH 2

static void dma_cmd8 (SB16State *s, int mask, int dma_len)
{
    s->fmt = AUD_FMT_U8;
    s->use_hdma = 0;
    s->fmt_bits = 8;
    s->fmt_signed = 0;
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
    if (-1 == s->time_const) {
        s->freq = 11025;
    }
    else {
        int tmp = (256 - s->time_const);
        s->freq = (1000000 + (tmp / 2)) / tmp;
    }
211
    if (dma_len != -1) {
bellard authored
212
        s->block_size = dma_len << s->fmt_stereo;
213
    }
bellard authored
214
215
216
217
218
219
220
221
222
223
    else {
        /* This is apparently the only way to make both Act1/PL
           and SecondReality/FC work

           Act1 sets block size via command 0x48 and it's an odd number
           SR does the same with even number
           Both use stereo, and Creatives own documentation states that
           0x48 sets block size in bytes less one.. go figure */
        s->block_size &= ~s->fmt_stereo;
    }
bellard authored
224
225
226
227
228
229
230
231

    s->freq >>= s->fmt_stereo;
    s->left_till_irq = s->block_size;
    s->bytes_per_second = (s->freq << s->fmt_stereo);
    /* s->highspeed = (mask & DMA8_HIGH) != 0; */
    s->dma_auto = (mask & DMA8_AUTO) != 0;
    s->align = (1 << s->fmt_stereo) - 1;
232
233
234
235
    if (s->block_size & s->align) {
        dolog ("warning: misaligned block size %d, alignment %d\n",
               s->block_size, s->align + 1);
    }
bellard authored
236
bellard authored
237
238
239
240
241
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
            "dma %d, auto %d, fifo %d, high %d\n",
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
242
    if (s->freq) {
bellard authored
243
244
        audsettings_t as;
245
        s->audio_free = 0;
bellard authored
246
247
248
249
250

        as.freq = s->freq;
        as.nchannels = 1 << s->fmt_stereo;
        as.fmt = s->fmt;
251
        s->voice = AUD_open_out (
bellard authored
252
            &s->card,
253
254
255
256
            s->voice,
            "sb16",
            s,
            SB_audio_callback,
257
258
            &as,
            0                   /* little endian */
259
260
            );
    }
bellard authored
261
262
263
264

    control (s, 1);
    speaker (s, 1);
}
265
bellard authored
266
267
268
269
270
271
272
static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
{
    s->use_hdma = cmd < 0xc0;
    s->fifo = (cmd >> 1) & 1;
    s->dma_auto = (cmd >> 2) & 1;
    s->fmt_signed = (d0 >> 4) & 1;
    s->fmt_stereo = (d0 >> 5) & 1;
273
274
275

    switch (cmd >> 4) {
    case 11:
bellard authored
276
        s->fmt_bits = 16;
277
278
279
        break;

    case 12:
bellard authored
280
        s->fmt_bits = 8;
281
282
283
        break;
    }
bellard authored
284
285
286
287
288
289
290
291
292
    if (-1 != s->time_const) {
#if 1
        int tmp = 256 - s->time_const;
        s->freq = (1000000 + (tmp / 2)) / tmp;
#else
        /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
        s->freq = 1000000 / ((255 - s->time_const));
#endif
        s->time_const = -1;
293
294
    }
bellard authored
295
296
    s->block_size = dma_len + 1;
    s->block_size <<= (s->fmt_bits == 16);
bellard authored
297
298
299
300
301
    if (!s->dma_auto) {
        /* It is clear that for DOOM and auto-init this value
           shouldn't take stereo into account, while Miles Sound Systems
           setsound.exe with single transfer mode wouldn't work without it
           wonders of SB16 yet again */
bellard authored
302
        s->block_size <<= s->fmt_stereo;
bellard authored
303
    }
304
bellard authored
305
306
307
308
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
            "dma %d, auto %d, fifo %d, high %d\n",
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
309
bellard authored
310
311
312
    if (16 == s->fmt_bits) {
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S16;
313
314
        }
        else {
bellard authored
315
            s->fmt = AUD_FMT_U16;
316
317
318
        }
    }
    else {
bellard authored
319
320
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S8;
321
322
        }
        else {
bellard authored
323
            s->fmt = AUD_FMT_U8;
324
325
326
        }
    }
bellard authored
327
    s->left_till_irq = s->block_size;
328
bellard authored
329
330
331
    s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
    s->highspeed = 0;
    s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
332
333
334
335
    if (s->block_size & s->align) {
        dolog ("warning: misaligned block size %d, alignment %d\n",
               s->block_size, s->align + 1);
    }
336
337
    if (s->freq) {
bellard authored
338
339
        audsettings_t as;
340
        s->audio_free = 0;
bellard authored
341
342
343
344
345

        as.freq = s->freq;
        as.nchannels = 1 << s->fmt_stereo;
        as.fmt = s->fmt;
346
        s->voice = AUD_open_out (
bellard authored
347
            &s->card,
348
349
350
351
            s->voice,
            "sb16",
            s,
            SB_audio_callback,
352
353
            &as,
            0                   /* little endian */
354
355
            );
    }
356
bellard authored
357
358
    control (s, 1);
    speaker (s, 1);
359
360
}
bellard authored
361
static inline void dsp_out_data (SB16State *s, uint8_t val)
bellard authored
362
{
bellard authored
363
    ldebug ("outdata %#x\n", val);
bellard authored
364
    if ((size_t) s->out_data_len < sizeof (s->out_data)) {
bellard authored
365
        s->out_data[s->out_data_len++] = val;
366
    }
bellard authored
367
368
}
bellard authored
369
static inline uint8_t dsp_get_data (SB16State *s)
370
{
371
    if (s->in_index) {
bellard authored
372
        return s->in2_data[--s->in_index];
373
    }
bellard authored
374
375
    else {
        dolog ("buffer underflow\n");
376
        return 0;
bellard authored
377
    }
378
379
}
bellard authored
380
static void command (SB16State *s, uint8_t cmd)
381
{
bellard authored
382
    ldebug ("command %#x\n", cmd);
383
384

    if (cmd > 0xaf && cmd < 0xd0) {
bellard authored
385
386
387
        if (cmd & 8) {
            dolog ("ADC not yet supported (command %#x)\n", cmd);
        }
388
389
390
391
392
393

        switch (cmd >> 4) {
        case 11:
        case 12:
            break;
        default:
bellard authored
394
            dolog ("%#x wrong bits\n", cmd);
395
        }
bellard authored
396
        s->needed_bytes = 3;
397
398
    }
    else {
399
400
        s->needed_bytes = 0;
401
        switch (cmd) {
402
        case 0x03:
bellard authored
403
404
405
            dsp_out_data (s, 0x10); /* s->csp_param); */
            goto warn;
bellard authored
406
        case 0x04:
bellard authored
407
408
            s->needed_bytes = 1;
            goto warn;
bellard authored
409
410

        case 0x05:
bellard authored
411
412
413
414
415
416
            s->needed_bytes = 2;
            goto warn;

        case 0x08:
            /* __asm__ ("int3"); */
            goto warn;
417
bellard authored
418
        case 0x0e:
bellard authored
419
420
421
422
423
424
            s->needed_bytes = 2;
            goto warn;

        case 0x09:
            dsp_out_data (s, 0xf8);
            goto warn;
bellard authored
425
426

        case 0x0f:
bellard authored
427
428
            s->needed_bytes = 1;
            goto warn;
bellard authored
429
430
        case 0x10:
bellard authored
431
432
            s->needed_bytes = 1;
            goto warn;
433
434

        case 0x14:
bellard authored
435
436
            s->needed_bytes = 2;
            s->block_size = 0;
437
438
            break;
bellard authored
439
440
441
442
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
            control (s, 1);
            break;
bellard authored
443
444
445
        case 0x20:              /* Direct ADC, Juice/PL */
            dsp_out_data (s, 0xff);
            goto warn;
446
447

        case 0x35:
448
            dolog ("0x35 - MIDI command not implemented\n");
449
450
451
            break;

        case 0x40:
bellard authored
452
453
454
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 1;
455
456
457
            break;

        case 0x41:
bellard authored
458
459
460
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 2;
461
462
            break;
bellard authored
463
464
465
466
467
468
        case 0x42:
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 2;
            goto warn;
469
        case 0x45:
bellard authored
470
471
472
            dsp_out_data (s, 0xaa);
            goto warn;
473
474
475
476
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
            break;

        case 0x48:
bellard authored
477
            s->needed_bytes = 2;
478
479
            break;
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
        case 0x74:
            s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
            dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
            break;

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

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

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

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

        case 0x7f:
            dolog (
                "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
                );
            dolog ("not implemented\n");
            break;
512
        case 0x80:
bellard authored
513
            s->needed_bytes = 2;
514
515
516
517
            break;

        case 0x90:
        case 0x91:
bellard authored
518
519
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
            break;
520
bellard authored
521
522
523
        case 0xd0:              /* halt DMA operation. 8bit */
            control (s, 0);
            break;
524
bellard authored
525
526
        case 0xd1:              /* speaker on */
            speaker (s, 1);
527
528
            break;
bellard authored
529
530
531
        case 0xd3:              /* speaker off */
            speaker (s, 0);
            break;
532
bellard authored
533
534
        case 0xd4:              /* continue DMA operation. 8bit */
            control (s, 1);
535
536
            break;
bellard authored
537
538
        case 0xd5:              /* halt DMA operation. 16bit */
            control (s, 0);
539
540
            break;
bellard authored
541
542
        case 0xd6:              /* continue DMA operation. 16bit */
            control (s, 1);
543
544
            break;
bellard authored
545
546
547
        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
            s->dma_auto = 0;
            break;
548
bellard authored
549
550
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
            s->dma_auto = 0;
551
552
            break;
553
        case 0xe0:              /* DSP identification */
bellard authored
554
            s->needed_bytes = 1;
555
            break;
556
557

        case 0xe1:
bellard authored
558
559
560
561
562
563
564
            dsp_out_data (s, s->ver & 0xff);
            dsp_out_data (s, s->ver >> 8);
            break;

        case 0xe2:
            s->needed_bytes = 1;
            goto warn;
565
bellard authored
566
567
568
        case 0xe3:
            {
                int i;
bellard authored
569
570
                for (i = sizeof (e3) - 1; i >= 0; --i)
                    dsp_out_data (s, e3[i]);
bellard authored
571
            }
bellard authored
572
            break;
bellard authored
573
574
        case 0xe4:              /* write test reg */
bellard authored
575
            s->needed_bytes = 1;
576
577
            break;
bellard authored
578
579
        case 0xe7:
            dolog ("Attempt to probe for ESS (0xe7)?\n");
580
            break;
bellard authored
581
582
        case 0xe8:              /* read test reg */
bellard authored
583
            dsp_out_data (s, s->test_reg);
584
585
            break;
586
        case 0xf2:
bellard authored
587
588
589
590
591
        case 0xf3:
            dsp_out_data (s, 0xaa);
            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
            pic_set_irq (s->irq, 1);
            break;
592
593
        case 0xf9:
bellard authored
594
595
            s->needed_bytes = 1;
            goto warn;
596
597

        case 0xfa:
bellard authored
598
599
            dsp_out_data (s, 0);
            goto warn;
600
601

        case 0xfc:              /* FIXME */
bellard authored
602
603
            dsp_out_data (s, 0);
            goto warn;
604
605
        default:
606
607
            dolog ("Unrecognized command %#x\n", cmd);
            break;
608
609
        }
    }
bellard authored
610
611
    if (!s->needed_bytes) {
bellard authored
612
        ldebug ("\n");
613
614
615
616
617
618
619
620
621
    }

 exit:
    if (!s->needed_bytes) {
        s->cmd = -1;
    }
    else {
        s->cmd = cmd;
    }
622
623
    return;
bellard authored
624
 warn:
bellard authored
625
    dolog ("warning: command %#x,%d is not truly understood yet\n",
bellard authored
626
           cmd, s->needed_bytes);
627
628
    goto exit;
629
630
}
bellard authored
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
static uint16_t dsp_get_lohi (SB16State *s)
{
    uint8_t hi = dsp_get_data (s);
    uint8_t lo = dsp_get_data (s);
    return (hi << 8) | lo;
}

static uint16_t dsp_get_hilo (SB16State *s)
{
    uint8_t lo = dsp_get_data (s);
    uint8_t hi = dsp_get_data (s);
    return (hi << 8) | lo;
}

static void complete (SB16State *s)
646
{
647
    int d0, d1, d2;
bellard authored
648
649
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
            s->cmd, s->in_index, s->needed_bytes);
650
bellard authored
651
652
653
654
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
        d2 = dsp_get_data (s);
        d1 = dsp_get_data (s);
        d0 = dsp_get_data (s);
655
bellard authored
656
657
658
659
660
661
662
663
664
        if (s->cmd & 8) {
            dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
                   s->cmd, d0, d1, d2);
        }
        else {
            ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
                    s->cmd, d0, d1, d2);
            dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
        }
665
666
    }
    else {
bellard authored
667
        switch (s->cmd) {
bellard authored
668
        case 0x04:
bellard authored
669
670
671
672
            s->csp_mode = dsp_get_data (s);
            s->csp_reg83r = 0;
            s->csp_reg83w = 0;
            ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
673
674
            break;
bellard authored
675
676
677
678
679
680
        case 0x05:
            s->csp_param = dsp_get_data (s);
            s->csp_value = dsp_get_data (s);
            ldebug ("CSP command 0x05: param=%#x value=%#x\n",
                    s->csp_param,
                    s->csp_value);
bellard authored
681
            break;
682
683
        case 0x0e:
bellard authored
684
685
686
687
688
689
690
691
            d0 = dsp_get_data (s);
            d1 = dsp_get_data (s);
            ldebug ("write CSP register %d <- %#x\n", d1, d0);
            if (d1 == 0x83) {
                ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
                s->csp_reg83[s->csp_reg83r % 4] = d0;
                s->csp_reg83r += 1;
            }
692
            else {
bellard authored
693
                s->csp_regs[d1] = d0;
694
            }
695
696
            break;
bellard authored
697
698
699
700
701
702
703
704
705
706
707
        case 0x0f:
            d0 = dsp_get_data (s);
            ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
                    d0, s->csp_regs[d0], s->csp_mode);
            if (d0 == 0x83) {
                ldebug ("0x83[%d] -> %#x\n",
                        s->csp_reg83w,
                        s->csp_reg83[s->csp_reg83w % 4]);
                dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
                s->csp_reg83w += 1;
            }
708
            else {
bellard authored
709
                dsp_out_data (s, s->csp_regs[d0]);
710
            }
bellard authored
711
            break;
712
bellard authored
713
714
715
716
        case 0x10:
            d0 = dsp_get_data (s);
            dolog ("cmd 0x10 d0=%#x\n", d0);
            break;
717
bellard authored
718
        case 0x14:
bellard authored
719
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
bellard authored
720
            break;
721
722

        case 0x40:
bellard authored
723
724
            s->time_const = dsp_get_data (s);
            ldebug ("set time const %d\n", s->time_const);
725
726
            break;
bellard authored
727
        case 0x42:              /* FT2 sets output freq with this, go figure */
728
#if 0
bellard authored
729
            dolog ("cmd 0x42 might not do what it think it should\n");
730
#endif
bellard authored
731
732
733
        case 0x41:
            s->freq = dsp_get_hilo (s);
            ldebug ("set freq %d\n", s->freq);
734
735
736
            break;

        case 0x48:
bellard authored
737
            s->block_size = dsp_get_lohi (s) + 1;
bellard authored
738
739
740
            ldebug ("set dma block len %d\n", s->block_size);
            break;
741
742
743
744
745
746
747
        case 0x74:
        case 0x75:
        case 0x76:
        case 0x77:
            /* ADPCM stuff, ignore */
            break;
bellard authored
748
749
        case 0x80:
            {
bellard authored
750
                int freq, samples, bytes;
bellard authored
751
752
                int64_t ticks;
bellard authored
753
754
                freq = s->freq > 0 ? s->freq : 11025;
                samples = dsp_get_lohi (s) + 1;
bellard authored
755
                bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
bellard authored
756
                ticks = (bytes * ticks_per_sec) / freq;
757
                if (ticks < ticks_per_sec / 1024) {
bellard authored
758
                    pic_set_irq (s->irq, 1);
759
760
761
762
763
764
765
766
767
                }
                else {
                    if (s->aux_ts) {
                        qemu_mod_timer (
                            s->aux_ts,
                            qemu_get_clock (vm_clock) + ticks
                            );
                    }
                }
bellard authored
768
769
                ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
            }
770
771
772
            break;

        case 0xe0:
bellard authored
773
774
775
            d0 = dsp_get_data (s);
            s->out_data_len = 0;
            ldebug ("E0 data = %#x\n", d0);
776
            dsp_out_data (s, ~d0);
777
778
            break;
bellard authored
779
780
        case 0xe2:
            d0 = dsp_get_data (s);
bellard authored
781
            ldebug ("E2 = %#x\n", d0);
782
783
            break;
bellard authored
784
785
786
        case 0xe4:
            s->test_reg = dsp_get_data (s);
            break;
787
788

        case 0xf9:
bellard authored
789
790
            d0 = dsp_get_data (s);
            ldebug ("command 0xf9 with %#x\n", d0);
791
            switch (d0) {
bellard authored
792
793
794
795
796
797
798
799
            case 0x0e:
                dsp_out_data (s, 0xff);
                break;

            case 0x0f:
                dsp_out_data (s, 0x07);
                break;
800
            case 0x37:
bellard authored
801
802
803
                dsp_out_data (s, 0x38);
                break;
804
            default:
bellard authored
805
806
                dsp_out_data (s, 0x00);
                break;
807
            }
808
809
810
            break;

        default:
bellard authored
811
            dolog ("complete: unrecognized command %#x\n", s->cmd);
812
            return;
813
814
815
        }
    }
bellard authored
816
817
    ldebug ("\n");
    s->cmd = -1;
818
819
820
    return;
}
bellard authored
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
static void reset (SB16State *s)
{
    pic_set_irq (s->irq, 0);
    if (s->dma_auto) {
        pic_set_irq (s->irq, 1);
        pic_set_irq (s->irq, 0);
    }

    s->mixer_regs[0x82] = 0;
    s->dma_auto = 0;
    s->in_index = 0;
    s->out_data_len = 0;
    s->left_till_irq = 0;
    s->needed_bytes = 0;
    s->block_size = -1;
    s->nzero = 0;
    s->highspeed = 0;
    s->v2x6 = 0;
839
    s->cmd = -1;
bellard authored
840
841
842
843
844
845

    dsp_out_data(s, 0xaa);
    speaker (s, 0);
    control (s, 0);
}
846
847
static IO_WRITE_PROTO (dsp_write)
{
bellard authored
848
    SB16State *s = opaque;
849
850
    int iport;
bellard authored
851
    iport = nport - s->port;
852
bellard authored
853
    ldebug ("write %#x <- %#x\n", nport, val);
854
    switch (iport) {
bellard authored
855
856
857
858
859
860
861
862
863
    case 0x06:
        switch (val) {
        case 0x00:
            if (s->v2x6 == 1) {
                if (0 && s->highspeed) {
                    s->highspeed = 0;
                    pic_set_irq (s->irq, 0);
                    control (s, 0);
                }
864
                else {
bellard authored
865
                    reset (s);
866
                }
bellard authored
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
            }
            s->v2x6 = 0;
            break;

        case 0x01:
        case 0x03:              /* FreeBSD kludge */
            s->v2x6 = 1;
            break;

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

        case 0xb8:              /* Panic */
            reset (s);
            break;

        case 0x39:
            dsp_out_data (s, 0x38);
            reset (s);
            s->v2x6 = 0x39;
            break;

        default:
            s->v2x6 = val;
            break;
893
894
895
        }
        break;
bellard authored
896
897
898
899
900
901
902
903
904
    case 0x0c:                  /* write data or command | write status */
/*         if (s->highspeed) */
/*             break; */

        if (0 == s->needed_bytes) {
            command (s, val);
#if 0
            if (0 == s->needed_bytes) {
                log_dsp (s);
905
            }
bellard authored
906
#endif
907
908
        }
        else {
bellard authored
909
            if (s->in_index == sizeof (s->in2_data)) {
910
911
912
                dolog ("in data overrun\n");
            }
            else {
bellard authored
913
914
915
916
917
918
919
920
                s->in2_data[s->in_index++] = val;
                if (s->in_index == s->needed_bytes) {
                    s->needed_bytes = 0;
                    complete (s);
#if 0
                    log_dsp (s);
#endif
                }
921
922
923
924
925
            }
        }
        break;

    default:
bellard authored
926
        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
927
        break;
928
929
930
931
932
    }
}

static IO_READ_PROTO (dsp_read)
{
bellard authored
933
934
    SB16State *s = opaque;
    int iport, retval, ack = 0;
935
bellard authored
936
    iport = nport - s->port;
937
938

    switch (iport) {
bellard authored
939
940
    case 0x06:                  /* reset */
        retval = 0xff;
941
        break;
942
bellard authored
943
944
945
946
947
948
    case 0x0a:                  /* read data */
        if (s->out_data_len) {
            retval = s->out_data[--s->out_data_len];
            s->last_read_byte = retval;
        }
        else {
949
950
951
952
            if (s->cmd != -1) {
                dolog ("empty output buffer for command %#x\n",
                       s->cmd);
            }
bellard authored
953
            retval = s->last_read_byte;
954
            /* goto error; */
955
956
957
        }
        break;
bellard authored
958
959
    case 0x0c:                  /* 0 can write */
        retval = s->can_write ? 0 : 0x80;
960
961
        break;
bellard authored
962
963
964
965
    case 0x0d:                  /* timer interrupt clear */
        /* dolog ("timer interrupt clear\n"); */
        retval = 0;
        break;
966
bellard authored
967
968
969
970
971
972
973
    case 0x0e:                  /* data available status | irq 8 ack */
        retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
        if (s->mixer_regs[0x82] & 1) {
            ack = 1;
            s->mixer_regs[0x82] &= 1;
            pic_set_irq (s->irq, 0);
        }
974
975
        break;
bellard authored
976
    case 0x0f:                  /* irq 16 ack */
bellard authored
977
        retval = 0xff;
bellard authored
978
979
980
981
982
        if (s->mixer_regs[0x82] & 2) {
            ack = 1;
            s->mixer_regs[0x82] &= 2;
            pic_set_irq (s->irq, 0);
        }
983
984
985
986
987
988
        break;

    default:
        goto error;
    }
989
    if (!ack) {
bellard authored
990
        ldebug ("read %#x -> %#x\n", nport, retval);
991
    }
992
993
994
995

    return retval;

 error:
996
    dolog ("warning: dsp_read %#x error\n", nport);
997
    return 0xff;
998
999
}
bellard authored
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
static void reset_mixer (SB16State *s)
{
    int i;

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

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

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

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

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

    for (i = 0x30; i < 0x48; i++) {
        s->mixer_regs[i] = 0x20;
    }
}
1030
1031
static IO_WRITE_PROTO(mixer_write_indexb)
{
bellard authored
1032
    SB16State *s = opaque;
bellard authored
1033
    (void) nport;
bellard authored
1034
    s->mixer_nreg = val;
1035
1036
1037
1038
}

static IO_WRITE_PROTO(mixer_write_datab)
{
bellard authored
1039
1040
    SB16State *s = opaque;
bellard authored
1041
    (void) nport;
bellard authored
1042
    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
bellard authored
1043
bellard authored
1044
    switch (s->mixer_nreg) {
1045
    case 0x00:
bellard authored
1046
        reset_mixer (s);
1047
1048
1049
        break;

    case 0x80:
bellard authored
1050
1051
1052
        {
            int irq = irq_of_magic (val);
            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1053
            if (irq > 0) {
bellard authored
1054
                s->irq = irq;
1055
            }
bellard authored
1056
        }
1057
        break;
1058
bellard authored
1059
1060
1061
    case 0x81:
        {
            int dma, hdma;
1062
bellard authored
1063
1064
            dma = lsbindex (val & 0xf);
            hdma = lsbindex (val & 0xf0);
1065
1066
1067
1068
1069
1070
            if (dma != s->dma || hdma != s->hdma) {
                dolog (
                    "attempt to change DMA "
                    "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
                    dma, s->dma, hdma, s->hdma, val);
            }
bellard authored
1071
1072
1073
1074
1075
1076
#if 0
            s->dma = dma;
            s->hdma = hdma;
#endif
        }
        break;
1077
bellard authored
1078
1079
1080
1081
    case 0x82:
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
               val);
        return;
1082
bellard authored
1083
    default:
1084
1085
1086
        if (s->mixer_nreg >= 0x80) {
            ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
        }
bellard authored
1087
1088
1089
1090
        break;
    }

    s->mixer_regs[s->mixer_nreg] = val;
1091
1092
}
1093
1094
static IO_WRITE_PROTO(mixer_write_indexw)
{
bellard authored
1095
1096
    mixer_write_indexb (opaque, nport, val & 0xff);
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1097
1098
1099
1100
}

static IO_READ_PROTO(mixer_read)
{
bellard authored
1101
    SB16State *s = opaque;
bellard authored
1102
1103

    (void) nport;
bellard authored
1104
#ifndef DEBUG_SB16_MOST
1105
1106
1107
1108
1109
    if (s->mixer_nreg != 0x82) {
        ldebug ("mixer_read[%#x] -> %#x\n",
                s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
    }
#else
bellard authored
1110
1111
    ldebug ("mixer_read[%#x] -> %#x\n",
            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1112
#endif
bellard authored
1113
    return s->mixer_regs[s->mixer_nreg];
1114
1115
}
bellard authored
1116
1117
static int write_audio (SB16State *s, int nchan, int dma_pos,
                        int dma_len, int len)
1118
1119
{
    int temp, net;
1120
    uint8_t tmpbuf[4096];
1121
bellard authored
1122
    temp = len;
1123
1124
1125
    net = 0;

    while (temp) {
bellard authored
1126
        int left = dma_len - dma_pos;
bellard authored
1127
1128
        int copied;
        size_t to_copy;
1129
bellard authored
1130
        to_copy = audio_MIN (temp, left);
bellard authored
1131
1132
        if (to_copy > sizeof (tmpbuf)) {
            to_copy = sizeof (tmpbuf);
1133
        }
1134
bellard authored
1135
1136
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
        copied = AUD_write (s->voice, tmpbuf, copied);
1137
bellard authored
1138
1139
        temp -= copied;
        dma_pos = (dma_pos + copied) % dma_len;
1140
1141
        net += copied;
1142
        if (!copied) {
bellard authored
1143
            break;
1144
        }
1145
1146
1147
1148
1149
    }

    return net;
}
bellard authored
1150
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1151
{
bellard authored
1152
    SB16State *s = opaque;
1153
    int till, copy, written, free;
1154
bellard authored
1155
1156
    if (s->left_till_irq < 0) {
        s->left_till_irq = s->block_size;
1157
1158
    }
1159
1160
1161
1162
1163
1164
1165
1166
    if (s->voice) {
        free = s->audio_free & ~s->align;
        if ((free <= 0) || !dma_len) {
            return dma_pos;
        }
    }
    else {
        free = dma_len;
1167
1168
    }
bellard authored
1169
1170
    copy = free;
    till = s->left_till_irq;
1171
1172
#ifdef DEBUG_SB16_MOST
1173
1174
    dolog ("pos:%06d %d till:%d len:%d\n",
           dma_pos, free, till, dma_len);
1175
1176
#endif
1177
    if (till <= copy) {
bellard authored
1178
        if (0 == s->dma_auto) {
1179
1180
1181
1182
            copy = till;
        }
    }
bellard authored
1183
1184
1185
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
    dma_pos = (dma_pos + written) % dma_len;
    s->left_till_irq -= written;
1186
bellard authored
1187
1188
1189
1190
1191
1192
    if (s->left_till_irq <= 0) {
        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
        pic_set_irq (s->irq, 1);
        if (0 == s->dma_auto) {
            control (s, 0);
            speaker (s, 0);
1193
1194
1195
        }
    }
1196
#ifdef DEBUG_SB16_MOST
bellard authored
1197
1198
1199
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
            dma_pos, free, dma_len, s->left_till_irq, copy, written,
            s->block_size);
1200
#endif
1201
bellard authored
1202
1203
    while (s->left_till_irq <= 0) {
        s->left_till_irq = s->block_size + s->left_till_irq;
1204
1205
    }
bellard authored
1206
    return dma_pos;
1207
1208
}
1209
static void SB_audio_callback (void *opaque, int free)
1210
{
bellard authored
1211
    SB16State *s = opaque;
1212
    s->audio_free = free;
1213
1214
}
bellard authored
1215
static void SB_save (QEMUFile *f, void *opaque)
1216
{
bellard authored
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
    SB16State *s = opaque;

    qemu_put_be32s (f, &s->irq);
    qemu_put_be32s (f, &s->dma);
    qemu_put_be32s (f, &s->hdma);
    qemu_put_be32s (f, &s->port);
    qemu_put_be32s (f, &s->ver);
    qemu_put_be32s (f, &s->in_index);
    qemu_put_be32s (f, &s->out_data_len);
    qemu_put_be32s (f, &s->fmt_stereo);
    qemu_put_be32s (f, &s->fmt_signed);
    qemu_put_be32s (f, &s->fmt_bits);
    qemu_put_be32s (f, &s->fmt);
    qemu_put_be32s (f, &s->dma_auto);
    qemu_put_be32s (f, &s->block_size);
    qemu_put_be32s (f, &s->fifo);
    qemu_put_be32s (f, &s->freq);
    qemu_put_be32s (f, &s->time_const);
    qemu_put_be32s (f, &s->speaker);
    qemu_put_be32s (f, &s->needed_bytes);
    qemu_put_be32s (f, &s->cmd);
    qemu_put_be32s (f, &s->use_hdma);
    qemu_put_be32s (f, &s->highspeed);
    qemu_put_be32s (f, &s->can_write);
    qemu_put_be32s (f, &s->v2x6);

    qemu_put_8s (f, &s->csp_param);
    qemu_put_8s (f, &s->csp_value);
    qemu_put_8s (f, &s->csp_mode);
    qemu_put_8s (f, &s->csp_param);
    qemu_put_buffer (f, s->csp_regs, 256);
    qemu_put_8s (f, &s->csp_index);
    qemu_put_buffer (f, s->csp_reg83, 4);
    qemu_put_be32s (f, &s->csp_reg83r);
    qemu_put_be32s (f, &s->csp_reg83w);

    qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
    qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
    qemu_put_8s (f, &s->test_reg);
    qemu_put_8s (f, &s->last_read_byte);

    qemu_put_be32s (f, &s->nzero);
    qemu_put_be32s (f, &s->left_till_irq);
    qemu_put_be32s (f, &s->dma_running);
    qemu_put_be32s (f, &s->bytes_per_second);
    qemu_put_be32s (f, &s->align);

    qemu_put_be32s (f, &s->mixer_nreg);
    qemu_put_buffer (f, s->mixer_regs, 256);
1266
1267
}
bellard authored
1268
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1269
{
bellard authored
1270
1271
    SB16State *s = opaque;
1272
    if (version_id != 1) {
bellard authored
1273
        return -EINVAL;
1274
    }
bellard authored
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323

    qemu_get_be32s (f, &s->irq);
    qemu_get_be32s (f, &s->dma);
    qemu_get_be32s (f, &s->hdma);
    qemu_get_be32s (f, &s->port);
    qemu_get_be32s (f, &s->ver);
    qemu_get_be32s (f, &s->in_index);
    qemu_get_be32s (f, &s->out_data_len);
    qemu_get_be32s (f, &s->fmt_stereo);
    qemu_get_be32s (f, &s->fmt_signed);
    qemu_get_be32s (f, &s->fmt_bits);
    qemu_get_be32s (f, &s->fmt);
    qemu_get_be32s (f, &s->dma_auto);
    qemu_get_be32s (f, &s->block_size);
    qemu_get_be32s (f, &s->fifo);
    qemu_get_be32s (f, &s->freq);
    qemu_get_be32s (f, &s->time_const);
    qemu_get_be32s (f, &s->speaker);
    qemu_get_be32s (f, &s->needed_bytes);
    qemu_get_be32s (f, &s->cmd);
    qemu_get_be32s (f, &s->use_hdma);
    qemu_get_be32s (f, &s->highspeed);
    qemu_get_be32s (f, &s->can_write);
    qemu_get_be32s (f, &s->v2x6);

    qemu_get_8s (f, &s->csp_param);
    qemu_get_8s (f, &s->csp_value);
    qemu_get_8s (f, &s->csp_mode);
    qemu_get_8s (f, &s->csp_param);
    qemu_get_buffer (f, s->csp_regs, 256);
    qemu_get_8s (f, &s->csp_index);
    qemu_get_buffer (f, s->csp_reg83, 4);
    qemu_get_be32s (f, &s->csp_reg83r);
    qemu_get_be32s (f, &s->csp_reg83w);

    qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
    qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
    qemu_get_8s (f, &s->test_reg);
    qemu_get_8s (f, &s->last_read_byte);

    qemu_get_be32s (f, &s->nzero);
    qemu_get_be32s (f, &s->left_till_irq);
    qemu_get_be32s (f, &s->dma_running);
    qemu_get_be32s (f, &s->bytes_per_second);
    qemu_get_be32s (f, &s->align);

    qemu_get_be32s (f, &s->mixer_nreg);
    qemu_get_buffer (f, s->mixer_regs, 256);
1324
    if (s->voice) {
bellard authored
1325
        AUD_close_out (&s->card, s->voice);
1326
1327
        s->voice = NULL;
    }
bellard authored
1328
1329

    if (s->dma_running) {
1330
        if (s->freq) {
bellard authored
1331
1332
            audsettings_t as;
1333
            s->audio_free = 0;
bellard authored
1334
1335
1336
1337
1338

            as.freq = s->freq;
            as.nchannels = 1 << s->fmt_stereo;
            as.fmt = s->fmt;
1339
            s->voice = AUD_open_out (
bellard authored
1340
                &s->card,
1341
1342
1343
1344
                s->voice,
                "sb16",
                s,
                SB_audio_callback,
1345
1346
                &as,
                0               /* little endian */
1347
1348
                );
        }
bellard authored
1349
1350
1351

        control (s, 1);
        speaker (s, s->speaker);
1352
    }
bellard authored
1353
    return 0;
1354
1355
}
bellard authored
1356
int SB16_init (AudioState *audio)
1357
{
bellard authored
1358
    SB16State *s;
1359
1360
1361
1362
    int i;
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
bellard authored
1363
1364
1365
1366
1367
1368
1369
    if (!audio) {
        dolog ("No audio state\n");
        return -1;
    }

    s = qemu_mallocz (sizeof (*s));
    if (!s) {
bellard authored
1370
        dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
bellard authored
1371
1372
1373
1374
               sizeof (*s));
        return -1;
    }
1375
    s->cmd = -1;
bellard authored
1376
1377
1378
1379
1380
    s->irq = conf.irq;
    s->dma = conf.dma;
    s->hdma = conf.hdma;
    s->port = conf.port;
    s->ver = conf.ver_lo | (conf.ver_hi << 8);
bellard authored
1381
bellard authored
1382
1383
1384
1385
1386
1387
1388
1389
1390
    s->mixer_regs[0x80] = magic_of_irq (s->irq);
    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
    s->mixer_regs[0x82] = 2 << 5;

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

    reset_mixer (s);
    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1391
    if (!s->aux_ts) {
bellard authored
1392
        dolog ("warning: Could not create auxiliary timer\n");
1393
    }
1394
1395

    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
bellard authored
1396
        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1397
1398
1399
    }

    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
bellard authored
1400
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1401
1402
    }
bellard authored
1403
1404
1405
1406
    register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
    register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
    register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
    register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1407
bellard authored
1408
1409
1410
    DMA_register_channel (s->hdma, SB_read_DMA, s);
    DMA_register_channel (s->dma, SB_read_DMA, s);
    s->can_write = 1;
1411
bellard authored
1412
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
bellard authored
1413
1414
    AUD_register_card (audio, "sb16", &s->card);
    return 0;
1415
}