Blame view

hw/sb16.c 31.7 KB
1
2
3
/*
 * QEMU Soundblaster 16 emulation
 * 
bellard authored
4
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5
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
57
58
59
60
61
    int irq;
    int dma;
    int hdma;
    int port;
    int ver;
62
63
64
65
66
    int in_index;
    int out_data_len;
    int fmt_stereo;
    int fmt_signed;
    int fmt_bits;
bellard authored
67
    audfmt_e fmt;
68
    int dma_auto;
bellard authored
69
    int block_size;
70
71
72
73
74
75
76
    int fifo;
    int freq;
    int time_const;
    int speaker;
    int needed_bytes;
    int cmd;
    int use_hdma;
bellard authored
77
78
    int highspeed;
    int can_write;
79
80
81

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

    int left_till_irq;
bellard authored
99
100
101
102
103
104
    int dma_running;
    int bytes_per_second;
    int align;
    SWVoice *voice;

    QEMUTimer *ts, *aux_ts;
105
106
    /* mixer state */
    int mixer_nreg;
bellard authored
107
    uint8_t mixer_regs[256];
108
} SB16State;
109
110
111
/* XXX: suppress that and use a context */
static struct SB16State dsp;
112
bellard authored
113
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
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
148
149
static void log_dsp (SB16State *dsp)
{
bellard authored
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    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); */
166
167
}
bellard authored
168
static void control (SB16State *s, int hold)
169
{
bellard authored
170
171
172
173
174
    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);
175
    if (hold) {
bellard authored
176
177
        DMA_hold_DREQ (dma);
        AUD_enable (s->voice, 1);
178
179
    }
    else {
bellard authored
180
181
        DMA_release_DREQ (dma);
        AUD_enable (s->voice, 0);
182
183
184
    }
}
bellard authored
185
static void aux_timer (void *opaque)
186
{
bellard authored
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    SB16State *s = opaque;
    s->can_write = 1;
    pic_set_irq (s->irq, 1);
}

#define DMA8_AUTO 1
#define DMA8_HIGH 2

static void dma_cmd8 (SB16State *s, int mask, int dma_len)
{
    s->fmt = AUD_FMT_U8;
    s->use_hdma = 0;
    s->fmt_bits = 8;
    s->fmt_signed = 0;
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
    if (-1 == s->time_const) {
        s->freq = 11025;
    }
    else {
        int tmp = (256 - s->time_const);
        s->freq = (1000000 + (tmp / 2)) / tmp;
    }
bellard authored
210
211
212
213
214
215
216
217
218
219
220
221
    if (dma_len != -1)
        s->block_size = dma_len << s->fmt_stereo;
    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
222
223
224
225
226
227
228
229

    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;
bellard authored
230
231
232
    if (s->block_size & s->align)
        dolog ("warning: unaligned buffer\n");
bellard authored
233
234
235
236
237
238
239
240
241
242
243
244
    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);

    if (s->freq)
        s->voice = AUD_open (s->voice, "sb16", s->freq,
                             1 << s->fmt_stereo, s->fmt);

    control (s, 1);
    speaker (s, 1);
}
245
bellard authored
246
247
248
249
250
251
252
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;
253
254
255

    switch (cmd >> 4) {
    case 11:
bellard authored
256
        s->fmt_bits = 16;
257
258
259
        break;

    case 12:
bellard authored
260
        s->fmt_bits = 8;
261
262
263
        break;
    }
bellard authored
264
265
266
267
268
269
270
271
272
    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;
273
274
    }
bellard authored
275
276
    s->block_size = dma_len + 1;
    s->block_size <<= (s->fmt_bits == 16);
bellard authored
277
278
279
280
281
    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
282
        s->block_size <<= s->fmt_stereo;
bellard authored
283
    }
284
bellard authored
285
286
287
288
    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);
289
bellard authored
290
291
292
    if (16 == s->fmt_bits) {
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S16;
293
294
        }
        else {
bellard authored
295
            s->fmt = AUD_FMT_U16;
296
297
298
        }
    }
    else {
bellard authored
299
300
        if (s->fmt_signed) {
            s->fmt = AUD_FMT_S8;
301
302
        }
        else {
bellard authored
303
            s->fmt = AUD_FMT_U8;
304
305
306
        }
    }
