Statistics
| Branch: | Revision:

root / hw / sb16.c @ 16f62432

History | View | Annotate | Download (16.2 kB)

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

    
28
#include "vl.h"
29

    
30
#define MIN(a, b) ((a)>(b)?(b):(a))
31
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
32

    
33
#define DEREF(x) (void)x
34
#define log(...) fprintf (stderr, "sb16: " __VA_ARGS__)
35
#define Fail(...) do {                          \
36
    fprintf (stderr, "sb16: " __VA_ARGS__);     \
37
    abort ();                                   \
38
} while (0)
39

    
40
/* #define DEBUG_SB16 */
41
#ifdef DEBUG_SB16
42
#define lwarn(...) fprintf (stderr, "sb16: " __VA_ARGS__)
43
#define linfo(...) fprintf (stderr, "sb16: " __VA_ARGS__)
44
#define ldebug(...) fprintf (stderr, "sb16: " __VA_ARGS__)
45
#else
46
#define lwarn(...)
47
#define linfo(...)
48
#define ldebug(...)
49
#endif
50

    
51
#define IO_READ_PROTO(name) \
52
    uint32_t name (struct CPUState *env, uint32_t nport)
53
#define IO_WRITE_PROTO(name) \
54
    void name (struct CPUState *env, uint32_t nport, uint32_t val)
55

    
56
static struct {
57
    int ver_lo;
58
    int ver_hi;
59
    int irq;
60
    int dma;
61
    int hdma;
62
    int port;
63
    int mix_block;
64
} sb = {5, 4, 5, 1, 5, 0x220, -1};
65

    
66
static int mix_block, noirq;
67

    
68
static struct mixer {
69
    int nreg;
70
    uint8_t regs[0x83];
71
} mixer;
72

    
73
static struct dsp {
74
    int in_index;
75
    int out_data_len;
76
    int fmt_stereo;
77
    int fmt_signed;
78
    int fmt_bits;
79
    int dma_auto;
80
    int dma_buffer_size;
81
    int fifo;
82
    int freq;
83
    int time_const;
84
    int speaker;
85
    int needed_bytes;
86
    int cmd;
87
    int dma_pos;
88
    int use_hdma;
89

    
90
    int v2x6;
91

    
92
    uint8_t in_data[10];
93
    uint8_t out_data[10];
94

    
95
    int left_till_irq;
96
} dsp;
97

    
98
#define nocmd ~0
99

    
100
static void log_dsp (const char *cap)
101
{
102
    DEREF (cap);
103

    
104
    linfo ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",
105
           dsp.fmt_stereo ? 'S' : 'M',
106
           dsp.fmt_signed ? 'S' : 'U',
107
           dsp.fmt_bits,
108
           dsp.dma_auto ? 'a' : 's',
109
           dsp.dma_buffer_size,
110
           dsp.dma_pos,
111
           dsp.freq,
112
           dsp.time_const,
113
           dsp.speaker);
114
}
115

    
116
static void control (int hold)
117
{
118
    linfo ("%d high %d\n", hold, dsp.use_hdma);
119
    if (hold) {
120
        if (dsp.use_hdma)
121
            DMA_hold_DREQ (sb.hdma);
122
        else
123
            DMA_hold_DREQ (sb.dma);
124
    }
125
    else {
126
        if (dsp.use_hdma)
127
            DMA_release_DREQ (sb.hdma);
128
        else
129
            DMA_release_DREQ (sb.dma);
130
    }
131
}
132

    
133
static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)
134
{
135
    int bps;
136
    audfmt_e fmt;
137

    
138
    dsp.use_hdma = cmd < 0xc0;
139
    dsp.fifo = (cmd >> 1) & 1;
140
    dsp.dma_auto = (cmd >> 2) & 1;
141

    
142
    switch (cmd >> 4) {
143
    case 11:
144
        dsp.fmt_bits = 16;
145
        break;
146

    
147
    case 12:
148
        dsp.fmt_bits = 8;
149
        break;
150
    }
151

    
152
    dsp.fmt_signed = (d0 >> 4) & 1;
153
    dsp.fmt_stereo = (d0 >> 5) & 1;
154

    
155
    if (-1 != dsp.time_const) {
156
        int tmp;
157

    
158
        tmp = 256 - dsp.time_const;
159
        dsp.freq = (1000000 + (tmp / 2)) / tmp;
160
    }
161
    bps = 1 << (16 == dsp.fmt_bits);
162

    
163
    if (-1 != dma_len)
164
        dsp.dma_buffer_size = (dma_len + 1) * bps;
165

    
166
    linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",
167
           dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,
168
           dsp.dma_buffer_size, dsp.dma_auto);
