Blame view

hw/sb16.c 35.6 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
    SB16State *s = opaque;
    s->can_write = 1;
    pic_set_irq (s->irq, 1);
}

#define DMA8_AUTO 1
#define DMA8_HIGH 2
196
197
198
199
200
201
202
203
204
205
static void continue_dma8 (SB16State *s)
{
    if (s->freq > 0) {
        audsettings_t as;

        s->audio_free = 0;

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

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

    control (s, 1);
}
bellard authored
221
222
223
224
225
226
227
228
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) {
229
230
        if (s->freq <= 0)
            s->freq = 11025;
bellard authored
231
232
233
234
235
236
    }
    else {
        int tmp = (256 - s->time_const);
        s->freq = (1000000 + (tmp / 2)) / tmp;
    }
237
    if (dma_len != -1) {
bellard authored
238
        s->block_size = dma_len << s->fmt_stereo;
239
    }
bellard authored
240
241
242
243
244
245
246
247
248
249
    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
250
251
252
253
254
255
256
257

    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;
258
259
260
261
    if (s->block_size & s->align) {
        dolog ("warning: misaligned block size %d, alignment %d\n",
               s->block_size, s->align + 1);
    }
bellard authored
262
bellard authored
263
264
265
266
267
    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);
268
    continue_dma8 (s);
bellard authored
269
270
    speaker (s, 1);
}
271
bellard authored
272
273
274
275
276
277
278
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;
279
280
281

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

    case 12:
bellard authored
286
        s->fmt_bits = 8;
287
288
289
        break;
    }
bellard authored
290
291
292
293
294
295
296
297
298
    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;
299
300
    }
bellard authored
301
302
    s->block_size = dma_len + 1;
    s->block_size <<= (s->fmt_bits == 16);
bellard authored
303
304
305
306
307
    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
308
        s->block_size <<= s->fmt_stereo;
bellard authored
309
    }
310
bellard authored
311
312
313
314
    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);
315
bellard authored
316
317
318
    if (16 == s->fmt_bits) {
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S16;
319
320
        }
        else {
bellard authored
321
            s->fmt = AUD_FMT_U16;
322
323
324
        }
    }
    else {
bellard authored
325
326
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S8;
327
328
        }
        else {
bellard authored
329
            s->fmt = AUD_FMT_U8;
330
331
332
        }
    }
bellard authored
333
    s->left_till_irq = s->block_size;
334
bellard authored
335
336
337
    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;
338
339
340
341
    if (s->block_size & s->align) {
        dolog ("warning: misaligned block size %d, alignment %d\n",
               s->block_size, s->align + 1);
    }