bellard authored
307
    s->left_till_irq = s->block_size;
308
bellard authored
309
310
311
    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;
bellard authored
312
313
    if (s->block_size & s->align)
        dolog ("warning: unaligned buffer\n");
314
bellard authored
315
316
317
    if (s->freq)
        s->voice = AUD_open (s->voice, "sb16", s->freq,
                             1 << s->fmt_stereo, s->fmt);
318
bellard authored
319
320
    control (s, 1);
    speaker (s, 1);
321
322
}
bellard authored
323
static inline void dsp_out_data (SB16State *s, uint8_t val)
bellard authored
324
{
bellard authored
325
326
327
    ldebug ("outdata %#x\n", val);
    if (s->out_data_len < sizeof (s->out_data))
        s->out_data[s->out_data_len++] = val;
bellard authored
328
329
}
bellard authored
330
static inline uint8_t dsp_get_data (SB16State *s)
331
{
bellard authored
332
333
334
335
    if (s->in_index)
        return s->in2_data[--s->in_index];
    else {
        dolog ("buffer underflow\n");
336
        return 0;
bellard authored
337
    }
338
339
}
bellard authored
340
static void command (SB16State *s, uint8_t cmd)
341
{
bellard authored
342
    ldebug ("command %#x\n", cmd);
343
344

    if (cmd > 0xaf && cmd < 0xd0) {
bellard authored
345
346
347
        if (cmd & 8) {
            dolog ("ADC not yet supported (command %#x)\n", cmd);
        }
348
349
350
351
352
353

        switch (cmd >> 4) {
        case 11:
        case 12:
            break;
        default:
bellard authored
354
            dolog ("%#x wrong bits\n", cmd);
355
        }
bellard authored
356
        s->needed_bytes = 3;
357
358
359
    }
    else {
        switch (cmd) {
360
        case 0x03:
bellard authored
361
362
363
            dsp_out_data (s, 0x10); /* s->csp_param); */
            goto warn;
bellard authored
364
        case 0x04:
bellard authored
365
366
            s->needed_bytes = 1;
            goto warn;
bellard authored
367
368

        case 0x05:
bellard authored
369
370
371
372
373
374
            s->needed_bytes = 2;
            goto warn;

        case 0x08:
            /* __asm__ ("int3"); */
            goto warn;
375
bellard authored
376
        case 0x0e:
bellard authored
377
378
379
380
381
382
            s->needed_bytes = 2;
            goto warn;

        case 0x09:
            dsp_out_data (s, 0xf8);
            goto warn;
bellard authored
383
384

        case 0x0f:
bellard authored
385
386
            s->needed_bytes = 1;
            goto warn;
bellard authored
387
388
        case 0x10:
bellard authored
389
390
            s->needed_bytes = 1;
            goto warn;
391
392

        case 0x14:
bellard authored
393
394
            s->needed_bytes = 2;
            s->block_size = 0;
395
396
            break;
bellard authored
397
398
399
400
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
            control (s, 1);
            break;
bellard authored
401
402
403
        case 0x20:              /* Direct ADC, Juice/PL */
            dsp_out_data (s, 0xff);
            goto warn;
404
405

        case 0x35:
bellard authored
406
            dolog ("MIDI command(0x35) not implemented\n");
407
408
409
            break;

        case 0x40:
bellard authored
410
411
412
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 1;
413
414
415
            break;

        case 0x41:
bellard authored
416
417
418
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 2;
419
420
            break;
bellard authored
421
422
423
424
425
426
        case 0x42:
            s->freq = -1;
            s->time_const = -1;
            s->needed_bytes = 2;
            goto warn;
427
        case 0x45:
bellard authored
428
429
430
            dsp_out_data (s, 0xaa);
            goto warn;
431
432
433
434
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
            break;

        case 0x48:
bellard authored
435
            s->needed_bytes = 2;
436
437
438
            break;

        case 0x80:
bellard authored
439
            s->needed_bytes = 2;
440
441
442
443
            break;

        case 0x90:
        case 0x91:
bellard authored
444
445
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
            break;
446
bellard authored
447
448
449
        case 0xd0:              /* halt DMA operation. 8bit */
            control (s, 0);
            break;
450
bellard authored
451
452
        case 0xd1:              /* speaker on */
            speaker (s, 1);
453
454
            break;
bellard authored
455
456
457
        case 0xd3:              /* speaker off */
            speaker (s, 0);
            break;
458
bellard authored
459
460
        case 0xd4:              /* continue DMA operation. 8bit */
            control (s, 1);
461
462
            break;
bellard authored
463
464
        case 0xd5:              /* halt DMA operation. 16bit */
            control (s, 0);
465
466
            break;
bellard authored
467
468
        case 0xd6:              /* continue DMA operation. 16bit */
            control (s, 1);
469
470
            break;
bellard authored
471
472
473
        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
            s->dma_auto = 0;
            break;
474
bellard authored
475
476
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
            s->dma_auto = 0;
477
478
479
            break;

        case 0xe0:
bellard authored
480
481
            s->needed_bytes = 1;
            goto warn;
482
483

        case 0xe1:
bellard authored
484
485
486
487
488
489
490
            dsp_out_data (s, s->ver & 0xff);
            dsp_out_data (s, s->ver >> 8);
            break;

        case 0xe2:
            s->needed_bytes = 1;
            goto warn;
491
bellard authored
492
493
494
        case 0xe3:
            {
                int i;
bellard authored
495
496
                for (i = sizeof (e3) - 1; i >= 0; --i)
                    dsp_out_data (s, e3[i]);
bellard authored
497
            }
bellard authored
498
            break;
bellard authored
499
500
        case 0xe4:              /* write test reg */
bellard authored
501
            s->needed_bytes = 1;
502
503
            break;
bellard authored
504
505
506
507
        case 0xe7:
            dolog ("Attempt to probe for ESS (0xe7)?\n");
            return;
508
        case 0xe8:              /* read test reg */
bellard authored
509
            dsp_out_data (s, s->test_reg);
510
511
            break;
512
        case 0xf2:
bellard authored
513
514
515
516
517
        case 0xf3:
            dsp_out_data (s, 0xaa);
            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
            pic_set_irq (s->irq, 1);
            break;
518
519
        case 0xf9:
bellard authored
520
521
            s->needed_bytes = 1;
            goto warn;
522
523

        case 0xfa:
bellard authored
524
525
            dsp_out_data (s, 0);
            goto warn;
526
527

        case 0xfc:              /* FIXME */
bellard authored
528
529
            dsp_out_data (s, 0);
            goto warn;
530
531
        default:
532
            dolog ("unrecognized command %#x\n", cmd);
bellard authored
533
            return;
534
535
        }
    }
bellard authored
536
537
538
539

    s->cmd = cmd;
    if (!s->needed_bytes)
        ldebug ("\n");
540
541
    return;
bellard authored
542
 warn:
543
    dolog ("warning: command %#x,%d is not trully understood yet\n",
bellard authored
544
545
           cmd, s->needed_bytes);
    s->cmd = cmd;
546
547
548
    return;
}
bellard authored
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
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)
564
{
565
    int d0, d1, d2;
bellard authored
566
567
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
            s->cmd, s->in_index, s->needed_bytes);
