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