Statistics
| Branch: | Revision:

root / hw / sb16.c @ d64477af

History | View | Annotate | Download (16.5 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 "vl.h"
25

    
26
#define MIN(a, b) ((a)>(b)?(b):(a))
27
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
28

    
29
#define log(...) fprintf (stderr, "sb16: " __VA_ARGS__)
30

    
31
/* #define DEBUG_SB16 */
32
#ifdef DEBUG_SB16
33
#define lwarn(...) fprintf (stderr, "sb16: " __VA_ARGS__)
34
#define linfo(...) fprintf (stderr, "sb16: " __VA_ARGS__)
35
#define ldebug(...) fprintf (stderr, "sb16: " __VA_ARGS__)
36
#else
37
#define lwarn(...)
38
#define linfo(...)
39
#define ldebug(...)
40
#endif
41

    
42
#define IO_READ_PROTO(name) \
43
    uint32_t name (void *opaque, uint32_t nport)
44
#define IO_WRITE_PROTO(name) \
45
    void name (void *opaque, uint32_t nport, uint32_t val)
46

    
47
static struct {
48
    int ver_lo;
49
    int ver_hi;
50
    int irq;
51
    int dma;
52
    int hdma;
53
    int port;
54
    int mix_block;
55
} sb = {5, 4, 5, 1, 5, 0x220, -1};
56

    
57
static int mix_block, noirq;
58

    
59
typedef struct SB16State {
60
    int in_index;
61
    int out_data_len;
62
    int fmt_stereo;
63
    int fmt_signed;
64
    int fmt_bits;
65
    int dma_auto;
66
    int dma_buffer_size;
67
    int fifo;
68
    int freq;
69
    int time_const;
70
    int speaker;
71
    int needed_bytes;
72
    int cmd;
73
    int dma_pos;
74
    int use_hdma;
75

    
76
    int v2x6;
77

    
78
    uint8_t in_data[10];
79
    uint8_t out_data[10];
80

    
81
    int left_till_irq;
82

    
83
    /* mixer state */
84
    int mixer_nreg;
85
    uint8_t mixer_regs[256];
86
} SB16State;
87

    
88
/* XXX: suppress that and use a context */
89
static struct SB16State dsp;
90

    
91
static void log_dsp (SB16State *dsp)
92
{
93
    linfo ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",
94
           dsp->fmt_stereo ? 'S' : 'M',
95
           dsp->fmt_signed ? 'S' : 'U',
96
           dsp->fmt_bits,
97
           dsp->dma_auto ? 'a' : 's',
98
           dsp->dma_buffer_size,
99
           dsp->dma_pos,
100
           dsp->freq,
101
           dsp->time_const,
102
           dsp->speaker);
103
}
104

    
105
static void control (int hold)
106
{
107
    linfo ("%d high %d\n", hold, dsp.use_hdma);
108
    if (hold) {
109
        if (dsp.use_hdma)
110
            DMA_hold_DREQ (sb.hdma);
111
        else
112
            DMA_hold_DREQ (sb.dma);
113
    }
114
    else {
115
        if (dsp.use_hdma)
116
            DMA_release_DREQ (sb.hdma);
117
        else
118
            DMA_release_DREQ (sb.dma);
119
    }
120
}
121

    
122
static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)
123
{
124
    int bps;
125
    audfmt_e fmt;
126

    
127
    dsp.use_hdma = cmd < 0xc0;
128
    dsp.fifo = (cmd >> 1) & 1;
129
    dsp.dma_auto = (cmd >> 2) & 1;
130

    
131
    switch (cmd >> 4) {
132
    case 11:
133
        dsp.fmt_bits = 16;
134
        break;
135

    
136
    case 12:
137
        dsp.fmt_bits = 8;
138
        break;
139
    }
140

    
141
    dsp.fmt_signed = (d0 >> 4) & 1;
142
    dsp.fmt_stereo = (d0 >> 5) & 1;
143

    
144
    if (-1 != dsp.time_const) {
145
        int tmp;
146

    
147
        tmp = 256 - dsp.time_const;
148
        dsp.freq = (1000000 + (tmp / 2)) / tmp;
149
    }
150
    bps = 1 << (16 == dsp.fmt_bits);
151

    
152
    if (-1 != dma_len)
153
        dsp.dma_buffer_size = (dma_len + 1) * bps;
154

    
155
    linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",
156
           dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,
157
           dsp.dma_buffer_size, dsp.dma_auto);