568
bellard authored
569
570
571
572
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
        d2 = dsp_get_data (s);
        d1 = dsp_get_data (s);
        d0 = dsp_get_data (s);
573
bellard authored
574
575
576
577
578
579
580
581
582
        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));
        }
583
584
    }
    else {
bellard authored
585
        switch (s->cmd) {
bellard authored
586
        case 0x04:
bellard authored
587
588
589
590
            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);
591
592
            break;
bellard authored
593
594
595
596
597
598
        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
599
            break;
600
601
        case 0x0e:
bellard authored
602
603
604
605
606
607
608
609
610
611
            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;
            }
            else
                s->csp_regs[d1] = d0;
612
613
            break;
bellard authored
614
615
616
617
618
619
620
621
622
623
624
625
626
627
        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;
            }
            else
                dsp_out_data (s, s->csp_regs[d0]);
            break;
628
bellard authored
629
630
631
632
        case 0x10:
            d0 = dsp_get_data (s);
            dolog ("cmd 0x10 d0=%#x\n", d0);
            break;
633
bellard authored
634
        case 0x14:
bellard authored
635
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
bellard authored
636
            break;
637
638

        case 0x40:
bellard authored
639
640
            s->time_const = dsp_get_data (s);
            ldebug ("set time const %d\n", s->time_const);