342
343
    if (s->freq) {
bellard authored
344
345
        audsettings_t as;
346
        s->audio_free = 0;
bellard authored
347
348
349
350

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

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

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

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

        case 0x08:
            /* __asm__ ("int3"); */
            goto warn;
423
bellard authored
424
        case 0x0e:
bellard authored
425
426
427
428
429
430
            s->needed_bytes = 2;
            goto warn;

        case 0x09:
            dsp_out_data (s, 0xf8);
            goto warn;
bellard authored
431
432

        case 0x0f:
bellard authored
433
434
            s->needed_bytes = 1;
            goto warn;
bellard authored
435
436
        case 0x10:
bellard authored
437
438
            s->needed_bytes = 1;
            goto warn;
439
440

        case 0x14:
bellard authored
441
442
            s->needed_bytes = 2;
            s->block_size = 0;
443
444
            break;
bellard authored
445
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
446
            dma_cmd8 (s, DMA8_AUTO, -1);
bellard authored
447
448
            break;
bellard authored
449
450
451
        case 0x20:              /* Direct ADC, Juice/PL */
            dsp_out_data (s, 0xff);
            goto warn;
452
453

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

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

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

        case 0x48:
bellard authored
483
            s->needed_bytes = 2;
484
485
            break;
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
512
513
514
515
516
517
        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;
518
        case 0x80:
bellard authored
519
            s->needed_bytes = 2;
520
521
522
523
            break;

        case 0x90:
        case 0x91:
bellard authored
524
525
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
            break;
526
bellard authored
527
528
529
        case 0xd0:              /* halt DMA operation. 8bit */
            control (s, 0);
            break;
530
bellard authored
531
532
        case 0xd1:              /* speaker on */
            speaker (s, 1);
533
534
            break;
bellard authored
535
536
537
        case 0xd3:              /* speaker off */
            speaker (s, 0);
            break;
538
bellard authored
539
        case 0xd4:              /* continue DMA operation. 8bit */
540
541
542
            /* KQ6 (or maybe Sierras audblst.drv in general) resets
               the frequency between halt/continue */
            continue_dma8 (s);
543
544
            break;
bellard authored
545
546
        case 0xd5:              /* halt DMA operation. 16bit */
            control (s, 0);
547
548
            break;
bellard authored
549
550
        case 0xd6:              /* continue DMA operation. 16bit */
            control (s, 1);
551
552
            break;
bellard authored
553
554
555
        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
            s->dma_auto = 0;
            break;
556
bellard authored
557
558
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
            s->dma_auto = 0;
559
560
            break;
561
        case 0xe0:              /* DSP identification */
bellard authored
562
            s->needed_bytes = 1;
563
            break;
564
565

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

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

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

        case 0xfc:              /* FIXME */
bellard authored
610
611
            dsp_out_data (s, 0);
            goto warn;
612
613
        default:
614
615
            dolog ("Unrecognized command %#x\n", cmd);
            break;
616
617
        }
    }
bellard authored
618
619
    if (!s->needed_bytes) {
bellard authored
620
        ldebug ("\n");
621
622
623
624
625
626
627
628
629
    }

 exit:
    if (!s->needed_bytes) {
        s->cmd = -1;
    }
    else {
        s->cmd = cmd;
    }
630
631
    return;
bellard authored
632
 warn:
bellard authored
633
    dolog ("warning: command %#x,%d is not truly understood yet\n",
bellard authored
634
           cmd, s->needed_bytes);
635
636
    goto exit;
637
638
}
bellard authored
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
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)
654
{
655
    int d0, d1, d2;
bellard authored
656
657
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
            s->cmd, s->in_index, s->needed_bytes);
658
bellard authored
659
660
661
662
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
        d2 = dsp_get_data (s);
        d1 = dsp_get_data (s);
        d0 = dsp_get_data (s);
663
bellard authored
664
665
666
667
668
669
670
671
672
        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));
        }
673
674
    }
    else {
bellard authored
675
        switch (s->cmd) {
bellard authored
676
        case 0x04:
bellard authored
677
678
679
680
            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);
681
682
            break;
bellard authored
683
684
685
686
687
688
        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
689
            break;
690
691
        case 0x0e:
bellard authored
692
693
694
695
696
697
698
699
            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;
            }
700
            else {
bellard authored
701
                s->csp_regs[d1] = d0;
702
            }
703
704
            break;
bellard authored
705
706
707
708
709
710
711
712
713
714
715
        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;
            }
716
            else {
bellard authored
717
                dsp_out_data (s, s->csp_regs[d0]);
718
            }
bellard authored
719
            break;
720
bellard authored
721
722
723
724
        case 0x10:
            d0 = dsp_get_data (s);
            dolog ("cmd 0x10 d0=%#x\n", d0);
            break;
725
bellard authored
726
        case 0x14:
bellard authored
727
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
bellard authored
728
            break;
729
730

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

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

        case 0xe0:
bellard authored
781
782
783
            d0 = dsp_get_data (s);
            s->out_data_len = 0;
            ldebug ("E0 data = %#x\n", d0);
784
            dsp_out_data (s, ~d0);
785
786
            break;
bellard authored
787
788
        case 0xe2:
            d0 = dsp_get_data (s);
bellard authored
789
            ldebug ("E2 = %#x\n", d0);
790
791
            break;
bellard authored
792
793
794
        case 0xe4:
            s->test_reg = dsp_get_data (s);
            break;
795
796

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

            case 0x0f:
                dsp_out_data (s, 0x07);
                break;