158

    
159
    if (16 == dsp.fmt_bits) {
160
        if (dsp.fmt_signed) {
161
            fmt = AUD_FMT_S16;
162
        }
163
        else {
164
            fmt = AUD_FMT_U16;
165
        }
166
    }
167
    else {
168
        if (dsp.fmt_signed) {
169
            fmt = AUD_FMT_S8;
170
        }
171
        else {
172
            fmt = AUD_FMT_U8;
173
        }
174
    }
175

    
176
    dsp.dma_pos = 0;
177
    dsp.left_till_irq = dsp.dma_buffer_size;
178

    
179
    if (sb.mix_block) {
180
        mix_block = sb.mix_block;
181
    }
182
    else {
183
        int align;
184

    
185
        align = bps << dsp.fmt_stereo;
186
        mix_block = ((dsp.freq * align) / 100) & ~(align - 1);
187
    }
188

    
189
    AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);
190
    control (1);
191
    dsp.speaker = 1;
192
}
193

    
194
static inline void dsp_out_data(SB16State *dsp, int val)
195
{
196
    if (dsp->out_data_len < sizeof(dsp->out_data))
197
        dsp->out_data[dsp->out_data_len++] = val;
198
}
199

    
200
static void command (SB16State *dsp, uint8_t cmd)
201
{
202
    linfo ("%#x\n", cmd);
203

    
204
    if (cmd > 0xaf && cmd < 0xd0) {
205
        if (cmd & 8)
206
            goto error;
207

    
208
        switch (cmd >> 4) {
209
        case 11:
210
        case 12:
211
            break;
212
        default:
213
            log("%#x wrong bits", cmd);
214
            goto error;
215
        }
216
        dsp->needed_bytes = 3;
217
    }
218
    else {
219
        switch (cmd) {
220
        case 0x00:
221
        case 0x03:
222
        case 0xe7:
223
            /* IMS uses those when probing for sound devices */
224
            return;
225

    
226
        case 0x10:
227
            dsp->needed_bytes = 1;
228
            break;
229

    
230
        case 0x14:
231
            dsp->needed_bytes = 2;
232
            dsp->dma_buffer_size = 0;
233
            break;
234

    
235
        case 0x20:
236
            dsp_out_data(dsp, 0xff);
237
            break;
238

    
239
        case 0x35:
240
            lwarn ("MIDI commands not implemented\n");
241
            break;
242

    
243
        case 0x40:
244
            dsp->freq = -1;
245
            dsp->time_const = -1;
246
            dsp->needed_bytes = 1;
247
            break;
248

    
249
        case 0x41:
250
        case 0x42:
251
            dsp->freq = -1;
252
            dsp->time_const = -1;
253
            dsp->needed_bytes = 2;
254
            break;
255

    
256
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
257
            break;
258

    
259
        case 0x48:
260
            dsp->needed_bytes = 2;
261
            break;
262

    
263
        case 0x27:                /* ????????? */
264
        case 0x4e:
265
            return;
266

    
267
        case 0x80:
268
            cmd = -1;
269
            break;
270

    
271
        case 0x90:
272
        case 0x91:
273
            {
274
                uint8_t d0;
275

    
276
                d0 = 4;
277
                if (dsp->fmt_signed) d0 |= 16;
278
                if (dsp->fmt_stereo) d0 |= 32;
279
                dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
280
                cmd = -1;
281
                break;
282
            }
283

    
284
        case 0xd0:                /* XXX */
285
            control (0);
286
            return;
287

    
288
        case 0xd1:
289
            dsp->speaker = 1;
290
            break;
291

    
292
        case 0xd3:
293
            dsp->speaker = 0;
294
            return;
295

    
296
        case 0xd4:
297
            control (1);
298
            break;
299

    
300
        case 0xd5:
301
            control (0);
302
            break;
303

    
304
        case 0xd6:
305
            control (1);
306
            break;
307

    
308
        case 0xd9:
309
            control (0);
310
            dsp->dma_auto = 0;
311
            return;
312

    
313
        case 0xda:
314
            control (0);
315
            dsp->dma_auto = 0;
316
            break;
317

    
318
        case 0xe0:
319
            dsp->needed_bytes = 1;
320
            break;
321

    
322
        case 0xe1:
323
            dsp_out_data(dsp, sb.ver_lo);
324
            dsp_out_data(dsp, sb.ver_hi);
325
            return;
326

    
327
        case 0xf2:
328
            dsp_out_data(dsp, 0xaa);
329
            dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
330
            pic_set_irq (sb.irq, 1);
331
            return;
332

    
333
        default:
334
            log("%#x is unknown", cmd);
335
            goto error;
336
        }
337
    }
338
    dsp->cmd = cmd;
339
    return;
340

    
341
 error:
342
    return;
343
}
344

    
345
static void complete (SB16State *dsp)
346
{
347
    linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
348
           dsp->cmd, dsp->in_index, dsp->needed_bytes);