641
642
            break;
bellard authored
643
644
        case 0x42:              /* FT2 sets output freq with this, go figure */
            dolog ("cmd 0x42 might not do what it think it should\n");
645
bellard authored
646
647
648
        case 0x41:
            s->freq = dsp_get_hilo (s);
            ldebug ("set freq %d\n", s->freq);
649
650
651
            break;

        case 0x48:
bellard authored
652
            s->block_size = dsp_get_lohi (s) + 1;
bellard authored
653
654
655
656
657
            ldebug ("set dma block len %d\n", s->block_size);
            break;

        case 0x80:
            {
bellard authored
658
                int freq, samples, bytes;
bellard authored
659
660
                int64_t ticks;
bellard authored
661
662
                freq = s->freq > 0 ? s->freq : 11025;
                samples = dsp_get_lohi (s) + 1;
bellard authored
663
                bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
bellard authored
664
665
                ticks = (bytes * ticks_per_sec) / freq;
                if (ticks < ticks_per_sec / 1024)
bellard authored
666
667
668
669
670
                    pic_set_irq (s->irq, 1);
                else
                    qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
                ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
            }
671
672
673
            break;

        case 0xe0:
bellard authored
674
675
676
677
            d0 = dsp_get_data (s);
            s->out_data_len = 0;
            ldebug ("E0 data = %#x\n", d0);
            dsp_out_data(s, ~d0);
678
679
            break;
bellard authored
680
681
        case 0xe2:
            d0 = dsp_get_data (s);
bellard authored
682
            ldebug ("E2 = %#x\n", d0);
683
684
            break;
bellard authored
685
686
687
        case 0xe4:
            s->test_reg = dsp_get_data (s);
            break;
688
689

        case 0xf9:
bellard authored
690
691
            d0 = dsp_get_data (s);
            ldebug ("command 0xf9 with %#x\n", d0);
692
            switch (d0) {
bellard authored
693
694
695
696
697
698
699
700
            case 0x0e:
                dsp_out_data (s, 0xff);
                break;

            case 0x0f:
                dsp_out_data (s, 0x07);
                break;
701
            case 0x37:
bellard authored
702
703
704
                dsp_out_data (s, 0x38);
                break;
705
            default:
bellard authored
706
707
                dsp_out_data (s, 0x00);
                break;
708
            }
709
710
711
            break;

        default:
bellard authored
712
            dolog ("complete: unrecognized command %#x\n", s->cmd);
713
            return;
714
715
716
        }
    }
bellard authored
717
718
    ldebug ("\n");
    s->cmd = -1;
719
720
721
    return;
}
bellard authored
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
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;

    dsp_out_data(s, 0xaa);
    speaker (s, 0);
    control (s, 0);
}
746
747
static IO_WRITE_PROTO (dsp_write)
{
bellard authored
748
    SB16State *s = opaque;
749
750
    int iport;
bellard authored
751
    iport = nport - s->port;
752
bellard authored
753
    ldebug ("write %#x <- %#x\n", nport, val);
754
    switch (iport) {
bellard authored
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
    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);
                }
                else
                    reset (s);
            }
            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;
792
793
794
        }
        break;
bellard authored
795
796
797
798
799
800
801
802
803
    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);
804
            }
bellard authored
805
#endif
806
807
        }
        else {
bellard authored
808
            if (s->in_index == sizeof (s->in2_data)) {
809
810
811
                dolog ("in data overrun\n");
            }
            else {
bellard authored
812
813
814
815
816
817
818
819
                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
                }
820
821
822
823
824
            }
        }
        break;

    default:
bellard authored
825
        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
826
        break;
827
828
829
830
831
    }
}