169

    
170
    if (16 == dsp.fmt_bits) {
171
        if (dsp.fmt_signed) {
172
            fmt = AUD_FMT_S16;
173
        }
174
        else {
175
            fmt = AUD_FMT_U16;
176
        }
177
    }
178
    else {
179
        if (dsp.fmt_signed) {
180
            fmt = AUD_FMT_S8;
181
        }
182
        else {
183
            fmt = AUD_FMT_U8;
184
        }
185
    }
186

    
187
    dsp.dma_pos = 0;
188
    dsp.left_till_irq = dsp.dma_buffer_size;
189

    
190
    if (sb.mix_block) {
191
        mix_block = sb.mix_block;
192
    }
193
    else {
194
        int align;
195

    
196
        align = bps << dsp.fmt_stereo;
197
        mix_block = ((dsp.freq * align) / 100) & ~(align - 1);
198
    }
199

    
200
    AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);
201
    control (1);
202
    dsp.speaker = 1;
203
}
204

    
205
static void command (uint8_t cmd)
206
{
207
    char *msg;
208

    
209
    msg = (char *) -1;
210

    
211
    linfo ("%#x\n", cmd);
212

    
213
    if (cmd > 0xaf && cmd < 0xd0) {
214
        if (cmd & 8)
215
            goto error;
216

    
217
        switch (cmd >> 4) {
218
        case 11:
219
        case 12:
220
            break;
221
        default:
222
            msg = "wrong bits";
223
            goto error;
224
        }
225
        dsp.needed_bytes = 3;
226
    }
227
    else {
228
        switch (cmd) {
229
        case 0x00:
230
        case 0x03:
231
        case 0xe7:
232
            /* IMS uses those when probing for sound devices */
233
            return;
234

    
235
        case 0x10:
236
            dsp.needed_bytes = 1;
237
            break;
238

    
239
        case 0x14:
240
            dsp.needed_bytes = 2;
241
            dsp.dma_buffer_size = 0;
242
            break;
243

    
244
        case 0x20:
245
            dsp.out_data[dsp.out_data_len++] = 0xff;
246
            break;
247

    
248
        case 0x35:
249
            lwarn ("MIDI commands not implemented\n");
250
            break;
251

    
252
        case 0x40:
253
            dsp.freq = -1;
254
            dsp.time_const = -1;
255
            dsp.needed_bytes = 1;
256
            break;
257

    
258
        case 0x41:
259
        case 0x42:
260
            dsp.freq = -1;
261
            dsp.time_const = -1;
262
            dsp.needed_bytes = 2;
263
            break;
264

    
265
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
266
            break;
267

    
268
        case 0x48:
269
            dsp.needed_bytes = 2;
270
            break;
271

    
272
        case 0x27:                /* ????????? */
273
        case 0x4e:
274
            return;
275

    
276
        case 0x80:
277
            cmd = nocmd;
278
            break;
279

    
280
        case 0x90:
281
        case 0x91:
282
            {
283
                uint8_t d0;
284

    
285
                d0 = 4;
286
                if (dsp.fmt_signed) d0 |= 16;
287
                if (dsp.fmt_stereo) d0 |= 32;
288
                dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
289
                cmd = nocmd;
290
                break;
291
            }
292

    
293
        case 0xd0:                /* XXX */
294
            control (0);
295
            return;
296

    
297
        case 0xd1:
298
            dsp.speaker = 1;
299
            break;
300

    
301
        case 0xd3:
302
            dsp.speaker = 0;
303
            return;
304

    
305
        case 0xd4:
306
            control (1);
307
            break;
308

    
309
        case 0xd5:
310
            control (0);
311
            break;
312

    
313
        case 0xd6:
314
            control (1);
315
            break;
316

    
317
        case 0xd9:
318
            control (0);
319
            dsp.dma_auto = 0;
320
            return;
321

    
322
        case 0xda:
323
            control (0);
324
            dsp.dma_auto = 0;
325
            break;
326

    
327
        case 0xe0:
328
            dsp.needed_bytes = 1;
329
            break;
330

    
331
        case 0xe1:
332
            dsp.out_data[dsp.out_data_len++] = sb.ver_lo;
333
            dsp.out_data[dsp.out_data_len++] = sb.ver_hi;
334
            return;
335

    
336
        case 0xf2:
337
            dsp.out_data[dsp.out_data_len++] = 0xaa;
338
            mixer.regs[0x82] |= mixer.regs[0x80];
339
            pic_set_irq (sb.irq, 1);
340
            return;
341

    
342
        default:
343
            msg = "is unknown";
344
            goto error;
345
        }
346
    }
347
    dsp.cmd = cmd;
348
    return;
349

    
350
 error:
351
    Fail ("%#x %s", cmd, msg);
352
    return;
353
}
354

    
355
static void complete (void)
356
{
357
    linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
358
           dsp.cmd, dsp.in_index, dsp.needed_bytes);