808
            case 0x37:
bellard authored
809
810
811
                dsp_out_data (s, 0x38);
                break;
812
            default:
bellard authored
813
814
                dsp_out_data (s, 0x00);
                break;
815
            }
816
817
818
            break;

        default:
bellard authored
819
            dolog ("complete: unrecognized command %#x\n", s->cmd);
820
            return;
821
822
823
        }
    }
bellard authored
824
825
    ldebug ("\n");
    s->cmd = -1;
826
827
828
    return;
}
829
830
831
832
833
834
835
836
837
838
839
840
static void legacy_reset (SB16State *s)
{
    audsettings_t as;

    s->freq = 11025;
    s->fmt_signed = 0;
    s->fmt_bits = 8;
    s->fmt_stereo = 0;

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

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

    /* Not sure about that... */
    /* AUD_set_active_out (s->voice, 1); */
}
bellard authored
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
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;
874
    s->cmd = -1;
bellard authored
875
876
877
878

    dsp_out_data(s, 0xaa);
    speaker (s, 0);
    control (s, 0);
879
    legacy_reset (s);
bellard authored
880
881
}
882
883
static IO_WRITE_PROTO (dsp_write)
{
bellard authored
884
    SB16State *s = opaque;
885
886
    int iport;
bellard authored
887
    iport = nport - s->port;
888
bellard authored
889
    ldebug ("write %#x <- %#x\n", nport, val);
890
    switch (iport) {
bellard authored
891
892
893
894
895
896
897
898
899
    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);
                }
900
                else {
bellard authored
901
                    reset (s);
902
                }
bellard authored
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
            }
            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;
929
930
931
        }
        break;
bellard authored
932
933
934
935
936
937
938
939
940
    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);
941
            }
bellard authored
942
#endif
943
944
        }
        else {
bellard authored
945
            if (s->in_index == sizeof (s->in2_data)) {
946
947
948
                dolog ("in data overrun\n");
            }
            else {
bellard authored
949
950
951
952
953
954
955
956
                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
                }
957
958
959
960
961
            }
        }
        break;

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

static IO_READ_PROTO (dsp_read)
{
bellard authored
969
970
    SB16State *s = opaque;
    int iport, retval, ack = 0;
971
bellard authored
972
    iport = nport - s->port;
973
974

    switch (iport) {
bellard authored
975
976
    case 0x06:                  /* reset */
        retval = 0xff;
977
        break;
978
bellard authored
979
980
981
982
983
984
    case 0x0a:                  /* read data */
        if (s->out_data_len) {
            retval = s->out_data[--s->out_data_len];
            s->last_read_byte = retval;
        }
        else {
985
986
987
988
            if (s->cmd != -1) {
                dolog ("empty output buffer for command %#x\n",
                       s->cmd);
            }
bellard authored
989
            retval = s->last_read_byte;
990
            /* goto error; */
991
992
993
        }
        break;
bellard authored
994
995
    case 0x0c:                  /* 0 can write */
        retval = s->can_write ? 0 : 0x80;
996
997
        break;
bellard authored
998
999
1000
1001
    case 0x0d:                  /* timer interrupt clear */
        /* dolog ("timer interrupt clear\n"); */
        retval = 0;
        break;
1002
bellard authored
1003
1004
1005
1006
1007
1008
1009
    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);
        }
1010
1011
        break;
bellard authored
1012
    case 0x0f:                  /* irq 16 ack */
bellard authored
1013
        retval = 0xff;
bellard authored
1014
1015
1016
1017
1018
        if (s->mixer_regs[0x82] & 2) {
            ack = 1;
            s->mixer_regs[0x82] &= 2;
            pic_set_irq (s->irq, 0);
        }
1019
1020
1021
1022
1023
1024
        break;

    default:
        goto error;
    }
1025
    if (!ack) {
bellard authored
1026
        ldebug ("read %#x -> %#x\n", nport, retval);
1027
    }
1028
1029
1030
1031

    return retval;

 error:
1032
    dolog ("warning: dsp_read %#x error\n", nport);