static IO_READ_PROTO (dsp_read)
{
bellard authored
832
833
    SB16State *s = opaque;
    int iport, retval, ack = 0;
834
bellard authored
835
    iport = nport - s->port;
836
837

    switch (iport) {
bellard authored
838
839
    case 0x06:                  /* reset */
        retval = 0xff;
840
        break;
841
bellard authored
842
843
844
845
846
847
    case 0x0a:                  /* read data */
        if (s->out_data_len) {
            retval = s->out_data[--s->out_data_len];
            s->last_read_byte = retval;
        }
        else {
848
            dolog ("empty output buffer\n");
bellard authored
849
            retval = s->last_read_byte;
850
            /* goto error; */
851
852
853
        }
        break;
bellard authored
854
855
    case 0x0c:                  /* 0 can write */
        retval = s->can_write ? 0 : 0x80;
856
857
        break;
bellard authored
858
859
860
861
    case 0x0d:                  /* timer interrupt clear */
        /* dolog ("timer interrupt clear\n"); */
        retval = 0;
        break;
862
bellard authored
863
864
865
866
867
868
869
    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);
        }
870
871
        break;
bellard authored
872
    case 0x0f:                  /* irq 16 ack */
bellard authored
873
        retval = 0xff;
bellard authored
874
875
876
877
878
        if (s->mixer_regs[0x82] & 2) {
            ack = 1;
            s->mixer_regs[0x82] &= 2;
            pic_set_irq (s->irq, 0);
        }
879
880
881
882
883
884
        break;

    default:
        goto error;
    }
bellard authored
885
886
    if (!ack)
        ldebug ("read %#x -> %#x\n", nport, retval);
887
888
889
890

    return retval;

 error:
bellard authored
891
    dolog ("WARNING dsp_read %#x error\n", nport);
892
    return 0xff;
893
894
}
bellard authored
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
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;
    }
}
925
926
static IO_WRITE_PROTO(mixer_write_indexb)
{
bellard authored
927
928
    SB16State *s = opaque;
    s->mixer_nreg = val;
929
930
931
932
}

static IO_WRITE_PROTO(mixer_write_datab)
{
bellard authored
933
934
935
936
937
    SB16State *s = opaque;

    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
    if (s->mixer_nreg > sizeof (s->mixer_regs))
        return;
bellard authored
938
bellard authored
939
    switch (s->mixer_nreg) {
940
    case 0x00:
bellard authored
941
        reset_mixer (s);
942
943
944
        break;

    case 0x80:
bellard authored
945
946
947
948
949
950
        {
            int irq = irq_of_magic (val);
            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
            if (irq > 0)
                s->irq = irq;
        }
951
        break;
952
bellard authored
953
954
955
    case 0x81:
        {
            int dma, hdma;
956
bellard authored
957
958
959
960
961
962
963
964
965
966
            dma = lsbindex (val & 0xf);
            hdma = lsbindex (val & 0xf0);
            dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
                   dma, hdma, val);
#if 0
            s->dma = dma;
            s->hdma = hdma;
#endif
        }
        break;
967
bellard authored
968
969
970
971
    case 0x82:
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
               val);
        return;
972
bellard authored
973
974
975
976
977
978
979
    default:
        if (s->mixer_nreg >= 0x80)
            dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
        break;
    }

    s->mixer_regs[s->mixer_nreg] = val;
980
981
}
982
983
static IO_WRITE_PROTO(mixer_write_indexw)
{
bellard authored
984
985
    mixer_write_indexb (opaque, nport, val & 0xff);
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
986
987
988
989
}