359

    
360
    if (dsp.cmd > 0xaf && dsp.cmd < 0xd0) {
361
        int d0, d1, d2;
362

    
363
        d0 = dsp.in_data[0];
364
        d1 = dsp.in_data[1];
365
        d2 = dsp.in_data[2];
366

    
367
        ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
368
                d0, d1, d2);
369
        dma_cmd (dsp.cmd, d0, d1 + (d2 << 8));
370
    }
371
    else {
372
        switch (dsp.cmd) {
373

    
374
        case 0x10:
375
            break;
376

    
377
        case 0x14:
378
            {
379
                int d0, d1;
380
                int save_left;
381
                int save_pos;
382

    
383
                d0 = dsp.in_data[0];
384
                d1 = dsp.in_data[1];
385

    
386
                save_left = dsp.left_till_irq;
387
                save_pos = dsp.dma_pos;
388
                dma_cmd (0xc0, 0, d0 + (d1 << 8));
389
                dsp.left_till_irq = save_left;
390
                dsp.dma_pos = save_pos;
391

    
392
                linfo ("set buffer size data[%d, %d] %d pos %d\n",
393
                       d0, d1, dsp.dma_buffer_size, dsp.dma_pos);
394
                break;
395
            }
396

    
397
        case 0x40:
398
            dsp.time_const = dsp.in_data[0];
399
            linfo ("set time const %d\n", dsp.time_const);
400
            break;
401

    
402
        case 0x41:
403
        case 0x42:
404
            dsp.freq = dsp.in_data[1] + (dsp.in_data[0] << 8);
405
            linfo ("set freq %#x, %#x = %d\n",
406
                   dsp.in_data[1], dsp.in_data[0], dsp.freq);
407
            break;
408

    
409
        case 0x48:
410
            dsp.dma_buffer_size = dsp.in_data[1] + (dsp.in_data[0] << 8);
411
            linfo ("set dma len %#x, %#x = %d\n",
412
                   dsp.in_data[1], dsp.in_data[0], dsp.dma_buffer_size);
413
            break;
414

    
415
        case 0xe0:
416
            dsp.out_data_len = 1;
417
            linfo ("data = %#x\n", dsp.in_data[0]);
418
            dsp.out_data[0] = dsp.in_data[0] ^ 0xff;
419
            break;
420

    
421
        default:
422
            goto error;
423
        }
424
    }
425

    
426
    dsp.cmd = -1;
427
    return;
428

    
429
 error:
430
    Fail ("unrecognized command %#x", dsp.cmd);
