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