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