349

    
350
    if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {
351
        int d0, d1, d2;
352

    
353
        d0 = dsp->in_data[0];
354
        d1 = dsp->in_data[1];
355
        d2 = dsp->in_data[2];
356

    
357
        ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
358
                d0, d1, d2);
359
        dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));
360
    }
361
    else {
362
        switch (dsp->cmd) {
363

    
364
        case 0x10:
365
            break;
366

    
367
        case 0x14:
368
            {
369
                int d0, d1;
370
                int save_left;
371
                int save_pos;
372

    
373
                d0 = dsp->in_data[0];
374
                d1 = dsp->in_data[1];
375

    
376
                save_left = dsp->left_till_irq;
377
                save_pos = dsp->dma_pos;
378
                dma_cmd (0xc0, 0, d0 + (d1 << 8));
379
                dsp->left_till_irq = save_left;
380
                dsp->dma_pos = save_pos;
381

    
382
                linfo ("set buffer size data[%d, %d] %d pos %d\n",
383
                       d0, d1, dsp->dma_buffer_size, dsp->dma_pos);
384
                break;
385
            }
386

    
387
        case 0x40:
388
            dsp->time_const = dsp->in_data[0];
389
            linfo ("set time const %d\n", dsp->time_const);
390
            break;
391

    
392
        case 0x41:
393
        case 0x42:
394
            dsp->freq = dsp->in_data[1] + (dsp->in_data[0] << 8);
395
            linfo ("set freq %#x, %#x = %d\n",
396
                   dsp->in_data[1], dsp->in_data[0], dsp->freq);
397
            break;
398

    
399
        case 0x48:
400
            dsp->dma_buffer_size = dsp->in_data[1] + (dsp->in_data[0] << 8);
401
            linfo ("set dma len %#x, %#x = %d\n",
402
                   dsp->in_data[1], dsp->in_data[0], dsp->dma_buffer_size);
403
            break;
404

    
405
        case 0xe0:
406
            dsp->out_data_len = 0;
407
            linfo ("data = %#x\n", dsp->in_data[0]);
408
            dsp_out_data(dsp, dsp->in_data[0] ^ 0xff);
409
            break;
410

    
411
        default:
412
            log ("unrecognized command %#x", dsp->cmd);
413
            return;
414
        }
415
    }
416

    
417
    dsp->cmd = -1;
418
    return;
