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