1033
    return 0xff;
1034
1035
}
bellard authored
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
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;
    }
}
1066
1067
static IO_WRITE_PROTO(mixer_write_indexb)
{
bellard authored
1068
    SB16State *s = opaque;
bellard authored
1069
    (void) nport;
bellard authored
1070
    s->mixer_nreg = val;
1071
1072
1073
1074
}

static IO_WRITE_PROTO(mixer_write_datab)
{
bellard authored
1075
1076
    SB16State *s = opaque;
bellard authored
1077
    (void) nport;
bellard authored
1078
    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
bellard authored
1079
bellard authored
1080
    switch (s->mixer_nreg) {
1081
    case 0x00:
bellard authored
1082
        reset_mixer (s);
1083
1084
1085
        break;

    case 0x80:
bellard authored
1086
1087
1088
        {
            int irq = irq_of_magic (val);
            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1089
            if (irq > 0) {
bellard authored
1090
                s->irq = irq;
1091
            }
bellard authored
1092
        }
1093
        break;
1094
bellard authored
1095
1096
1097
    case 0x81:
        {
            int dma, hdma;
1098
bellard authored
1099
1100
            dma = lsbindex (val & 0xf);
            hdma = lsbindex (val & 0xf0);
1101
1102
1103
1104
1105
1106
            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
1107
1108
1109
1110
1111
1112
#if 0
            s->dma = dma;
            s->hdma = hdma;
#endif
        }
        break;
1113
bellard authored
1114
1115
1116
1117
    case 0x82:
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
               val);
        return;
1118
bellard authored
1119
    default:
1120
1121
1122
        if (s->mixer_nreg >= 0x80) {
            ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
        }
bellard authored
1123
1124
1125
1126
        break;
    }

    s->mixer_regs[s->mixer_nreg] = val;
1127
1128
}
1129
1130
static IO_WRITE_PROTO(mixer_write_indexw)
{
bellard authored
1131
1132
    mixer_write_indexb (opaque, nport, val & 0xff);
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1133
1134
1135
1136
}

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

    (void) nport;
bellard authored
1140
#ifndef DEBUG_SB16_MOST
1141
1142
1143
1144
1145
    if (s->mixer_nreg != 0x82) {
        ldebug ("mixer_read[%#x] -> %#x\n",
                s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
    }
#else
bellard authored
1146
1147
    ldebug ("mixer_read[%#x] -> %#x\n",
            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1148
#endif
bellard authored
1149
    return s->mixer_regs[s->mixer_nreg];
1150
1151
}
bellard authored
1152
1153
static int write_audio (SB16State *s, int nchan, int dma_pos,
                        int dma_len, int len)
1154
1155
{
    int temp, net;
1156
    uint8_t tmpbuf[4096];
1157
bellard authored
1158
    temp = len;
1159
1160
1161
    net = 0;

    while (temp) {
bellard authored
1162
        int left = dma_len - dma_pos;
bellard authored
1163
1164
        int copied;
        size_t to_copy;
1165
bellard authored
1166
        to_copy = audio_MIN (temp, left);
bellard authored
1167
1168
        if (to_copy > sizeof (tmpbuf)) {
            to_copy = sizeof (tmpbuf);
1169
        }
1170
bellard authored
1171
1172
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
        copied = AUD_write (s->voice, tmpbuf, copied);
1173
bellard authored
1174
1175
        temp -= copied;
        dma_pos = (dma_pos + copied) % dma_len;
1176
1177
        net += copied;
1178
        if (!copied) {
bellard authored
1179
            break;
1180
        }
1181
1182
1183
1184
1185
    }

    return net;
}
bellard authored
1186
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1187
{
bellard authored
1188
    SB16State *s = opaque;
1189
    int till, copy, written, free;
1190
bellard authored
1191
1192
    if (s->left_till_irq < 0) {
        s->left_till_irq = s->block_size;
1193
1194
    }
1195
1196
1197
1198
1199
1200
1201
1202
    if (s->voice) {
        free = s->audio_free & ~s->align;
        if ((free <= 0) || !dma_len) {
            return dma_pos;
        }
    }
    else {
        free = dma_len;
1203
1204
    }
bellard authored
1205
1206
    copy = free;
    till = s->left_till_irq;
1207
1208
#ifdef DEBUG_SB16_MOST
1209
1210
    dolog ("pos:%06d %d till:%d len:%d\n",
           dma_pos, free, till, dma_len);
1211
1212
#endif
1213
    if (till <= copy) {
bellard authored
1214
        if (0 == s->dma_auto) {
1215
1216
1217
1218
            copy = till;
        }
    }
bellard authored
1219
1220
1221
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
    dma_pos = (dma_pos + written) % dma_len;
    s->left_till_irq -= written;
1222
bellard authored
1223
1224
1225
1226
1227
1228
    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);
1229
1230
1231
        }
    }