static IO_READ_PROTO(mixer_read)
{
bellard authored
990
    SB16State *s = opaque;
bellard authored
991
992
993
#ifndef DEBUG_SB16_MOST
    if (s->mixer_nreg != 0x82)
#endif
bellard authored
994
995
996
    ldebug ("mixer_read[%#x] -> %#x\n",
            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
    return s->mixer_regs[s->mixer_nreg];
997
998
}
bellard authored
999
1000
static int write_audio (SB16State *s, int nchan, int dma_pos,
                        int dma_len, int len)
1001
1002
{
    int temp, net;
1003
    uint8_t tmpbuf[4096];
1004
bellard authored
1005
    temp = len;
1006
1007
1008
    net = 0;

    while (temp) {
bellard authored
1009
1010
        int left = dma_len - dma_pos;
        int to_copy, copied;
1011
bellard authored
1012
        to_copy = audio_MIN (temp, left);
1013
1014
        if (to_copy > sizeof(tmpbuf))
            to_copy = sizeof(tmpbuf);
1015
bellard authored
1016
1017
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
        copied = AUD_write (s->voice, tmpbuf, copied);
1018
bellard authored
1019
1020
        temp -= copied;
        dma_pos = (dma_pos + copied) % dma_len;
1021
1022
        net += copied;
bellard authored
1023
1024
        if (!copied)
            break;
1025
1026
1027
1028
1029
    }

    return net;
}
bellard authored
1030
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1031
{
bellard authored
1032
1033
    SB16State *s = opaque;
    int free, rfree, till, copy, written, elapsed;
1034
bellard authored
1035
1036
    if (s->left_till_irq < 0) {
        s->left_till_irq = s->block_size;
1037
1038
    }
bellard authored
1039
1040
1041
1042
    elapsed = AUD_calc_elapsed (s->voice);
    free = elapsed;/* AUD_get_free (s->voice); */
    rfree = free;
    free = audio_MIN (free, elapsed) & ~s->align;
1043
bellard authored
1044
1045
    if ((free <= 0) || !dma_len) {
        return dma_pos;
1046
1047
    }
bellard authored
1048
1049
    copy = free;
    till = s->left_till_irq;
1050
1051
#ifdef DEBUG_SB16_MOST
bellard authored
1052
1053
    dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
           dma_pos, free, AUD_get_free (s->voice), till, dma_len);
1054
1055
#endif
1056
    if (till <= copy) {
bellard authored
1057
        if (0 == s->dma_auto) {
1058
1059
1060
1061
            copy = till;
        }
    }
bellard authored
1062
1063
1064
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
    dma_pos = (dma_pos + written) % dma_len;
    s->left_till_irq -= written;
1065
bellard authored
1066
1067
1068
1069
1070
1071
    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);
1072
1073
1074
        }
    }
1075
#ifdef DEBUG_SB16_MOST
bellard authored
1076
1077
1078
    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);
1079
#endif
1080
bellard authored
1081
1082
    while (s->left_till_irq <= 0) {
        s->left_till_irq = s->block_size + s->left_till_irq;
1083
1084
    }
bellard authored
1085
1086
    AUD_adjust (s->voice, written);
    return dma_pos;
1087
1088
}
bellard authored
1089
void SB_timer (void *opaque)
1090
{
bellard authored
1091
1092
1093
    SB16State *s = opaque;
    AUD_run ();
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
1094
1095
}
bellard authored
1096
static void SB_save (QEMUFile *f, void *opaque)
1097
{
bellard authored
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
    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);
1147
1148
}
bellard authored
1149
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1150
{
bellard authored
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
    SB16State *s = opaque;

    if (version_id != 1)
        return -EINVAL;

    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);
1204
1205
1206
1207
    if (s->voice) {
        AUD_close (s->voice);
        s->voice = NULL;
    }
bellard authored
1208
1209
1210
1211
1212
1213
1214
1215

    if (s->dma_running) {
        if (s->freq)
            s->voice = AUD_open (s->voice, "sb16", s->freq,
                                 1 << s->fmt_stereo, s->fmt);

        control (s, 1);
        speaker (s, s->speaker);
1216
    }
bellard authored
1217
    return 0;
1218
1219
}
1220
1221
void SB16_init (void)
{
1222
    SB16State *s = &dsp;
1223
1224
1225
1226
    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
1227
1228
1229
1230
1231
1232
1233
1234
1235
    s->ts = qemu_new_timer (vm_clock, SB_timer, s);
    if (!s->ts)
        return;

    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
1236
bellard authored
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
    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);
    if (!s->aux_ts)
        return;
1248
1249

    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
bellard authored
1250
        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1251
1252
1253
    }

    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
bellard authored
1254
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1255
1256
    }
bellard authored
1257
1258
1259
1260
    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);
1261
bellard authored
1262
1263
1264
    DMA_register_channel (s->hdma, SB_read_DMA, s);
    DMA_register_channel (s->dma, SB_read_DMA, s);
    s->can_write = 1;
1265
bellard authored
1266
1267
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1268
}