Blame view

hw/sb16.c 35.7 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;
pbrook authored
57
    qemu_irq *pic;
bellard authored
58
59
60
61
62
63
    int irq;
    int dma;
    int hdma;
    int port;
    int ver;
64
65
66
67
68
    int in_index;
    int out_data_len;
    int fmt_stereo;
    int fmt_signed;
    int fmt_bits;
bellard authored
69
    audfmt_e fmt;
70
    int dma_auto;
bellard authored
71
    int block_size;
72
73
74
75
76
77
78
    int fifo;
    int freq;
    int time_const;
    int speaker;
    int needed_bytes;
    int cmd;
    int use_hdma;
bellard authored
79
80
    int highspeed;
    int can_write;
81
82
83

    int v2x6;
bellard authored
84
85
86
87
88
89
90
91
92
    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;
93
    uint8_t in2_data[10];
bellard authored
94
95
96
97
    uint8_t out_data[50];
    uint8_t test_reg;
    uint8_t last_read_byte;
    int nzero;
98
99
100

    int left_till_irq;
bellard authored
101
102
103
    int dma_running;
    int bytes_per_second;
    int align;
104
105
    int audio_free;
    SWVoiceOut *voice;
bellard authored
106
107
    QEMUTimer *aux_ts;
108
109
    /* mixer state */
    int mixer_nreg;
bellard authored
110
    uint8_t mixer_regs[256];
111
} SB16State;
112
113
114
static void SB_audio_callback (void *opaque, int free);
bellard authored
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
149
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
150
151
static void log_dsp (SB16State *dsp)
{
bellard authored
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    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); */
168
169
}
bellard authored
170
static void control (SB16State *s, int hold)
171
{
bellard authored
172
173
174
175
176
    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);
177
    if (hold) {
bellard authored
178
        DMA_hold_DREQ (dma);
179
        AUD_set_active_out (s->voice, 1);
180
181
    }
    else {
bellard authored
182
        DMA_release_DREQ (dma);
183
        AUD_set_active_out (s->voice, 0);
184
185
186
    }
}
bellard authored
187
static void aux_timer (void *opaque)
188
{
bellard authored
189
190
    SB16State *s = opaque;
    s->can_write = 1;
pbrook authored
191
    qemu_irq_raise (s->pic[s->irq]);
bellard authored
192
193
194
195
196
}

#define DMA8_AUTO 1
#define DMA8_HIGH 2
197
198
199
200
201
202
203
204
205
206
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;
207
        as.endianness = 0;
208
209
210
211
212
213
214

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        case 0x48:
bellard authored
484
            s->needed_bytes = 2;
485
486
            break;
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
518
        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;
519
        case 0x80:
bellard authored
520
            s->needed_bytes = 2;
521
522
523
524
            break;

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

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

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

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

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

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

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

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

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

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

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

        default:
bellard authored
820
            dolog ("complete: unrecognized command %#x\n", s->cmd);
821
            return;
822
823
824
        }
    }
bellard authored
825
826
    ldebug ("\n");
    s->cmd = -1;
827
828
829
    return;
}
830
831
832
833
834
835
836
837
838
839
840
841
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;
842
    as.endianness = 0;
843
844
845
846
847
848
849

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

    /* Not sure about that... */
    /* AUD_set_active_out (s->voice, 1); */
}
bellard authored
857
858
static void reset (SB16State *s)
{
pbrook authored
859
    qemu_irq_lower (s->pic[s->irq]);
bellard authored
860
    if (s->dma_auto) {
pbrook authored
861
862
        qemu_irq_raise (s->pic[s->irq]);
        qemu_irq_lower (s->pic[s->irq]);
bellard authored
863
864
865
866
867
868
869
870
871
872
873
874
    }

    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;
875
    s->cmd = -1;
bellard authored
876
877
878
879

    dsp_out_data(s, 0xaa);
    speaker (s, 0);
    control (s, 0);
880
    legacy_reset (s);
bellard authored
881
882
}
883
884
static IO_WRITE_PROTO (dsp_write)
{
bellard authored
885
    SB16State *s = opaque;
886
887
    int iport;
bellard authored
888
    iport = nport - s->port;
889
bellard authored
890
    ldebug ("write %#x <- %#x\n", nport, val);
891
    switch (iport) {
bellard authored
892
893
894
895
896
897
    case 0x06:
        switch (val) {
        case 0x00:
            if (s->v2x6 == 1) {
                if (0 && s->highspeed) {
                    s->highspeed = 0;
pbrook authored
898
                    qemu_irq_lower (s->pic[s->irq]);
bellard authored
899
900
                    control (s, 0);
                }
901
                else {
bellard authored
902
                    reset (s);
903
                }
bellard authored
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
929
            }
            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;
930
931
932
        }
        break;
bellard authored
933
934
935
936
937
938
939
940
941
    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);
942
            }