431
}
432

    
433
static IO_WRITE_PROTO (dsp_write)
434
{
435
    int iport;
436

    
437
    iport = nport - sb.port;
438

    
439
    switch (iport) {
440
    case 0x6:
441
        if (0 == val)
442
            dsp.v2x6 = 0;
443
        else if ((1 == val) && (0 == dsp.v2x6)) {
444
            dsp.v2x6 = 1;
445
            dsp.out_data[dsp.out_data_len++] = 0xaa;
446
        }
447
        else
448
            dsp.v2x6 = ~0;
449
        break;
450

    
451
    case 0xc:                   /* write data or command | write status */
452
        if (0 == dsp.needed_bytes) {
453
            command (val);
454
            if (0 == dsp.needed_bytes) {
455
                log_dsp (__func__);
456
            }
457
        }
458
        else {
459
            dsp.in_data[dsp.in_index++] = val;
460
            if (dsp.in_index == dsp.needed_bytes) {
461
                dsp.needed_bytes = 0;
462
                dsp.in_index = 0;
463
                complete ();
464
                log_dsp (__func__);
465
            }
466
        }
467
        break;
468

    
469
    default:
470
        Fail ("(nport=%#x, val=%#x)", nport, val);
471
    }
472
}
473

    
474
static IO_READ_PROTO (dsp_read)
475
{
476
    char *msg;
477
    int iport, retval;
478

    
479
    msg = (char *) -1;
480
    iport = nport - sb.port;
481

    
482
    switch (iport) {
483

    
484
    case 0x6:                   /* reset */
485
        return 0;
486

    
487
    case 0xa:                   /* read data */
488
        if (dsp.out_data_len) {
489
            retval = dsp.out_data[--dsp.out_data_len];
490
        }
491
        else {
492
#if 1
493
            lwarn ("empty output buffer\n");
494
            retval = 0;
495
#else
496
            msg = "empty output buffer";
497
            goto error;
498
#endif
499
        }
500
        break;
501

    
502
    case 0xc:                   /* 0 can write */
503
        retval = 0;
504
        break;
505

    
506
    case 0xd:                   /* timer interrupt clear */
507
        goto error;
508

    
509
    case 0xe:                   /* data available status | irq 8 ack */
510
        /* XXX drop pic irq line here? */
511
        ldebug ("8 ack\n");
512
        retval = (0 == dsp.out_data_len) ? 0 : 0x80;
513
        mixer.regs[0x82] &= ~mixer.regs[0x80];
514
        pic_set_irq (sb.irq, 0);
515
        break;
516

    
517
    case 0xf:                   /* irq 16 ack */
518
        /* XXX drop pic irq line here? */
519
        ldebug ("16 ack\n");
520
        retval = 0xff;
521
        mixer.regs[0x82] &= ~mixer.regs[0x80];
522
        pic_set_irq (sb.irq, 0);
523
        break;
524

    
525
    default:
526
        goto error;
527
    }
528

    
529
    if ((0xc != iport) && (0xe != iport)) {
530
        ldebug ("nport=%#x iport %#x = %#x\n",
531
                nport, iport, retval);
532
    }
533

    
534
    return retval;
535

    
536
 error:
537
    Fail ("(nport=%#x) %s",  nport, msg);
538
}
539

    
540
static IO_WRITE_PROTO(mixer_write_indexb)
541
{
542
    mixer.nreg = val & 0xff;
543
}
544

    
545
static IO_WRITE_PROTO(mixer_write_datab)
546
{
547
    mixer.regs[mixer.nreg] = val;
548
}
549

    
550
static IO_WRITE_PROTO(mixer_write_indexw)
551
{
552
    mixer_write_indexb (env, nport, val & 0xff);
553
    mixer_write_datab (env, nport, (val >> 8) & 0xff);
554
}
555

    
556
static IO_READ_PROTO(mixer_read)
557
{
558
    return mixer.regs[mixer.nreg];
559
}
560

    
561
void SB16_run (void)
562
{
563
    if (0 == dsp.speaker)
564
        return;
565

    
566
    AUD_run ();
567
}
568

    
569
static int write_audio (uint32_t addr, int len, int size)
570
{
571
    int temp, net;
572

    
573
    temp = size;
574

    
575
    net = 0;
576

    
577
    while (temp) {
578
        int left_till_end;
579
        int to_copy;
580
        int copied;
581

    
582
        left_till_end = len - dsp.dma_pos;
583

    
584
        to_copy = MIN (temp, left_till_end);
585

    
586
        copied = AUD_write ((void *) (addr + dsp.dma_pos), to_copy);
587

    
588
        temp -= copied;
589
        dsp.dma_pos += copied;
590

    
591
        if (dsp.dma_pos == len) {
592
            dsp.dma_pos = 0;
593
        }
594

    
595
        net += copied;
596

    
597
        if (copied != to_copy)
598
            return net;
599
    }
600

    
601
    return net;
602
}
603

    
604
static int SB_read_DMA (uint32_t addr, int size, int *_irq)
605
{
606
    int free, till, copy, written;
607

    
608
    if (0 == dsp.speaker)
609
        return 0;
610

    
611
    if (dsp.left_till_irq < 0) {
612
        dsp.left_till_irq += dsp.dma_buffer_size;
613
        return dsp.dma_pos;
614
    }
615

    
616
    free = AUD_get_free ();
617

    
618
    if ((free <= 0) || (0 == size)) {
619
        return dsp.dma_pos;
620
    }
621

    
622
    if (mix_block > 0) {
623
        copy = MIN (free, mix_block);
624
    }
625
    else {
626
        copy = free;
627
    }
628

    
629
    till = dsp.left_till_irq;
630

    
631
    ldebug ("addr:%#010x free:%d till:%d size:%d\n",
632
            addr, free, till, size);
633
    if (till <= copy) {
634
        if (0 == dsp.dma_auto) {
635
            copy = till;
636
        }
637
    }
638

    
639
    written = write_audio (addr, size, copy);
640
    dsp.left_till_irq -= written;
641
    AUD_adjust_estimate (free - written);
642

    
643
    if (dsp.left_till_irq <= 0) {
644
        mixer.regs[0x82] |= mixer.regs[0x80];
645
        if (0 == noirq) {
646
            ldebug ("request irq\n");
647
            *_irq = sb.irq;
648
        }
649

    
650
        if (0 == dsp.dma_auto) {
651
            control (0);
652
        }
653
    }
654

    
655
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
656
            dsp.dma_pos, free, size, dsp.left_till_irq, copy,
657
            dsp.dma_buffer_size);