419
}
420

    
421
static IO_WRITE_PROTO (dsp_write)
422
{
423
    SB16State *dsp = opaque;
424
    int iport;
425

    
426
    iport = nport - sb.port;
427

    
428
    switch (iport) {
429
    case 0x6:
430
        if (0 == val)
431
            dsp->v2x6 = 0;
432
        else if ((1 == val) && (0 == dsp->v2x6)) {
433
            dsp->v2x6 = 1;
434
            dsp_out_data(dsp, 0xaa);
435
        }
436
        else
437
            dsp->v2x6 = ~0;
438
        break;
439

    
440
    case 0xc:                   /* write data or command | write status */
441
        if (0 == dsp->needed_bytes) {
442
            command (dsp, val);
443
            if (0 == dsp->needed_bytes) {
444
                log_dsp (dsp);
445
            }
446
        }
447
        else {
448
            dsp->in_data[dsp->in_index++] = val;
449
            if (dsp->in_index == dsp->needed_bytes) {
450
                dsp->needed_bytes = 0;
451
                dsp->in_index = 0;
452
                complete (dsp);
453
                log_dsp (dsp);
454
            }
455
        }
456
        break;
457

    
458
    default:
459
        log ("(nport=%#x, val=%#x)", nport, val);
460
        break;
461
    }
462
}
463

    
464
static IO_READ_PROTO (dsp_read)
465
{
466
    SB16State *dsp = opaque;
467
    int iport, retval;
468

    
469
    iport = nport - sb.port;
470

    
471
    switch (iport) {
472

    
473
    case 0x6:                   /* reset */
474
        return 0;
475

    
476
    case 0xa:                   /* read data */
477
        if (dsp->out_data_len) {
478
            retval = dsp->out_data[--dsp->out_data_len];
479
        } else {
480
            log("empty output buffer\n");
481
            goto error;
482
        }
483
        break;
484

    
485
    case 0xc:                   /* 0 can write */
486
        retval = 0;
487
        break;
488

    
489
    case 0xd:                   /* timer interrupt clear */
490
        log("timer interrupt clear\n");
491
        goto error;
492

    
493
    case 0xe:                   /* data available status | irq 8 ack */
494
        /* XXX drop pic irq line here? */
495
        ldebug ("8 ack\n");
496
        retval = (0 == dsp->out_data_len) ? 0 : 0x80;
497
        dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
498
        pic_set_irq (sb.irq, 0);
499
        break;
500

    
501
    case 0xf:                   /* irq 16 ack */
502
        /* XXX drop pic irq line here? */
503
        ldebug ("16 ack\n");
504
        retval = 0xff;
505
        dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
506
        pic_set_irq (sb.irq, 0);
507
        break;
508

    
509
    default:
510
        goto error;
511
    }
512

    
513
    if ((0xc != iport) && (0xe != iport)) {
514
        ldebug ("nport=%#x iport %#x = %#x\n",
515
                nport, iport, retval);
516
    }
517

    
518
    return retval;
519

    
520
 error:
521
    return 0;
522
}
523

    
524
static IO_WRITE_PROTO(mixer_write_indexb)
525
{
526
    SB16State *dsp = opaque;
527
    dsp->mixer_nreg = val;
528
}
529

    
530
static IO_WRITE_PROTO(mixer_write_datab)
531
{
532
    SB16State *dsp = opaque;
533

    
534
    if (dsp->mixer_nreg > 0x83)
535
        return;
536
    dsp->mixer_regs[dsp->mixer_nreg] = val;
537
}
538

    
539
static IO_WRITE_PROTO(mixer_write_indexw)
540
{
541
    mixer_write_indexb (opaque, nport, val & 0xff);
542
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
543
}
544

    
545
static IO_READ_PROTO(mixer_read)
546
{
547
    SB16State *dsp = opaque;
548
    return dsp->mixer_regs[dsp->mixer_nreg];
549
}
550

    
551
void SB16_run (void)
552
{
553
    if (0 == dsp.speaker)
554
        return;
555

    
556
    AUD_run ();
557
}
558

    
559
static int write_audio (uint32_t addr, int len, int size)
560
{
561
    int temp, net;
562
    uint8_t tmpbuf[4096];
563

    
564
    temp = size;
565

    
566
    net = 0;
567

    
568
    while (temp) {
569
        int left_till_end;
570
        int to_copy;
571
        int copied;
572

    
573
        left_till_end = len - dsp.dma_pos;
574

    
575
        to_copy = MIN (temp, left_till_end);
576
        if (to_copy > sizeof(tmpbuf))
577
            to_copy = sizeof(tmpbuf);
578
        cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);
579
        copied = AUD_write (tmpbuf, to_copy);
580

    
581
        temp -= copied;
582
        dsp.dma_pos += copied;
583

    
584
        if (dsp.dma_pos == len) {
585
            dsp.dma_pos = 0;
586
        }
587

    
588
        net += copied;
589

    
590
        if (copied != to_copy)
591
            return net;
592
    }
