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