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