593

    
594
    return net;
595
}
596

    
597
static int SB_read_DMA (void *opaque, target_ulong addr, int size)
598
{
599
    SB16State *dsp = opaque;
600
    int free, till, copy, written;
601

    
602
    if (0 == dsp->speaker)
603
        return 0;
604

    
605
    if (dsp->left_till_irq < 0) {
606
        dsp->left_till_irq += dsp->dma_buffer_size;
607
        return dsp->dma_pos;
608
    }
609

    
610
    free = AUD_get_free ();
611

    
612
    if ((free <= 0) || (0 == size)) {
613
        return dsp->dma_pos;
614
    }
615

    
616
    if (mix_block > 0) {
617
        copy = MIN (free, mix_block);
618
    }
619
    else {
620
        copy = free;
621
    }
622

    
623
    till = dsp->left_till_irq;
624

    
625
    ldebug ("addr:%#010x free:%d till:%d size:%d\n",
626
            addr, free, till, size);
627
    if (till <= copy) {
628
        if (0 == dsp->dma_auto) {
629
            copy = till;
630
        }
631
    }
632

    
633
    written = write_audio (addr, size, copy);
634
    dsp->left_till_irq -= written;
635
    AUD_adjust_estimate (free - written);
636

    
637
    if (dsp->left_till_irq <= 0) {
638
        dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
639
        if (0 == noirq) {
640
            ldebug ("request irq\n");
641
            pic_set_irq(sb.irq, 1);
642
        }
643

    
644
        if (0 == dsp->dma_auto) {
645
            control (0);
646
        }
647
    }
648

    
649
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
650
            dsp->dma_pos, free, size, dsp->left_till_irq, copy,
651
            dsp->dma_buffer_size);
652

    
653
    if (dsp->left_till_irq <= 0) {
654
        dsp->left_till_irq += dsp->dma_buffer_size;
655
    }
656

    
657
    return dsp->dma_pos;
658
}
659

    
660
static int magic_of_irq (int irq)
661
{
662
    switch (irq) {
663
    case 2:
664
        return 1;
665
    case 5:
666
        return 2;
667
    case 7:
668
        return 4;
669
    case 10:
670
        return 8;
671
    default:
672
        log ("bad irq %d\n", irq);
673
        return 2;
674
    }
675
}
676

    
677
#if 0
678
static int irq_of_magic (int magic)
679
{
680
    switch (magic) {
681
    case 1:
682
        return 2;
683
    case 2:
684
        return 5;
685
    case 4:
686
        return 7;
687
    case 8:
688
        return 10;
689
    default:
690
        log ("bad irq magic %d\n", magic);
691
        return 2;
692
    }
693
}
694
#endif
695

    
696
void SB16_init (void)
697
{
698
    SB16State *s = &dsp;
699
    int i;
700
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
701
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
702

    
703
    memset(s->mixer_regs, 0xff, sizeof(s->mixer_regs));
704

    
705
    s->mixer_regs[0x0e] = ~0;
706
    s->mixer_regs[0x80] = magic_of_irq (sb.irq);
707
    s->mixer_regs[0x81] = 0x20 | (sb.dma << 1);
708

    
709
    for (i = 0x30; i < 0x48; i++) {
710
        s->mixer_regs[i] = 0x20;
711
    }
712

    
713
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
714
        register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);
715
    }
716

    
717
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
718
        register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);
719
    }
720

    
721
    register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);
722
    register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);
723
    register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);
724
    register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);
725

    
726
    DMA_register_channel (sb.hdma, SB_read_DMA, s);
727
    DMA_register_channel (sb.dma, SB_read_DMA, s);
728
}