658

    
659
    if (dsp.left_till_irq <= 0) {
660
        dsp.left_till_irq += dsp.dma_buffer_size;
661
    }
662

    
663
    return dsp.dma_pos;
664
}
665

    
666
static int dma_misc_handler (int moo)
667
{
668
    return -1;
669
}
670

    
671
static int magic_of_irq (int irq)
672
{
673
    switch (irq) {
674
    case 2:
675
        return 1;
676
    case 5:
677
        return 2;
678
    case 7:
679
        return 4;
680
    case 10:
681
        return 8;
682
    default:
683
        log ("bad irq %d\n", irq);
684
        return 2;
685
    }
686
}
687

    
688
static int irq_of_magic (int magic)
689
{
690
    switch (magic) {
691
    case 1:
692
        return 2;
693
    case 2:
694
        return 5;
695
    case 4:
696
        return 7;
697
    case 8:
698
        return 10;
699
    default:
700
        log ("bad irq magic %d\n", magic);
701
        return 2;
702
    }
703
}
704

    
705
void SB16_init (void)
706
{
707
    int i;
708
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
709
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
710

    
711
    mixer.regs[0x0e] = ~0;
712
    mixer.regs[0x80] = magic_of_irq (sb.irq);
713
    mixer.regs[0x81] = 0x20 | (sb.dma << 1);
714

    
715
    DEREF (irq_of_magic);
716

    
717
    for (i = 0x30; i < 0x48; i++) {
718
        mixer.regs[i] = 0x20;
719
    }
720

    
721
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
722
        register_ioport_write (sb.port + dsp_write_ports[i], 1, dsp_write, 1);
723
    }
724

    
725
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
726
        register_ioport_read (sb.port + dsp_read_ports[i], 1, dsp_read, 1);
727
    }
728

    
729
    register_ioport_write (sb.port + 0x4, 1, mixer_write_indexb, 1);
730
    register_ioport_write (sb.port + 0x4, 1, mixer_write_indexw, 2);
731
    register_ioport_read (sb.port + 0x5, 1, mixer_read, 1);
732
    register_ioport_write (sb.port + 0x5, 1, mixer_write_datab, 1);
733

    
734
    DMA_register_channel (sb.hdma, SB_read_DMA, dma_misc_handler);
735
    DMA_register_channel (sb.dma, SB_read_DMA, dma_misc_handler);
736
}