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