]> git.proxmox.com Git - qemu.git/blob - hw/sb16.c
SDL Audio support and SB16 fixes (malc)
[qemu.git] / hw / sb16.c
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 dolog(...) fprintf (stderr, "sb16: " __VA_ARGS__);
30
31 /* #define DEBUG_SB16 */
32
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 const char e3[] =
49 "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992\0"
50 "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994-1997";
51 /* "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994."; */
52
53 static struct {
54 int ver_lo;
55 int ver_hi;
56 int irq;
57 int dma;
58 int hdma;
59 int port;
60 int mix_block;
61 } sb = {5, 4, 5, 1, 5, 0x220, -1};
62
63 static int mix_block, noirq;
64
65 typedef struct SB16State {
66 int in_index;
67 int out_data_len;
68 int fmt_stereo;
69 int fmt_signed;
70 int fmt_bits;
71 int dma_auto;
72 int dma_buffer_size;
73 int fifo;
74 int freq;
75 int time_const;
76 int speaker;
77 int needed_bytes;
78 int cmd;
79 int dma_pos;
80 int use_hdma;
81
82 int v2x6;
83
84 uint8_t in2_data[10];
85 uint8_t out_data[1024];
86
87 int left_till_irq;
88 uint64_t nzero;
89 uint8_t last_read_byte;
90 uint8_t test_reg;
91
92 /* mixer state */
93 int mixer_nreg;
94 uint8_t mixer_regs[256];
95 } SB16State;
96
97 /* XXX: suppress that and use a context */
98 static struct SB16State dsp;
99
100 static void log_dsp (SB16State *dsp)
101 {
102 ldebug ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",
103 dsp->fmt_stereo ? 'S' : 'M',
104 dsp->fmt_signed ? 'S' : 'U',
105 dsp->fmt_bits,
106 dsp->dma_auto ? 'a' : 's',
107 dsp->dma_buffer_size,
108 dsp->dma_pos,
109 dsp->freq,
110 dsp->time_const,
111 dsp->speaker);
112 }
113
114 static void control (int hold)
115 {
116 linfo ("%d high %d\n", hold, dsp.use_hdma);
117 if (hold) {
118 if (dsp.use_hdma)
119 DMA_hold_DREQ (sb.hdma);
120 else
121 DMA_hold_DREQ (sb.dma);
122 }
123 else {
124 if (dsp.use_hdma)
125 DMA_release_DREQ (sb.hdma);
126 else
127 DMA_release_DREQ (sb.dma);
128 }
129 }
130
131 static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)
132 {
133 int bps;
134 audfmt_e fmt;
135
136 dsp.use_hdma = cmd < 0xc0;
137 dsp.fifo = (cmd >> 1) & 1;
138 dsp.dma_auto = (cmd >> 2) & 1;
139
140 switch (cmd >> 4) {
141 case 11:
142 dsp.fmt_bits = 16;
143 break;
144
145 case 12:
146 dsp.fmt_bits = 8;
147 break;
148 }
149
150 dsp.fmt_signed = (d0 >> 4) & 1;
151 dsp.fmt_stereo = (d0 >> 5) & 1;
152
153 if (-1 != dsp.time_const) {
154 int tmp;
155
156 tmp = 256 - dsp.time_const;
157 dsp.freq = (1000000 + (tmp / 2)) / tmp;
158 }
159 bps = 1 << (16 == dsp.fmt_bits);
160
161 if (-1 != dma_len)
162 dsp.dma_buffer_size = (dma_len + 1) * bps;
163
164 linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",
165 dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,
166 dsp.dma_buffer_size, dsp.dma_auto);
167
168 if (16 == dsp.fmt_bits) {
169 if (dsp.fmt_signed) {
170 fmt = AUD_FMT_S16;
171 }
172 else {
173 fmt = AUD_FMT_U16;
174 }
175 }
176 else {
177 if (dsp.fmt_signed) {
178 fmt = AUD_FMT_S8;
179 }
180 else {
181 fmt = AUD_FMT_U8;
182 }
183 }
184
185 dsp.dma_pos = 0;
186 dsp.left_till_irq = dsp.dma_buffer_size;
187
188 if (sb.mix_block) {
189 mix_block = sb.mix_block;
190 }
191 else {
192 int align;
193
194 align = bps << dsp.fmt_stereo;
195 mix_block = ((dsp.freq * align) / 100) & ~(align - 1);
196 }
197
198 if (dsp.freq)
199 AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);
200 control (1);
201 dsp.speaker = 1;
202 }
203
204 static inline void dsp_out_data(SB16State *dsp, int val)
205 {
206 if (dsp->out_data_len < sizeof(dsp->out_data))
207 dsp->out_data[dsp->out_data_len++] = val;
208 }
209
210 static inline uint8_t dsp_get_data(SB16State *dsp)
211 {
212 if (dsp->in_index)
213 return dsp->in2_data[--dsp->in_index];
214 else
215 return 0;
216 }
217
218 static void command (SB16State *dsp, uint8_t cmd)
219 {
220 linfo ("command: %#x\n", cmd);
221
222 if (cmd > 0xaf && cmd < 0xd0) {
223 if (cmd & 8)
224 goto error;
225
226 switch (cmd >> 4) {
227 case 11:
228 case 12:
229 break;
230 default:
231 dolog ("command: %#x wrong bits specification\n", cmd);
232 goto error;
233 }
234 dsp->needed_bytes = 3;
235 }
236 else {
237 switch (cmd) {
238 case 0x00:
239 case 0xe7:
240 /* IMS uses those when probing for sound devices */
241 return;
242
243 case 0x03:
244 case 0x04:
245 dsp_out_data (dsp, 0);
246 return;
247
248 case 0x05:
249 dsp->needed_bytes = 2;
250 break;
251
252 case 0x0e:
253 dsp->needed_bytes = 2;
254 break;
255
256 case 0x0f:
257 dsp->needed_bytes = 1;
258 break;
259
260 case 0x10:
261 dsp->needed_bytes = 1;
262 break;
263
264 case 0x14:
265 dsp->needed_bytes = 2;
266 dsp->dma_buffer_size = 0;
267 break;
268
269 case 0x20:
270 dsp_out_data(dsp, 0xff);
271 break;
272
273 case 0x35:
274 lwarn ("MIDI commands not implemented\n");
275 break;
276
277 case 0x40:
278 dsp->freq = -1;
279 dsp->time_const = -1;
280 dsp->needed_bytes = 1;
281 break;
282
283 case 0x41:
284 case 0x42:
285 dsp->freq = -1;
286 dsp->time_const = -1;
287 dsp->needed_bytes = 2;
288 break;
289
290 case 0x45:
291 dsp_out_data (dsp, 0xaa);
292 case 0x47: /* Continue Auto-Initialize DMA 16bit */
293 break;
294
295 case 0x48:
296 dsp->needed_bytes = 2;
297 break;
298
299 case 0x27: /* ????????? */
300 case 0x4e:
301 return;
302
303 case 0x80:
304 cmd = -1;
305 break;
306
307 case 0x90:
308 case 0x91:
309 {
310 uint8_t d0;
311
312 d0 = 4;
313 /* if (dsp->fmt_signed) d0 |= 16; */
314 /* if (dsp->fmt_stereo) d0 |= 32; */
315 dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
316 cmd = -1;
317 break;
318 }
319
320 case 0xd0: /* XXX */
321 control (0);
322 return;
323
324 case 0xd1:
325 dsp->speaker = 1;
326 break;
327
328 case 0xd3:
329 dsp->speaker = 0;
330 return;
331
332 case 0xd4:
333 control (1);
334 break;
335
336 case 0xd5:
337 control (0);
338 break;
339
340 case 0xd6:
341 control (1);
342 break;
343
344 case 0xd9:
345 control (0);
346 dsp->dma_auto = 0;
347 return;
348
349 case 0xda:
350 control (0);
351 dsp->dma_auto = 0;
352 break;
353
354 case 0xe0:
355 dsp->needed_bytes = 1;
356 break;
357
358 case 0xe1:
359 dsp_out_data(dsp, sb.ver_lo);
360 dsp_out_data(dsp, sb.ver_hi);
361 return;
362
363 case 0xe3:
364 {
365 int i;
366 for (i = sizeof (e3) - 1; i >= 0; i--)
367 dsp_out_data (dsp, e3[i]);
368 return;
369 }
370
371 case 0xe4: /* write test reg */
372 dsp->needed_bytes = 1;
373 break;
374
375 case 0xe8: /* read test reg */
376 dsp_out_data (dsp, dsp->test_reg);
377 break;
378
379 case 0xf2:
380 dsp_out_data (dsp, 0xaa);
381 dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
382 pic_set_irq (sb.irq, 1);
383 return;
384
385 case 0xf9:
386 dsp->needed_bytes = 1;
387 break;
388
389 case 0xfa:
390 dsp_out_data (dsp, 0);
391 break;
392
393 case 0xfc: /* FIXME */
394 dsp_out_data (dsp, 0);
395 break;
396
397 default:
398 dolog ("unrecognized command %#x\n", cmd);
399 goto error;
400 }
401 }
402 dsp->cmd = cmd;
403 return;
404
405 error:
406 return;
407 }
408
409 static void complete (SB16State *dsp)
410 {
411 int d0, d1, d2;
412 linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
413 dsp->cmd, dsp->in_index, dsp->needed_bytes);
414
415 if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {
416 d2 = dsp_get_data (dsp);
417 d1 = dsp_get_data (dsp);
418 d0 = dsp_get_data (dsp);
419
420 ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
421 d0, d1, d2);
422 dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));
423 }
424 else {
425 switch (dsp->cmd) {
426 case 0x04:
427 case 0x10:
428 dsp_get_data (dsp);
429 break;
430
431 case 0x0f:
432 d0 = dsp_get_data (dsp);
433 dsp_out_data (dsp, 0xf8);
434 break;
435
436 case 0x05:
437 case 0x0e:
438 dsp_get_data (dsp);
439 dsp_get_data (dsp);
440 break;
441
442 case 0x14:
443 {
444 int save_left;
445 int save_pos;
446
447 d1 = dsp_get_data (dsp);
448 d0 = dsp_get_data (dsp);
449
450 save_left = dsp->left_till_irq;
451 save_pos = dsp->dma_pos;
452 dma_cmd (0xc0, 0, d0 + (d1 << 8));
453 dsp->left_till_irq = save_left;
454 dsp->dma_pos = save_pos;
455
456 linfo ("set buffer size data[%d, %d] %d pos %d\n",
457 d0, d1, dsp->dma_buffer_size, dsp->dma_pos);
458 break;
459 }
460
461 case 0x40:
462 dsp->time_const = dsp_get_data (dsp);
463 linfo ("set time const %d\n", dsp->time_const);
464 break;
465
466 case 0x41:
467 case 0x42:
468 d1 = dsp_get_data (dsp);
469 d0 = dsp_get_data (dsp);
470
471 dsp->freq = d1 + (d0 << 8);
472 linfo ("set freq %#x, %#x = %d\n", d1, d0, dsp->freq);
473 break;
474
475 case 0x48:
476 d1 = dsp_get_data (dsp);
477 d0 = dsp_get_data (dsp);
478 dsp->dma_buffer_size = d1 + (d0 << 8);
479 linfo ("set dma len %#x, %#x = %d\n",
480 d1, d0, dsp->dma_buffer_size);
481 break;
482
483 case 0xe0:
484 d0 = dsp_get_data (dsp);
485 dsp->out_data_len = 0;
486 linfo ("data = %#x\n", d0);
487 dsp_out_data (dsp, d0 ^ 0xff);
488 break;
489
490 case 0xe4:
491 dsp->test_reg = dsp_get_data (dsp);
492 break;
493
494
495 case 0xf9:
496 d0 = dsp_get_data (dsp);
497 ldebug ("f9 <- %#x\n", d0);
498 switch (d0) {
499 case 0x0e: dsp_out_data (dsp, 0xff); break;
500 case 0x0f: dsp_out_data (dsp, 0x07); break;
501 case 0xf9: dsp_out_data (dsp, 0x00); break;
502 case 0x37:
503 dsp_out_data (dsp, 0x38); break;
504 default:
505 dsp_out_data (dsp, 0);
506 }
507 break;
508
509 default:
510 dolog ("complete: unrecognized command %#x\n", dsp->cmd);
511 return;
512 }
513 }
514
515 dsp->needed_bytes = 0;
516 dsp->cmd = -1;
517 return;
518 }
519
520 static IO_WRITE_PROTO (dsp_write)
521 {
522 SB16State *dsp = opaque;
523 int iport;
524
525 iport = nport - sb.port;
526
527 ldebug ("dsp_write %#x <- %#x\n", nport, val);
528 switch (iport) {
529 case 0x6:
530 control (0);
531 if (0 == val)
532 dsp->v2x6 = 0;
533 else if ((1 == val) && (0 == dsp->v2x6)) {
534 dsp->v2x6 = 1;
535 dsp->dma_pos = 0;
536 dsp->dma_auto = 0;
537 dsp->in_index = 0;
538 dsp->out_data_len = 0;
539 dsp->left_till_irq = 0;
540 dsp->speaker = 0;
541 dsp->needed_bytes = 0;
542 pic_set_irq (sb.irq, 0);
543 dsp_out_data(dsp, 0xaa);
544 }
545 else
546 dsp->v2x6 = ~0;
547 break;
548
549 case 0xc: /* write data or command | write status */
550 if (0 == dsp->needed_bytes) {
551 command (dsp, val);
552 if (0 == dsp->needed_bytes) {
553 log_dsp (dsp);
554 }
555 }
556 else {
557 if (dsp->in_index == sizeof (dsp->in2_data)) {
558 dolog ("in data overrun\n");
559 }
560 else {
561 dsp->in2_data[dsp->in_index++] = val;
562 if (dsp->in_index == dsp->needed_bytes) {
563 dsp->needed_bytes = 0;
564 complete (dsp);
565 log_dsp (dsp);
566 }
567 }
568 }
569 break;
570
571 default:
572 dolog ("dsp_write (nport=%#x, val=%#x)\n", nport, val);
573 break;
574 }
575 }
576
577 static IO_READ_PROTO (dsp_read)
578 {
579 SB16State *dsp = opaque;
580 int iport, retval;
581
582 iport = nport - sb.port;
583
584 switch (iport) {
585 case 0x6: /* reset */
586 control (0);
587 retval = 0;
588 dsp->speaker = 0;
589 break;
590
591 case 0xa: /* read data */
592 if (dsp->out_data_len) {
593 retval = dsp->out_data[--dsp->out_data_len];
594 dsp->last_read_byte = retval;
595 } else {
596 retval = dsp->last_read_byte;
597 dolog ("empty output buffer\n");
598 /* goto error; */
599 }
600 break;
601
602 case 0xc: /* 0xxxxxxx can write */
603 retval = 0;
604 if (dsp->out_data_len == sizeof (dsp->out_data)) retval |= 0x80;
605 break;
606
607 case 0xd: /* timer interrupt clear */
608 dolog ("timer interrupt clear\n");
609 goto error;
610
611 case 0xe: /* data available status | irq 8 ack */
612 /* XXX drop pic irq line here? */
613 /* ldebug ("8 ack\n"); */
614 retval = dsp->out_data_len ? 0x80 : 0;
615 dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
616 pic_set_irq (sb.irq, 0);
617 break;
618
619 case 0xf: /* irq 16 ack */
620 /* XXX drop pic irq line here? */
621 ldebug ("16 ack\n");
622 retval = 0xff;
623 dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
624 pic_set_irq (sb.irq, 0);
625 break;
626
627 default:
628 goto error;
629 }
630
631 if (0xe == iport) {
632 if (0 == retval) {
633 if (!dsp->nzero) {
634 ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",
635 nport, iport, retval, dsp->nzero);
636 }
637 dsp->nzero += 1;
638 }
639 else {
640 ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",
641 nport, iport, retval, dsp->nzero);
642 dsp->nzero = 0;
643 }
644 }
645 else {
646 ldebug ("dsp_read (nport=%#x iport %#x) = %#x\n",
647 nport, iport, retval);
648 }
649
650 return retval;
651
652 error:
653 printf ("dsp_read error %#x\n", nport);
654 return 0xff;
655 }
656
657 static IO_WRITE_PROTO(mixer_write_indexb)
658 {
659 SB16State *dsp = opaque;
660 dsp->mixer_nreg = val;
661 }
662
663 static IO_WRITE_PROTO(mixer_write_datab)
664 {
665 SB16State *dsp = opaque;
666 int i;
667
668 linfo ("mixer [%#x] <- %#x\n", dsp->mixer_nreg, val);
669 switch (dsp->mixer_nreg) {
670 case 0x00:
671 /* Bochs */
672 dsp->mixer_regs[0x04] = 0xcc;
673 dsp->mixer_regs[0x0a] = 0x00;
674 dsp->mixer_regs[0x22] = 0xcc;
675 dsp->mixer_regs[0x26] = 0xcc;
676 dsp->mixer_regs[0x28] = 0x00;
677 dsp->mixer_regs[0x2e] = 0x00;
678 dsp->mixer_regs[0x3c] = 0x1f;
679 dsp->mixer_regs[0x3d] = 0x15;
680 dsp->mixer_regs[0x3e] = 0x0b;
681
682 for (i = 0x30; i <= 0x35; i++)
683 dsp->mixer_regs[i] = 0xc0;
684
685 for (i = 0x36; i <= 0x3b; i++)
686 dsp->mixer_regs[i] = 0x00;
687
688 for (i = 0x3f; i <= 0x43; i++)
689 dsp->mixer_regs[i] = 0x00;
690
691 for (i = 0x44; i <= 0x47; i++)
692 dsp->mixer_regs[i] = 0x80;
693
694 for (i = 0x30; i < 0x48; i++) {
695 dsp->mixer_regs[i] = 0x20;
696 }
697 break;
698
699 case 0x04:
700 case 0x0a:
701 case 0x22:
702 case 0x26:
703 case 0x28:
704 case 0x2e:
705 case 0x30:
706 case 0x31:
707 case 0x32:
708 case 0x33:
709 case 0x34:
710 case 0x35:
711 case 0x36:
712 case 0x37:
713 case 0x38:
714 case 0x39:
715 case 0x3a:
716 case 0x3b:
717 case 0x3c:
718 case 0x3d:
719 case 0x3e:
720 case 0x3f:
721 case 0x40:
722 case 0x41:
723 case 0x42:
724 case 0x43:
725 case 0x44:
726 case 0x45:
727 case 0x46:
728 case 0x47:
729 case 0x80:
730 case 0x81:
731 break;
732 default:
733 return;
734 }
735 dsp->mixer_regs[dsp->mixer_nreg] = val;
736 }
737
738 static IO_WRITE_PROTO(mpu_write)
739 {
740 linfo ("mpu: %#x\n", val);
741 }
742
743 static IO_WRITE_PROTO(adlib_write)
744 {
745 linfo ("adlib: %#x\n", val);
746 }
747
748 static IO_READ_PROTO(mpu_read)
749 {
750 linfo ("mpu read: %#x\n", nport);
751 return 0x80;
752 }
753
754 static IO_READ_PROTO(adlib_read)
755 {
756 linfo ("adlib read: %#x\n", nport);
757 return 0;
758 }
759
760 static IO_WRITE_PROTO(mixer_write_indexw)
761 {
762 mixer_write_indexb (opaque, nport, val & 0xff);
763 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
764 }
765
766 static IO_READ_PROTO(mixer_read)
767 {
768 SB16State *dsp = opaque;
769 linfo ("mixer [%#x] -> %#x\n", dsp->mixer_nreg, dsp->mixer_regs[dsp->mixer_nreg]);
770 return dsp->mixer_regs[dsp->mixer_nreg];
771 }
772
773 void SB16_run (void)
774 {
775 if (0 == dsp.speaker)
776 return;
777
778 AUD_run ();
779 }
780
781 static int write_audio (uint32_t addr, int len, int size)
782 {
783 int temp, net;
784 uint8_t tmpbuf[4096];
785
786 temp = size;
787
788 net = 0;
789
790 while (temp) {
791 int left_till_end;
792 int to_copy;
793 int copied;
794
795 left_till_end = len - dsp.dma_pos;
796
797 to_copy = MIN (temp, left_till_end);
798 if (to_copy > sizeof(tmpbuf))
799 to_copy = sizeof(tmpbuf);
800 cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);
801 copied = AUD_write (tmpbuf, to_copy);
802
803 temp -= copied;
804 dsp.dma_pos += copied;
805
806 if (dsp.dma_pos == len) {
807 dsp.dma_pos = 0;
808 }
809
810 net += copied;
811
812 if (copied != to_copy)
813 return net;
814 }
815
816 return net;
817 }
818
819 static int SB_read_DMA (void *opaque, target_ulong addr, int size)
820 {
821 SB16State *dsp = opaque;
822 int free, till, copy, written;
823
824 if (0 == dsp->speaker)
825 return 0;
826
827 if (dsp->left_till_irq < 0) {
828 ldebug ("left_till_irq < 0, %d, pos %d \n",
829 dsp->left_till_irq, dsp->dma_buffer_size);
830 dsp->left_till_irq += dsp->dma_buffer_size;
831 return dsp->dma_pos;
832 }
833
834 free = AUD_get_free ();
835
836 if ((free <= 0) || (0 == size)) {
837 ldebug ("returning, since free = %d and size = %d\n", free, size);
838 return dsp->dma_pos;
839 }
840
841 if (mix_block > 0) {
842 copy = MIN (free, mix_block);
843 }
844 else {
845 copy = free;
846 }
847
848 till = dsp->left_till_irq;
849
850 #ifdef DEBUG_SB16_MOST
851 ldebug ("addr:%#010x free:%d till:%d size:%d\n",
852 addr, free, till, size);
853 #endif
854
855 if (till <= copy) {
856 if (0 == dsp->dma_auto) {
857 copy = till;
858 }
859 }
860
861 written = write_audio (addr, size, copy);
862 dsp->left_till_irq -= written;
863 AUD_adjust_estimate (free - written);
864
865 if (dsp->left_till_irq <= 0) {
866 dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
867 if (0 == noirq) {
868 ldebug ("request irq pos %d, left %d\n",
869 dsp->dma_pos, dsp->left_till_irq);
870 pic_set_irq(sb.irq, 1);
871 }
872
873 if (0 == dsp->dma_auto) {
874 control (0);
875 }
876 }
877
878 #ifdef DEBUG_SB16_MOST
879 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
880 dsp->dma_pos, free, size, dsp->left_till_irq, copy,
881 dsp->dma_buffer_size);
882 #endif
883
884 if (dsp->left_till_irq <= 0) {
885 dsp->left_till_irq += dsp->dma_buffer_size;
886 }
887
888 return dsp->dma_pos;
889 }
890
891 static int magic_of_irq (int irq)
892 {
893 switch (irq) {
894 case 2:
895 return 1;
896 case 5:
897 return 2;
898 case 7:
899 return 4;
900 case 10:
901 return 8;
902 default:
903 dolog ("bad irq %d\n", irq);
904 return 2;
905 }
906 }
907
908 #if 0
909 static int irq_of_magic (int magic)
910 {
911 switch (magic) {
912 case 1:
913 return 2;
914 case 2:
915 return 5;
916 case 4:
917 return 7;
918 case 8:
919 return 10;
920 default:
921 dolog ("bad irq magic %d\n", magic);
922 return 2;
923 }
924 }
925 #endif
926
927 #ifdef SB16_TRAP_ALL
928 static IO_READ_PROTO (trap_read)
929 {
930 switch (nport) {
931 case 0x220:
932 return 0;
933 case 0x226:
934 case 0x22a:
935 case 0x22c:
936 case 0x22d:
937 case 0x22e:
938 case 0x22f:
939 return dsp_read (opaque, nport);
940 }
941 linfo ("trap_read: %#x\n", nport);
942 return 0xff;
943 }
944
945 static IO_WRITE_PROTO (trap_write)
946 {
947 switch (nport) {
948 case 0x226:
949 case 0x22c:
950 dsp_write (opaque, nport, val);
951 return;
952 }
953 linfo ("trap_write: %#x = %#x\n", nport, val);
954 }
955 #endif
956
957 void SB16_init (void)
958 {
959 SB16State *s = &dsp;
960 int i;
961 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
962 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
963
964 memset(s->mixer_regs, 0xff, sizeof(s->mixer_regs));
965
966 s->mixer_regs[0x00] = 0;
967 s->mixer_regs[0x0e] = ~0;
968 s->mixer_regs[0x80] = magic_of_irq (sb.irq);
969 s->mixer_regs[0x81] = 0x80 | 0x10 | (sb.dma << 1);
970 s->mixer_regs[0x82] = 0;
971 s->mixer_regs[0xfd] = 16; /* bochs */
972 s->mixer_regs[0xfe] = 6; /* bochs */
973 mixer_write_indexw (s, 0x224, 0);
974
975 #ifdef SB16_TRAP_ALL
976 for (i = 0; i < 0x100; i++) {
977 if (i != 4 && i != 5) {
978 register_ioport_write (sb.port + i, 1, 1, trap_write, s);
979 register_ioport_read (sb.port + i, 1, 1, trap_read, s);
980 }
981 }
982 #else
983
984 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
985 register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);
986 }
987
988 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
989 register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);
990 }
991 #endif
992
993 register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);
994 register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);
995 register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);
996 register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);
997
998 for (i = 0; 4 < 4; i++) {
999 register_ioport_read (0x330 + i, 1, 1, mpu_read, s);
1000 register_ioport_write (0x330 + i, 1, 1, mpu_write, s);
1001 register_ioport_read (0x388 + i, 1, 1, adlib_read, s);
1002 register_ioport_write (0x388 + i, 1, 1, adlib_write, s);
1003 }
1004
1005 DMA_register_channel (sb.hdma, SB_read_DMA, s);
1006 DMA_register_channel (sb.dma, SB_read_DMA, s);
1007 }