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