bellard authored
943
#endif
944
945
        }
        else {
bellard authored
946
            if (s->in_index == sizeof (s->in2_data)) {
947
948
949
                dolog ("in data overrun\n");
            }
            else {
bellard authored
950
951
952
953
954
955
956
957
                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
                }
958
959
960
961
962
            }
        }
        break;

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

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

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

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

    return retval;

 error:
1033
    dolog ("warning: dsp_read %#x error\n", nport);
1034
    return 0xff;
1035
1036
}
bellard authored
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
1066
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;
    }
}
1067
1068
static IO_WRITE_PROTO(mixer_write_indexb)
{
bellard authored
1069
    SB16State *s = opaque;
bellard authored
1070
    (void) nport;
bellard authored
1071
    s->mixer_nreg = val;
1072
1073
1074
1075
}

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

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

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

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

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

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

    return net;
}
bellard authored
1187
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1188
{
bellard authored
1189
    SB16State *s = opaque;
1190
    int till, copy, written, free;
1191
bellard authored
1192
1193
    if (s->left_till_irq < 0) {
        s->left_till_irq = s->block_size;
1194
1195
    }
1196
1197
1198
1199
1200
1201
1202
1203
    if (s->voice) {
        free = s->audio_free & ~s->align;
        if ((free <= 0) || !dma_len) {
            return dma_pos;
        }
    }
    else {
        free = dma_len;
1204
1205
    }
bellard authored
1206
1207
    copy = free;
    till = s->left_till_irq;
1208
1209
#ifdef DEBUG_SB16_MOST
1210
1211
    dolog ("pos:%06d %d till:%d len:%d\n",
           dma_pos, free, till, dma_len);
1212
1213
#endif
1214
    if (till <= copy) {
bellard authored
1215
        if (0 == s->dma_auto) {
1216
1217
1218
1219
            copy = till;
        }
    }
bellard authored
1220
1221
1222
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
    dma_pos = (dma_pos + written) % dma_len;
    s->left_till_irq -= written;
1223
bellard authored
1224
1225
    if (s->left_till_irq <= 0) {
        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
pbrook authored
1226
        qemu_irq_raise (s->pic[s->irq]);
bellard authored
1227
1228
1229
        if (0 == s->dma_auto) {
            control (s, 0);
            speaker (s, 0);
1230
1231
1232
        }
    }
1233
#ifdef DEBUG_SB16_MOST
bellard authored
1234
1235
1236
    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);
1237
#endif
1238
bellard authored
1239
1240
    while (s->left_till_irq <= 0) {
        s->left_till_irq = s->block_size + s->left_till_irq;
1241
1242
    }
bellard authored
1243
    return dma_pos;
1244
1245
}
1246
static void SB_audio_callback (void *opaque, int free)
1247
{
bellard authored
1248
    SB16State *s = opaque;
1249
    s->audio_free = free;
1250
1251
}
bellard authored
1252
static void SB_save (QEMUFile *f, void *opaque)
1253
{
bellard authored
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
1302
    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);
1303
1304
}
bellard authored
1305
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1306
{
bellard authored
1307
1308
    SB16State *s = opaque;
1309
    if (version_id != 1) {
bellard authored
1310
        return -EINVAL;
1311
    }
bellard authored
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
1360

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

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

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

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

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

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

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