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