]> Git Repo - qemu.git/blame - hw/sb16.c
merged 15a_aqemu.patch audio patch (malc)
[qemu.git] / hw / sb16.c
CommitLineData
27503323
FB
1/*
2 * QEMU Soundblaster 16 emulation
1d14ffa9
FB
3 *
4 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 *
27503323
FB
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 */
27503323
FB
24#include "vl.h"
25
85571bc7 26#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
d75d9f6b 27
fb065187 28#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
15b61470
FB
29
30/* #define DEBUG */
31/* #define DEBUG_SB16_MOST */
32
fb065187
FB
33#ifdef DEBUG
34#define ldebug(...) dolog (__VA_ARGS__)
35#else
36#define ldebug(...)
37#endif
38
85571bc7 39#define IO_READ_PROTO(name) \
7d977de7 40 uint32_t name (void *opaque, uint32_t nport)
85571bc7 41#define IO_WRITE_PROTO(name) \
7d977de7 42 void name (void *opaque, uint32_t nport, uint32_t val)
27503323 43
85571bc7 44static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
d329a6fb 45
27503323
FB
46static struct {
47 int ver_lo;
48 int ver_hi;
49 int irq;
50 int dma;
51 int hdma;
52 int port;
85571bc7 53} conf = {5, 4, 5, 1, 5, 0x220};
27503323 54
5e2a6443 55typedef struct SB16State {
85571bc7
FB
56 int irq;
57 int dma;
58 int hdma;
59 int port;
60 int ver;
61
27503323
FB
62 int in_index;
63 int out_data_len;
64 int fmt_stereo;
65 int fmt_signed;
66 int fmt_bits;
85571bc7 67 audfmt_e fmt;
27503323 68 int dma_auto;
85571bc7 69 int block_size;
27503323
FB
70 int fifo;
71 int freq;
72 int time_const;
73 int speaker;
74 int needed_bytes;
75 int cmd;
27503323 76 int use_hdma;
85571bc7
FB
77 int highspeed;
78 int can_write;
27503323
FB
79
80 int v2x6;
81
85571bc7
FB
82 uint8_t csp_param;
83 uint8_t csp_value;
84 uint8_t csp_mode;
85 uint8_t csp_regs[256];
86 uint8_t csp_index;
87 uint8_t csp_reg83[4];
88 int csp_reg83r;
89 int csp_reg83w;
90
d75d9f6b 91 uint8_t in2_data[10];
85571bc7
FB
92 uint8_t out_data[50];
93 uint8_t test_reg;
94 uint8_t last_read_byte;
95 int nzero;
27503323
FB
96
97 int left_till_irq;
27503323 98
85571bc7
FB
99 int dma_running;
100 int bytes_per_second;
101 int align;
1d14ffa9
FB
102 int audio_free;
103 SWVoiceOut *voice;
85571bc7 104
1d14ffa9 105 QEMUTimer *aux_ts;
5e2a6443
FB
106 /* mixer state */
107 int mixer_nreg;
202a456a 108 uint8_t mixer_regs[256];
5e2a6443 109} SB16State;
27503323 110
5e2a6443
FB
111/* XXX: suppress that and use a context */
112static struct SB16State dsp;
27503323 113
1d14ffa9
FB
114static void SB_audio_callback (void *opaque, int free);
115
85571bc7
FB
116static int magic_of_irq (int irq)
117{
118 switch (irq) {
119 case 5:
120 return 2;
121 case 7:
122 return 4;
123 case 9:
124 return 1;
125 case 10:
126 return 8;
127 default:
128 dolog ("bad irq %d\n", irq);
129 return 2;
130 }
131}
132
133static int irq_of_magic (int magic)
134{
135 switch (magic) {
136 case 1:
137 return 9;
138 case 2:
139 return 5;
140 case 4:
141 return 7;
142 case 8:
143 return 10;
144 default:
145 dolog ("bad irq magic %d\n", magic);
146 return -1;
147 }
148}
149
150#if 0
5e2a6443
FB
151static void log_dsp (SB16State *dsp)
152{
85571bc7
FB
153 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
154 dsp->fmt_stereo ? "Stereo" : "Mono",
155 dsp->fmt_signed ? "Signed" : "Unsigned",
156 dsp->fmt_bits,
157 dsp->dma_auto ? "Auto" : "Single",
158 dsp->block_size,
159 dsp->freq,
160 dsp->time_const,
161 dsp->speaker);
162}
163#endif
164
165static void speaker (SB16State *s, int on)
166{
167 s->speaker = on;
168 /* AUD_enable (s->voice, on); */
27503323
FB
169}
170
85571bc7 171static void control (SB16State *s, int hold)
27503323 172{
85571bc7
FB
173 int dma = s->use_hdma ? s->hdma : s->dma;
174 s->dma_running = hold;
175
176 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
177
27503323 178 if (hold) {
85571bc7 179 DMA_hold_DREQ (dma);
1d14ffa9 180 AUD_set_active_out (s->voice, 1);
27503323
FB
181 }
182 else {
85571bc7 183 DMA_release_DREQ (dma);
1d14ffa9 184 AUD_set_active_out (s->voice, 0);
27503323
FB
185 }
186}
187
85571bc7 188static void aux_timer (void *opaque)
27503323 189{
85571bc7
FB
190 SB16State *s = opaque;
191 s->can_write = 1;
192 pic_set_irq (s->irq, 1);
193}
194
195#define DMA8_AUTO 1
196#define DMA8_HIGH 2
197
198static void dma_cmd8 (SB16State *s, int mask, int dma_len)
199{
200 s->fmt = AUD_FMT_U8;
201 s->use_hdma = 0;
202 s->fmt_bits = 8;
203 s->fmt_signed = 0;
204 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
205 if (-1 == s->time_const) {
206 s->freq = 11025;
207 }
208 else {
209 int tmp = (256 - s->time_const);
210 s->freq = (1000000 + (tmp / 2)) / tmp;
211 }
212
1d14ffa9 213 if (dma_len != -1) {
15b61470 214 s->block_size = dma_len << s->fmt_stereo;
1d14ffa9 215 }
15b61470
FB
216 else {
217 /* This is apparently the only way to make both Act1/PL
218 and SecondReality/FC work
219
220 Act1 sets block size via command 0x48 and it's an odd number
221 SR does the same with even number
222 Both use stereo, and Creatives own documentation states that
223 0x48 sets block size in bytes less one.. go figure */
224 s->block_size &= ~s->fmt_stereo;
225 }
85571bc7
FB
226
227 s->freq >>= s->fmt_stereo;
228 s->left_till_irq = s->block_size;
229 s->bytes_per_second = (s->freq << s->fmt_stereo);
230 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
231 s->dma_auto = (mask & DMA8_AUTO) != 0;
232 s->align = (1 << s->fmt_stereo) - 1;
233
1d14ffa9
FB
234 if (s->block_size & s->align) {
235 dolog ("warning: misaligned block size %d, alignment %d\n",
236 s->block_size, s->align + 1);
237 }
15b61470 238
85571bc7
FB
239 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
240 "dma %d, auto %d, fifo %d, high %d\n",
241 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
242 s->block_size, s->dma_auto, s->fifo, s->highspeed);
243
1d14ffa9
FB
244 if (s->freq) {
245 s->audio_free = 0;
246 s->voice = AUD_open_out (
247 s->voice,
248 "sb16",
249 s,
250 SB_audio_callback,
251 s->freq,
252 1 << s->fmt_stereo,
253 s->fmt
254 );
255 }
85571bc7
FB
256
257 control (s, 1);
258 speaker (s, 1);
259}
27503323 260
85571bc7
FB
261static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
262{
263 s->use_hdma = cmd < 0xc0;
264 s->fifo = (cmd >> 1) & 1;
265 s->dma_auto = (cmd >> 2) & 1;
266 s->fmt_signed = (d0 >> 4) & 1;
267 s->fmt_stereo = (d0 >> 5) & 1;
27503323
FB
268
269 switch (cmd >> 4) {
270 case 11:
85571bc7 271 s->fmt_bits = 16;
27503323
FB
272 break;
273
274 case 12:
85571bc7 275 s->fmt_bits = 8;
27503323
FB
276 break;
277 }
278
85571bc7
FB
279 if (-1 != s->time_const) {
280#if 1
281 int tmp = 256 - s->time_const;
282 s->freq = (1000000 + (tmp / 2)) / tmp;
283#else
284 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
285 s->freq = 1000000 / ((255 - s->time_const));
286#endif
287 s->time_const = -1;
27503323 288 }
27503323 289
85571bc7
FB
290 s->block_size = dma_len + 1;
291 s->block_size <<= (s->fmt_bits == 16);
15b61470
FB
292 if (!s->dma_auto) {
293 /* It is clear that for DOOM and auto-init this value
294 shouldn't take stereo into account, while Miles Sound Systems
295 setsound.exe with single transfer mode wouldn't work without it
296 wonders of SB16 yet again */
85571bc7 297 s->block_size <<= s->fmt_stereo;
15b61470 298 }
27503323 299
85571bc7
FB
300 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
301 "dma %d, auto %d, fifo %d, high %d\n",
302 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
303 s->block_size, s->dma_auto, s->fifo, s->highspeed);
27503323 304
85571bc7
FB
305 if (16 == s->fmt_bits) {
306 if (s->fmt_signed) {
307 s->fmt = AUD_FMT_S16;
27503323
FB
308 }
309 else {
85571bc7 310 s->fmt = AUD_FMT_U16;
27503323
FB
311 }
312 }
313 else {
85571bc7
FB
314 if (s->fmt_signed) {
315 s->fmt = AUD_FMT_S8;
27503323
FB
316 }
317 else {
85571bc7 318 s->fmt = AUD_FMT_U8;
27503323
FB
319 }
320 }
321
85571bc7 322 s->left_till_irq = s->block_size;
27503323 323
85571bc7
FB
324 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
325 s->highspeed = 0;
326 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
1d14ffa9
FB
327 if (s->block_size & s->align) {
328 dolog ("warning: misaligned block size %d, alignment %d\n",
329 s->block_size, s->align + 1);
330 }
27503323 331
1d14ffa9
FB
332 if (s->freq) {
333 s->audio_free = 0;
334 s->voice = AUD_open_out (
335 s->voice,
336 "sb16",
337 s,
338 SB_audio_callback,
339 s->freq,
340 1 << s->fmt_stereo,
341 s->fmt
342 );
343 }
27503323 344
85571bc7
FB
345 control (s, 1);
346 speaker (s, 1);
27503323
FB
347}
348
85571bc7 349static inline void dsp_out_data (SB16State *s, uint8_t val)
202a456a 350{
85571bc7 351 ldebug ("outdata %#x\n", val);
1d14ffa9 352 if (s->out_data_len < sizeof (s->out_data)) {
85571bc7 353 s->out_data[s->out_data_len++] = val;
1d14ffa9 354 }
202a456a
FB
355}
356
85571bc7 357static inline uint8_t dsp_get_data (SB16State *s)
d75d9f6b 358{
1d14ffa9 359 if (s->in_index) {
85571bc7 360 return s->in2_data[--s->in_index];
1d14ffa9 361 }
85571bc7
FB
362 else {
363 dolog ("buffer underflow\n");
d75d9f6b 364 return 0;
85571bc7 365 }
d75d9f6b
FB
366}
367
85571bc7 368static void command (SB16State *s, uint8_t cmd)
27503323 369{
85571bc7 370 ldebug ("command %#x\n", cmd);
27503323
FB
371
372 if (cmd > 0xaf && cmd < 0xd0) {
85571bc7
FB
373 if (cmd & 8) {
374 dolog ("ADC not yet supported (command %#x)\n", cmd);
375 }
27503323
FB
376
377 switch (cmd >> 4) {
378 case 11:
379 case 12:
380 break;
381 default:
85571bc7 382 dolog ("%#x wrong bits\n", cmd);
27503323 383 }
85571bc7 384 s->needed_bytes = 3;
27503323
FB
385 }
386 else {
1d14ffa9
FB
387 s->needed_bytes = 0;
388
27503323 389 switch (cmd) {
d75d9f6b 390 case 0x03:
85571bc7
FB
391 dsp_out_data (s, 0x10); /* s->csp_param); */
392 goto warn;
393
d329a6fb 394 case 0x04:
85571bc7
FB
395 s->needed_bytes = 1;
396 goto warn;
d329a6fb
FB
397
398 case 0x05:
85571bc7
FB
399 s->needed_bytes = 2;
400 goto warn;
401
402 case 0x08:
403 /* __asm__ ("int3"); */
404 goto warn;
d75d9f6b 405
d329a6fb 406 case 0x0e:
85571bc7
FB
407 s->needed_bytes = 2;
408 goto warn;
409
410 case 0x09:
411 dsp_out_data (s, 0xf8);
412 goto warn;
d329a6fb
FB
413
414 case 0x0f:
85571bc7
FB
415 s->needed_bytes = 1;
416 goto warn;
d329a6fb 417
27503323 418 case 0x10:
85571bc7
FB
419 s->needed_bytes = 1;
420 goto warn;
27503323
FB
421
422 case 0x14:
85571bc7
FB
423 s->needed_bytes = 2;
424 s->block_size = 0;
27503323
FB
425 break;
426
15b61470
FB
427 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
428 control (s, 1);
429 break;
430
85571bc7
FB
431 case 0x20: /* Direct ADC, Juice/PL */
432 dsp_out_data (s, 0xff);
433 goto warn;
27503323
FB
434
435 case 0x35:
1d14ffa9 436 dolog ("0x35 - MIDI command not implemented\n");
27503323
FB
437 break;
438
439 case 0x40:
85571bc7
FB
440 s->freq = -1;
441 s->time_const = -1;
442 s->needed_bytes = 1;
27503323
FB
443 break;
444
445 case 0x41:
85571bc7
FB
446 s->freq = -1;
447 s->time_const = -1;
448 s->needed_bytes = 2;
27503323
FB
449 break;
450
85571bc7
FB
451 case 0x42:
452 s->freq = -1;
453 s->time_const = -1;
454 s->needed_bytes = 2;
455 goto warn;
456
d75d9f6b 457 case 0x45:
85571bc7
FB
458 dsp_out_data (s, 0xaa);
459 goto warn;
460
27503323
FB
461 case 0x47: /* Continue Auto-Initialize DMA 16bit */
462 break;
463
464 case 0x48:
85571bc7 465 s->needed_bytes = 2;
27503323
FB
466 break;
467
1d14ffa9
FB
468 case 0x74:
469 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
470 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
471 break;
472
473 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
474 s->needed_bytes = 2;
475 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
476 break;
477
478 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
479 s->needed_bytes = 2;
480 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
481 break;
482
483 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
484 s->needed_bytes = 2;
485 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
486 break;
487
488 case 0x7d:
489 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
490 dolog ("not implemented\n");
491 break;
492
493 case 0x7f:
494 dolog (
495 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
496 );
497 dolog ("not implemented\n");
498 break;
499
27503323 500 case 0x80:
85571bc7 501 s->needed_bytes = 2;
27503323
FB
502 break;
503
504 case 0x90:
505 case 0x91:
85571bc7
FB
506 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
507 break;
27503323 508
85571bc7
FB
509 case 0xd0: /* halt DMA operation. 8bit */
510 control (s, 0);
511 break;
27503323 512
85571bc7
FB
513 case 0xd1: /* speaker on */
514 speaker (s, 1);
27503323
FB
515 break;
516
85571bc7
FB
517 case 0xd3: /* speaker off */
518 speaker (s, 0);
519 break;
27503323 520
85571bc7
FB
521 case 0xd4: /* continue DMA operation. 8bit */
522 control (s, 1);
27503323
FB
523 break;
524
85571bc7
FB
525 case 0xd5: /* halt DMA operation. 16bit */
526 control (s, 0);
27503323
FB
527 break;
528
85571bc7
FB
529 case 0xd6: /* continue DMA operation. 16bit */
530 control (s, 1);
27503323
FB
531 break;
532
85571bc7
FB
533 case 0xd9: /* exit auto-init DMA after this block. 16bit */
534 s->dma_auto = 0;
535 break;
27503323 536
85571bc7
FB
537 case 0xda: /* exit auto-init DMA after this block. 8bit */
538 s->dma_auto = 0;
27503323
FB
539 break;
540
1d14ffa9 541 case 0xe0: /* DSP identification */
85571bc7 542 s->needed_bytes = 1;
1d14ffa9 543 break;
27503323
FB
544
545 case 0xe1:
85571bc7
FB
546 dsp_out_data (s, s->ver & 0xff);
547 dsp_out_data (s, s->ver >> 8);
548 break;
549
550 case 0xe2:
551 s->needed_bytes = 1;
552 goto warn;
27503323 553
d329a6fb
FB
554 case 0xe3:
555 {
556 int i;
85571bc7
FB
557 for (i = sizeof (e3) - 1; i >= 0; --i)
558 dsp_out_data (s, e3[i]);
d329a6fb 559 }
85571bc7 560 break;
d329a6fb 561
d75d9f6b 562 case 0xe4: /* write test reg */
85571bc7 563 s->needed_bytes = 1;
d75d9f6b
FB
564 break;
565
85571bc7
FB
566 case 0xe7:
567 dolog ("Attempt to probe for ESS (0xe7)?\n");
1d14ffa9 568 break;
85571bc7 569
d75d9f6b 570 case 0xe8: /* read test reg */
85571bc7 571 dsp_out_data (s, s->test_reg);
d75d9f6b
FB
572 break;
573
27503323 574 case 0xf2:
85571bc7
FB
575 case 0xf3:
576 dsp_out_data (s, 0xaa);
577 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
578 pic_set_irq (s->irq, 1);
579 break;
27503323 580
d75d9f6b 581 case 0xf9:
85571bc7
FB
582 s->needed_bytes = 1;
583 goto warn;
d75d9f6b
FB
584
585 case 0xfa:
85571bc7
FB
586 dsp_out_data (s, 0);
587 goto warn;
d75d9f6b
FB
588
589 case 0xfc: /* FIXME */
85571bc7
FB
590 dsp_out_data (s, 0);
591 goto warn;
d75d9f6b 592
27503323 593 default:
1d14ffa9
FB
594 dolog ("Unrecognized command %#x\n", cmd);
595 break;
27503323
FB
596 }
597 }
85571bc7 598
1d14ffa9 599 if (!s->needed_bytes) {
85571bc7 600 ldebug ("\n");
1d14ffa9
FB
601 }
602
603 exit:
604 if (!s->needed_bytes) {
605 s->cmd = -1;
606 }
607 else {
608 s->cmd = cmd;
609 }
27503323
FB
610 return;
611
85571bc7 612 warn:
81eea5eb 613 dolog ("warning: command %#x,%d is not truly understood yet\n",
85571bc7 614 cmd, s->needed_bytes);
1d14ffa9
FB
615 goto exit;
616
27503323
FB
617}
618
85571bc7
FB
619static uint16_t dsp_get_lohi (SB16State *s)
620{
621 uint8_t hi = dsp_get_data (s);
622 uint8_t lo = dsp_get_data (s);
623 return (hi << 8) | lo;
624}
625
626static uint16_t dsp_get_hilo (SB16State *s)
627{
628 uint8_t lo = dsp_get_data (s);
629 uint8_t hi = dsp_get_data (s);
630 return (hi << 8) | lo;
631}
632
633static void complete (SB16State *s)
27503323 634{
d75d9f6b 635 int d0, d1, d2;
85571bc7
FB
636 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
637 s->cmd, s->in_index, s->needed_bytes);
27503323 638
85571bc7
FB
639 if (s->cmd > 0xaf && s->cmd < 0xd0) {
640 d2 = dsp_get_data (s);
641 d1 = dsp_get_data (s);
642 d0 = dsp_get_data (s);
27503323 643
85571bc7
FB
644 if (s->cmd & 8) {
645 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
646 s->cmd, d0, d1, d2);
647 }
648 else {
649 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
650 s->cmd, d0, d1, d2);
651 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
652 }
27503323
FB
653 }
654 else {
85571bc7 655 switch (s->cmd) {
d329a6fb 656 case 0x04:
85571bc7
FB
657 s->csp_mode = dsp_get_data (s);
658 s->csp_reg83r = 0;
659 s->csp_reg83w = 0;
660 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
d75d9f6b
FB
661 break;
662
85571bc7
FB
663 case 0x05:
664 s->csp_param = dsp_get_data (s);
665 s->csp_value = dsp_get_data (s);
666 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
667 s->csp_param,
668 s->csp_value);
d329a6fb 669 break;
27503323 670
d75d9f6b 671 case 0x0e:
85571bc7
FB
672 d0 = dsp_get_data (s);
673 d1 = dsp_get_data (s);
674 ldebug ("write CSP register %d <- %#x\n", d1, d0);
675 if (d1 == 0x83) {
676 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
677 s->csp_reg83[s->csp_reg83r % 4] = d0;
678 s->csp_reg83r += 1;
679 }
1d14ffa9 680 else {
85571bc7 681 s->csp_regs[d1] = d0;
1d14ffa9 682 }
27503323
FB
683 break;
684
85571bc7
FB
685 case 0x0f:
686 d0 = dsp_get_data (s);
687 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
688 d0, s->csp_regs[d0], s->csp_mode);
689 if (d0 == 0x83) {
690 ldebug ("0x83[%d] -> %#x\n",
691 s->csp_reg83w,
692 s->csp_reg83[s->csp_reg83w % 4]);
693 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
694 s->csp_reg83w += 1;
695 }
1d14ffa9 696 else {
85571bc7 697 dsp_out_data (s, s->csp_regs[d0]);
1d14ffa9 698 }
85571bc7 699 break;
27503323 700
85571bc7
FB
701 case 0x10:
702 d0 = dsp_get_data (s);
703 dolog ("cmd 0x10 d0=%#x\n", d0);
704 break;
27503323 705
85571bc7 706 case 0x14:
15b61470 707 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
85571bc7 708 break;
27503323
FB
709
710 case 0x40:
85571bc7
FB
711 s->time_const = dsp_get_data (s);
712 ldebug ("set time const %d\n", s->time_const);
27503323
FB
713 break;
714
85571bc7 715 case 0x42: /* FT2 sets output freq with this, go figure */
1d14ffa9 716#if 0
85571bc7 717 dolog ("cmd 0x42 might not do what it think it should\n");
1d14ffa9 718#endif
85571bc7
FB
719 case 0x41:
720 s->freq = dsp_get_hilo (s);
721 ldebug ("set freq %d\n", s->freq);
27503323
FB
722 break;
723
724 case 0x48:
15b61470 725 s->block_size = dsp_get_lohi (s) + 1;
85571bc7
FB
726 ldebug ("set dma block len %d\n", s->block_size);
727 break;
728
1d14ffa9
FB
729 case 0x74:
730 case 0x75:
731 case 0x76:
732 case 0x77:
733 /* ADPCM stuff, ignore */
734 break;
735
85571bc7
FB
736 case 0x80:
737 {
15b61470 738 int freq, samples, bytes;
85571bc7
FB
739 int64_t ticks;
740
15b61470
FB
741 freq = s->freq > 0 ? s->freq : 11025;
742 samples = dsp_get_lohi (s) + 1;
85571bc7 743 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
15b61470 744 ticks = (bytes * ticks_per_sec) / freq;
1d14ffa9 745 if (ticks < ticks_per_sec / 1024) {
85571bc7 746 pic_set_irq (s->irq, 1);
1d14ffa9
FB
747 }
748 else {
749 if (s->aux_ts) {
750 qemu_mod_timer (
751 s->aux_ts,
752 qemu_get_clock (vm_clock) + ticks
753 );
754 }
755 }
85571bc7
FB
756 ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
757 }
27503323
FB
758 break;
759
760 case 0xe0:
85571bc7
FB
761 d0 = dsp_get_data (s);
762 s->out_data_len = 0;
763 ldebug ("E0 data = %#x\n", d0);
1d14ffa9 764 dsp_out_data (s, ~d0);
d75d9f6b
FB
765 break;
766
85571bc7
FB
767 case 0xe2:
768 d0 = dsp_get_data (s);
15b61470 769 ldebug ("E2 = %#x\n", d0);
d75d9f6b
FB
770 break;
771
85571bc7
FB
772 case 0xe4:
773 s->test_reg = dsp_get_data (s);
774 break;
d75d9f6b
FB
775
776 case 0xf9:
85571bc7
FB
777 d0 = dsp_get_data (s);
778 ldebug ("command 0xf9 with %#x\n", d0);
d75d9f6b 779 switch (d0) {
85571bc7
FB
780 case 0x0e:
781 dsp_out_data (s, 0xff);
782 break;
783
784 case 0x0f:
785 dsp_out_data (s, 0x07);
786 break;
787
d75d9f6b 788 case 0x37:
85571bc7
FB
789 dsp_out_data (s, 0x38);
790 break;
791
d75d9f6b 792 default:
85571bc7
FB
793 dsp_out_data (s, 0x00);
794 break;
d75d9f6b 795 }
27503323
FB
796 break;
797
798 default:
85571bc7 799 dolog ("complete: unrecognized command %#x\n", s->cmd);
5e2a6443 800 return;
27503323
FB
801 }
802 }
803
85571bc7
FB
804 ldebug ("\n");
805 s->cmd = -1;
27503323 806 return;
27503323
FB
807}
808
85571bc7
FB
809static void reset (SB16State *s)
810{
811 pic_set_irq (s->irq, 0);
812 if (s->dma_auto) {
813 pic_set_irq (s->irq, 1);
814 pic_set_irq (s->irq, 0);
815 }
816
817 s->mixer_regs[0x82] = 0;
818 s->dma_auto = 0;
819 s->in_index = 0;
820 s->out_data_len = 0;
821 s->left_till_irq = 0;
822 s->needed_bytes = 0;
823 s->block_size = -1;
824 s->nzero = 0;
825 s->highspeed = 0;
826 s->v2x6 = 0;
1d14ffa9 827 s->cmd = -1;
85571bc7
FB
828
829 dsp_out_data(s, 0xaa);
830 speaker (s, 0);
831 control (s, 0);
832}
833
27503323
FB
834static IO_WRITE_PROTO (dsp_write)
835{
85571bc7 836 SB16State *s = opaque;
27503323
FB
837 int iport;
838
85571bc7 839 iport = nport - s->port;
27503323 840
85571bc7 841 ldebug ("write %#x <- %#x\n", nport, val);
27503323 842 switch (iport) {
85571bc7
FB
843 case 0x06:
844 switch (val) {
845 case 0x00:
846 if (s->v2x6 == 1) {
847 if (0 && s->highspeed) {
848 s->highspeed = 0;
849 pic_set_irq (s->irq, 0);
850 control (s, 0);
851 }
1d14ffa9 852 else {
85571bc7 853 reset (s);
1d14ffa9 854 }
85571bc7
FB
855 }
856 s->v2x6 = 0;
857 break;
858
859 case 0x01:
860 case 0x03: /* FreeBSD kludge */
861 s->v2x6 = 1;
862 break;
863
864 case 0xc6:
865 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
866 break;
867
868 case 0xb8: /* Panic */
869 reset (s);
870 break;
871
872 case 0x39:
873 dsp_out_data (s, 0x38);
874 reset (s);
875 s->v2x6 = 0x39;
876 break;
877
878 default:
879 s->v2x6 = val;
880 break;
27503323 881 }
27503323
FB
882 break;
883
85571bc7
FB
884 case 0x0c: /* write data or command | write status */
885/* if (s->highspeed) */
886/* break; */
887
888 if (0 == s->needed_bytes) {
889 command (s, val);
890#if 0
891 if (0 == s->needed_bytes) {
892 log_dsp (s);
27503323 893 }
85571bc7 894#endif
27503323
FB
895 }
896 else {
85571bc7 897 if (s->in_index == sizeof (s->in2_data)) {
d75d9f6b
FB
898 dolog ("in data overrun\n");
899 }
900 else {
85571bc7
FB
901 s->in2_data[s->in_index++] = val;
902 if (s->in_index == s->needed_bytes) {
903 s->needed_bytes = 0;
904 complete (s);
905#if 0
906 log_dsp (s);
907#endif
908 }
27503323
FB
909 }
910 }
911 break;
912
913 default:
85571bc7 914 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
5e2a6443 915 break;
27503323
FB
916 }
917}
918
919static IO_READ_PROTO (dsp_read)
920{
85571bc7
FB
921 SB16State *s = opaque;
922 int iport, retval, ack = 0;
27503323 923
85571bc7 924 iport = nport - s->port;
27503323
FB
925
926 switch (iport) {
85571bc7
FB
927 case 0x06: /* reset */
928 retval = 0xff;
d75d9f6b 929 break;
27503323 930
85571bc7
FB
931 case 0x0a: /* read data */
932 if (s->out_data_len) {
933 retval = s->out_data[--s->out_data_len];
934 s->last_read_byte = retval;
935 }
936 else {
1d14ffa9
FB
937 if (s->cmd != -1) {
938 dolog ("empty output buffer for command %#x\n",
939 s->cmd);
940 }
85571bc7 941 retval = s->last_read_byte;
d75d9f6b 942 /* goto error; */
27503323
FB
943 }
944 break;
945
85571bc7
FB
946 case 0x0c: /* 0 can write */
947 retval = s->can_write ? 0 : 0x80;
27503323
FB
948 break;
949
85571bc7
FB
950 case 0x0d: /* timer interrupt clear */
951 /* dolog ("timer interrupt clear\n"); */
952 retval = 0;
953 break;
27503323 954
85571bc7
FB
955 case 0x0e: /* data available status | irq 8 ack */
956 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
957 if (s->mixer_regs[0x82] & 1) {
958 ack = 1;
959 s->mixer_regs[0x82] &= 1;
960 pic_set_irq (s->irq, 0);
961 }
27503323
FB
962 break;
963
85571bc7 964 case 0x0f: /* irq 16 ack */
bc0b1dc1 965 retval = 0xff;
85571bc7
FB
966 if (s->mixer_regs[0x82] & 2) {
967 ack = 1;
968 s->mixer_regs[0x82] &= 2;
969 pic_set_irq (s->irq, 0);
970 }
27503323
FB
971 break;
972
973 default:
974 goto error;
975 }
976
1d14ffa9 977 if (!ack) {
85571bc7 978 ldebug ("read %#x -> %#x\n", nport, retval);
1d14ffa9 979 }
27503323
FB
980
981 return retval;
982
983 error:
1d14ffa9 984 dolog ("warning: dsp_read %#x error\n", nport);
d75d9f6b 985 return 0xff;
27503323
FB
986}
987
85571bc7
FB
988static void reset_mixer (SB16State *s)
989{
990 int i;
991
992 memset (s->mixer_regs, 0xff, 0x7f);
993 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
994
995 s->mixer_regs[0x02] = 4; /* master volume 3bits */
996 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
997 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
998 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
999
1000 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1001 s->mixer_regs[0x0c] = 0;
1002
1003 /* d5=output filt, d1=stereo switch */
1004 s->mixer_regs[0x0e] = 0;
1005
1006 /* voice volume L d5,d7, R d1,d3 */
1007 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1008 /* master ... */
1009 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1010 /* MIDI ... */
1011 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1012
1013 for (i = 0x30; i < 0x48; i++) {
1014 s->mixer_regs[i] = 0x20;
1015 }
1016}
1017
27503323
FB
1018static IO_WRITE_PROTO(mixer_write_indexb)
1019{
85571bc7
FB
1020 SB16State *s = opaque;
1021 s->mixer_nreg = val;
27503323
FB
1022}
1023
1024static IO_WRITE_PROTO(mixer_write_datab)
1025{
85571bc7
FB
1026 SB16State *s = opaque;
1027
1028 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1d14ffa9 1029 if (s->mixer_nreg > sizeof (s->mixer_regs)) {
85571bc7 1030 return;
1d14ffa9 1031 }
202a456a 1032
85571bc7 1033 switch (s->mixer_nreg) {
d75d9f6b 1034 case 0x00:
85571bc7 1035 reset_mixer (s);
d75d9f6b
FB
1036 break;
1037
d75d9f6b 1038 case 0x80:
85571bc7
FB
1039 {
1040 int irq = irq_of_magic (val);
1041 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1d14ffa9 1042 if (irq > 0) {
85571bc7 1043 s->irq = irq;
1d14ffa9 1044 }
85571bc7 1045 }
d75d9f6b 1046 break;
27503323 1047
85571bc7
FB
1048 case 0x81:
1049 {
1050 int dma, hdma;
d75d9f6b 1051
85571bc7
FB
1052 dma = lsbindex (val & 0xf);
1053 hdma = lsbindex (val & 0xf0);
1d14ffa9
FB
1054 if (dma != s->dma || hdma != s->hdma) {
1055 dolog (
1056 "attempt to change DMA "
1057 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1058 dma, s->dma, hdma, s->hdma, val);
1059 }
85571bc7
FB
1060#if 0
1061 s->dma = dma;
1062 s->hdma = hdma;
1063#endif
1064 }
1065 break;
d75d9f6b 1066
85571bc7
FB
1067 case 0x82:
1068 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1069 val);
1070 return;
d75d9f6b 1071
85571bc7 1072 default:
1d14ffa9
FB
1073 if (s->mixer_nreg >= 0x80) {
1074 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1075 }
85571bc7
FB
1076 break;
1077 }
1078
1079 s->mixer_regs[s->mixer_nreg] = val;
d75d9f6b
FB
1080}
1081
27503323
FB
1082static IO_WRITE_PROTO(mixer_write_indexw)
1083{
7d977de7
FB
1084 mixer_write_indexb (opaque, nport, val & 0xff);
1085 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
27503323
FB
1086}
1087
1088static IO_READ_PROTO(mixer_read)
1089{
85571bc7 1090 SB16State *s = opaque;
15b61470 1091#ifndef DEBUG_SB16_MOST
1d14ffa9
FB
1092 if (s->mixer_nreg != 0x82) {
1093 ldebug ("mixer_read[%#x] -> %#x\n",
1094 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1095 }
1096#else
85571bc7
FB
1097 ldebug ("mixer_read[%#x] -> %#x\n",
1098 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1d14ffa9 1099#endif
85571bc7 1100 return s->mixer_regs[s->mixer_nreg];
27503323
FB
1101}
1102
85571bc7
FB
1103static int write_audio (SB16State *s, int nchan, int dma_pos,
1104 int dma_len, int len)
27503323
FB
1105{
1106 int temp, net;
f9e92e97 1107 uint8_t tmpbuf[4096];
27503323 1108
85571bc7 1109 temp = len;
27503323
FB
1110 net = 0;
1111
1112 while (temp) {
85571bc7
FB
1113 int left = dma_len - dma_pos;
1114 int to_copy, copied;
27503323 1115
85571bc7 1116 to_copy = audio_MIN (temp, left);
1d14ffa9 1117 if (to_copy > sizeof(tmpbuf)) {
f9e92e97 1118 to_copy = sizeof(tmpbuf);
1d14ffa9 1119 }
27503323 1120
85571bc7
FB
1121 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1122 copied = AUD_write (s->voice, tmpbuf, copied);
27503323 1123
85571bc7
FB
1124 temp -= copied;
1125 dma_pos = (dma_pos + copied) % dma_len;
27503323
FB
1126 net += copied;
1127
1d14ffa9 1128 if (!copied) {
85571bc7 1129 break;
1d14ffa9 1130 }
27503323
FB
1131 }
1132
1133 return net;
1134}
1135
85571bc7 1136static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
27503323 1137{
85571bc7 1138 SB16State *s = opaque;
1d14ffa9 1139 int till, copy, written, free;
27503323 1140
85571bc7
FB
1141 if (s->left_till_irq < 0) {
1142 s->left_till_irq = s->block_size;
27503323
FB
1143 }
1144
1d14ffa9
FB
1145 if (s->voice) {
1146 free = s->audio_free & ~s->align;
1147 if ((free <= 0) || !dma_len) {
1148 return dma_pos;
1149 }
1150 }
1151 else {
1152 free = dma_len;
27503323
FB
1153 }
1154
85571bc7
FB
1155 copy = free;
1156 till = s->left_till_irq;
27503323 1157
d75d9f6b 1158#ifdef DEBUG_SB16_MOST
1d14ffa9
FB
1159 dolog ("pos:%06d %d till:%d len:%d\n",
1160 dma_pos, free, till, dma_len);
d75d9f6b
FB
1161#endif
1162
27503323 1163 if (till <= copy) {
85571bc7 1164 if (0 == s->dma_auto) {
27503323
FB
1165 copy = till;
1166 }
1167 }
1168
85571bc7
FB
1169 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1170 dma_pos = (dma_pos + written) % dma_len;
1171 s->left_till_irq -= written;
27503323 1172
85571bc7
FB
1173 if (s->left_till_irq <= 0) {
1174 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1175 pic_set_irq (s->irq, 1);
1176 if (0 == s->dma_auto) {
1177 control (s, 0);
1178 speaker (s, 0);
27503323
FB
1179 }
1180 }
1181
d75d9f6b 1182#ifdef DEBUG_SB16_MOST
15b61470
FB
1183 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1184 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1185 s->block_size);
d75d9f6b 1186#endif
27503323 1187
85571bc7
FB
1188 while (s->left_till_irq <= 0) {
1189 s->left_till_irq = s->block_size + s->left_till_irq;
27503323
FB
1190 }
1191
85571bc7 1192 return dma_pos;
27503323
FB
1193}
1194
1d14ffa9 1195static void SB_audio_callback (void *opaque, int free)
27503323 1196{
85571bc7 1197 SB16State *s = opaque;
1d14ffa9 1198 s->audio_free = free;
27503323
FB
1199}
1200
85571bc7 1201static void SB_save (QEMUFile *f, void *opaque)
d75d9f6b 1202{
85571bc7
FB
1203 SB16State *s = opaque;
1204
1205 qemu_put_be32s (f, &s->irq);
1206 qemu_put_be32s (f, &s->dma);
1207 qemu_put_be32s (f, &s->hdma);
1208 qemu_put_be32s (f, &s->port);
1209 qemu_put_be32s (f, &s->ver);
1210 qemu_put_be32s (f, &s->in_index);
1211 qemu_put_be32s (f, &s->out_data_len);
1212 qemu_put_be32s (f, &s->fmt_stereo);
1213 qemu_put_be32s (f, &s->fmt_signed);
1214 qemu_put_be32s (f, &s->fmt_bits);
1215 qemu_put_be32s (f, &s->fmt);
1216 qemu_put_be32s (f, &s->dma_auto);
1217 qemu_put_be32s (f, &s->block_size);
1218 qemu_put_be32s (f, &s->fifo);
1219 qemu_put_be32s (f, &s->freq);
1220 qemu_put_be32s (f, &s->time_const);
1221 qemu_put_be32s (f, &s->speaker);
1222 qemu_put_be32s (f, &s->needed_bytes);
1223 qemu_put_be32s (f, &s->cmd);
1224 qemu_put_be32s (f, &s->use_hdma);
1225 qemu_put_be32s (f, &s->highspeed);
1226 qemu_put_be32s (f, &s->can_write);
1227 qemu_put_be32s (f, &s->v2x6);
1228
1229 qemu_put_8s (f, &s->csp_param);
1230 qemu_put_8s (f, &s->csp_value);
1231 qemu_put_8s (f, &s->csp_mode);
1232 qemu_put_8s (f, &s->csp_param);
1233 qemu_put_buffer (f, s->csp_regs, 256);
1234 qemu_put_8s (f, &s->csp_index);
1235 qemu_put_buffer (f, s->csp_reg83, 4);
1236 qemu_put_be32s (f, &s->csp_reg83r);
1237 qemu_put_be32s (f, &s->csp_reg83w);
1238
1239 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1240 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1241 qemu_put_8s (f, &s->test_reg);
1242 qemu_put_8s (f, &s->last_read_byte);
1243
1244 qemu_put_be32s (f, &s->nzero);
1245 qemu_put_be32s (f, &s->left_till_irq);
1246 qemu_put_be32s (f, &s->dma_running);
1247 qemu_put_be32s (f, &s->bytes_per_second);
1248 qemu_put_be32s (f, &s->align);
1249
1250 qemu_put_be32s (f, &s->mixer_nreg);
1251 qemu_put_buffer (f, s->mixer_regs, 256);
d75d9f6b
FB
1252}
1253
85571bc7 1254static int SB_load (QEMUFile *f, void *opaque, int version_id)
d75d9f6b 1255{
85571bc7
FB
1256 SB16State *s = opaque;
1257
1d14ffa9 1258 if (version_id != 1) {
85571bc7 1259 return -EINVAL;
1d14ffa9 1260 }
85571bc7
FB
1261
1262 qemu_get_be32s (f, &s->irq);
1263 qemu_get_be32s (f, &s->dma);
1264 qemu_get_be32s (f, &s->hdma);
1265 qemu_get_be32s (f, &s->port);
1266 qemu_get_be32s (f, &s->ver);
1267 qemu_get_be32s (f, &s->in_index);
1268 qemu_get_be32s (f, &s->out_data_len);
1269 qemu_get_be32s (f, &s->fmt_stereo);
1270 qemu_get_be32s (f, &s->fmt_signed);
1271 qemu_get_be32s (f, &s->fmt_bits);
1272 qemu_get_be32s (f, &s->fmt);
1273 qemu_get_be32s (f, &s->dma_auto);
1274 qemu_get_be32s (f, &s->block_size);
1275 qemu_get_be32s (f, &s->fifo);
1276 qemu_get_be32s (f, &s->freq);
1277 qemu_get_be32s (f, &s->time_const);
1278 qemu_get_be32s (f, &s->speaker);
1279 qemu_get_be32s (f, &s->needed_bytes);
1280 qemu_get_be32s (f, &s->cmd);
1281 qemu_get_be32s (f, &s->use_hdma);
1282 qemu_get_be32s (f, &s->highspeed);
1283 qemu_get_be32s (f, &s->can_write);
1284 qemu_get_be32s (f, &s->v2x6);
1285
1286 qemu_get_8s (f, &s->csp_param);
1287 qemu_get_8s (f, &s->csp_value);
1288 qemu_get_8s (f, &s->csp_mode);
1289 qemu_get_8s (f, &s->csp_param);
1290 qemu_get_buffer (f, s->csp_regs, 256);
1291 qemu_get_8s (f, &s->csp_index);
1292 qemu_get_buffer (f, s->csp_reg83, 4);
1293 qemu_get_be32s (f, &s->csp_reg83r);
1294 qemu_get_be32s (f, &s->csp_reg83w);
1295
1296 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1297 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1298 qemu_get_8s (f, &s->test_reg);
1299 qemu_get_8s (f, &s->last_read_byte);
1300
1301 qemu_get_be32s (f, &s->nzero);
1302 qemu_get_be32s (f, &s->left_till_irq);
1303 qemu_get_be32s (f, &s->dma_running);
1304 qemu_get_be32s (f, &s->bytes_per_second);
1305 qemu_get_be32s (f, &s->align);
1306
1307 qemu_get_be32s (f, &s->mixer_nreg);
1308 qemu_get_buffer (f, s->mixer_regs, 256);
1309
fb065187 1310 if (s->voice) {
1d14ffa9 1311 AUD_close_out (s->voice);
fb065187
FB
1312 s->voice = NULL;
1313 }
85571bc7
FB
1314
1315 if (s->dma_running) {
1d14ffa9
FB
1316 if (s->freq) {
1317 s->audio_free = 0;
1318 s->voice = AUD_open_out (
1319 s->voice,
1320 "sb16",
1321 s,
1322 SB_audio_callback,
1323 s->freq,
1324 1 << s->fmt_stereo,
1325 s->fmt
1326 );
1327 }
85571bc7
FB
1328
1329 control (s, 1);
1330 speaker (s, s->speaker);
d75d9f6b 1331 }
85571bc7 1332 return 0;
d75d9f6b 1333}
d75d9f6b 1334
27503323
FB
1335void SB16_init (void)
1336{
5e2a6443 1337 SB16State *s = &dsp;
27503323
FB
1338 int i;
1339 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1340 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1341
1d14ffa9 1342 s->cmd = -1;
85571bc7
FB
1343 s->irq = conf.irq;
1344 s->dma = conf.dma;
1345 s->hdma = conf.hdma;
1346 s->port = conf.port;
1347 s->ver = conf.ver_lo | (conf.ver_hi << 8);
202a456a 1348
85571bc7
FB
1349 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1350 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1351 s->mixer_regs[0x82] = 2 << 5;
1352
1353 s->csp_regs[5] = 1;
1354 s->csp_regs[9] = 0xf8;
1355
1356 reset_mixer (s);
1357 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1d14ffa9
FB
1358 if (!s->aux_ts) {
1359 dolog ("Can not create auxiliary timer\n");
1360 }
27503323
FB
1361
1362 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
85571bc7 1363 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
27503323
FB
1364 }
1365
1366 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
85571bc7 1367 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
27503323
FB
1368 }
1369
85571bc7
FB
1370 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1371 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1372 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1373 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
27503323 1374
85571bc7
FB
1375 DMA_register_channel (s->hdma, SB_read_DMA, s);
1376 DMA_register_channel (s->dma, SB_read_DMA, s);
1377 s->can_write = 1;
d75d9f6b 1378
85571bc7 1379 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
27503323 1380}
This page took 0.258455 seconds and 4 git commands to generate.