VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevSB16.cpp@ 33000

Last change on this file since 33000 was 32456, checked in by vboxsync, 14 years ago

SB16: Do not copy too much at once, the guest must see all interrupts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.5 KB
Line 
1/* $Id: DevSB16.cpp 32456 2010-09-13 15:12:08Z vboxsync $ */
2/** @file
3 * DevSB16 - VBox SB16 Audio Controller.
4 *
5 * (r3917 sb16.c)
6 *
7 * @todo hiccups on NT4 and Win98.
8 */
9
10/*
11 * QEMU Soundblaster 16 emulation
12 *
13 * Copyright (c) 2003-2005 Vassili Karpov (malc)
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining a copy
16 * of this software and associated documentation files (the "Software"), to deal
17 * in the Software without restriction, including without limitation the rights
18 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 * copies of the Software, and to permit persons to whom the Software is
20 * furnished to do so, subject to the following conditions:
21 *
22 * The above copyright notice and this permission notice shall be included in
23 * all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 * THE SOFTWARE.
32 */
33
34#define LOG_GROUP LOG_GROUP_DEV_AUDIO
35#include <VBox/pdmdev.h>
36#include <iprt/assert.h>
37#include <iprt/string.h>
38#include <iprt/uuid.h>
39#include "../vl_vbox.h"
40
41extern "C" {
42#include "audio.h"
43}
44
45#ifndef VBOX
46
47#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
48
49#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
50
51/* #define DEBUG */
52/* #define DEBUG_SB16_MOST */
53
54#ifdef DEBUG
55#define ldebug(...) dolog (__VA_ARGS__)
56#else
57#define ldebug(...)
58#endif
59
60#else /* VBOX */
61
62/** Current saved state version. */
63#define SB16_SAVE_STATE_VERSION 2
64/** The version used in VirtualBox version 3.0 and earlier. This didn't include
65 * the config dump. */
66#define SB16_SAVE_STATE_VERSION_VBOX_30 1
67
68DECLINLINE(void) dolog (const char *fmt, ...)
69{
70 va_list ap;
71 va_start (ap, fmt);
72 AUD_vlog ("sb16", fmt, ap);
73 va_end (ap);
74}
75
76# ifdef DEBUG
77static void ldebug (const char *fmt, ...)
78{
79 va_list ap;
80
81 va_start (ap, fmt);
82 AUD_vlog ("sb16", fmt, ap);
83 va_end (ap);
84}
85# else
86DECLINLINE(void) ldebug (const char *fmt, ...)
87{
88 (void)fmt;
89}
90# endif
91
92#endif /* VBOX */
93
94#ifndef VBOX
95#define IO_READ_PROTO(name) \
96 uint32_t name (void *opaque, uint32_t nport)
97#define IO_WRITE_PROTO(name) \
98 void name (void *opaque, uint32_t nport, uint32_t val)
99#else /* VBOX */
100#define IO_READ_PROTO(name) \
101 DECLCALLBACK(int) name (PPDMDEVINS pDevIns, void *opaque, \
102 RTIOPORT nport, uint32_t *pu32, unsigned cb)
103
104#define IO_WRITE_PROTO(name) \
105 DECLCALLBACK(int) name (PPDMDEVINS pDevIns, void *opaque, \
106 RTIOPORT nport, uint32_t val, unsigned cb)
107#endif /* VBOX */
108
109static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
110
111#ifndef VBOX
112static struct {
113 int ver_lo;
114 int ver_hi;
115 int irq;
116 int dma;
117 int hdma;
118 int port;
119} conf = {5, 4, 5, 1, 5, 0x220};
120#endif /* !VBOX */
121
122typedef struct SB16State {
123#ifdef VBOX
124 PPDMDEVINSR3 pDevIns;
125#endif
126 QEMUSoundCard card;
127#ifndef VBOX
128 qemu_irq *pic;
129#endif
130#ifdef VBOX /* lazy bird */
131 int irqCfg;
132 int dmaCfg;
133 int hdmaCfg;
134 int portCfg;
135 int verCfg;
136#endif
137 int irq;
138 int dma;
139 int hdma;
140 int port;
141 int ver;
142
143 int in_index;
144 int out_data_len;
145 int fmt_stereo;
146 int fmt_signed;
147 int fmt_bits;
148 audfmt_e fmt;
149 int dma_auto;
150 int block_size;
151 int fifo;
152 int freq;
153 int time_const;
154 int speaker;
155 int needed_bytes;
156 int cmd;
157 int use_hdma;
158 int highspeed;
159 int can_write;
160
161 int v2x6;
162
163 uint8_t csp_param;
164 uint8_t csp_value;
165 uint8_t csp_mode;
166 uint8_t csp_regs[256];
167 uint8_t csp_index;
168 uint8_t csp_reg83[4];
169 int csp_reg83r;
170 int csp_reg83w;
171
172 uint8_t in2_data[10];
173 uint8_t out_data[50];
174 uint8_t test_reg;
175 uint8_t last_read_byte;
176 int nzero;
177
178 int left_till_irq;
179
180 int dma_running;
181 int bytes_per_second;
182 int align;
183 int audio_free;
184 SWVoiceOut *voice;
185
186#ifndef VBOX
187 QEMUTimer *aux_ts;
188#else
189 PTMTIMER pTimer;
190 PPDMIBASE pDrvBase;
191 /** LUN\#0: Base interface. */
192 PDMIBASE IBase;
193#endif
194 /* mixer state */
195 int mixer_nreg;
196 uint8_t mixer_regs[256];
197} SB16State;
198
199static void SB_audio_callback (void *opaque, int free);
200
201static int magic_of_irq (int irq)
202{
203 switch (irq) {
204 case 5:
205 return 2;
206 case 7:
207 return 4;
208 case 9:
209 return 1;
210 case 10:
211 return 8;
212 default:
213 dolog ("bad irq %d\n", irq);
214 return 2;
215 }
216}
217
218static int irq_of_magic (int magic)
219{
220 switch (magic) {
221 case 1:
222 return 9;
223 case 2:
224 return 5;
225 case 4:
226 return 7;
227 case 8:
228 return 10;
229 default:
230 dolog ("bad irq magic %d\n", magic);
231 return -1;
232 }
233}
234
235#if 0
236static void log_dsp (SB16State *dsp)
237{
238 ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
239 dsp->fmt_stereo ? "Stereo" : "Mono",
240 dsp->fmt_signed ? "Signed" : "Unsigned",
241 dsp->fmt_bits,
242 dsp->dma_auto ? "Auto" : "Single",
243 dsp->block_size,
244 dsp->freq,
245 dsp->time_const,
246 dsp->speaker);
247}
248#endif
249
250static void speaker (SB16State *s, int on)
251{
252 s->speaker = on;
253 /* AUD_enable (s->voice, on); */
254}
255
256static void control (SB16State *s, int hold)
257{
258 int dma = s->use_hdma ? s->hdma : s->dma;
259 s->dma_running = hold;
260
261 ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
262
263#ifndef VBOX
264 if (hold) {
265 DMA_hold_DREQ (dma);
266 AUD_set_active_out (s->voice, 1);
267 }
268 else {
269 DMA_release_DREQ (dma);
270 AUD_set_active_out (s->voice, 0);
271 }
272#else /* VBOX */
273 if (hold)
274 {
275 PDMDevHlpDMASetDREQ (s->pDevIns, dma, 1);
276 PDMDevHlpDMASchedule (s->pDevIns);
277 AUD_set_active_out (s->voice, 1);
278 }
279 else
280 {
281 PDMDevHlpDMASetDREQ (s->pDevIns, dma, 0);
282 AUD_set_active_out (s->voice, 0);
283 }
284#endif /* VBOX */
285}
286
287#ifndef VBOX
288static void aux_timer (void *opaque)
289{
290 SB16State *s = opaque;
291 s->can_write = 1;
292 qemu_irq_raise (s->pic[s->irq]);
293}
294#else /* VBOX */
295static DECLCALLBACK(void) sb16Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis)
296{
297 SB16State *s = (SB16State *)pvThis;
298 s->can_write = 1;
299 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
300}
301#endif /* VBOX */
302
303#define DMA8_AUTO 1
304#define DMA8_HIGH 2
305
306static void continue_dma8 (SB16State *s)
307{
308 if (s->freq > 0) {
309 audsettings_t as;
310
311 s->audio_free = 0;
312
313 as.freq = s->freq;
314 as.nchannels = 1 << s->fmt_stereo;
315 as.fmt = s->fmt;
316 as.endianness = 0;
317
318 s->voice = AUD_open_out (
319 &s->card,
320 s->voice,
321 "sb16",
322 s,
323 SB_audio_callback,
324 &as
325 );
326 }
327
328 control (s, 1);
329}
330
331static void dma_cmd8 (SB16State *s, int mask, int dma_len)
332{
333 s->fmt = AUD_FMT_U8;
334 s->use_hdma = 0;
335 s->fmt_bits = 8;
336 s->fmt_signed = 0;
337 s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
338 if (-1 == s->time_const) {
339 if (s->freq <= 0)
340 s->freq = 11025;
341 }
342 else {
343 int tmp = (256 - s->time_const);
344 s->freq = (1000000 + (tmp / 2)) / tmp;
345 }
346
347 if (dma_len != -1) {
348 s->block_size = dma_len << s->fmt_stereo;
349 }
350 else {
351 /* This is apparently the only way to make both Act1/PL
352 and SecondReality/FC work
353
354 Act1 sets block size via command 0x48 and it's an odd number
355 SR does the same with even number
356 Both use stereo, and Creatives own documentation states that
357 0x48 sets block size in bytes less one.. go figure */
358 s->block_size &= ~s->fmt_stereo;
359 }
360
361 s->freq >>= s->fmt_stereo;
362 s->left_till_irq = s->block_size;
363 s->bytes_per_second = (s->freq << s->fmt_stereo);
364 /* s->highspeed = (mask & DMA8_HIGH) != 0; */
365 s->dma_auto = (mask & DMA8_AUTO) != 0;
366 s->align = (1 << s->fmt_stereo) - 1;
367
368 if (s->block_size & s->align) {
369 dolog ("warning: misaligned block size %d, alignment %d\n",
370 s->block_size, s->align + 1);
371 }
372
373 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
374 "dma %d, auto %d, fifo %d, high %d\n",
375 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
376 s->block_size, s->dma_auto, s->fifo, s->highspeed);
377
378 continue_dma8 (s);
379 speaker (s, 1);
380}
381
382static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
383{
384 s->use_hdma = cmd < 0xc0;
385 s->fifo = (cmd >> 1) & 1;
386 s->dma_auto = (cmd >> 2) & 1;
387 s->fmt_signed = (d0 >> 4) & 1;
388 s->fmt_stereo = (d0 >> 5) & 1;
389
390 switch (cmd >> 4) {
391 case 11:
392 s->fmt_bits = 16;
393 break;
394
395 case 12:
396 s->fmt_bits = 8;
397 break;
398 }
399
400 if (-1 != s->time_const) {
401#if 1
402 int tmp = 256 - s->time_const;
403 s->freq = (1000000 + (tmp / 2)) / tmp;
404#else
405 /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
406 s->freq = 1000000 / ((255 - s->time_const));
407#endif
408 s->time_const = -1;
409 }
410
411 s->block_size = dma_len + 1;
412 s->block_size <<= ((s->fmt_bits == 16) ? 1 : 0);
413 if (!s->dma_auto) {
414 /* It is clear that for DOOM and auto-init this value
415 shouldn't take stereo into account, while Miles Sound Systems
416 setsound.exe with single transfer mode wouldn't work without it
417 wonders of SB16 yet again */
418 s->block_size <<= s->fmt_stereo;
419 }
420
421 ldebug ("freq %d, stereo %d, sign %d, bits %d, "
422 "dma %d, auto %d, fifo %d, high %d\n",
423 s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
424 s->block_size, s->dma_auto, s->fifo, s->highspeed);
425
426 if (16 == s->fmt_bits) {
427 if (s->fmt_signed) {
428 s->fmt = AUD_FMT_S16;
429 }
430 else {
431 s->fmt = AUD_FMT_U16;
432 }
433 }
434 else {
435 if (s->fmt_signed) {
436 s->fmt = AUD_FMT_S8;
437 }
438 else {
439 s->fmt = AUD_FMT_U8;
440 }
441 }
442
443 s->left_till_irq = s->block_size;
444
445 s->bytes_per_second = (s->freq << s->fmt_stereo) << ((s->fmt_bits == 16) ? 1 : 0);
446 s->highspeed = 0;
447 s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
448 if (s->block_size & s->align) {
449 dolog ("warning: misaligned block size %d, alignment %d\n",
450 s->block_size, s->align + 1);
451 }
452
453 if (s->freq) {
454 audsettings_t as;
455
456 s->audio_free = 0;
457
458 as.freq = s->freq;
459 as.nchannels = 1 << s->fmt_stereo;
460 as.fmt = s->fmt;
461 as.endianness = 0;
462
463 s->voice = AUD_open_out (
464 &s->card,
465 s->voice,
466 "sb16",
467 s,
468 SB_audio_callback,
469 &as
470 );
471 }
472
473 control (s, 1);
474 speaker (s, 1);
475}
476
477static inline void dsp_out_data (SB16State *s, uint8_t val)
478{
479 ldebug ("outdata %#x\n", val);
480 if ((size_t) s->out_data_len < sizeof (s->out_data)) {
481 s->out_data[s->out_data_len++] = val;
482 }
483}
484
485static inline uint8_t dsp_get_data (SB16State *s)
486{
487 if (s->in_index) {
488 return s->in2_data[--s->in_index];
489 }
490 else {
491 dolog ("buffer underflow\n");
492 return 0;
493 }
494}
495
496static void command (SB16State *s, uint8_t cmd)
497{
498 ldebug ("command %#x\n", cmd);
499
500 if (cmd > 0xaf && cmd < 0xd0) {
501 if (cmd & 8) {
502 dolog ("ADC not yet supported (command %#x)\n", cmd);
503 }
504
505 switch (cmd >> 4) {
506 case 11:
507 case 12:
508 break;
509 default:
510 dolog ("%#x wrong bits\n", cmd);
511 }
512 s->needed_bytes = 3;
513 }
514 else {
515 s->needed_bytes = 0;
516
517 switch (cmd) {
518 case 0x03:
519 dsp_out_data (s, 0x10); /* s->csp_param); */
520 goto warn;
521
522 case 0x04:
523 s->needed_bytes = 1;
524 goto warn;
525
526 case 0x05:
527 s->needed_bytes = 2;
528 goto warn;
529
530 case 0x08:
531 /* __asm__ ("int3"); */
532 goto warn;
533
534 case 0x0e:
535 s->needed_bytes = 2;
536 goto warn;
537
538 case 0x09:
539 dsp_out_data (s, 0xf8);
540 goto warn;
541
542 case 0x0f:
543 s->needed_bytes = 1;
544 goto warn;
545
546 case 0x10:
547 s->needed_bytes = 1;
548 goto warn;
549
550 case 0x14:
551 s->needed_bytes = 2;
552 s->block_size = 0;
553 break;
554
555 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
556 dma_cmd8 (s, DMA8_AUTO, -1);
557 break;
558
559 case 0x20: /* Direct ADC, Juice/PL */
560 dsp_out_data (s, 0xff);
561 goto warn;
562
563 case 0x35:
564 dolog ("0x35 - MIDI command not implemented\n");
565 break;
566
567 case 0x40:
568 s->freq = -1;
569 s->time_const = -1;
570 s->needed_bytes = 1;
571 break;
572
573 case 0x41:
574 s->freq = -1;
575 s->time_const = -1;
576 s->needed_bytes = 2;
577 break;
578
579 case 0x42:
580 s->freq = -1;
581 s->time_const = -1;
582 s->needed_bytes = 2;
583 goto warn;
584
585 case 0x45:
586 dsp_out_data (s, 0xaa);
587 goto warn;
588
589 case 0x47: /* Continue Auto-Initialize DMA 16bit */
590 break;
591
592 case 0x48:
593 s->needed_bytes = 2;
594 break;
595
596 case 0x74:
597 s->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
598 dolog ("0x75 - DMA DAC, 4-bit ADPCM not implemented\n");
599 break;
600
601 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
602 s->needed_bytes = 2;
603 dolog ("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n");
604 break;
605
606 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
607 s->needed_bytes = 2;
608 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n");
609 break;
610
611 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
612 s->needed_bytes = 2;
613 dolog ("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n");
614 break;
615
616 case 0x7d:
617 dolog ("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n");
618 dolog ("not implemented\n");
619 break;
620
621 case 0x7f:
622 dolog (
623 "0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"
624 );
625 dolog ("not implemented\n");
626 break;
627
628 case 0x80:
629 s->needed_bytes = 2;
630 break;
631
632 case 0x90:
633 case 0x91:
634 dma_cmd8 (s, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1);
635 break;
636
637 case 0xd0: /* halt DMA operation. 8bit */
638 control (s, 0);
639 break;
640
641 case 0xd1: /* speaker on */
642 speaker (s, 1);
643 break;
644
645 case 0xd3: /* speaker off */
646 speaker (s, 0);
647 break;
648
649 case 0xd4: /* continue DMA operation. 8bit */
650 /* KQ6 (or maybe Sierras audblst.drv in general) resets
651 the frequency between halt/continue */
652 continue_dma8 (s);
653 break;
654
655 case 0xd5: /* halt DMA operation. 16bit */
656 control (s, 0);
657 break;
658
659 case 0xd6: /* continue DMA operation. 16bit */
660 control (s, 1);
661 break;
662
663 case 0xd9: /* exit auto-init DMA after this block. 16bit */
664 s->dma_auto = 0;
665 break;
666
667 case 0xda: /* exit auto-init DMA after this block. 8bit */
668 s->dma_auto = 0;
669 break;
670
671 case 0xe0: /* DSP identification */
672 s->needed_bytes = 1;
673 break;
674
675 case 0xe1:
676 dsp_out_data (s, s->ver & 0xff);
677 dsp_out_data (s, s->ver >> 8);
678 break;
679
680 case 0xe2:
681 s->needed_bytes = 1;
682 goto warn;
683
684 case 0xe3:
685 {
686 int i;
687 for (i = sizeof (e3) - 1; i >= 0; --i)
688 dsp_out_data (s, e3[i]);
689 }
690 break;
691
692 case 0xe4: /* write test reg */
693 s->needed_bytes = 1;
694 break;
695
696 case 0xe7:
697 dolog ("Attempt to probe for ESS (0xe7)?\n");
698 break;
699
700 case 0xe8: /* read test reg */
701 dsp_out_data (s, s->test_reg);
702 break;
703
704 case 0xf2:
705 case 0xf3:
706 dsp_out_data (s, 0xaa);
707 s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
708#ifndef VBOX
709 qemu_irq_raise (s->pic[s->irq]);
710#else
711 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
712#endif
713 break;
714
715 case 0xf9:
716 s->needed_bytes = 1;
717 goto warn;
718
719 case 0xfa:
720 dsp_out_data (s, 0);
721 goto warn;
722
723 case 0xfc: /* FIXME */
724 dsp_out_data (s, 0);
725 goto warn;
726
727 default:
728 dolog ("Unrecognized command %#x\n", cmd);
729 break;
730 }
731 }
732
733 if (!s->needed_bytes) {
734 ldebug ("\n");
735 }
736
737 exit:
738 if (!s->needed_bytes) {
739 s->cmd = -1;
740 }
741 else {
742 s->cmd = cmd;
743 }
744 return;
745
746 warn:
747 dolog ("warning: command %#x,%d is not truly understood yet\n",
748 cmd, s->needed_bytes);
749 goto exit;
750
751}
752
753static uint16_t dsp_get_lohi (SB16State *s)
754{
755 uint8_t hi = dsp_get_data (s);
756 uint8_t lo = dsp_get_data (s);
757 return (hi << 8) | lo;
758}
759
760static uint16_t dsp_get_hilo (SB16State *s)
761{
762 uint8_t lo = dsp_get_data (s);
763 uint8_t hi = dsp_get_data (s);
764 return (hi << 8) | lo;
765}
766
767static void complete (SB16State *s)
768{
769 int d0, d1, d2;
770 ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
771 s->cmd, s->in_index, s->needed_bytes);
772
773 if (s->cmd > 0xaf && s->cmd < 0xd0) {
774 d2 = dsp_get_data (s);
775 d1 = dsp_get_data (s);
776 d0 = dsp_get_data (s);
777
778 if (s->cmd & 8) {
779 dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
780 s->cmd, d0, d1, d2);
781 }
782 else {
783 ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
784 s->cmd, d0, d1, d2);
785 dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
786 }
787 }
788 else {
789 switch (s->cmd) {
790 case 0x04:
791 s->csp_mode = dsp_get_data (s);
792 s->csp_reg83r = 0;
793 s->csp_reg83w = 0;
794 ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
795 break;
796
797 case 0x05:
798 s->csp_param = dsp_get_data (s);
799 s->csp_value = dsp_get_data (s);
800 ldebug ("CSP command 0x05: param=%#x value=%#x\n",
801 s->csp_param,
802 s->csp_value);
803 break;
804
805 case 0x0e:
806 d0 = dsp_get_data (s);
807 d1 = dsp_get_data (s);
808 ldebug ("write CSP register %d <- %#x\n", d1, d0);
809 if (d1 == 0x83) {
810 ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
811 s->csp_reg83[s->csp_reg83r % 4] = d0;
812 s->csp_reg83r += 1;
813 }
814 else {
815 s->csp_regs[d1] = d0;
816 }
817 break;
818
819 case 0x0f:
820 d0 = dsp_get_data (s);
821 ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
822 d0, s->csp_regs[d0], s->csp_mode);
823 if (d0 == 0x83) {
824 ldebug ("0x83[%d] -> %#x\n",
825 s->csp_reg83w,
826 s->csp_reg83[s->csp_reg83w % 4]);
827 dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
828 s->csp_reg83w += 1;
829 }
830 else {
831 dsp_out_data (s, s->csp_regs[d0]);
832 }
833 break;
834
835 case 0x10:
836 d0 = dsp_get_data (s);
837 dolog ("cmd 0x10 d0=%#x\n", d0);
838 break;
839
840 case 0x14:
841 dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
842 break;
843
844 case 0x40:
845 s->time_const = dsp_get_data (s);
846 ldebug ("set time const %d\n", s->time_const);
847 break;
848
849 case 0x42: /* FT2 sets output freq with this, go figure */
850#if 0
851 dolog ("cmd 0x42 might not do what it think it should\n");
852#endif
853 case 0x41:
854 s->freq = dsp_get_hilo (s);
855 ldebug ("set freq %d\n", s->freq);
856 break;
857
858 case 0x48:
859 s->block_size = dsp_get_lohi (s) + 1;
860 ldebug ("set dma block len %d\n", s->block_size);
861 break;
862
863 case 0x74:
864 case 0x75:
865 case 0x76:
866 case 0x77:
867 /* ADPCM stuff, ignore */
868 break;
869
870 case 0x80:
871 {
872 int freq, samples, bytes;
873 uint64_t ticks;
874
875 freq = s->freq > 0 ? s->freq : 11025;
876 samples = dsp_get_lohi (s) + 1;
877 bytes = samples << s->fmt_stereo << ((s->fmt_bits == 16) ? 1 : 0);
878#ifndef VBOX
879 ticks = (bytes * ticks_per_sec) / freq;
880 if (ticks < ticks_per_sec / 1024) {
881 qemu_irq_raise (s->pic[s->irq]);
882 }
883 else {
884 if (s->aux_ts) {
885 qemu_mod_timer (
886 s->aux_ts,
887 qemu_get_clock (vm_clock) + ticks
888 );
889 }
890 }
891 ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
892#else /* VBOX */
893 ticks = (bytes * TMTimerGetFreq(s->pTimer)) / freq;
894 if (ticks < TMTimerGetFreq(s->pTimer) / 1024)
895 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
896 else
897 TMTimerSet(s->pTimer, TMTimerGet(s->pTimer) + ticks);
898 ldebug ("mix silence %d %d % %RU64\n", samples, bytes, ticks);
899#endif /* VBOX */
900 }
901 break;
902
903 case 0xe0:
904 d0 = dsp_get_data (s);
905 s->out_data_len = 0;
906 ldebug ("E0 data = %#x\n", d0);
907 dsp_out_data (s, ~d0);
908 break;
909
910 case 0xe2:
911 d0 = dsp_get_data (s);
912 ldebug ("E2 = %#x\n", d0);
913 break;
914
915 case 0xe4:
916 s->test_reg = dsp_get_data (s);
917 break;
918
919 case 0xf9:
920 d0 = dsp_get_data (s);
921 ldebug ("command 0xf9 with %#x\n", d0);
922 switch (d0) {
923 case 0x0e:
924 dsp_out_data (s, 0xff);
925 break;
926
927 case 0x0f:
928 dsp_out_data (s, 0x07);
929 break;
930
931 case 0x37:
932 dsp_out_data (s, 0x38);
933 break;
934
935 default:
936 dsp_out_data (s, 0x00);
937 break;
938 }
939 break;
940
941 default:
942 dolog ("complete: unrecognized command %#x\n", s->cmd);
943 return;
944 }
945 }
946
947 ldebug ("\n");
948 s->cmd = -1;
949 return;
950}
951
952static void legacy_reset (SB16State *s)
953{
954 audsettings_t as;
955
956 s->freq = 11025;
957 s->fmt_signed = 0;
958 s->fmt_bits = 8;
959 s->fmt_stereo = 0;
960
961 as.freq = s->freq;
962 as.nchannels = 1;
963 as.fmt = AUD_FMT_U8;
964 as.endianness = 0;
965
966 s->voice = AUD_open_out (
967 &s->card,
968 s->voice,
969 "sb16",
970 s,
971 SB_audio_callback,
972 &as
973 );
974
975 /* Not sure about that... */
976 /* AUD_set_active_out (s->voice, 1); */
977}
978
979static void reset (SB16State *s)
980{
981#ifndef VBOX
982 qemu_irq_lower (s->pic[s->irq]);
983 if (s->dma_auto) {
984 qemu_irq_raise (s->pic[s->irq]);
985 qemu_irq_lower (s->pic[s->irq]);
986 }
987#else /* VBOX */
988 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 0);
989 if (s->dma_auto) {
990 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
991 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 0);
992 }
993#endif /* VBOX */
994
995 s->mixer_regs[0x82] = 0;
996 s->dma_auto = 0;
997 s->in_index = 0;
998 s->out_data_len = 0;
999 s->left_till_irq = 0;
1000 s->needed_bytes = 0;
1001 s->block_size = -1;
1002 s->nzero = 0;
1003 s->highspeed = 0;
1004 s->v2x6 = 0;
1005 s->cmd = -1;
1006
1007 dsp_out_data(s, 0xaa);
1008 speaker (s, 0);
1009 control (s, 0);
1010 legacy_reset (s);
1011}
1012
1013static IO_WRITE_PROTO (dsp_write)
1014{
1015 SB16State *s = (SB16State*)opaque;
1016 int iport = nport - s->port;
1017
1018 ldebug ("write %#x <- %#x\n", nport, val);
1019 switch (iport) {
1020 case 0x06:
1021 switch (val) {
1022 case 0x00:
1023 if (s->v2x6 == 1) {
1024 if (0 && s->highspeed) {
1025 s->highspeed = 0;
1026#ifndef VBOX
1027 qemu_irq_lower (s->pic[s->irq]);
1028#else
1029 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 0);
1030#endif
1031 control (s, 0);
1032 }
1033 else {
1034 reset (s);
1035 }
1036 }
1037 s->v2x6 = 0;
1038 break;
1039
1040 case 0x01:
1041 case 0x03: /* FreeBSD kludge */
1042 s->v2x6 = 1;
1043 break;
1044
1045 case 0xc6:
1046 s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
1047 break;
1048
1049 case 0xb8: /* Panic */
1050 reset (s);
1051 break;
1052
1053 case 0x39:
1054 dsp_out_data (s, 0x38);
1055 reset (s);
1056 s->v2x6 = 0x39;
1057 break;
1058
1059 default:
1060 s->v2x6 = val;
1061 break;
1062 }
1063 break;
1064
1065 case 0x0c: /* write data or command | write status */
1066/* if (s->highspeed) */
1067/* break; */
1068
1069 if (0 == s->needed_bytes) {
1070 command (s, val);
1071#if 0
1072 if (0 == s->needed_bytes) {
1073 log_dsp (s);
1074 }
1075#endif
1076 }
1077 else {
1078 if (s->in_index == sizeof (s->in2_data)) {
1079 dolog ("in data overrun\n");
1080 }
1081 else {
1082 s->in2_data[s->in_index++] = val;
1083 if (s->in_index == s->needed_bytes) {
1084 s->needed_bytes = 0;
1085 complete (s);
1086#if 0
1087 log_dsp (s);
1088#endif
1089 }
1090 }
1091 }
1092 break;
1093
1094 default:
1095 ldebug ("(nport=%#x, val=%#x)\n", nport, val);
1096 break;
1097 }
1098
1099#ifdef VBOX
1100 return VINF_SUCCESS;
1101#endif
1102}
1103
1104static IO_READ_PROTO (dsp_read)
1105{
1106 SB16State *s = (SB16State*)opaque;
1107 int iport, retval, ack = 0;
1108
1109 iport = nport - s->port;
1110#ifdef VBOX
1111 /** @todo reject non-byte access?
1112 * The spec does not mention a non-byte access so we should check how real hardware behaves. */
1113#endif
1114
1115 switch (iport) {
1116 case 0x06: /* reset */
1117 retval = 0xff;
1118 break;
1119
1120 case 0x0a: /* read data */
1121 if (s->out_data_len) {
1122 retval = s->out_data[--s->out_data_len];
1123 s->last_read_byte = retval;
1124 }
1125 else {
1126 if (s->cmd != -1) {
1127 dolog ("empty output buffer for command %#x\n",
1128 s->cmd);
1129 }
1130 retval = s->last_read_byte;
1131 /* goto error; */
1132 }
1133 break;
1134
1135 case 0x0c: /* 0 can write */
1136 retval = s->can_write ? 0 : 0x80;
1137 break;
1138
1139 case 0x0d: /* timer interrupt clear */
1140 /* dolog ("timer interrupt clear\n"); */
1141 retval = 0;
1142 break;
1143
1144 case 0x0e: /* data available status | irq 8 ack */
1145 retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
1146 if (s->mixer_regs[0x82] & 1) {
1147 ack = 1;
1148 s->mixer_regs[0x82] &= 1;
1149#ifndef VBOX
1150 qemu_irq_lower (s->pic[s->irq]);
1151#else
1152 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 0);
1153#endif
1154 }
1155 break;
1156
1157 case 0x0f: /* irq 16 ack */
1158 retval = 0xff;
1159 if (s->mixer_regs[0x82] & 2) {
1160 ack = 1;
1161 s->mixer_regs[0x82] &= 2;
1162#ifndef VBOX
1163 qemu_irq_lower (s->pic[s->irq]);
1164#else
1165 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 0);
1166#endif
1167 }
1168 break;
1169
1170 default:
1171 goto error;
1172 }
1173
1174 if (!ack) {
1175 ldebug ("read %#x -> %#x\n", nport, retval);
1176 }
1177
1178#ifndef VBOX
1179 return retval;
1180#else
1181 *pu32 = retval;
1182 return VINF_SUCCESS;
1183#endif
1184
1185 error:
1186 dolog ("warning: dsp_read %#x error\n", nport);
1187#ifndef VBOX
1188 return 0xff;
1189#else
1190 return VERR_IOM_IOPORT_UNUSED;
1191#endif
1192}
1193
1194static void reset_mixer (SB16State *s)
1195{
1196 int i;
1197
1198 memset (s->mixer_regs, 0xff, 0x7f);
1199 memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
1200
1201 s->mixer_regs[0x02] = 4; /* master volume 3bits */
1202 s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1203 s->mixer_regs[0x08] = 0; /* CD volume 3bits */
1204 s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1205
1206 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1207 s->mixer_regs[0x0c] = 0;
1208
1209 /* d5=output filt, d1=stereo switch */
1210 s->mixer_regs[0x0e] = 0;
1211
1212 /* voice volume L d5,d7, R d1,d3 */
1213 s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
1214 /* master ... */
1215 s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
1216 /* MIDI ... */
1217 s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
1218
1219 for (i = 0x30; i < 0x48; i++) {
1220 s->mixer_regs[i] = 0x20;
1221 }
1222}
1223
1224static IO_WRITE_PROTO(mixer_write_indexb)
1225{
1226 SB16State *s = (SB16State*)opaque;
1227 (void) nport;
1228 s->mixer_nreg = val;
1229
1230#ifdef VBOX
1231 return VINF_SUCCESS;
1232#endif
1233}
1234
1235static IO_WRITE_PROTO(mixer_write_datab)
1236{
1237 SB16State *s = (SB16State*)opaque;
1238
1239 (void) nport;
1240 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1241
1242 switch (s->mixer_nreg) {
1243 case 0x00:
1244 reset_mixer (s);
1245 break;
1246
1247 case 0x80:
1248 {
1249 int irq = irq_of_magic (val);
1250 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1251 if (irq > 0) {
1252 s->irq = irq;
1253 }
1254 }
1255 break;
1256
1257 case 0x81:
1258 {
1259 int dma, hdma;
1260
1261 dma = lsbindex (val & 0xf);
1262 hdma = lsbindex (val & 0xf0);
1263 if (dma != s->dma || hdma != s->hdma) {
1264 dolog (
1265 "attempt to change DMA "
1266 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1267 dma, s->dma, hdma, s->hdma, val);
1268 }
1269#if 0
1270 s->dma = dma;
1271 s->hdma = hdma;
1272#endif
1273 }
1274 break;
1275
1276 case 0x82:
1277 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1278 val);
1279#ifdef VBOX
1280 return VINF_SUCCESS;
1281#endif
1282
1283 default:
1284 if (s->mixer_nreg >= 0x80) {
1285 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1286 }
1287 break;
1288 }
1289
1290 s->mixer_regs[s->mixer_nreg] = val;
1291
1292#ifdef VBOX
1293 /* allow to set the PCM_out volume */
1294 if (s->mixer_nreg == 0x30 || s->mixer_nreg == 0x31)
1295 {
1296 int mute = 0;
1297 uint8_t lvol = s->mixer_regs[0x30];
1298 uint8_t rvol = s->mixer_regs[0x31];
1299 AUD_set_volume (AUD_MIXER_VOLUME, &mute, &lvol, &rvol);
1300 }
1301#endif /* VBOX */
1302
1303#ifdef VBOX
1304 return VINF_SUCCESS;
1305#endif
1306}
1307
1308static IO_WRITE_PROTO(mixer_write)
1309{
1310#ifndef VBOX
1311 mixer_write_indexb (opaque, nport, val & 0xff);
1312 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1313#else /* VBOX */
1314 SB16State *s = (SB16State*)opaque;
1315 int iport = nport - s->port;
1316 switch (cb)
1317 {
1318 case 1:
1319 switch (iport)
1320 {
1321 case 4:
1322 mixer_write_indexb (pDevIns, opaque, nport, val, 1);
1323 break;
1324 case 5:
1325 mixer_write_datab (pDevIns, opaque, nport, val, 1);
1326 break;
1327 }
1328 break;
1329 case 2:
1330 mixer_write_indexb (pDevIns, opaque, nport, val & 0xff, 1);
1331 mixer_write_datab (pDevIns, opaque, nport, (val >> 8) & 0xff, 1);
1332 break;
1333 default:
1334 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", nport, cb, val));
1335 break;
1336 }
1337 return VINF_SUCCESS;
1338#endif /* VBOX */
1339}
1340
1341static IO_READ_PROTO(mixer_read)
1342{
1343 SB16State *s = (SB16State*)opaque;
1344
1345 (void) nport;
1346#ifndef DEBUG_SB16_MOST
1347 if (s->mixer_nreg != 0x82) {
1348 ldebug ("mixer_read[%#x] -> %#x\n",
1349 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1350 }
1351#else
1352 ldebug ("mixer_read[%#x] -> %#x\n",
1353 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1354#endif
1355#ifndef VBOX
1356 return s->mixer_regs[s->mixer_nreg];
1357#else
1358 *pu32 = s->mixer_regs[s->mixer_nreg];
1359 return VINF_SUCCESS;
1360#endif
1361}
1362
1363static int write_audio (SB16State *s, int nchan, int dma_pos,
1364 int dma_len, int len)
1365{
1366 int temp, net;
1367 uint8_t tmpbuf[4096];
1368
1369 temp = len;
1370 net = 0;
1371
1372 while (temp) {
1373 int left = dma_len - dma_pos;
1374#ifndef VBOX
1375 int copied;
1376 size_t to_copy;
1377#else
1378 uint32_t copied;
1379 uint32_t to_copy;
1380#endif
1381
1382 to_copy = audio_MIN (temp, left);
1383 if (to_copy > sizeof (tmpbuf)) {
1384 to_copy = sizeof (tmpbuf);
1385 }
1386
1387#ifndef VBOX
1388 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1389#else
1390 int rc = PDMDevHlpDMAReadMemory(s->pDevIns, nchan, tmpbuf, dma_pos,
1391 to_copy, &copied);
1392 AssertMsgRC (rc, ("DMAReadMemory -> %Rrc\n", rc));
1393#endif
1394
1395 copied = AUD_write (s->voice, tmpbuf, copied);
1396
1397 temp -= copied;
1398 dma_pos = (dma_pos + copied) % dma_len;
1399 net += copied;
1400
1401 if (!copied) {
1402 break;
1403 }
1404 }
1405
1406 return net;
1407}
1408
1409#ifndef VBOX
1410static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1411#else
1412static DECLCALLBACK(uint32_t) SB_read_DMA (PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len)
1413#endif
1414{
1415 SB16State *s = (SB16State*)opaque;
1416 int till, copy, written, free;
1417
1418 if (s->block_size <= 0) {
1419 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1420 s->block_size, nchan, dma_pos, dma_len);
1421 return dma_pos;
1422 }
1423
1424 if (s->left_till_irq < 0) {
1425 s->left_till_irq = s->block_size;
1426 }
1427
1428 if (s->voice) {
1429 free = s->audio_free & ~s->align;
1430 if ((free <= 0) || !dma_len) {
1431 return dma_pos;
1432 }
1433 }
1434 else {
1435 free = dma_len;
1436 }
1437
1438 copy = free;
1439 till = s->left_till_irq;
1440
1441#ifdef DEBUG_SB16_MOST
1442 dolog ("pos:%06d %d till:%d len:%d\n",
1443 dma_pos, free, till, dma_len);
1444#endif
1445
1446 if (copy >= till) {
1447 if (0 == s->dma_auto) {
1448 copy = till;
1449 } else {
1450 if( copy >= till + s->block_size ) {
1451 copy = till; /* Make sure we won't skip IRQs. */
1452 }
1453 }
1454 }
1455
1456 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1457 dma_pos = (dma_pos + written) % dma_len;
1458 s->left_till_irq -= written;
1459
1460 if (s->left_till_irq <= 0) {
1461 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1462#ifndef VBOX
1463 qemu_irq_raise (s->pic[s->irq]);
1464#else
1465 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
1466#endif
1467 if (0 == s->dma_auto) {
1468 control (s, 0);
1469 speaker (s, 0);
1470 }
1471 }
1472
1473#ifdef DEBUG_SB16_MOST
1474 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1475 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1476 s->block_size);
1477#endif
1478
1479 while (s->left_till_irq <= 0) {
1480 s->left_till_irq = s->block_size + s->left_till_irq;
1481 }
1482
1483 return dma_pos;
1484}
1485
1486static void SB_audio_callback (void *opaque, int free)
1487{
1488 SB16State *s = (SB16State*)opaque;
1489 s->audio_free = free;
1490#ifdef VBOX
1491 /* New space available, see if we can transfer more. There is no cyclic DMA timer in VBox. */
1492 PDMDevHlpDMASchedule (s->pDevIns);
1493#endif
1494}
1495
1496static void SB_save (QEMUFile *f, void *opaque)
1497{
1498#ifndef VBOX
1499 SB16State *s = opaque;
1500#else
1501 SB16State *s = (SB16State *)opaque;
1502#endif
1503
1504 qemu_put_be32 (f, s->irq);
1505 qemu_put_be32 (f, s->dma);
1506 qemu_put_be32 (f, s->hdma);
1507 qemu_put_be32 (f, s->port);
1508 qemu_put_be32 (f, s->ver);
1509 qemu_put_be32 (f, s->in_index);
1510 qemu_put_be32 (f, s->out_data_len);
1511 qemu_put_be32 (f, s->fmt_stereo);
1512 qemu_put_be32 (f, s->fmt_signed);
1513 qemu_put_be32 (f, s->fmt_bits);
1514 qemu_put_be32s (f, &s->fmt);
1515 qemu_put_be32 (f, s->dma_auto);
1516 qemu_put_be32 (f, s->block_size);
1517 qemu_put_be32 (f, s->fifo);
1518 qemu_put_be32 (f, s->freq);
1519 qemu_put_be32 (f, s->time_const);
1520 qemu_put_be32 (f, s->speaker);
1521 qemu_put_be32 (f, s->needed_bytes);
1522 qemu_put_be32 (f, s->cmd);
1523 qemu_put_be32 (f, s->use_hdma);
1524 qemu_put_be32 (f, s->highspeed);
1525 qemu_put_be32 (f, s->can_write);
1526 qemu_put_be32 (f, s->v2x6);
1527
1528 qemu_put_8s (f, &s->csp_param);
1529 qemu_put_8s (f, &s->csp_value);
1530 qemu_put_8s (f, &s->csp_mode);
1531 qemu_put_8s (f, &s->csp_param);
1532 qemu_put_buffer (f, s->csp_regs, 256);
1533 qemu_put_8s (f, &s->csp_index);
1534 qemu_put_buffer (f, s->csp_reg83, 4);
1535 qemu_put_be32 (f, s->csp_reg83r);
1536 qemu_put_be32 (f, s->csp_reg83w);
1537
1538 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1539 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1540 qemu_put_8s (f, &s->test_reg);
1541 qemu_put_8s (f, &s->last_read_byte);
1542
1543 qemu_put_be32 (f, s->nzero);
1544 qemu_put_be32 (f, s->left_till_irq);
1545 qemu_put_be32 (f, s->dma_running);
1546 qemu_put_be32 (f, s->bytes_per_second);
1547 qemu_put_be32 (f, s->align);
1548
1549 qemu_put_be32 (f, s->mixer_nreg);
1550 qemu_put_buffer (f, s->mixer_regs, 256);
1551}
1552
1553static int SB_load (QEMUFile *f, void *opaque, int version_id)
1554{
1555#ifndef VBOX
1556 SB16State *s = opaque;
1557
1558 if (version_id != 1) {
1559 return -EINVAL;
1560 }
1561#else
1562 SB16State *s = (SB16State *)opaque;
1563#endif
1564
1565 s->irq=qemu_get_be32 (f);
1566 s->dma=qemu_get_be32 (f);
1567 s->hdma=qemu_get_be32 (f);
1568 s->port=qemu_get_be32 (f);
1569 s->ver=qemu_get_be32 (f);
1570 s->in_index=qemu_get_be32 (f);
1571 s->out_data_len=qemu_get_be32 (f);
1572 s->fmt_stereo=qemu_get_be32 (f);
1573 s->fmt_signed=qemu_get_be32 (f);
1574 s->fmt_bits=qemu_get_be32 (f);
1575 qemu_get_be32s (f, (uint32_t*)&s->fmt);
1576 s->dma_auto=qemu_get_be32 (f);
1577 s->block_size=qemu_get_be32 (f);
1578 s->fifo=qemu_get_be32 (f);
1579 s->freq=qemu_get_be32 (f);
1580 s->time_const=qemu_get_be32 (f);
1581 s->speaker=qemu_get_be32 (f);
1582 s->needed_bytes=qemu_get_be32 (f);
1583 s->cmd=qemu_get_be32 (f);
1584 s->use_hdma=qemu_get_be32 (f);
1585 s->highspeed=qemu_get_be32 (f);
1586 s->can_write=qemu_get_be32 (f);
1587 s->v2x6=qemu_get_be32 (f);
1588
1589 qemu_get_8s (f, &s->csp_param);
1590 qemu_get_8s (f, &s->csp_value);
1591 qemu_get_8s (f, &s->csp_mode);
1592 qemu_get_8s (f, &s->csp_param);
1593 qemu_get_buffer (f, s->csp_regs, 256);
1594 qemu_get_8s (f, &s->csp_index);
1595 qemu_get_buffer (f, s->csp_reg83, 4);
1596 s->csp_reg83r=qemu_get_be32 (f);
1597 s->csp_reg83w=qemu_get_be32 (f);
1598
1599 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1600 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1601 qemu_get_8s (f, &s->test_reg);
1602 qemu_get_8s (f, &s->last_read_byte);
1603
1604 s->nzero=qemu_get_be32 (f);
1605 s->left_till_irq=qemu_get_be32 (f);
1606 s->dma_running=qemu_get_be32 (f);
1607 s->bytes_per_second=qemu_get_be32 (f);
1608 s->align=qemu_get_be32 (f);
1609
1610 s->mixer_nreg=qemu_get_be32 (f);
1611 qemu_get_buffer (f, s->mixer_regs, 256);
1612
1613 if (s->voice) {
1614 AUD_close_out (&s->card, s->voice);
1615 s->voice = NULL;
1616 }
1617
1618 if (s->dma_running) {
1619 if (s->freq) {
1620 audsettings_t as;
1621
1622 s->audio_free = 0;
1623
1624 as.freq = s->freq;
1625 as.nchannels = 1 << s->fmt_stereo;
1626 as.fmt = s->fmt;
1627 as.endianness = 0;
1628
1629 s->voice = AUD_open_out (
1630 &s->card,
1631 s->voice,
1632 "sb16",
1633 s,
1634 SB_audio_callback,
1635 &as
1636 );
1637 }
1638
1639 control (s, 1);
1640 speaker (s, s->speaker);
1641 }
1642
1643#ifdef VBOX
1644 return VINF_SUCCESS;
1645#endif
1646}
1647
1648#ifndef VBOX
1649int SB16_init (AudioState *audio, qemu_irq *pic)
1650{
1651 SB16State *s;
1652 int i;
1653 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1654 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1655
1656 if (!audio) {
1657 dolog ("No audio state\n");
1658 return -1;
1659 }
1660
1661 s = qemu_mallocz (sizeof (*s));
1662 if (!s) {
1663 dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1664 sizeof (*s));
1665 return -1;
1666 }
1667
1668 s->cmd = -1;
1669 s->pic = pic;
1670 s->irq = conf.irq;
1671 s->dma = conf.dma;
1672 s->hdma = conf.hdma;
1673 s->port = conf.port;
1674 s->ver = conf.ver_lo | (conf.ver_hi << 8);
1675
1676 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1677 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1678 s->mixer_regs[0x82] = 2 << 5;
1679
1680 s->csp_regs[5] = 1;
1681 s->csp_regs[9] = 0xf8;
1682
1683 reset_mixer (s);
1684 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1685 if (!s->aux_ts) {
1686 dolog ("warning: Could not create auxiliary timer\n");
1687 }
1688
1689 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1690 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1691 }
1692
1693 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1694 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1695 }
1696
1697 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1698 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1699 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1700 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1701
1702 DMA_register_channel (s->hdma, SB_read_DMA, s);
1703 DMA_register_channel (s->dma, SB_read_DMA, s);
1704 s->can_write = 1;
1705
1706 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1707 AUD_register_card (audio, "sb16", &s->card);
1708 return 0;
1709}
1710
1711#else /* VBOX */
1712
1713
1714static DECLCALLBACK(int) sb16LiveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
1715{
1716 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1717
1718 SSMR3PutS32(pSSM, pThis->irqCfg);
1719 SSMR3PutS32(pSSM, pThis->dmaCfg);
1720 SSMR3PutS32(pSSM, pThis->hdmaCfg);
1721 SSMR3PutS32(pSSM, pThis->portCfg);
1722 SSMR3PutS32(pSSM, pThis->verCfg);
1723 return VINF_SSM_DONT_CALL_AGAIN;
1724}
1725
1726static DECLCALLBACK(int) sb16SaveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1727{
1728 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1729
1730 sb16LiveExec (pDevIns, pSSM, 0);
1731 SB_save (pSSM, pThis);
1732 return VINF_SUCCESS;
1733}
1734
1735static DECLCALLBACK(int) sb16LoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM,
1736 uint32_t uVersion, uint32_t uPass)
1737{
1738 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1739
1740 AssertMsgReturn( uVersion == SB16_SAVE_STATE_VERSION
1741 || uVersion == SB16_SAVE_STATE_VERSION_VBOX_30,
1742 ("%u\n", uVersion),
1743 VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1744 if (uVersion > SB16_SAVE_STATE_VERSION_VBOX_30)
1745 {
1746 int32_t irq;
1747 SSMR3GetS32 (pSSM, &irq);
1748 int32_t dma;
1749 SSMR3GetS32 (pSSM, &dma);
1750 int32_t hdma;
1751 SSMR3GetS32 (pSSM, &hdma);
1752 int32_t port;
1753 SSMR3GetS32 (pSSM, &port);
1754 int32_t ver;
1755 int rc = SSMR3GetS32 (pSSM, &ver);
1756 AssertRCReturn (rc, rc);
1757
1758 if ( irq != pThis->irqCfg
1759 || dma != pThis->dmaCfg
1760 || hdma != pThis->hdmaCfg
1761 || port != pThis->portCfg
1762 || ver != pThis->verCfg )
1763 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
1764 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"),
1765 irq, pThis->irqCfg,
1766 dma, pThis->dmaCfg,
1767 hdma, pThis->hdmaCfg,
1768 port, pThis->portCfg,
1769 ver, pThis->verCfg);
1770 }
1771 if (uPass != SSM_PASS_FINAL)
1772 return VINF_SUCCESS;
1773
1774 SB_load(pSSM, pThis, uVersion);
1775 return VINF_SUCCESS;
1776}
1777
1778/**
1779 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1780 */
1781static DECLCALLBACK(void *) sb16QueryInterface (struct PDMIBASE *pInterface,
1782 const char *pszIID)
1783{
1784 SB16State *pThis = RT_FROM_MEMBER(pInterface, SB16State, IBase);
1785 Assert(&pThis->IBase == pInterface);
1786
1787 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
1788 return NULL;
1789}
1790
1791static DECLCALLBACK(int) sb16Construct (PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1792{
1793 SB16State *s = PDMINS_2_DATA(pDevIns, SB16State *);
1794 int rc;
1795
1796 /*
1797 * Validations.
1798 */
1799 Assert(iInstance == 0);
1800 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1801 if (!CFGMR3AreValuesValid(pCfgHandle,
1802 "IRQ\0"
1803 "DMA\0"
1804 "DMA16\0"
1805 "Port\0"
1806 "Version\0"))
1807 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1808 N_("Invalid configuration for sb16 device"));
1809
1810 /*
1811 * Read config data.
1812 */
1813 rc = CFGMR3QuerySIntDef(pCfgHandle, "IRQ", &s->irq, 5);
1814 if (RT_FAILURE(rc))
1815 return PDMDEV_SET_ERROR(pDevIns, rc,
1816 N_("Configuration error: Failed to get the \"IRQ\" value"));
1817 s->irqCfg = s->irq;
1818
1819 rc = CFGMR3QuerySIntDef(pCfgHandle, "DMA", &s->dma, 1);
1820 if (RT_FAILURE(rc))
1821 return PDMDEV_SET_ERROR(pDevIns, rc,
1822 N_("Configuration error: Failed to get the \"DMA\" value"));
1823 s->dmaCfg = s->dma;
1824
1825 rc = CFGMR3QuerySIntDef(pCfgHandle, "DMA16", &s->hdma, 5);
1826 if (RT_FAILURE(rc))
1827 return PDMDEV_SET_ERROR(pDevIns, rc,
1828 N_("Configuration error: Failed to get the \"DMA16\" value"));
1829 s->hdmaCfg = s->hdma;
1830
1831 RTIOPORT Port;
1832 rc = CFGMR3QueryPortDef(pCfgHandle, "Port", &Port, 0x220);
1833 if (RT_FAILURE(rc))
1834 return PDMDEV_SET_ERROR(pDevIns, rc,
1835 N_("Configuration error: Failed to get the \"Port\" value"));
1836 s->port = Port;
1837 s->portCfg = Port;
1838
1839 uint16_t u16Version;
1840 rc = CFGMR3QueryU16Def(pCfgHandle, "Version", &u16Version, 0x0405);
1841 if (RT_FAILURE(rc))
1842 return PDMDEV_SET_ERROR(pDevIns, rc,
1843 N_("Configuration error: Failed to get the \"Version\" value"));
1844 s->ver = u16Version;
1845 s->verCfg = u16Version;
1846
1847 /*
1848 * Init instance data.
1849 */
1850 s->pDevIns = pDevIns;
1851 s->IBase.pfnQueryInterface = sb16QueryInterface;
1852 s->cmd = -1;
1853
1854 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1855 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1856 s->mixer_regs[0x82] = 2 << 5;
1857
1858 s->csp_regs[5] = 1;
1859 s->csp_regs[9] = 0xf8;
1860
1861 reset_mixer(s);
1862
1863 /*
1864 * Create timer, register & attach stuff.
1865 */
1866 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16Timer, s,
1867 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 timer", &s->pTimer);
1868 if (RT_FAILURE(rc))
1869 AssertMsgFailedReturn(("pfnTMTimerCreate -> %Rrc\n", rc), rc);
1870
1871 rc = PDMDevHlpIOPortRegister(pDevIns, s->port + 0x04, 2, s,
1872 mixer_write, mixer_read, NULL, NULL, "SB16");
1873 if (RT_FAILURE(rc))
1874 return rc;
1875 rc = PDMDevHlpIOPortRegister(pDevIns, s->port + 0x06, 10, s,
1876 dsp_write, dsp_read, NULL, NULL, "SB16");
1877 if (RT_FAILURE(rc))
1878 return rc;
1879
1880 rc = PDMDevHlpDMARegister(pDevIns, s->hdma, SB_read_DMA, s);
1881 if (RT_FAILURE(rc))
1882 return rc;
1883 rc = PDMDevHlpDMARegister(pDevIns, s->dma, SB_read_DMA, s);
1884 if (RT_FAILURE(rc))
1885 return rc;
1886
1887 s->can_write = 1;
1888
1889 rc = PDMDevHlpSSMRegister3(pDevIns, SB16_SAVE_STATE_VERSION, sizeof(*s), sb16LiveExec, sb16SaveExec, sb16LoadExec);
1890 if (RT_FAILURE(rc))
1891 return rc;
1892
1893 rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase, "Audio Driver Port");
1894 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1895 Log(("sb16: No attached driver!\n"));
1896 else if (RT_FAILURE(rc))
1897 AssertMsgFailedReturn(("Failed to attach SB16 LUN #0! rc=%Rrc\n", rc), rc);
1898
1899 AUD_register_card("sb16", &s->card);
1900 legacy_reset(s);
1901
1902 if (!s->voice)
1903 {
1904 AUD_close_out(&s->card, s->voice);
1905 s->voice = NULL;
1906 AUD_init_null();
1907 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1908 N_("No audio devices could be opened. Selecting the NULL audio backend "
1909 "with the consequence that no sound is audible"));
1910 }
1911 return VINF_SUCCESS;
1912}
1913
1914const PDMDEVREG g_DeviceSB16 =
1915{
1916 /* u32Version */
1917 PDM_DEVREG_VERSION,
1918 /* szName */
1919 "sb16",
1920 /* szRCMod */
1921 "",
1922 /* szR0Mod */
1923 "",
1924 /* pszDescription */
1925 "Sound Blaster 16 Controller",
1926 /* fFlags */
1927 PDM_DEVREG_FLAGS_DEFAULT_BITS,
1928 /* fClass */
1929 PDM_DEVREG_CLASS_AUDIO,
1930 /* cMaxInstances */
1931 1,
1932 /* cbInstance */
1933 sizeof(SB16State),
1934 /* pfnConstruct */
1935 sb16Construct,
1936 /* pfnDesctruct */
1937 NULL,
1938 /* pfnRelocate */
1939 NULL,
1940 /* pfnIOCtl */
1941 NULL,
1942 /* pfnPowerOn */
1943 NULL,
1944 /* pfnReset */
1945 NULL,
1946 /* pfnSuspend */
1947 NULL,
1948 /* pfnResume */
1949 NULL,
1950 /* pfnAttach */
1951 NULL,
1952 /* pfnDetach */
1953 NULL,
1954 /* pfnQueryInterface */
1955 NULL,
1956 /* pfnInitComplete */
1957 NULL,
1958 /* pfnPowerOff */
1959 NULL,
1960 /* pfnSoftReset */
1961 NULL,
1962 /* u32VersionEnd */
1963 PDM_DEVREG_VERSION
1964};
1965
1966#endif /* VBOX */
1967
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use