1232
#ifdef DEBUG_SB16_MOST
bellard authored
1233
1234
1235
    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);
1236
#endif
1237
bellard authored
1238
1239
    while (s->left_till_irq <= 0) {
        s->left_till_irq = s->block_size + s->left_till_irq;
1240
1241
    }
bellard authored
1242
    return dma_pos;
1243
1244
}
1245
static void SB_audio_callback (void *opaque, int free)
1246
{
bellard authored
1247
    SB16State *s = opaque;
1248
    s->audio_free = free;
1249
1250
}
bellard authored
1251
static void SB_save (QEMUFile *f, void *opaque)
1252
{
bellard authored
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
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
    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);
1302
1303
}
bellard authored
1304
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1305
{
bellard authored
1306
1307
    SB16State *s = opaque;
1308
    if (version_id != 1) {
bellard authored
1309
        return -EINVAL;
1310
    }
bellard authored
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359

    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);
1360
    if (s->voice) {
bellard authored
1361
        AUD_close_out (&s->card, s->voice);
1362
1363
        s->voice = NULL;
    }
bellard authored
1364
1365

    if (s->dma_running) {
1366
        if (s->freq) {
bellard authored
1367
1368
            audsettings_t as;
1369
            s->audio_free = 0;
bellard authored
1370
1371
1372
1373

            as.freq = s->freq;
            as.nchannels = 1 << s->fmt_stereo;
            as.fmt = s->fmt;
1374
            as.endianness = 0;
bellard authored
1375
1376
            s->voice = AUD_open_out (
bellard authored
1377
                &s->card,
1378
1379
1380
1381
                s->voice,
                "sb16",
                s,
                SB_audio_callback,
1382
                &as
1383
1384
                );
        }
bellard authored
1385
1386
1387

        control (s, 1);
        speaker (s, s->speaker);
1388
    }
bellard authored
1389
    return 0;
1390
1391
}
bellard authored
1392
int SB16_init (AudioState *audio)
1393
{
bellard authored
1394
    SB16State *s;
1395
1396
1397
1398
    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
1399
1400
1401
1402
1403
1404
1405
    if (!audio) {
        dolog ("No audio state\n");
        return -1;
    }

    s = qemu_mallocz (sizeof (*s));
    if (!s) {
bellard authored
1406
        dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
bellard authored
1407
1408
1409
1410
               sizeof (*s));
        return -1;
    }
1411
    s->cmd = -1;
bellard authored
1412
1413
1414
1415
1416
    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
1417
bellard authored
1418
1419
1420
1421
1422
1423
1424
1425
1426
    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);
1427
    if (!s->aux_ts) {
bellard authored
1428
        dolog ("warning: Could not create auxiliary timer\n");
1429
    }
1430
1431

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

    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
bellard authored
1436
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1437
1438
    }
bellard authored
1439
1440
1441
1442
    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);
1443
bellard authored
1444
1445
1446
    DMA_register_channel (s->hdma, SB_read_DMA, s);
    DMA_register_channel (s->dma, SB_read_DMA, s);
    s->can_write = 1;
1447
bellard authored
1448
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
bellard authored
1449
1450
    AUD_register_card (audio, "sb16", &s->card);
    return 0;
1451
}