VirtualBox

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

Last change on this file since 49983 was 45025, checked in by vboxsync, 12 years ago

Update PDMDEVREG initialization comment so they refer to pfnMemSetup instead of pfnIOCtl.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.1 KB
Line 
1/* $Id: DevSB16.cpp 45025 2013-03-13 16:45:15Z 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/vmm/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 bool update_master = false;
1239 bool update_voice = false;
1240
1241 (void) nport;
1242 ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
1243
1244 switch (s->mixer_nreg) {
1245 case 0x00:
1246 reset_mixer(s);
1247 /* And update the actual volume, too. */
1248 update_master = true;
1249 update_voice = true;
1250 break;
1251
1252 case 0x04:
1253 /* Translate from old style voice volume (L/R). */
1254 s->mixer_regs[0x32] = val & 0xff;
1255 s->mixer_regs[0x33] = val << 4;
1256 update_voice = true;
1257 break;
1258
1259 case 0x22:
1260 /* Translate from old style master volume (L/R). */
1261 s->mixer_regs[0x30] = val & 0xff;
1262 s->mixer_regs[0x31] = val << 4;
1263 update_master = true;
1264 break;
1265
1266 case 0x30:
1267 /* Translate to old style master volume (L). */
1268 s->mixer_regs[0x22] = (s->mixer_regs[0x22] & 0x0f) | val;
1269 update_master = true;
1270 break;
1271
1272 case 0x31:
1273 /* Translate to old style master volume (R). */
1274 s->mixer_regs[0x22] = (s->mixer_regs[0x22] & 0xf0) | (val >> 4);
1275 update_master = true;
1276 break;
1277
1278 case 0x32:
1279 /* Translate to old style voice volume (L). */
1280 s->mixer_regs[0x04] = (s->mixer_regs[0x04] & 0x0f) | val;
1281 update_voice = true;
1282 break;
1283
1284 case 0x33:
1285 /* Translate to old style voice volume (R). */
1286 s->mixer_regs[0x04] = (s->mixer_regs[0x04] & 0xf0) | (val >> 4);
1287 update_voice = true;
1288 break;
1289
1290 case 0x80:
1291 {
1292 int irq = irq_of_magic (val);
1293 ldebug ("setting irq to %d (val=%#x)\n", irq, val);
1294 if (irq > 0) {
1295 s->irq = irq;
1296 }
1297 }
1298 break;
1299
1300 case 0x81:
1301 {
1302 int dma, hdma;
1303
1304 dma = lsbindex (val & 0xf);
1305 hdma = lsbindex (val & 0xf0);
1306 if (dma != s->dma || hdma != s->hdma) {
1307 dolog (
1308 "attempt to change DMA "
1309 "8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1310 dma, s->dma, hdma, s->hdma, val);
1311 }
1312#if 0
1313 s->dma = dma;
1314 s->hdma = hdma;
1315#endif
1316 }
1317 break;
1318
1319 case 0x82:
1320 dolog ("attempt to write into IRQ status register (val=%#x)\n",
1321 val);
1322#ifdef VBOX
1323 return VINF_SUCCESS;
1324#endif
1325
1326 default:
1327 if (s->mixer_nreg >= 0x80) {
1328 ldebug ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
1329 }
1330 break;
1331 }
1332
1333 s->mixer_regs[s->mixer_nreg] = val;
1334
1335#ifdef VBOX
1336 /* Update the master (mixer) volume. */
1337 if (update_master)
1338 {
1339 int mute = 0;
1340 uint8_t lvol = s->mixer_regs[0x30];
1341 uint8_t rvol = s->mixer_regs[0x31];
1342 AUD_set_volume(AUD_MIXER_VOLUME, &mute, &lvol, &rvol);
1343 }
1344 /* Update the voice (PCM) volume. */
1345 if (update_voice)
1346 {
1347 int mute = 0;
1348 uint8_t lvol = s->mixer_regs[0x32];
1349 uint8_t rvol = s->mixer_regs[0x33];
1350 AUD_set_volume(AUD_MIXER_PCM, &mute, &lvol, &rvol);
1351 }
1352#endif /* VBOX */
1353
1354#ifdef VBOX
1355 return VINF_SUCCESS;
1356#endif
1357}
1358
1359static IO_WRITE_PROTO(mixer_write)
1360{
1361#ifndef VBOX
1362 mixer_write_indexb (opaque, nport, val & 0xff);
1363 mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
1364#else /* VBOX */
1365 SB16State *s = (SB16State*)opaque;
1366 int iport = nport - s->port;
1367 switch (cb)
1368 {
1369 case 1:
1370 switch (iport)
1371 {
1372 case 4:
1373 mixer_write_indexb (pDevIns, opaque, nport, val, 1);
1374 break;
1375 case 5:
1376 mixer_write_datab (pDevIns, opaque, nport, val, 1);
1377 break;
1378 }
1379 break;
1380 case 2:
1381 mixer_write_indexb (pDevIns, opaque, nport, val & 0xff, 1);
1382 mixer_write_datab (pDevIns, opaque, nport, (val >> 8) & 0xff, 1);
1383 break;
1384 default:
1385 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", nport, cb, val));
1386 break;
1387 }
1388 return VINF_SUCCESS;
1389#endif /* VBOX */
1390}
1391
1392static IO_READ_PROTO(mixer_read)
1393{
1394 SB16State *s = (SB16State*)opaque;
1395
1396 (void) nport;
1397#ifndef DEBUG_SB16_MOST
1398 if (s->mixer_nreg != 0x82) {
1399 ldebug ("mixer_read[%#x] -> %#x\n",
1400 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1401 }
1402#else
1403 ldebug ("mixer_read[%#x] -> %#x\n",
1404 s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
1405#endif
1406#ifndef VBOX
1407 return s->mixer_regs[s->mixer_nreg];
1408#else
1409 *pu32 = s->mixer_regs[s->mixer_nreg];
1410 return VINF_SUCCESS;
1411#endif
1412}
1413
1414static int write_audio (SB16State *s, int nchan, int dma_pos,
1415 int dma_len, int len)
1416{
1417 int temp, net;
1418 uint8_t tmpbuf[4096];
1419
1420 temp = len;
1421 net = 0;
1422
1423 while (temp) {
1424 int left = dma_len - dma_pos;
1425#ifndef VBOX
1426 int copied;
1427 size_t to_copy;
1428#else
1429 uint32_t copied;
1430 uint32_t to_copy;
1431#endif
1432
1433 to_copy = audio_MIN (temp, left);
1434 if (to_copy > sizeof (tmpbuf)) {
1435 to_copy = sizeof (tmpbuf);
1436 }
1437
1438#ifndef VBOX
1439 copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1440#else
1441 int rc = PDMDevHlpDMAReadMemory(s->pDevIns, nchan, tmpbuf, dma_pos,
1442 to_copy, &copied);
1443 AssertMsgRC (rc, ("DMAReadMemory -> %Rrc\n", rc));
1444#endif
1445
1446 copied = AUD_write (s->voice, tmpbuf, copied);
1447
1448 temp -= copied;
1449 dma_pos = (dma_pos + copied) % dma_len;
1450 net += copied;
1451
1452 if (!copied) {
1453 break;
1454 }
1455 }
1456
1457 return net;
1458}
1459
1460#ifndef VBOX
1461static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1462#else
1463static DECLCALLBACK(uint32_t) SB_read_DMA (PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len)
1464#endif
1465{
1466 SB16State *s = (SB16State*)opaque;
1467 int till, copy, written, free;
1468
1469 if (s->block_size <= 0) {
1470 dolog ("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1471 s->block_size, nchan, dma_pos, dma_len);
1472 return dma_pos;
1473 }
1474
1475 if (s->left_till_irq < 0) {
1476 s->left_till_irq = s->block_size;
1477 }
1478
1479 if (s->voice) {
1480 free = s->audio_free & ~s->align;
1481 if ((free <= 0) || !dma_len) {
1482 return dma_pos;
1483 }
1484 }
1485 else {
1486 free = dma_len;
1487 }
1488
1489 copy = free;
1490 till = s->left_till_irq;
1491
1492#ifdef DEBUG_SB16_MOST
1493 dolog ("pos:%06d %d till:%d len:%d\n",
1494 dma_pos, free, till, dma_len);
1495#endif
1496
1497 if (copy >= till) {
1498 if (0 == s->dma_auto) {
1499 copy = till;
1500 } else {
1501 if( copy >= till + s->block_size ) {
1502 copy = till; /* Make sure we won't skip IRQs. */
1503 }
1504 }
1505 }
1506
1507 written = write_audio (s, nchan, dma_pos, dma_len, copy);
1508 dma_pos = (dma_pos + written) % dma_len;
1509 s->left_till_irq -= written;
1510
1511 if (s->left_till_irq <= 0) {
1512 s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1513#ifndef VBOX
1514 qemu_irq_raise (s->pic[s->irq]);
1515#else
1516 PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
1517#endif
1518 if (0 == s->dma_auto) {
1519 control (s, 0);
1520 speaker (s, 0);
1521 }
1522 }
1523
1524#ifdef DEBUG_SB16_MOST
1525 ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1526 dma_pos, free, dma_len, s->left_till_irq, copy, written,
1527 s->block_size);
1528#endif
1529
1530 while (s->left_till_irq <= 0) {
1531 s->left_till_irq = s->block_size + s->left_till_irq;
1532 }
1533
1534 return dma_pos;
1535}
1536
1537static void SB_audio_callback (void *opaque, int free)
1538{
1539 SB16State *s = (SB16State*)opaque;
1540 s->audio_free = free;
1541#ifdef VBOX
1542 /* New space available, see if we can transfer more. There is no cyclic DMA timer in VBox. */
1543 PDMDevHlpDMASchedule (s->pDevIns);
1544#endif
1545}
1546
1547static void SB_save (QEMUFile *f, void *opaque)
1548{
1549#ifndef VBOX
1550 SB16State *s = opaque;
1551#else
1552 SB16State *s = (SB16State *)opaque;
1553#endif
1554
1555 qemu_put_be32 (f, s->irq);
1556 qemu_put_be32 (f, s->dma);
1557 qemu_put_be32 (f, s->hdma);
1558 qemu_put_be32 (f, s->port);
1559 qemu_put_be32 (f, s->ver);
1560 qemu_put_be32 (f, s->in_index);
1561 qemu_put_be32 (f, s->out_data_len);
1562 qemu_put_be32 (f, s->fmt_stereo);
1563 qemu_put_be32 (f, s->fmt_signed);
1564 qemu_put_be32 (f, s->fmt_bits);
1565 qemu_put_be32s (f, &s->fmt);
1566 qemu_put_be32 (f, s->dma_auto);
1567 qemu_put_be32 (f, s->block_size);
1568 qemu_put_be32 (f, s->fifo);
1569 qemu_put_be32 (f, s->freq);
1570 qemu_put_be32 (f, s->time_const);
1571 qemu_put_be32 (f, s->speaker);
1572 qemu_put_be32 (f, s->needed_bytes);
1573 qemu_put_be32 (f, s->cmd);
1574 qemu_put_be32 (f, s->use_hdma);
1575 qemu_put_be32 (f, s->highspeed);
1576 qemu_put_be32 (f, s->can_write);
1577 qemu_put_be32 (f, s->v2x6);
1578
1579 qemu_put_8s (f, &s->csp_param);
1580 qemu_put_8s (f, &s->csp_value);
1581 qemu_put_8s (f, &s->csp_mode);
1582 qemu_put_8s (f, &s->csp_param);
1583 qemu_put_buffer (f, s->csp_regs, 256);
1584 qemu_put_8s (f, &s->csp_index);
1585 qemu_put_buffer (f, s->csp_reg83, 4);
1586 qemu_put_be32 (f, s->csp_reg83r);
1587 qemu_put_be32 (f, s->csp_reg83w);
1588
1589 qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1590 qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1591 qemu_put_8s (f, &s->test_reg);
1592 qemu_put_8s (f, &s->last_read_byte);
1593
1594 qemu_put_be32 (f, s->nzero);
1595 qemu_put_be32 (f, s->left_till_irq);
1596 qemu_put_be32 (f, s->dma_running);
1597 qemu_put_be32 (f, s->bytes_per_second);
1598 qemu_put_be32 (f, s->align);
1599
1600 qemu_put_be32 (f, s->mixer_nreg);
1601 qemu_put_buffer (f, s->mixer_regs, 256);
1602}
1603
1604static int SB_load (QEMUFile *f, void *opaque, int version_id)
1605{
1606#ifndef VBOX
1607 SB16State *s = opaque;
1608
1609 if (version_id != 1) {
1610 return -EINVAL;
1611 }
1612#else
1613 SB16State *s = (SB16State *)opaque;
1614#endif
1615
1616 s->irq=qemu_get_be32 (f);
1617 s->dma=qemu_get_be32 (f);
1618 s->hdma=qemu_get_be32 (f);
1619 s->port=qemu_get_be32 (f);
1620 s->ver=qemu_get_be32 (f);
1621 s->in_index=qemu_get_be32 (f);
1622 s->out_data_len=qemu_get_be32 (f);
1623 s->fmt_stereo=qemu_get_be32 (f);
1624 s->fmt_signed=qemu_get_be32 (f);
1625 s->fmt_bits=qemu_get_be32 (f);
1626 qemu_get_be32s (f, (uint32_t*)&s->fmt);
1627 s->dma_auto=qemu_get_be32 (f);
1628 s->block_size=qemu_get_be32 (f);
1629 s->fifo=qemu_get_be32 (f);
1630 s->freq=qemu_get_be32 (f);
1631 s->time_const=qemu_get_be32 (f);
1632 s->speaker=qemu_get_be32 (f);
1633 s->needed_bytes=qemu_get_be32 (f);
1634 s->cmd=qemu_get_be32 (f);
1635 s->use_hdma=qemu_get_be32 (f);
1636 s->highspeed=qemu_get_be32 (f);
1637 s->can_write=qemu_get_be32 (f);
1638 s->v2x6=qemu_get_be32 (f);
1639
1640 qemu_get_8s (f, &s->csp_param);
1641 qemu_get_8s (f, &s->csp_value);
1642 qemu_get_8s (f, &s->csp_mode);
1643 qemu_get_8s (f, &s->csp_param);
1644 qemu_get_buffer (f, s->csp_regs, 256);
1645 qemu_get_8s (f, &s->csp_index);
1646 qemu_get_buffer (f, s->csp_reg83, 4);
1647 s->csp_reg83r=qemu_get_be32 (f);
1648 s->csp_reg83w=qemu_get_be32 (f);
1649
1650 qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1651 qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1652 qemu_get_8s (f, &s->test_reg);
1653 qemu_get_8s (f, &s->last_read_byte);
1654
1655 s->nzero=qemu_get_be32 (f);
1656 s->left_till_irq=qemu_get_be32 (f);
1657 s->dma_running=qemu_get_be32 (f);
1658 s->bytes_per_second=qemu_get_be32 (f);
1659 s->align=qemu_get_be32 (f);
1660
1661 s->mixer_nreg=qemu_get_be32 (f);
1662 qemu_get_buffer (f, s->mixer_regs, 256);
1663
1664 if (s->voice) {
1665 AUD_close_out (&s->card, s->voice);
1666 s->voice = NULL;
1667 }
1668
1669 if (s->dma_running) {
1670 if (s->freq) {
1671 audsettings_t as;
1672
1673 s->audio_free = 0;
1674
1675 as.freq = s->freq;
1676 as.nchannels = 1 << s->fmt_stereo;
1677 as.fmt = s->fmt;
1678 as.endianness = 0;
1679
1680 s->voice = AUD_open_out (
1681 &s->card,
1682 s->voice,
1683 "sb16",
1684 s,
1685 SB_audio_callback,
1686 &as
1687 );
1688 }
1689
1690 control (s, 1);
1691 speaker (s, s->speaker);
1692 }
1693
1694#ifdef VBOX
1695 return VINF_SUCCESS;
1696#endif
1697}
1698
1699#ifndef VBOX
1700int SB16_init (AudioState *audio, qemu_irq *pic)
1701{
1702 SB16State *s;
1703 int i;
1704 static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1705 static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1706
1707 if (!audio) {
1708 dolog ("No audio state\n");
1709 return -1;
1710 }
1711
1712 s = qemu_mallocz (sizeof (*s));
1713 if (!s) {
1714 dolog ("Could not allocate memory for SB16 (%zu bytes)\n",
1715 sizeof (*s));
1716 return -1;
1717 }
1718
1719 s->cmd = -1;
1720 s->pic = pic;
1721 s->irq = conf.irq;
1722 s->dma = conf.dma;
1723 s->hdma = conf.hdma;
1724 s->port = conf.port;
1725 s->ver = conf.ver_lo | (conf.ver_hi << 8);
1726
1727 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1728 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1729 s->mixer_regs[0x82] = 2 << 5;
1730
1731 s->csp_regs[5] = 1;
1732 s->csp_regs[9] = 0xf8;
1733
1734 reset_mixer (s);
1735 s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1736 if (!s->aux_ts) {
1737 dolog ("warning: Could not create auxiliary timer\n");
1738 }
1739
1740 for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1741 register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1742 }
1743
1744 for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1745 register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1746 }
1747
1748 register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1749 register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1750 register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1751 register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1752
1753 DMA_register_channel (s->hdma, SB_read_DMA, s);
1754 DMA_register_channel (s->dma, SB_read_DMA, s);
1755 s->can_write = 1;
1756
1757 register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1758 AUD_register_card (audio, "sb16", &s->card);
1759 return 0;
1760}
1761
1762#else /* VBOX */
1763
1764
1765static DECLCALLBACK(int) sb16LiveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
1766{
1767 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1768
1769 SSMR3PutS32(pSSM, pThis->irqCfg);
1770 SSMR3PutS32(pSSM, pThis->dmaCfg);
1771 SSMR3PutS32(pSSM, pThis->hdmaCfg);
1772 SSMR3PutS32(pSSM, pThis->portCfg);
1773 SSMR3PutS32(pSSM, pThis->verCfg);
1774 return VINF_SSM_DONT_CALL_AGAIN;
1775}
1776
1777static DECLCALLBACK(int) sb16SaveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1778{
1779 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1780
1781 sb16LiveExec (pDevIns, pSSM, 0);
1782 SB_save (pSSM, pThis);
1783 return VINF_SUCCESS;
1784}
1785
1786static DECLCALLBACK(int) sb16LoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSM,
1787 uint32_t uVersion, uint32_t uPass)
1788{
1789 SB16State *pThis = PDMINS_2_DATA (pDevIns, SB16State *);
1790
1791 AssertMsgReturn( uVersion == SB16_SAVE_STATE_VERSION
1792 || uVersion == SB16_SAVE_STATE_VERSION_VBOX_30,
1793 ("%u\n", uVersion),
1794 VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1795 if (uVersion > SB16_SAVE_STATE_VERSION_VBOX_30)
1796 {
1797 int32_t irq;
1798 SSMR3GetS32 (pSSM, &irq);
1799 int32_t dma;
1800 SSMR3GetS32 (pSSM, &dma);
1801 int32_t hdma;
1802 SSMR3GetS32 (pSSM, &hdma);
1803 int32_t port;
1804 SSMR3GetS32 (pSSM, &port);
1805 int32_t ver;
1806 int rc = SSMR3GetS32 (pSSM, &ver);
1807 AssertRCReturn (rc, rc);
1808
1809 if ( irq != pThis->irqCfg
1810 || dma != pThis->dmaCfg
1811 || hdma != pThis->hdmaCfg
1812 || port != pThis->portCfg
1813 || ver != pThis->verCfg )
1814 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
1815 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"),
1816 irq, pThis->irqCfg,
1817 dma, pThis->dmaCfg,
1818 hdma, pThis->hdmaCfg,
1819 port, pThis->portCfg,
1820 ver, pThis->verCfg);
1821 }
1822 if (uPass != SSM_PASS_FINAL)
1823 return VINF_SUCCESS;
1824
1825 SB_load(pSSM, pThis, uVersion);
1826 return VINF_SUCCESS;
1827}
1828
1829/**
1830 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1831 */
1832static DECLCALLBACK(void *) sb16QueryInterface (struct PDMIBASE *pInterface,
1833 const char *pszIID)
1834{
1835 SB16State *pThis = RT_FROM_MEMBER(pInterface, SB16State, IBase);
1836 Assert(&pThis->IBase == pInterface);
1837
1838 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
1839 return NULL;
1840}
1841
1842static DECLCALLBACK(int) sb16Construct (PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1843{
1844 SB16State *s = PDMINS_2_DATA(pDevIns, SB16State *);
1845 int rc;
1846
1847 /*
1848 * Validations.
1849 */
1850 Assert(iInstance == 0);
1851 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1852 if (!CFGMR3AreValuesValid(pCfgHandle,
1853 "IRQ\0"
1854 "DMA\0"
1855 "DMA16\0"
1856 "Port\0"
1857 "Version\0"))
1858 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1859 N_("Invalid configuration for sb16 device"));
1860
1861 /*
1862 * Read config data.
1863 */
1864 rc = CFGMR3QuerySIntDef(pCfgHandle, "IRQ", &s->irq, 5);
1865 if (RT_FAILURE(rc))
1866 return PDMDEV_SET_ERROR(pDevIns, rc,
1867 N_("Configuration error: Failed to get the \"IRQ\" value"));
1868 s->irqCfg = s->irq;
1869
1870 rc = CFGMR3QuerySIntDef(pCfgHandle, "DMA", &s->dma, 1);
1871 if (RT_FAILURE(rc))
1872 return PDMDEV_SET_ERROR(pDevIns, rc,
1873 N_("Configuration error: Failed to get the \"DMA\" value"));
1874 s->dmaCfg = s->dma;
1875
1876 rc = CFGMR3QuerySIntDef(pCfgHandle, "DMA16", &s->hdma, 5);
1877 if (RT_FAILURE(rc))
1878 return PDMDEV_SET_ERROR(pDevIns, rc,
1879 N_("Configuration error: Failed to get the \"DMA16\" value"));
1880 s->hdmaCfg = s->hdma;
1881
1882 RTIOPORT Port;
1883 rc = CFGMR3QueryPortDef(pCfgHandle, "Port", &Port, 0x220);
1884 if (RT_FAILURE(rc))
1885 return PDMDEV_SET_ERROR(pDevIns, rc,
1886 N_("Configuration error: Failed to get the \"Port\" value"));
1887 s->port = Port;
1888 s->portCfg = Port;
1889
1890 uint16_t u16Version;
1891 rc = CFGMR3QueryU16Def(pCfgHandle, "Version", &u16Version, 0x0405);
1892 if (RT_FAILURE(rc))
1893 return PDMDEV_SET_ERROR(pDevIns, rc,
1894 N_("Configuration error: Failed to get the \"Version\" value"));
1895 s->ver = u16Version;
1896 s->verCfg = u16Version;
1897
1898 /*
1899 * Init instance data.
1900 */
1901 s->pDevIns = pDevIns;
1902 s->IBase.pfnQueryInterface = sb16QueryInterface;
1903 s->cmd = -1;
1904
1905 s->mixer_regs[0x80] = magic_of_irq (s->irq);
1906 s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1907 s->mixer_regs[0x82] = 2 << 5;
1908
1909 s->csp_regs[5] = 1;
1910 s->csp_regs[9] = 0xf8;
1911
1912 reset_mixer(s);
1913
1914 /*
1915 * Create timer, register & attach stuff.
1916 */
1917 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16Timer, s,
1918 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 timer", &s->pTimer);
1919 if (RT_FAILURE(rc))
1920 AssertMsgFailedReturn(("pfnTMTimerCreate -> %Rrc\n", rc), rc);
1921
1922 rc = PDMDevHlpIOPortRegister(pDevIns, s->port + 0x04, 2, s,
1923 mixer_write, mixer_read, NULL, NULL, "SB16");
1924 if (RT_FAILURE(rc))
1925 return rc;
1926 rc = PDMDevHlpIOPortRegister(pDevIns, s->port + 0x06, 10, s,
1927 dsp_write, dsp_read, NULL, NULL, "SB16");
1928 if (RT_FAILURE(rc))
1929 return rc;
1930
1931 rc = PDMDevHlpDMARegister(pDevIns, s->hdma, SB_read_DMA, s);
1932 if (RT_FAILURE(rc))
1933 return rc;
1934 rc = PDMDevHlpDMARegister(pDevIns, s->dma, SB_read_DMA, s);
1935 if (RT_FAILURE(rc))
1936 return rc;
1937
1938 s->can_write = 1;
1939
1940 rc = PDMDevHlpSSMRegister3(pDevIns, SB16_SAVE_STATE_VERSION, sizeof(*s), sb16LiveExec, sb16SaveExec, sb16LoadExec);
1941 if (RT_FAILURE(rc))
1942 return rc;
1943
1944 rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase, "Audio Driver Port");
1945 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
1946 Log(("sb16: No attached driver!\n"));
1947 else if (RT_FAILURE(rc))
1948 AssertMsgFailedReturn(("Failed to attach SB16 LUN #0! rc=%Rrc\n", rc), rc);
1949
1950 AUD_register_card("sb16", &s->card);
1951 legacy_reset(s);
1952
1953 if (!AUD_is_host_voice_out_ok(s->voice))
1954 {
1955 LogRel (("SB16: WARNING: Unable to open PCM OUT!\n"));
1956 AUD_close_out(&s->card, s->voice);
1957 s->voice = NULL;
1958 AUD_init_null();
1959 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
1960 N_("No audio devices could be opened. Selecting the NULL audio backend "
1961 "with the consequence that no sound is audible"));
1962 }
1963 return VINF_SUCCESS;
1964}
1965
1966const PDMDEVREG g_DeviceSB16 =
1967{
1968 /* u32Version */
1969 PDM_DEVREG_VERSION,
1970 /* szName */
1971 "sb16",
1972 /* szRCMod */
1973 "",
1974 /* szR0Mod */
1975 "",
1976 /* pszDescription */
1977 "Sound Blaster 16 Controller",
1978 /* fFlags */
1979 PDM_DEVREG_FLAGS_DEFAULT_BITS,
1980 /* fClass */
1981 PDM_DEVREG_CLASS_AUDIO,
1982 /* cMaxInstances */
1983 1,
1984 /* cbInstance */
1985 sizeof(SB16State),
1986 /* pfnConstruct */
1987 sb16Construct,
1988 /* pfnDestruct */
1989 NULL,
1990 /* pfnRelocate */
1991 NULL,
1992 /* pfnMemSetup */
1993 NULL,
1994 /* pfnPowerOn */
1995 NULL,
1996 /* pfnReset */
1997 NULL,
1998 /* pfnSuspend */
1999 NULL,
2000 /* pfnResume */
2001 NULL,
2002 /* pfnAttach */
2003 NULL,
2004 /* pfnDetach */
2005 NULL,
2006 /* pfnQueryInterface */
2007 NULL,
2008 /* pfnInitComplete */
2009 NULL,
2010 /* pfnPowerOff */
2011 NULL,
2012 /* pfnSoftReset */
2013 NULL,
2014 /* u32VersionEnd */
2015 PDM_DEVREG_VERSION
2016};
2017
2018#endif /* VBOX */
2019
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette