Statistics
| Branch: | Revision:

root / hw / sb16.c @ 67b915a5

History | View | Annotate | Download (16.4 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 DEREF(x) (void)x
30
#define log(...) fprintf (stderr, "sb16: " __VA_ARGS__)
31

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

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

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

    
58
static int mix_block, noirq;
59

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

    
77
    int v2x6;
78

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

    
82
    int left_till_irq;
83

    
84
    /* mixer state */
85
    int mixer_nreg;
86
    uint8_t mixer_regs[0x83];
87
} SB16State;
88

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
195
static void command (SB16State *dsp, uint8_t cmd)
196
{
197
    linfo ("%#x\n", cmd);
198

    
199
    if (cmd > 0xaf && cmd < 0xd0) {
200
        if (cmd & 8)
201
            goto error;
202

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

    
221
        case 0x10:
222
            dsp->needed_bytes = 1;
223
            break;
224

    
225
        case 0x14:
226
            dsp->needed_bytes = 2;
227
            dsp->dma_buffer_size = 0;
228
            break;
229

    
230
        case 0x20:
231
            dsp->out_data[dsp->out_data_len++] = 0xff;
232
            break;
233

    
234
        case 0x35:
235
            lwarn ("MIDI commands not implemented\n");
236
            break;
237

    
238
        case 0x40:
239
            dsp->freq = -1;
240
            dsp->time_const = -1;
241
            dsp->needed_bytes = 1;
242
            break;
243

    
244
        case 0x41:
245
        case 0x42:
246
            dsp->freq = -1;
247
            dsp->time_const = -1;
248
            dsp->needed_bytes = 2;
249
            break;
250

    
251
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
252
            break;
253

    
254
        case 0x48:
255
            dsp->needed_bytes = 2;
256
            break;
257

    
258
        case 0x27:                /* ????????? */
259
        case 0x4e:
260
            return;
261

    
262
        case 0x80:
263
            cmd = -1;
264
            break;
265

    
266
        case 0x90:
267
        case 0x91:
268
            {
269
                uint8_t d0;
270

    
271
                d0 = 4;
272
                if (dsp->fmt_signed) d0 |= 16;
273
                if (dsp->fmt_stereo) d0 |= 32;
274
                dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
275
                cmd = -1;
276
                break;
277
            }
278

    
279
        case 0xd0:                /* XXX */
280
            control (0);
281
            return;
282

    
283
        case 0xd1:
284
            dsp->speaker = 1;
285
            break;
286

    
287
        case 0xd3:
288
            dsp->speaker = 0;
289
            return;
290

    
291
        case 0xd4:
292
            control (1);
293
            break;
294

    
295
        case 0xd5:
296
            control (0);
297
            break;
298

    
299
        case 0xd6:
300
            control (1);
301
            break;
302

    
303
        case 0xd9:
304
            control (0);
305
            dsp->dma_auto = 0;
306
            return;
307

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

    
313
        case 0xe0:
314
            dsp->needed_bytes = 1;
315
            break;
316

    
317
        case 0xe1:
318
            dsp->out_data[dsp->out_data_len++] = sb.ver_lo;
319
            dsp->out_data[dsp->out_data_len++] = sb.ver_hi;
320
            return;
321

    
322
        case 0xf2:
323
            dsp->out_data[dsp->out_data_len++] = 0xaa;
324
            dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
325
            pic_set_irq (sb.irq, 1);
326
            return;
327

    
328
        default:
329
            log("%#x is unknown", cmd);
330
            goto error;
331
        }
332
    }
333
    dsp->cmd = cmd;
334
    return;
335

    
336
 error:
337
    return;
338
}
339

    
340
static void complete (SB16State *dsp)
341
{
342
    linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
343
           dsp->cmd, dsp->in_index, dsp->needed_bytes);
344

    
345
    if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {
346
        int d0, d1, d2;
347

    
348
        d0 = dsp->in_data[0];
349
        d1 = dsp->in_data[1];
350
        d2 = dsp->in_data[2];
351

    
352
        ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
353
                d0, d1, d2);
354
        dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));
355
    }
356
    else {
357
        switch (dsp->cmd) {
358

    
359
        case 0x10:
360
            break;
361

    
362
        case 0x14:
363
            {
364
                int d0, d1;
365
                int save_left;
366
                int save_pos;
367

    
368
                d0 = dsp->in_data[0];
369
                d1 = dsp->in_data[1];
370

    
371
                save_left = dsp->left_till_irq;
372
                save_pos = dsp->dma_pos;
373
                dma_cmd (0xc0, 0, d0 + (d1 << 8));
374
                dsp->left_till_irq = save_left;
375
                dsp->dma_pos = save_pos;
376

    
377
                linfo ("set buffer size data[%d, %d] %d pos %d\n",
378
                       d0, d1, dsp->dma_buffer_size, dsp->dma_pos);
379
                break;
380
            }
381

    
382
        case 0x40:
383
            dsp->time_const = dsp->in_data[0];
384
            linfo ("set time const %d\n", dsp->time_const);
385
            break;
386

    
387
        case 0x41:
388
        case 0x42:
389
            dsp->freq = dsp->in_data[1] + (dsp->in_data[0] << 8);
390
            linfo ("set freq %#x, %#x = %d\n",
391
                   dsp->in_data[1], dsp->in_data[0], dsp->freq);
392
            break;
393

    
394
        case 0x48:
395
            dsp->dma_buffer_size = dsp->in_data[1] + (dsp->in_data[0] << 8);
396
            linfo ("set dma len %#x, %#x = %d\n",
397
                   dsp->in_data[1], dsp->in_data[0], dsp->dma_buffer_size);
398
            break;
399

    
400
        case 0xe0:
401
            dsp->out_data_len = 1;
402
            linfo ("data = %#x\n", dsp->in_data[0]);
403
            dsp->out_data[0] = dsp->in_data[0] ^ 0xff;
404
            break;
405

    
406
        default:
407
            log ("unrecognized command %#x", dsp->cmd);
408
            return;
409
        }
410
    }
411

    
412
    dsp->cmd = -1;
413
    return;
414
}
415

    
416
static IO_WRITE_PROTO (dsp_write)
417
{
418
    SB16State *dsp = opaque;
419
    int iport;
420

    
421
    iport = nport - sb.port;
422

    
423
    switch (iport) {
424
    case 0x6:
425
        if (0 == val)
426
            dsp->v2x6 = 0;
427
        else if ((1 == val) && (0 == dsp->v2x6)) {
428
            dsp->v2x6 = 1;
429
            dsp->out_data[dsp->out_data_len++] = 0xaa;
430
        }
431
        else
432
            dsp->v2x6 = ~0;
433
        break;
434

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

    
453
    default:
454
        log ("(nport=%#x, val=%#x)", nport, val);
455
        break;
456
    }
457
}
458

    
459
static IO_READ_PROTO (dsp_read)
460
{
461
    SB16State *dsp = opaque;
462
    int iport, retval;
463

    
464
    iport = nport - sb.port;
465

    
466
    switch (iport) {
467

    
468
    case 0x6:                   /* reset */
469
        return 0;
470

    
471
    case 0xa:                   /* read data */
472
        if (dsp->out_data_len) {
473
            retval = dsp->out_data[--dsp->out_data_len];
474
        } else {
475
            log("empty output buffer\n");
476
            goto error;
477
        }
478
        break;
479

    
480
    case 0xc:                   /* 0 can write */
481
        retval = 0;
482
        break;
483

    
484
    case 0xd:                   /* timer interrupt clear */
485
        log("timer interrupt clear\n");
486
        goto error;
487

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

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

    
504
    default:
505
        goto error;
506
    }
507

    
508
    if ((0xc != iport) && (0xe != iport)) {
509
        ldebug ("nport=%#x iport %#x = %#x\n",
510
                nport, iport, retval);
511
    }
512

    
513
    return retval;
514

    
515
 error:
516
    return 0;
517
}
518

    
519
static IO_WRITE_PROTO(mixer_write_indexb)
520
{
521
    SB16State *dsp = opaque;
522
    dsp->mixer_nreg = val & 0xff;
523
}
524

    
525
static IO_WRITE_PROTO(mixer_write_datab)
526
{
527
    SB16State *dsp = opaque;
528
    dsp->mixer_regs[dsp->mixer_nreg] = val;
529
}
530

    
531
static IO_WRITE_PROTO(mixer_write_indexw)
532
{
533
    mixer_write_indexb (opaque, nport, val & 0xff);
534
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
535
}
536

    
537
static IO_READ_PROTO(mixer_read)
538
{
539
    SB16State *dsp = opaque;
540
    return dsp->mixer_regs[dsp->mixer_nreg];
541
}
542

    
543
void SB16_run (void)
544
{
545
    if (0 == dsp.speaker)
546
        return;
547

    
548
    AUD_run ();
549
}
550

    
551
static int write_audio (uint32_t addr, int len, int size)
552
{
553
    int temp, net;
554
    uint8_t tmpbuf[4096];
555

    
556
    temp = size;
557

    
558
    net = 0;
559

    
560
    while (temp) {
561
        int left_till_end;
562
        int to_copy;
563
        int copied;
564

    
565
        left_till_end = len - dsp.dma_pos;
566

    
567
        to_copy = MIN (temp, left_till_end);
568
        if (to_copy > sizeof(tmpbuf))
569
            to_copy = sizeof(tmpbuf);
570
        cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);
571
        copied = AUD_write (tmpbuf, to_copy);
572

    
573
        temp -= copied;
574
        dsp.dma_pos += copied;
575

    
576
        if (dsp.dma_pos == len) {
577
            dsp.dma_pos = 0;
578
        }
579

    
580
        net += copied;
581

    
582
        if (copied != to_copy)
583
            return net;
584
    }
585

    
586
    return net;
587
}
588

    
589
static int SB_read_DMA (void *opaque, target_ulong addr, int size)
590
{
591
    SB16State *dsp = opaque;
592
    int free, till, copy, written;
593

    
594
    if (0 == dsp->speaker)
595
        return 0;
596

    
597
    if (dsp->left_till_irq < 0) {
598
        dsp->left_till_irq += dsp->dma_buffer_size;
599
        return dsp->dma_pos;
600
    }
601

    
602
    free = AUD_get_free ();
603

    
604
    if ((free <= 0) || (0 == size)) {
605
        return dsp->dma_pos;
606
    }
607

    
608
    if (mix_block > 0) {
609
        copy = MIN (free, mix_block);
610
    }
611
    else {
612
        copy = free;
613
    }
614

    
615
    till = dsp->left_till_irq;
616

    
617
    ldebug ("addr:%#010x free:%d till:%d size:%d\n",
618
            addr, free, till, size);
619
    if (till <= copy) {
620
        if (0 == dsp->dma_auto) {
621
            copy = till;
622
        }
623
    }
624

    
625
    written = write_audio (addr, size, copy);
626
    dsp->left_till_irq -= written;
627
    AUD_adjust_estimate (free - written);
628

    
629
    if (dsp->left_till_irq <= 0) {
630
        dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
631
        if (0 == noirq) {
632
            ldebug ("request irq\n");
633
            pic_set_irq(sb.irq, 1);
634
        }
635

    
636
        if (0 == dsp->dma_auto) {
637
            control (0);
638
        }
639
    }
640

    
641
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
642
            dsp->dma_pos, free, size, dsp->left_till_irq, copy,
643
            dsp->dma_buffer_size);
644

    
645
    if (dsp->left_till_irq <= 0) {
646
        dsp->left_till_irq += dsp->dma_buffer_size;
647
    }
648

    
649
    return dsp->dma_pos;
650
}
651

    
652
static int magic_of_irq (int irq)
653
{
654
    switch (irq) {
655
    case 2:
656
        return 1;
657
    case 5:
658
        return 2;
659
    case 7:
660
        return 4;
661
    case 10:
662
        return 8;
663
    default:
664
        log ("bad irq %d\n", irq);
665
        return 2;
666
    }
667
}
668

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

    
686
void SB16_init (void)
687
{
688
    SB16State *s = &dsp;
689
    int i;
690
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
691
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
692

    
693
    s->mixer_regs[0x0e] = ~0;
694
    s->mixer_regs[0x80] = magic_of_irq (sb.irq);
695
    s->mixer_regs[0x81] = 0x20 | (sb.dma << 1);
696

    
697
    DEREF (irq_of_magic);
698

    
699
    for (i = 0x30; i < 0x48; i++) {
700
        s->mixer_regs[i] = 0x20;
701
    }
702

    
703
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
704
        register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);
705
    }
706

    
707
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
708
        register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);
709
    }
710

    
711
    register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);
712
    register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);
713
    register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);
714
    register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);
715

    
716
    DMA_register_channel (sb.hdma, SB_read_DMA, s);
717
    DMA_register_channel (sb.dma, SB_read_DMA, s);
718
}