]> git.proxmox.com Git - qemu.git/blame - hw/sb16.c
audio clean up (initial patch by malc)
[qemu.git] / hw / sb16.c
CommitLineData
27503323
FB
1/*
2 * QEMU Soundblaster 16 emulation
3 *
85571bc7 4 * Copyright (c) 2003-2004 Vassili Karpov (malc)
27503323
FB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
27503323
FB
24#include "vl.h"
25
85571bc7 26#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
d75d9f6b 27
fb065187
FB
28#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
29#ifdef DEBUG
30#define ldebug(...) dolog (__VA_ARGS__)
31#else
32#define ldebug(...)
33#endif
34
35/* #define DEBUG */
85571bc7 36/* #define DEBUG_SB16_MOST */
27503323 37
85571bc7 38#define IO_READ_PROTO(name) \
7d977de7 39 uint32_t name (void *opaque, uint32_t nport)
85571bc7 40#define IO_WRITE_PROTO(name) \
7d977de7 41 void name (void *opaque, uint32_t nport, uint32_t val)
27503323 42
85571bc7 43static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
d329a6fb 44
27503323
FB
45static struct {
46 int ver_lo;
47 int ver_hi;
48 int irq;
49 int dma;
50 int hdma;
51 int port;
85571bc7 52} conf = {5, 4, 5, 1, 5, 0x220};
27503323 53
5e2a6443 54typedef struct SB16State {
85571bc7
FB
55 int irq;
56 int dma;
57 int hdma;
58 int port;
59 int ver;
60
27503323
FB
61 int in_index;
62 int out_data_len;
63 int fmt_stereo;
64 int fmt_signed;
65 int fmt_bits;
85571bc7 66 audfmt_e fmt;
27503323 67 int dma_auto;
85571bc7 68 int block_size;
27503323
FB
69 int fifo;
70 int freq;
71 int time_const;
72 int speaker;
73 int needed_bytes;
74 int cmd;
27503323 75 int use_hdma;
85571bc7
FB
76 int highspeed;
77 int can_write;
27503323
FB
78
79 int v2x6;
80
85571bc7
FB
81 uint8_t csp_param;
82 uint8_t csp_value;
83 uint8_t csp_mode;
84 uint8_t csp_regs[256];
85 uint8_t csp_index;
86 uint8_t csp_reg83[4];
87 int csp_reg83r;
88 int csp_reg83w;
89
d75d9f6b 90 uint8_t in2_data[10];
85571bc7
FB
91 uint8_t out_data[50];
92 uint8_t test_reg;
93 uint8_t last_read_byte;
94 int nzero;
27503323
FB
95
96 int left_till_irq;
27503323 97
85571bc7
FB
98 int dma_running;
99 int bytes_per_second;
100 int align;
101 SWVoice *voice;
102
103 QEMUTimer *ts, *aux_ts;
5e2a6443
FB
104 /* mixer state */
105 int mixer_nreg;
202a456a 106 uint8_t mixer_regs[256];
5e2a6443 107} SB16State;
27503323 108
5e2a6443
FB
109/* XXX: suppress that and use a context */
110static struct SB16State dsp;
27503323 111
85571bc7
FB
112static int magic_of_irq (int irq)
113{
114 switch (irq) {
115 case 5:
116 return 2;
117 case 7:
118 return 4;
119 case 9:
120 return 1;
121 case 10:
122 return 8;
123 default:
124 dolog ("bad irq %d\n", irq);
125 return 2;
126 }
127}
128
129static int irq_of_magic (int magic)
130{
131 switch (magic) {
132 case 1:
133 return 9;
134 case 2:
135 return 5;
136 case 4:
137 return 7;
138 case 8:
139 return 10;
140 default:
141 dolog ("bad irq magic %d\n", magic);
142 return -1;
143 }
144}
145
146#if 0
5e2a6443
FB
147static void log_dsp (SB16State *dsp)
148{
85571bc7
FB
149 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
150 dsp->fmt_stereo ? "Stereo" : "Mono",
151 dsp->fmt_signed ? "Signed" : "Unsigned",
152 dsp->fmt_bits,
153 dsp->dma_auto ? "Auto" : "Single",
154 dsp->block_size,
155 dsp->freq,
156 dsp->time_const,
157 dsp->speaker);
158}
159#endif
160
161static void speaker (SB16State *s, int on)
162{
163 s->speaker = on;
164 /* AUD_enable (s->voice, on); */
27503323
FB
165}
166
85571bc7 167static void control (SB16State *s, int hold)
27503323 168{
85571bc7
FB
169 int dma = s->use_hdma ? s->hdma : s->dma;
170 s->dma_running = hold;
171
172 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
173
27503323 174 if (hold) {
85571bc7
FB
175 DMA_hold_DREQ (dma);
176 AUD_enable (s->voice, 1);
27503323
FB
177 }
178 else {
85571bc7
FB
179 DMA_release_DREQ (dma);
180 AUD_enable (s->voice, 0);
27503323
FB
181 }
182}
183
85571bc7 184static void aux_timer (void *opaque)
27503323 185{
85571bc7
FB
186 SB16State *s = opaque;
187 s->can_write = 1;
188 pic_set_irq (s->irq, 1);
189}
190
191#define DMA8_AUTO 1
192#define DMA8_HIGH 2
193
194static void dma_cmd8 (SB16State *s, int mask, int dma_len)
195{
196 s->fmt = AUD_FMT_U8;
197 s->use_hdma = 0;
198 s->fmt_bits = 8;
199 s->fmt_signed = 0;
200 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
201 if (-1 == s->time_const) {
202 s->freq = 11025;
203 }
204 else {
205 int tmp = (256 - s->time_const);
206 s->freq = (1000000 + (tmp / 2)) / tmp;
207 }
208
209 if (-1 != dma_len)
210 s->block_size = dma_len + 1;
211
212 s->freq >>= s->fmt_stereo;
213 s->left_till_irq = s->block_size;
214 s->bytes_per_second = (s->freq << s->fmt_stereo);
215 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
216 s->dma_auto = (mask & DMA8_AUTO) != 0;
217 s->align = (1 << s->fmt_stereo) - 1;
218
219 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
220 "dma %d, auto %d, fifo %d, high %d\n",
221 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
222 s->block_size, s->dma_auto, s->fifo, s->highspeed);
223
224 if (s->freq)
225 s->voice = AUD_open (s->voice, "sb16", s->freq,
226 1 << s->fmt_stereo, s->fmt);
227
228 control (s, 1);
229 speaker (s, 1);
230}
27503323 231
85571bc7
FB
232static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
233{
234 s->use_hdma = cmd < 0xc0;
235 s->fifo = (cmd >> 1) & 1;
236 s->dma_auto = (cmd >> 2) & 1;
237 s->fmt_signed = (d0 >> 4) & 1;
238 s->fmt_stereo = (d0 >> 5) & 1;
27503323
FB
239
240 switch (cmd >> 4) {
241 case 11:
85571bc7 242 s->fmt_bits = 16;
27503323
FB
243 break;
244
245 case 12:
85571bc7 246 s->fmt_bits = 8;
27503323
FB
247 break;
248 }
249
85571bc7
FB
250 if (-1 != s->time_const) {
251#if 1
252 int tmp = 256 - s->time_const;
253 s->freq = (1000000 + (tmp / 2)) / tmp;
254#else
255 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
256 s->freq = 1000000 / ((255 - s->time_const));
257#endif
258 s->time_const = -1;
27503323 259 }
27503323 260
85571bc7
FB
261 s->block_size = dma_len + 1;
262 s->block_size <<= (s->fmt_bits == 16);
263 if (!s->dma_auto) /* Miles Sound System ? */
264 s->block_size <<= s->fmt_stereo;
27503323 265
85571bc7
FB
266 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
267 "dma %d, auto %d, fifo %d, high %d\n",
268 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
269 s->block_size, s->dma_auto, s->fifo, s->highspeed);
27503323 270
85571bc7
FB
271 if (16 == s->fmt_bits) {
272 if (s->fmt_signed) {
273 s->fmt = AUD_FMT_S16;
27503323
FB
274 }
275 else {
85571bc7 276 s->fmt = AUD_FMT_U16;
27503323
FB
277 }
278 }
279 else {
85571bc7
FB
280 if (s->fmt_signed) {
281 s->fmt = AUD_FMT_S8;
27503323
FB
282 }
283 else {
85571bc7 284 s->fmt = AUD_FMT_U8;
27503323
FB
285 }
286 }
287
85571bc7 288 s->left_till_irq = s->block_size;
27503323 289
85571bc7
FB
290 s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
291 s->highspeed = 0;
292 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
27503323 293
85571bc7
FB
294 if (s->freq)
295 s->voice = AUD_open (s->voice, "sb16", s->freq,
296 1 << s->fmt_stereo, s->fmt);
27503323 297
85571bc7
FB
298 control (s, 1);
299 speaker (s, 1);
27503323
FB
300}
301
85571bc7 302static inline void dsp_out_data (SB16State *s, uint8_t val)
202a456a 303{
85571bc7
FB
304 ldebug ("outdata %#x\n", val);
305 if (s->out_data_len < sizeof (s->out_data))
306 s->out_data[s->out_data_len++] = val;
202a456a
FB
307}
308
85571bc7 309static inline uint8_t dsp_get_data (SB16State *s)
d75d9f6b 310{
85571bc7
FB
311 if (s->in_index)
312 return s->in2_data[--s->in_index];
313 else {
314 dolog ("buffer underflow\n");
d75d9f6b 315 return 0;
85571bc7 316 }
d75d9f6b
FB
317}
318
85571bc7 319static void command (SB16State *s, uint8_t cmd)
27503323 320{
85571bc7 321 ldebug ("command %#x\n", cmd);
27503323
FB
322
323 if (cmd > 0xaf && cmd < 0xd0) {
85571bc7
FB
324 if (cmd & 8) {
325 dolog ("ADC not yet supported (command %#x)\n", cmd);
326 }
27503323
FB
327
328 switch (cmd >> 4) {
329 case 11:
330 case 12:
331 break;
332 default:
85571bc7 333 dolog ("%#x wrong bits\n", cmd);
27503323 334 }
85571bc7 335 s->needed_bytes = 3;
27503323
FB
336 }
337 else {
338 switch (cmd) {
d75d9f6b 339 case 0x03:
85571bc7
FB
340 dsp_out_data (s, 0x10); /* s->csp_param); */
341 goto warn;
342
d329a6fb 343 case 0x04:
85571bc7
FB
344 s->needed_bytes = 1;
345 goto warn;
d329a6fb
FB
346
347 case 0x05:
85571bc7
FB
348 s->needed_bytes = 2;
349 goto warn;
350
351 case 0x08:
352 /* __asm__ ("int3"); */
353 goto warn;
d75d9f6b 354
d329a6fb 355 case 0x0e:
85571bc7
FB
356 s->needed_bytes = 2;
357 goto warn;
358
359 case 0x09:
360 dsp_out_data (s, 0xf8);
361 goto warn;
d329a6fb
FB
362
363 case 0x0f:
85571bc7
FB
364 s->needed_bytes = 1;
365 goto warn;
d329a6fb 366
27503323 367 case 0x10:
85571bc7
FB
368 s->needed_bytes = 1;
369 goto warn;
27503323
FB
370
371 case 0x14:
85571bc7
FB
372 s->needed_bytes = 2;
373 s->block_size = 0;
27503323
FB
374 break;
375
85571bc7
FB
376 case 0x20: /* Direct ADC, Juice/PL */
377 dsp_out_data (s, 0xff);
378 goto warn;
27503323
FB
379
380 case 0x35:
85571bc7 381 dolog ("MIDI command(0x35) not implemented\n");
27503323
FB
382 break;
383
384 case 0x40:
85571bc7
FB
385 s->freq = -1;
386 s->time_const = -1;
387 s->needed_bytes = 1;
27503323
FB
388 break;
389
390 case 0x41:
85571bc7
FB
391 s->freq = -1;
392 s->time_const = -1;
393 s->needed_bytes = 2;
27503323
FB
394 break;
395
85571bc7
FB
396 case 0x42:
397 s->freq = -1;
398 s->time_const = -1;
399 s->needed_bytes = 2;
400 goto warn;
401
d75d9f6b 402 case 0x45:
85571bc7
FB
403 dsp_out_data (s, 0xaa);
404 goto warn;
405
27503323
FB
406 case 0x47: /* Continue Auto-Initialize DMA 16bit */
407 break;
408
409 case 0x48:
85571bc7 410 s->needed_bytes = 2;
27503323
FB
411 break;
412
27503323 413 case 0x80:
85571bc7 414 s->needed_bytes = 2;
27503323
FB
415 break;
416
417 case 0x90:
418 case 0x91:
85571bc7
FB
419 dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
420 break;
27503323 421
85571bc7
FB
422 case 0xd0: /* halt DMA operation. 8bit */
423 control (s, 0);
424 break;
27503323 425
85571bc7
FB
426 case 0xd1: /* speaker on */
427 speaker (s, 1);
27503323
FB
428 break;
429
85571bc7
FB
430 case 0xd3: /* speaker off */
431 speaker (s, 0);
432 break;
27503323 433
85571bc7
FB
434 case 0xd4: /* continue DMA operation. 8bit */
435 control (s, 1);
27503323
FB
436 break;
437
85571bc7
FB
438 case 0xd5: /* halt DMA operation. 16bit */
439 control (s, 0);
27503323
FB
440 break;
441
85571bc7
FB
442 case 0xd6: /* continue DMA operation. 16bit */
443 control (s, 1);
27503323
FB
444 break;
445
85571bc7
FB
446 case 0xd9: /* exit auto-init DMA after this block. 16bit */
447 s->dma_auto = 0;
448 break;
27503323 449
85571bc7
FB
450 case 0xda: /* exit auto-init DMA after this block. 8bit */
451 s->dma_auto = 0;
27503323
FB
452 break;
453
454 case 0xe0:
85571bc7
FB
455 s->needed_bytes = 1;
456 goto warn;
27503323
FB
457
458 case 0xe1:
85571bc7
FB
459 dsp_out_data (s, s->ver & 0xff);
460 dsp_out_data (s, s->ver >> 8);
461 break;
462
463 case 0xe2:
464 s->needed_bytes = 1;
465 goto warn;
27503323 466
d329a6fb
FB
467 case 0xe3:
468 {
469 int i;
85571bc7
FB
470 for (i = sizeof (e3) - 1; i >= 0; --i)
471 dsp_out_data (s, e3[i]);
d329a6fb 472 }
85571bc7 473 break;
d329a6fb 474
d75d9f6b 475 case 0xe4: /* write test reg */
85571bc7 476 s->needed_bytes = 1;
d75d9f6b
FB
477 break;
478
85571bc7
FB
479 case 0xe7:
480 dolog ("Attempt to probe for ESS (0xe7)?\n");
481 return;
482
d75d9f6b 483 case 0xe8: /* read test reg */
85571bc7 484 dsp_out_data (s, s->test_reg);
d75d9f6b
FB
485 break;
486
27503323 487 case 0xf2:
85571bc7
FB
488 case 0xf3:
489 dsp_out_data (s, 0xaa);
490 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
491 pic_set_irq (s->irq, 1);
492 break;
27503323 493
d75d9f6b 494 case 0xf9:
85571bc7
FB
495 s->needed_bytes = 1;
496 goto warn;
d75d9f6b
FB
497
498 case 0xfa:
85571bc7
FB
499 dsp_out_data (s, 0);
500 goto warn;
d75d9f6b
FB
501
502 case 0xfc: /* FIXME */
85571bc7
FB
503 dsp_out_data (s, 0);
504 goto warn;
d75d9f6b 505
27503323 506 default:
d75d9f6b 507 dolog ("unrecognized command %#x\n", cmd);
85571bc7 508 return;
27503323
FB
509 }
510 }
85571bc7
FB
511
512 s->cmd = cmd;
513 if (!s->needed_bytes)
514 ldebug ("\n");
27503323
FB
515 return;
516
85571bc7 517 warn:
fb065187 518 dolog ("warning: command %#x,%d is not trully understood yet\n",
85571bc7
FB
519 cmd, s->needed_bytes);
520 s->cmd = cmd;
27503323
FB
521 return;
522}
523
85571bc7
FB
524static uint16_t dsp_get_lohi (SB16State *s)
525{
526 uint8_t hi = dsp_get_data (s);
527 uint8_t lo = dsp_get_data (s);
528 return (hi << 8) | lo;
529}
530
531static uint16_t dsp_get_hilo (SB16State *s)
532{
533 uint8_t lo = dsp_get_data (s);
534 uint8_t hi = dsp_get_data (s);
535 return (hi << 8) | lo;
536}
537
538static void complete (SB16State *s)
27503323 539{
d75d9f6b 540 int d0, d1, d2;
85571bc7
FB
541 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
542 s->cmd, s->in_index, s->needed_bytes);
27503323 543
85571bc7
FB
544 if (s->cmd > 0xaf && s->cmd < 0xd0) {
545 d2 = dsp_get_data (s);
546 d1 = dsp_get_data (s);
547 d0 = dsp_get_data (s);
27503323 548
85571bc7
FB
549 if (s->cmd & 8) {
550 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
551 s->cmd, d0, d1, d2);
552 }
553 else {
554 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
555 s->cmd, d0, d1, d2);
556 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
557 }
27503323
FB
558 }
559 else {
85571bc7 560 switch (s->cmd) {
d329a6fb 561 case 0x04:
85571bc7
FB
562 s->csp_mode = dsp_get_data (s);
563 s->csp_reg83r = 0;
564 s->csp_reg83w = 0;
565 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
d75d9f6b
FB
566 break;
567
85571bc7
FB
568 case 0x05:
569 s->csp_param = dsp_get_data (s);
570 s->csp_value = dsp_get_data (s);
571 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
572 s->csp_param,
573 s->csp_value);
d329a6fb 574 break;
27503323 575
d75d9f6b 576 case 0x0e:
85571bc7
FB
577 d0 = dsp_get_data (s);
578 d1 = dsp_get_data (s);
579 ldebug ("write CSP register %d <- %#x\n", d1, d0);
580 if (d1 == 0x83) {
581 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
582 s->csp_reg83[s->csp_reg83r % 4] = d0;
583 s->csp_reg83r += 1;
584 }
585 else
586 s->csp_regs[d1] = d0;
27503323
FB
587 break;
588
85571bc7
FB
589 case 0x0f:
590 d0 = dsp_get_data (s);
591 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
592 d0, s->csp_regs[d0], s->csp_mode);
593 if (d0 == 0x83) {
594 ldebug ("0x83[%d] -> %#x\n",
595 s->csp_reg83w,
596 s->csp_reg83[s->csp_reg83w % 4]);
597 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
598 s->csp_reg83w += 1;
599 }
600 else
601 dsp_out_data (s, s->csp_regs[d0]);
602 break;
27503323 603
85571bc7
FB
604 case 0x10:
605 d0 = dsp_get_data (s);
606 dolog ("cmd 0x10 d0=%#x\n", d0);
607 break;
27503323 608
85571bc7
FB
609 case 0x14:
610 dma_cmd8 (s, 0, dsp_get_lohi (s));
611 /* s->can_write = 0; */
612 /* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */
613 break;
27503323
FB
614
615 case 0x40:
85571bc7
FB
616 s->time_const = dsp_get_data (s);
617 ldebug ("set time const %d\n", s->time_const);
27503323
FB
618 break;
619
85571bc7
FB
620 case 0x42: /* FT2 sets output freq with this, go figure */
621 dolog ("cmd 0x42 might not do what it think it should\n");
d75d9f6b 622
85571bc7
FB
623 case 0x41:
624 s->freq = dsp_get_hilo (s);
625 ldebug ("set freq %d\n", s->freq);
27503323
FB
626 break;
627
628 case 0x48:
85571bc7
FB
629 s->block_size = dsp_get_lohi (s);
630 /* s->highspeed = 1; */
631 ldebug ("set dma block len %d\n", s->block_size);
632 break;
633
634 case 0x80:
635 {
636 int samples, bytes;
637 int64_t ticks;
638
639 if (-1 == s->freq)
640 s->freq = 11025;
641 samples = dsp_get_lohi (s);
642 bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
643 ticks = ticks_per_sec / (s->freq / bytes);
644 if (ticks < ticks_per_sec / 1024)
645 pic_set_irq (s->irq, 1);
646 else
647 qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
648 ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
649 }
27503323
FB
650 break;
651
652 case 0xe0:
85571bc7
FB
653 d0 = dsp_get_data (s);
654 s->out_data_len = 0;
655 ldebug ("E0 data = %#x\n", d0);
656 dsp_out_data(s, ~d0);
d75d9f6b
FB
657 break;
658
85571bc7
FB
659 case 0xe2:
660 d0 = dsp_get_data (s);
661 dolog ("E2 = %#x\n", d0);
d75d9f6b
FB
662 break;
663
85571bc7
FB
664 case 0xe4:
665 s->test_reg = dsp_get_data (s);
666 break;
d75d9f6b
FB
667
668 case 0xf9:
85571bc7
FB
669 d0 = dsp_get_data (s);
670 ldebug ("command 0xf9 with %#x\n", d0);
d75d9f6b 671 switch (d0) {
85571bc7
FB
672 case 0x0e:
673 dsp_out_data (s, 0xff);
674 break;
675
676 case 0x0f:
677 dsp_out_data (s, 0x07);
678 break;
679
d75d9f6b 680 case 0x37:
85571bc7
FB
681 dsp_out_data (s, 0x38);
682 break;
683
d75d9f6b 684 default:
85571bc7
FB
685 dsp_out_data (s, 0x00);
686 break;
d75d9f6b 687 }
27503323
FB
688 break;
689
690 default:
85571bc7 691 dolog ("complete: unrecognized command %#x\n", s->cmd);
5e2a6443 692 return;
27503323
FB
693 }
694 }
695
85571bc7
FB
696 ldebug ("\n");
697 s->cmd = -1;
27503323 698 return;
27503323
FB
699}
700
85571bc7
FB
701static void reset (SB16State *s)
702{
703 pic_set_irq (s->irq, 0);
704 if (s->dma_auto) {
705 pic_set_irq (s->irq, 1);
706 pic_set_irq (s->irq, 0);
707 }
708
709 s->mixer_regs[0x82] = 0;
710 s->dma_auto = 0;
711 s->in_index = 0;
712 s->out_data_len = 0;
713 s->left_till_irq = 0;
714 s->needed_bytes = 0;
715 s->block_size = -1;
716 s->nzero = 0;
717 s->highspeed = 0;
718 s->v2x6 = 0;
719
720 dsp_out_data(s, 0xaa);
721 speaker (s, 0);
722 control (s, 0);
723}
724
27503323
FB
725static IO_WRITE_PROTO (dsp_write)
726{
85571bc7 727 SB16State *s = opaque;
27503323
FB
728 int iport;
729
85571bc7 730 iport = nport - s->port;
27503323 731
85571bc7 732 ldebug ("write %#x <- %#x\n", nport, val);
27503323 733 switch (iport) {
85571bc7
FB
734 case 0x06:
735 switch (val) {
736 case 0x00:
737 if (s->v2x6 == 1) {
738 if (0 && s->highspeed) {
739 s->highspeed = 0;
740 pic_set_irq (s->irq, 0);
741 control (s, 0);
742 }
743 else
744 reset (s);
745 }
746 s->v2x6 = 0;
747 break;
748
749 case 0x01:
750 case 0x03: /* FreeBSD kludge */
751 s->v2x6 = 1;
752 break;
753
754 case 0xc6:
755 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
756 break;
757
758 case 0xb8: /* Panic */
759 reset (s);
760 break;
761
762 case 0x39:
763 dsp_out_data (s, 0x38);
764 reset (s);
765 s->v2x6 = 0x39;
766 break;
767
768 default:
769 s->v2x6 = val;
770 break;
27503323 771 }
27503323
FB
772 break;
773
85571bc7
FB
774 case 0x0c: /* write data or command | write status */
775/* if (s->highspeed) */
776/* break; */
777
778 if (0 == s->needed_bytes) {
779 command (s, val);
780#if 0
781 if (0 == s->needed_bytes) {
782 log_dsp (s);
27503323 783 }
85571bc7 784#endif
27503323
FB
785 }
786 else {
85571bc7 787 if (s->in_index == sizeof (s->in2_data)) {
d75d9f6b
FB
788 dolog ("in data overrun\n");
789 }
790 else {
85571bc7
FB
791 s->in2_data[s->in_index++] = val;
792 if (s->in_index == s->needed_bytes) {
793 s->needed_bytes = 0;
794 complete (s);
795#if 0
796 log_dsp (s);
797#endif
798 }
27503323
FB
799 }
800 }
801 break;
802
803 default:
85571bc7 804 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
5e2a6443 805 break;
27503323
FB
806 }
807}
808
809static IO_READ_PROTO (dsp_read)
810{
85571bc7
FB
811 SB16State *s = opaque;
812 int iport, retval, ack = 0;
27503323 813
85571bc7 814 iport = nport - s->port;
27503323
FB
815
816 switch (iport) {
85571bc7
FB
817 case 0x06: /* reset */
818 retval = 0xff;
d75d9f6b 819 break;
27503323 820
85571bc7
FB
821 case 0x0a: /* read data */
822 if (s->out_data_len) {
823 retval = s->out_data[--s->out_data_len];
824 s->last_read_byte = retval;
825 }
826 else {
d75d9f6b 827 dolog ("empty output buffer\n");
85571bc7 828 retval = s->last_read_byte;
d75d9f6b 829 /* goto error; */
27503323
FB
830 }
831 break;
832
85571bc7
FB
833 case 0x0c: /* 0 can write */
834 retval = s->can_write ? 0 : 0x80;
27503323
FB
835 break;
836
85571bc7
FB
837 case 0x0d: /* timer interrupt clear */
838 /* dolog ("timer interrupt clear\n"); */
839 retval = 0;
840 break;
27503323 841
85571bc7
FB
842 case 0x0e: /* data available status | irq 8 ack */
843 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
844 if (s->mixer_regs[0x82] & 1) {
845 ack = 1;
846 s->mixer_regs[0x82] &= 1;
847 pic_set_irq (s->irq, 0);
848 }
27503323
FB
849 break;
850
85571bc7 851 case 0x0f: /* irq 16 ack */
bc0b1dc1 852 retval = 0xff;
85571bc7
FB
853 if (s->mixer_regs[0x82] & 2) {
854 ack = 1;
855 s->mixer_regs[0x82] &= 2;
856 pic_set_irq (s->irq, 0);
857 }
27503323
FB
858 break;
859
860 default:
861 goto error;
862 }
863
85571bc7
FB
864 if (!ack)
865 ldebug ("read %#x -> %#x\n", nport, retval);
27503323
FB
866
867 return retval;
868
869 error:
85571bc7 870 dolog ("WARNING dsp_read %#x error\n", nport);
d75d9f6b 871 return 0xff;
27503323
FB
872}
873
85571bc7
FB
874static void reset_mixer (SB16State *s)
875{
876 int i;
877
878 memset (s->mixer_regs, 0xff, 0x7f);
879 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
880
881 s->mixer_regs[0x02] = 4; /* master volume 3bits */
882 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
883 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
884 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
885
886 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
887 s->mixer_regs[0x0c] = 0;
888
889 /* d5=output filt, d1=stereo switch */
890 s->mixer_regs[0x0e] = 0;
891
892 /* voice volume L d5,d7, R d1,d3 */
893 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
894 /* master ... */
895 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
896 /* MIDI ... */
897 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
898
899 for (i = 0x30; i < 0x48; i++) {
900 s->mixer_regs[i] = 0x20;
901 }
902}
903
27503323
FB
904static IO_WRITE_PROTO(mixer_write_indexb)
905{
85571bc7
FB
906 SB16State *s = opaque;
907 s->mixer_nreg = val;
27503323
FB
908}
909
910static IO_WRITE_PROTO(mixer_write_datab)
911{
85571bc7
FB
912 SB16State *s = opaque;
913
914 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
915 if (s->mixer_nreg > sizeof (s->mixer_regs))
916 return;
202a456a 917
85571bc7 918 switch (s->mixer_nreg) {
d75d9f6b 919 case 0x00:
85571bc7 920 reset_mixer (s);
d75d9f6b
FB
921 break;
922
d75d9f6b 923 case 0x80:
85571bc7
FB
924 {
925 int irq = irq_of_magic (val);
926 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
927 if (irq > 0)
928 s->irq = irq;
929 }
d75d9f6b 930 break;
27503323 931
85571bc7
FB
932 case 0x81:
933 {
934 int dma, hdma;
d75d9f6b 935
85571bc7
FB
936 dma = lsbindex (val & 0xf);
937 hdma = lsbindex (val & 0xf0);
938 dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
939 dma, hdma, val);
940#if 0
941 s->dma = dma;
942 s->hdma = hdma;
943#endif
944 }
945 break;
d75d9f6b 946
85571bc7
FB
947 case 0x82:
948 dolog ("attempt to write into IRQ status register (val=%#x)\n",
949 val);
950 return;
d75d9f6b 951
85571bc7
FB
952 default:
953 if (s->mixer_nreg >= 0x80)
954 dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
955 break;
956 }
957
958 s->mixer_regs[s->mixer_nreg] = val;
d75d9f6b
FB
959}
960
27503323
FB
961static IO_WRITE_PROTO(mixer_write_indexw)
962{
7d977de7
FB
963 mixer_write_indexb (opaque, nport, val & 0xff);
964 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
27503323
FB
965}
966
967static IO_READ_PROTO(mixer_read)
968{
85571bc7
FB
969 SB16State *s = opaque;
970 ldebug ("mixer_read[%#x] -> %#x\n",
971 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
972 return s->mixer_regs[s->mixer_nreg];
27503323
FB
973}
974
85571bc7
FB
975static int write_audio (SB16State *s, int nchan, int dma_pos,
976 int dma_len, int len)
27503323
FB
977{
978 int temp, net;
f9e92e97 979 uint8_t tmpbuf[4096];
27503323 980
85571bc7 981 temp = len;
27503323
FB
982 net = 0;
983
984 while (temp) {
85571bc7
FB
985 int left = dma_len - dma_pos;
986 int to_copy, copied;
27503323 987
85571bc7 988 to_copy = audio_MIN (temp, left);
f9e92e97
FB
989 if (to_copy > sizeof(tmpbuf))
990 to_copy = sizeof(tmpbuf);
27503323 991
85571bc7
FB
992 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
993 copied = AUD_write (s->voice, tmpbuf, copied);
27503323 994
85571bc7
FB
995 temp -= copied;
996 dma_pos = (dma_pos + copied) % dma_len;
27503323
FB
997 net += copied;
998
85571bc7
FB
999 if (!copied)
1000 break;
27503323
FB
1001 }
1002
1003 return net;
1004}
1005
85571bc7 1006static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
27503323 1007{
85571bc7
FB
1008 SB16State *s = opaque;
1009 int free, rfree, till, copy, written, elapsed;
27503323 1010
85571bc7
FB
1011 if (s->left_till_irq < 0) {
1012 s->left_till_irq = s->block_size;
27503323
FB
1013 }
1014
85571bc7
FB
1015 elapsed = AUD_calc_elapsed (s->voice);
1016 free = elapsed;/* AUD_get_free (s->voice); */
1017 rfree = free;
1018 free = audio_MIN (free, elapsed) & ~s->align;
27503323 1019
85571bc7
FB
1020 if ((free <= 0) || !dma_len) {
1021 return dma_pos;
27503323
FB
1022 }
1023
85571bc7
FB
1024 copy = free;
1025 till = s->left_till_irq;
27503323 1026
d75d9f6b 1027#ifdef DEBUG_SB16_MOST
85571bc7
FB
1028 dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
1029 dma_pos, free, AUD_get_free (s->voice), till, dma_len);
d75d9f6b
FB
1030#endif
1031
27503323 1032 if (till <= copy) {
85571bc7 1033 if (0 == s->dma_auto) {
27503323
FB
1034 copy = till;
1035 }
1036 }
1037
85571bc7
FB
1038 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1039 dma_pos = (dma_pos + written) % dma_len;
1040 s->left_till_irq -= written;
27503323 1041
85571bc7
FB
1042 if (s->left_till_irq <= 0) {
1043 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1044 pic_set_irq (s->irq, 1);
1045 if (0 == s->dma_auto) {
1046 control (s, 0);
1047 speaker (s, 0);
27503323
FB
1048 }
1049 }
1050
d75d9f6b 1051#ifdef DEBUG_SB16_MOST
27503323 1052 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
85571bc7 1053 dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size);
d75d9f6b 1054#endif
27503323 1055
85571bc7
FB
1056 while (s->left_till_irq <= 0) {
1057 s->left_till_irq = s->block_size + s->left_till_irq;
27503323
FB
1058 }
1059
85571bc7
FB
1060 AUD_adjust (s->voice, written);
1061 return dma_pos;
27503323
FB
1062}
1063
85571bc7 1064void SB_timer (void *opaque)
27503323 1065{
85571bc7
FB
1066 SB16State *s = opaque;
1067 AUD_run ();
1068 qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
27503323
FB
1069}
1070
85571bc7 1071static void SB_save (QEMUFile *f, void *opaque)
d75d9f6b 1072{
85571bc7
FB
1073 SB16State *s = opaque;
1074
1075 qemu_put_be32s (f, &s->irq);
1076 qemu_put_be32s (f, &s->dma);
1077 qemu_put_be32s (f, &s->hdma);
1078 qemu_put_be32s (f, &s->port);
1079 qemu_put_be32s (f, &s->ver);
1080 qemu_put_be32s (f, &s->in_index);
1081 qemu_put_be32s (f, &s->out_data_len);
1082 qemu_put_be32s (f, &s->fmt_stereo);
1083 qemu_put_be32s (f, &s->fmt_signed);
1084 qemu_put_be32s (f, &s->fmt_bits);
1085 qemu_put_be32s (f, &s->fmt);
1086 qemu_put_be32s (f, &s->dma_auto);
1087 qemu_put_be32s (f, &s->block_size);
1088 qemu_put_be32s (f, &s->fifo);
1089 qemu_put_be32s (f, &s->freq);
1090 qemu_put_be32s (f, &s->time_const);
1091 qemu_put_be32s (f, &s->speaker);
1092 qemu_put_be32s (f, &s->needed_bytes);
1093 qemu_put_be32s (f, &s->cmd);
1094 qemu_put_be32s (f, &s->use_hdma);
1095 qemu_put_be32s (f, &s->highspeed);
1096 qemu_put_be32s (f, &s->can_write);
1097 qemu_put_be32s (f, &s->v2x6);
1098
1099 qemu_put_8s (f, &s->csp_param);
1100 qemu_put_8s (f, &s->csp_value);
1101 qemu_put_8s (f, &s->csp_mode);
1102 qemu_put_8s (f, &s->csp_param);
1103 qemu_put_buffer (f, s->csp_regs, 256);
1104 qemu_put_8s (f, &s->csp_index);
1105 qemu_put_buffer (f, s->csp_reg83, 4);
1106 qemu_put_be32s (f, &s->csp_reg83r);
1107 qemu_put_be32s (f, &s->csp_reg83w);
1108
1109 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1110 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1111 qemu_put_8s (f, &s->test_reg);
1112 qemu_put_8s (f, &s->last_read_byte);
1113
1114 qemu_put_be32s (f, &s->nzero);
1115 qemu_put_be32s (f, &s->left_till_irq);
1116 qemu_put_be32s (f, &s->dma_running);
1117 qemu_put_be32s (f, &s->bytes_per_second);
1118 qemu_put_be32s (f, &s->align);
1119
1120 qemu_put_be32s (f, &s->mixer_nreg);
1121 qemu_put_buffer (f, s->mixer_regs, 256);
d75d9f6b
FB
1122}
1123
85571bc7 1124static int SB_load (QEMUFile *f, void *opaque, int version_id)
d75d9f6b 1125{
85571bc7
FB
1126 SB16State *s = opaque;
1127
1128 if (version_id != 1)
1129 return -EINVAL;
1130
1131 qemu_get_be32s (f, &s->irq);
1132 qemu_get_be32s (f, &s->dma);
1133 qemu_get_be32s (f, &s->hdma);
1134 qemu_get_be32s (f, &s->port);
1135 qemu_get_be32s (f, &s->ver);
1136 qemu_get_be32s (f, &s->in_index);
1137 qemu_get_be32s (f, &s->out_data_len);
1138 qemu_get_be32s (f, &s->fmt_stereo);
1139 qemu_get_be32s (f, &s->fmt_signed);
1140 qemu_get_be32s (f, &s->fmt_bits);
1141 qemu_get_be32s (f, &s->fmt);
1142 qemu_get_be32s (f, &s->dma_auto);
1143 qemu_get_be32s (f, &s->block_size);
1144 qemu_get_be32s (f, &s->fifo);
1145 qemu_get_be32s (f, &s->freq);
1146 qemu_get_be32s (f, &s->time_const);
1147 qemu_get_be32s (f, &s->speaker);
1148 qemu_get_be32s (f, &s->needed_bytes);
1149 qemu_get_be32s (f, &s->cmd);
1150 qemu_get_be32s (f, &s->use_hdma);
1151 qemu_get_be32s (f, &s->highspeed);
1152 qemu_get_be32s (f, &s->can_write);
1153 qemu_get_be32s (f, &s->v2x6);
1154
1155 qemu_get_8s (f, &s->csp_param);
1156 qemu_get_8s (f, &s->csp_value);
1157 qemu_get_8s (f, &s->csp_mode);
1158 qemu_get_8s (f, &s->csp_param);
1159 qemu_get_buffer (f, s->csp_regs, 256);
1160 qemu_get_8s (f, &s->csp_index);
1161 qemu_get_buffer (f, s->csp_reg83, 4);
1162 qemu_get_be32s (f, &s->csp_reg83r);
1163 qemu_get_be32s (f, &s->csp_reg83w);
1164
1165 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1166 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1167 qemu_get_8s (f, &s->test_reg);
1168 qemu_get_8s (f, &s->last_read_byte);
1169
1170 qemu_get_be32s (f, &s->nzero);
1171 qemu_get_be32s (f, &s->left_till_irq);
1172 qemu_get_be32s (f, &s->dma_running);
1173 qemu_get_be32s (f, &s->bytes_per_second);
1174 qemu_get_be32s (f, &s->align);
1175
1176 qemu_get_be32s (f, &s->mixer_nreg);
1177 qemu_get_buffer (f, s->mixer_regs, 256);
1178
fb065187
FB
1179 if (s->voice) {
1180 AUD_close (s->voice);
1181 s->voice = NULL;
1182 }
85571bc7
FB
1183
1184 if (s->dma_running) {
1185 if (s->freq)
1186 s->voice = AUD_open (s->voice, "sb16", s->freq,
1187 1 << s->fmt_stereo, s->fmt);
1188
1189 control (s, 1);
1190 speaker (s, s->speaker);
d75d9f6b 1191 }
85571bc7 1192 return 0;
d75d9f6b 1193}
d75d9f6b 1194
27503323
FB
1195void SB16_init (void)
1196{
5e2a6443 1197 SB16State *s = &dsp;
27503323
FB
1198 int i;
1199 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1200 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1201
85571bc7
FB
1202 s->ts = qemu_new_timer (vm_clock, SB_timer, s);
1203 if (!s->ts)
1204 return;
1205
1206 s->irq = conf.irq;
1207 s->dma = conf.dma;
1208 s->hdma = conf.hdma;
1209 s->port = conf.port;
1210 s->ver = conf.ver_lo | (conf.ver_hi << 8);
202a456a 1211
85571bc7
FB
1212 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1213 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1214 s->mixer_regs[0x82] = 2 << 5;
1215
1216 s->csp_regs[5] = 1;
1217 s->csp_regs[9] = 0xf8;
1218
1219 reset_mixer (s);
1220 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1221 if (!s->aux_ts)
1222 return;
27503323
FB
1223
1224 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
85571bc7 1225 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
27503323
FB
1226 }
1227
1228 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
85571bc7 1229 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
27503323
FB
1230 }
1231
85571bc7
FB
1232 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1233 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1234 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1235 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
27503323 1236
85571bc7
FB
1237 DMA_register_channel (s->hdma, SB_read_DMA, s);
1238 DMA_register_channel (s->dma, SB_read_DMA, s);
1239 s->can_write = 1;
d75d9f6b 1240
85571bc7
FB
1241 qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
1242 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
27503323 1243}