VirtualBox

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

Last change on this file since 61167 was 61167, checked in by vboxsync, 9 years ago

Audio: Renaming.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 73.3 KB
Line 
1/* $Id: DevSB16.cpp 61167 2016-05-24 15:48:51Z vboxsync $ */
2/** @file
3 * DevSB16 - VBox SB16 Audio Controller.
4 *
5 * @todo hiccups on NT4 and Win98.
6 */
7
8/*
9 * Copyright (C) 2015-2016 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 * --------------------------------------------------------------------
19 *
20 * This code is based on: sb16.c from QEMU AUDIO subsystem (r3917).
21 * QEMU Soundblaster 16 emulation
22 *
23 * Copyright (c) 2003-2005 Vassili Karpov (malc)
24 *
25 * Permission is hereby granted, free of charge, to any person obtaining a copy
26 * of this software and associated documentation files (the "Software"), to deal
27 * in the Software without restriction, including without limitation the rights
28 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29 * copies of the Software, and to permit persons to whom the Software is
30 * furnished to do so, subject to the following conditions:
31 *
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 * THE SOFTWARE.
42 */
43#define LOG_GROUP LOG_GROUP_DEV_SB16
44#include <VBox/log.h>
45#include <iprt/assert.h>
46#ifdef IN_RING3
47# include <iprt/mem.h>
48# include <iprt/string.h>
49# include <iprt/uuid.h>
50#endif
51
52#include <VBox/vmm/pdmdev.h>
53#include <VBox/vmm/pdmaudioifs.h>
54
55#include "VBoxDD.h"
56
57#include "AudioMixBuffer.h"
58#include "AudioMixer.h"
59#include "DrvAudio.h"
60
61/** Current saved state version. */
62#define SB16_SAVE_STATE_VERSION 2
63/** The version used in VirtualBox version 3.0 and earlier. This didn't include the config dump. */
64#define SB16_SAVE_STATE_VERSION_VBOX_30 1
65
66#define IO_READ_PROTO(name) \
67 DECLCALLBACK(int) name (PPDMDEVINS pDevIns, void *opaque, \
68 RTIOPORT nport, uint32_t *pu32, unsigned cb)
69
70#define IO_WRITE_PROTO(name) \
71 DECLCALLBACK(int) name (PPDMDEVINS pDevIns, void *opaque, \
72 RTIOPORT nport, uint32_t val, unsigned cb)
73
74static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
75
76typedef struct SB16OUTPUTSTREAM
77{
78 /** PCM output stream. */
79 R3PTRTYPE(PPDMAUDIOSTREAM) pStream;
80 /** Mixer handle for output stream. */
81 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
82} SB16OUTPUTSTREAM, *PSB16OUTPUTSTREAM;
83
84/**
85 * Struct for maintaining a host backend driver.
86 */
87typedef struct SB16STATE *PSB16STATE;
88typedef struct SB16DRIVER
89{
90 /** Node for storing this driver in our device driver list of SB16STATE. */
91 RTLISTNODER3 Node;
92 /** Pointer to SB16 controller (state). */
93 R3PTRTYPE(PSB16STATE) pSB16State;
94 /** Driver flags. */
95 PDMAUDIODRVFLAGS Flags;
96 uint32_t PaddingFlags;
97 /** LUN # to which this driver has been assigned. */
98 uint8_t uLUN;
99 /** Whether this driver is in an attached state or not. */
100 bool fAttached;
101 uint8_t Padding[4];
102 /** Pointer to attached driver base interface. */
103 R3PTRTYPE(PPDMIBASE) pDrvBase;
104 /** Audio connector interface to the underlying host backend. */
105 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
106 /** Stream for output. */
107 SB16OUTPUTSTREAM Out;
108} SB16DRIVER, *PSB16DRIVER;
109
110typedef struct SB16STATE
111{
112#ifdef VBOX
113 /** Pointer to the device instance. */
114 PPDMDEVINSR3 pDevInsR3;
115 /** Pointer to the connector of the attached audio driver. */
116 PPDMIAUDIOCONNECTOR pDrv;
117 int irqCfg;
118 int dmaCfg;
119 int hdmaCfg;
120 int portCfg;
121 int verCfg;
122#endif
123 int irq;
124 int dma;
125 int hdma;
126 int port;
127 int ver;
128
129 int in_index;
130 int out_data_len;
131 int fmt_stereo;
132 int fmt_signed;
133 int fmt_bits;
134 PDMAUDIOFMT fmt;
135 int dma_auto;
136 int block_size;
137 int fifo;
138 int freq;
139 int time_const;
140 int speaker;
141 int needed_bytes;
142 int cmd;
143 int use_hdma;
144 int highspeed;
145 int can_write; /** @todo Value never gets 0? */
146
147 int v2x6;
148
149 uint8_t csp_param;
150 uint8_t csp_value;
151 uint8_t csp_mode;
152 uint8_t csp_regs[256];
153 uint8_t csp_index;
154 uint8_t csp_reg83[4];
155 int csp_reg83r;
156 int csp_reg83w;
157
158 uint8_t in2_data[10];
159 uint8_t out_data[50];
160 uint8_t test_reg;
161 uint8_t last_read_byte;
162 int nzero;
163
164 int left_till_irq; /** Note: Can be < 0. */
165
166 int dma_running;
167 int bytes_per_second;
168 int align;
169
170 RTLISTANCHOR lstDrv;
171 /** The device' software mixer. */
172 R3PTRTYPE(PAUDIOMIXER) pMixer;
173 /** Audio sink for PCM output. */
174 R3PTRTYPE(PAUDMIXSINK) pSinkOutput;
175 /** Number of active (running) SDn streams. */
176 uint8_t cStreamsActive;
177#ifndef VBOX_WITH_AUDIO_CALLBACKS
178 /** The timer for pumping data thru the attached LUN drivers. */
179 PTMTIMERR3 pTimerIO;
180 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
181 uint64_t cTimerTicksIO;
182 /** Timestamp of the last timer callback (sb16TimerIO).
183 * Used to calculate the time actually elapsed between two timer callbacks. */
184 uint64_t uTimerTSIO;
185#endif
186 PTMTIMER pTimerIRQ;
187 /** The base interface for LUN\#0. */
188 PDMIBASE IBase;
189
190 /* mixer state */
191 int mixer_nreg;
192 uint8_t mixer_regs[256];
193} SB16STATE, *PSB16STATE;
194
195static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);
196#ifndef VBOX_WITH_AUDIO_CALLBACKS
197static void sb16TimerMaybeStart(PSB16STATE pThis);
198static void sb16TimerMaybeStop(PSB16STATE pThis);
199#endif
200
201/**
202 * Attach command, internal version.
203 *
204 * This is called to let the device attach to a driver for a specified LUN
205 * during runtime. This is not called during VM construction, the device
206 * constructor has to attach to all the available drivers.
207 *
208 * @returns VBox status code.
209 * @param pDevIns The device instance.
210 * @param pDrv Driver to (re-)use for (re-)attaching to.
211 * If NULL is specified, a new driver will be created and appended
212 * to the driver list.
213 * @param uLUN The logical unit which is being detached.
214 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
215 */
216static DECLCALLBACK(int) sb16AttachInternal(PPDMDEVINS pDevIns, PSB16DRIVER pDrv, unsigned uLUN, uint32_t fFlags)
217{
218 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
219
220 /*
221 * Attach driver.
222 */
223 char *pszDesc = NULL;
224 if (RTStrAPrintf(&pszDesc, "Audio driver port (SB16) for LUN #%u", uLUN) <= 0)
225 AssertReleaseMsgReturn(pszDesc,
226 ("Not enough memory for SB16 driver port description of LUN #%u\n", uLUN),
227 VERR_NO_MEMORY);
228
229 PPDMIBASE pDrvBase;
230 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
231 &pThis->IBase, &pDrvBase, pszDesc);
232 if (RT_SUCCESS(rc))
233 {
234 if (pDrv == NULL)
235 pDrv = (PSB16DRIVER)RTMemAllocZ(sizeof(SB16DRIVER));
236 if (pDrv)
237 {
238 pDrv->pDrvBase = pDrvBase;
239 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
240 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN #%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
241 pDrv->pSB16State = pThis;
242 pDrv->uLUN = uLUN;
243
244 /*
245 * For now we always set the driver at LUN 0 as our primary
246 * host backend. This might change in the future.
247 */
248 if (pDrv->uLUN == 0)
249 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
250
251 LogFunc(("LUN#%RU8: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
252
253 /* Attach to driver list if not attached yet. */
254 if (!pDrv->fAttached)
255 {
256 RTListAppend(&pThis->lstDrv, &pDrv->Node);
257 pDrv->fAttached = true;
258 }
259 }
260 else
261 rc = VERR_NO_MEMORY;
262 }
263 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
264 {
265 LogFunc(("No attached driver for LUN #%u\n", uLUN));
266 }
267 else if (RT_FAILURE(rc))
268 AssertMsgFailed(("Failed to attach SB16 LUN #%u (\"%s\"), rc=%Rrc\n",
269 uLUN, pszDesc, rc));
270
271 if (RT_FAILURE(rc))
272 {
273 /* Only free this string on failure;
274 * must remain valid for the live of the driver instance. */
275 RTStrFree(pszDesc);
276 }
277
278 LogFunc(("iLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
279 return rc;
280}
281
282/**
283 * Attach command.
284 *
285 * This is called to let the device attach to a driver for a specified LUN
286 * during runtime. This is not called during VM construction, the device
287 * constructor has to attach to all the available drivers.
288 *
289 * @returns VBox status code.
290 * @param pDevIns The device instance.
291 * @param uLUN The logical unit which is being detached.
292 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
293 */
294static DECLCALLBACK(int) sb16Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
295{
296 return sb16AttachInternal(pDevIns, NULL /* pDrv */, uLUN, fFlags);
297}
298
299static DECLCALLBACK(void) sb16Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
300{
301 LogFunc(("iLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
302}
303
304/**
305 * Re-attach.
306 *
307 * @returns VBox status code.
308 * @param pThis Device instance.
309 * @param pDrv Driver instance used for attaching to.
310 * If NULL is specified, a new driver will be created and appended
311 * to the driver list.
312 * @param uLUN The logical unit which is being re-detached.
313 * @param pszDriver Driver name.
314 */
315static int sb16Reattach(PSB16STATE pThis, PSB16DRIVER pDrv, uint8_t uLUN, const char *pszDriver)
316{
317 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
318 AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
319
320 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
321 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
322 PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/SB16/0/");
323
324 /* Remove LUN branch. */
325 CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
326
327 if (pDrv)
328 {
329 /* Re-use the driver instance so detach it before. */
330 int rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
331 if (RT_FAILURE(rc))
332 return rc;
333 }
334
335#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
336
337 int rc = VINF_SUCCESS;
338 do
339 {
340 PCFGMNODE pLunL0;
341 rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN); RC_CHECK();
342 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
343 rc = CFGMR3InsertNode(pLunL0, "Config/", NULL); RC_CHECK();
344
345 PCFGMNODE pLunL1, pLunL2;
346 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver/", &pLunL1); RC_CHECK();
347 rc = CFGMR3InsertNode (pLunL1, "Config/", &pLunL2); RC_CHECK();
348 rc = CFGMR3InsertString(pLunL1, "Driver", pszDriver); RC_CHECK();
349
350 rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver); RC_CHECK();
351
352 } while (0);
353
354 if (RT_SUCCESS(rc))
355 rc = sb16AttachInternal(pThis->pDevInsR3, pDrv, uLUN, 0 /* fFlags */);
356
357 LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
358
359#undef RC_CHECK
360
361 return rc;
362}
363
364static void sb16AudioCallback(void *pvContext, uint32_t cbFree);
365
366static int magic_of_irq(int irq)
367{
368 switch (irq)
369 {
370 case 5:
371 return 2;
372 case 7:
373 return 4;
374 case 9:
375 return 1;
376 case 10:
377 return 8;
378 default:
379 break;
380 }
381
382 LogFlowFunc(("bad irq %d\n", irq));
383 return 2;
384}
385
386static int irq_of_magic(int magic)
387{
388 switch (magic)
389 {
390 case 1:
391 return 9;
392 case 2:
393 return 5;
394 case 4:
395 return 7;
396 case 8:
397 return 10;
398 default:
399 break;
400 }
401
402 LogFlowFunc(("bad irq magic %d\n", magic));
403 return -1;
404}
405
406#ifdef DEBUG
407static inline void log_dsp(PSB16STATE pThis)
408{
409 LogFlowFunc(("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
410 pThis->fmt_stereo ? "Stereo" : "Mono",
411 pThis->fmt_signed ? "Signed" : "Unsigned",
412 pThis->fmt_bits,
413 pThis->dma_auto ? "Auto" : "Single",
414 pThis->block_size,
415 pThis->freq,
416 pThis->time_const,
417 pThis->speaker));
418}
419#endif
420
421static void sb16SpeakerControl(PSB16STATE pThis, int on)
422{
423 pThis->speaker = on;
424 /* AUD_enable (pThis->voice, on); */
425}
426
427static void sb16Control(PSB16STATE pThis, int hold)
428{
429 int dma = pThis->use_hdma ? pThis->hdma : pThis->dma;
430 pThis->dma_running = hold;
431
432 LogFlowFunc(("hold %d high %d dma %d\n", hold, pThis->use_hdma, dma));
433
434 PDMDevHlpDMASetDREQ(pThis->pDevInsR3, dma, hold);
435
436 if (hold)
437 {
438 pThis->cStreamsActive++;
439#ifndef VBOX_WITH_AUDIO_CALLBACKS
440 sb16TimerMaybeStart(pThis);
441#endif
442 PDMDevHlpDMASchedule(pThis->pDevInsR3);
443 }
444#ifndef VBOX_WITH_AUDIO_CALLBACKS
445 else
446 {
447 if (pThis->cStreamsActive)
448 pThis->cStreamsActive--;
449 sb16TimerMaybeStop(pThis);
450 }
451#endif
452
453 AudioMixerSinkCtl(pThis->pSinkOutput,
454 hold == 1 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
455}
456
457static DECLCALLBACK(void) sb16TimerIRQ(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis)
458{
459 PSB16STATE pThis = (PSB16STATE)pvThis;
460 pThis->can_write = 1;
461 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
462}
463
464#define DMA8_AUTO 1
465#define DMA8_HIGH 2
466
467static void continue_dma8(PSB16STATE pThis)
468{
469 if (pThis->freq > 0)
470 {
471 PDMAUDIOSTREAMCFG streamCfg;
472 RT_ZERO(streamCfg);
473 streamCfg.enmDir = PDMAUDIODIR_OUT;
474 streamCfg.uHz = pThis->freq;
475 streamCfg.cChannels = 1 << pThis->fmt_stereo;
476 streamCfg.enmFormat = pThis->fmt;
477 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
478
479 int rc = sb16OpenOut(pThis, &streamCfg);
480 AssertRC(rc);
481 }
482
483 sb16Control(pThis, 1);
484}
485
486static void dma_cmd8(PSB16STATE pThis, int mask, int dma_len)
487{
488 pThis->fmt = PDMAUDIOFMT_U8;
489 pThis->use_hdma = 0;
490 pThis->fmt_bits = 8;
491 pThis->fmt_signed = 0;
492 pThis->fmt_stereo = (pThis->mixer_regs[0x0e] & 2) != 0;
493
494 if (-1 == pThis->time_const)
495 {
496 if (pThis->freq <= 0)
497 pThis->freq = 11025;
498 }
499 else
500 {
501 int tmp = (256 - pThis->time_const);
502 pThis->freq = (1000000 + (tmp / 2)) / tmp;
503 }
504
505 if (dma_len != -1)
506 {
507 pThis->block_size = dma_len << pThis->fmt_stereo;
508 }
509 else
510 {
511 /* This is apparently the only way to make both Act1/PL
512 and SecondReality/FC work
513
514 r=andy Wow, actually someone who remembers Future Crew :-)
515
516 Act1 sets block size via command 0x48 and it's an odd number
517 SR does the same with even number
518 Both use stereo, and Creatives own documentation states that
519 0x48 sets block size in bytes less one.. go figure */
520 pThis->block_size &= ~pThis->fmt_stereo;
521 }
522
523 pThis->freq >>= pThis->fmt_stereo;
524 pThis->left_till_irq = pThis->block_size;
525 pThis->bytes_per_second = (pThis->freq << pThis->fmt_stereo);
526 /* pThis->highspeed = (mask & DMA8_HIGH) != 0; */
527 pThis->dma_auto = (mask & DMA8_AUTO) != 0;
528 pThis->align = (1 << pThis->fmt_stereo) - 1;
529
530 if (pThis->block_size & pThis->align)
531 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n",
532 pThis->block_size, pThis->align + 1));
533
534 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n",
535 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits,
536 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed));
537
538 continue_dma8(pThis);
539 sb16SpeakerControl(pThis, 1);
540}
541
542static void dma_cmd(PSB16STATE pThis, uint8_t cmd, uint8_t d0, int dma_len)
543{
544 pThis->use_hdma = cmd < 0xc0;
545 pThis->fifo = (cmd >> 1) & 1;
546 pThis->dma_auto = (cmd >> 2) & 1;
547 pThis->fmt_signed = (d0 >> 4) & 1;
548 pThis->fmt_stereo = (d0 >> 5) & 1;
549
550 switch (cmd >> 4)
551 {
552 case 11:
553 pThis->fmt_bits = 16;
554 break;
555
556 case 12:
557 pThis->fmt_bits = 8;
558 break;
559 }
560
561 if (-1 != pThis->time_const)
562 {
563#if 1
564 int tmp = 256 - pThis->time_const;
565 pThis->freq = (1000000 + (tmp / 2)) / tmp;
566#else
567 /* pThis->freq = 1000000 / ((255 - pThis->time_const) << pThis->fmt_stereo); */
568 pThis->freq = 1000000 / ((255 - pThis->time_const));
569#endif
570 pThis->time_const = -1;
571 }
572
573 pThis->block_size = dma_len + 1;
574 pThis->block_size <<= ((pThis->fmt_bits == 16) ? 1 : 0);
575 if (!pThis->dma_auto)
576 {
577 /*
578 * It is clear that for DOOM and auto-init this value
579 * shouldn't take stereo into account, while Miles Sound Systems
580 * setsound.exe with single transfer mode wouldn't work without it
581 * wonders of SB16 yet again.
582 */
583 pThis->block_size <<= pThis->fmt_stereo;
584 }
585
586 LogFlowFunc(("freq %d, stereo %d, sign %d, bits %d, dma %d, auto %d, fifo %d, high %d\n",
587 pThis->freq, pThis->fmt_stereo, pThis->fmt_signed, pThis->fmt_bits,
588 pThis->block_size, pThis->dma_auto, pThis->fifo, pThis->highspeed));
589
590 if (16 == pThis->fmt_bits)
591 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S16 : PDMAUDIOFMT_U16;
592 else
593 pThis->fmt = pThis->fmt_signed ? PDMAUDIOFMT_S8 : PDMAUDIOFMT_U8;
594
595 pThis->left_till_irq = pThis->block_size;
596
597 pThis->bytes_per_second = (pThis->freq << pThis->fmt_stereo) << ((pThis->fmt_bits == 16) ? 1 : 0);
598 pThis->highspeed = 0;
599 pThis->align = (1 << (pThis->fmt_stereo + (pThis->fmt_bits == 16))) - 1;
600 if (pThis->block_size & pThis->align)
601 {
602 LogFlowFunc(("warning: misaligned block size %d, alignment %d\n",
603 pThis->block_size, pThis->align + 1));
604 }
605
606 if (pThis->freq)
607 {
608 PDMAUDIOSTREAMCFG streamCfg;
609 RT_ZERO(streamCfg);
610 streamCfg.enmDir = PDMAUDIODIR_OUT;
611 streamCfg.uHz = pThis->freq;
612 streamCfg.cChannels = 1 << pThis->fmt_stereo;
613 streamCfg.enmFormat = pThis->fmt;
614 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
615
616 int rc = sb16OpenOut(pThis, &streamCfg);
617 AssertRC(rc);
618 }
619
620 sb16Control(pThis, 1);
621 sb16SpeakerControl(pThis, 1);
622}
623
624static inline void dsp_out_data (PSB16STATE pThis, uint8_t val)
625{
626 LogFlowFunc(("outdata %#x\n", val));
627 if ((size_t) pThis->out_data_len < sizeof (pThis->out_data)) {
628 pThis->out_data[pThis->out_data_len++] = val;
629 }
630}
631
632static inline uint8_t dsp_get_data (PSB16STATE pThis)
633{
634 if (pThis->in_index) {
635 return pThis->in2_data[--pThis->in_index];
636 }
637 else {
638 LogFlowFunc(("buffer underflow\n"));
639 return 0;
640 }
641}
642
643static void sb16HandleCommand(PSB16STATE pThis, uint8_t cmd)
644{
645 LogFlowFunc(("command %#x\n", cmd));
646
647 if (cmd > 0xaf && cmd < 0xd0)
648 {
649 if (cmd & 8) /** @todo Handle recording. */
650 LogFlowFunc(("ADC not yet supported (command %#x)\n", cmd));
651
652 switch (cmd >> 4)
653 {
654 case 11:
655 case 12:
656 break;
657 default:
658 LogFlowFunc(("%#x wrong bits\n", cmd));
659 }
660
661 pThis->needed_bytes = 3;
662 }
663 else
664 {
665 pThis->needed_bytes = 0;
666
667 switch (cmd)
668 {
669 case 0x03:
670 dsp_out_data(pThis, 0x10); /* pThis->csp_param); */
671 goto warn;
672
673 case 0x04:
674 pThis->needed_bytes = 1;
675 goto warn;
676
677 case 0x05:
678 pThis->needed_bytes = 2;
679 goto warn;
680
681 case 0x08:
682 /* __asm__ ("int3"); */
683 goto warn;
684
685 case 0x0e:
686 pThis->needed_bytes = 2;
687 goto warn;
688
689 case 0x09:
690 dsp_out_data(pThis, 0xf8);
691 goto warn;
692
693 case 0x0f:
694 pThis->needed_bytes = 1;
695 goto warn;
696
697 case 0x10:
698 pThis->needed_bytes = 1;
699 goto warn;
700
701 case 0x14:
702 pThis->needed_bytes = 2;
703 pThis->block_size = 0;
704 break;
705
706 case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
707 dma_cmd8(pThis, DMA8_AUTO, -1);
708 break;
709
710 case 0x20: /* Direct ADC, Juice/PL */
711 dsp_out_data(pThis, 0xff);
712 goto warn;
713
714 case 0x35:
715 LogFlowFunc(("0x35 - MIDI command not implemented\n"));
716 break;
717
718 case 0x40:
719 pThis->freq = -1;
720 pThis->time_const = -1;
721 pThis->needed_bytes = 1;
722 break;
723
724 case 0x41:
725 pThis->freq = -1;
726 pThis->time_const = -1;
727 pThis->needed_bytes = 2;
728 break;
729
730 case 0x42:
731 pThis->freq = -1;
732 pThis->time_const = -1;
733 pThis->needed_bytes = 2;
734 goto warn;
735
736 case 0x45:
737 dsp_out_data(pThis, 0xaa);
738 goto warn;
739
740 case 0x47: /* Continue Auto-Initialize DMA 16bit */
741 break;
742
743 case 0x48:
744 pThis->needed_bytes = 2;
745 break;
746
747 case 0x74:
748 pThis->needed_bytes = 2; /* DMA DAC, 4-bit ADPCM */
749 LogFlowFunc(("0x75 - DMA DAC, 4-bit ADPCM not implemented\n"));
750 break;
751
752 case 0x75: /* DMA DAC, 4-bit ADPCM Reference */
753 pThis->needed_bytes = 2;
754 LogFlowFunc(("0x74 - DMA DAC, 4-bit ADPCM Reference not implemented\n"));
755 break;
756
757 case 0x76: /* DMA DAC, 2.6-bit ADPCM */
758 pThis->needed_bytes = 2;
759 LogFlowFunc(("0x74 - DMA DAC, 2.6-bit ADPCM not implemented\n"));
760 break;
761
762 case 0x77: /* DMA DAC, 2.6-bit ADPCM Reference */
763 pThis->needed_bytes = 2;
764 LogFlowFunc(("0x74 - DMA DAC, 2.6-bit ADPCM Reference not implemented\n"));
765 break;
766
767 case 0x7d:
768 LogFlowFunc(("0x7d - Autio-Initialize DMA DAC, 4-bit ADPCM Reference\n"));
769 LogFlowFunc(("not implemented\n"));
770 break;
771
772 case 0x7f:
773 LogFlowFunc(("0x7d - Autio-Initialize DMA DAC, 2.6-bit ADPCM Reference\n"));
774 LogFlowFunc(("not implemented\n"));
775 break;
776
777 case 0x80:
778 pThis->needed_bytes = 2;
779 break;
780
781 case 0x90:
782 case 0x91:
783 dma_cmd8(pThis, (((cmd & 1) == 0) ? 1 : 0) | DMA8_HIGH, -1);
784 break;
785
786 case 0xd0: /* halt DMA operation. 8bit */
787 sb16Control(pThis, 0);
788 break;
789
790 case 0xd1: /* speaker on */
791 sb16SpeakerControl(pThis, 1);
792 break;
793
794 case 0xd3: /* speaker off */
795 sb16SpeakerControl(pThis, 0);
796 break;
797
798 case 0xd4: /* continue DMA operation. 8bit */
799 /* KQ6 (or maybe Sierras audblst.drv in general) resets
800 the frequency between halt/continue */
801 continue_dma8(pThis);
802 break;
803
804 case 0xd5: /* halt DMA operation. 16bit */
805 sb16Control(pThis, 0);
806 break;
807
808 case 0xd6: /* continue DMA operation. 16bit */
809 sb16Control(pThis, 1);
810 break;
811
812 case 0xd9: /* exit auto-init DMA after this block. 16bit */
813 pThis->dma_auto = 0;
814 break;
815
816 case 0xda: /* exit auto-init DMA after this block. 8bit */
817 pThis->dma_auto = 0;
818 break;
819
820 case 0xe0: /* DSP identification */
821 pThis->needed_bytes = 1;
822 break;
823
824 case 0xe1:
825 dsp_out_data(pThis, pThis->ver & 0xff);
826 dsp_out_data(pThis, pThis->ver >> 8);
827 break;
828
829 case 0xe2:
830 pThis->needed_bytes = 1;
831 goto warn;
832
833 case 0xe3:
834 {
835 for (int i = sizeof (e3) - 1; i >= 0; --i)
836 dsp_out_data(pThis, e3[i]);
837
838 break;
839 }
840
841 case 0xe4: /* write test reg */
842 pThis->needed_bytes = 1;
843 break;
844
845 case 0xe7:
846 LogFlowFunc(("Attempt to probe for ESS (0xe7)?\n"));
847 break;
848
849 case 0xe8: /* read test reg */
850 dsp_out_data(pThis, pThis->test_reg);
851 break;
852
853 case 0xf2:
854 case 0xf3:
855 dsp_out_data(pThis, 0xaa);
856 pThis->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
857 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
858 break;
859
860 case 0xf8:
861 /* Undocumented, used by old Creative diagnostic programs. */
862 dsp_out_data (pThis, 0);
863 goto warn;
864
865 case 0xf9:
866 pThis->needed_bytes = 1;
867 goto warn;
868
869 case 0xfa:
870 dsp_out_data (pThis, 0);
871 goto warn;
872
873 case 0xfc: /* FIXME */
874 dsp_out_data (pThis, 0);
875 goto warn;
876
877 default:
878 LogFlowFunc(("Unrecognized command %#x\n", cmd));
879 break;
880 }
881 }
882
883 if (!pThis->needed_bytes)
884 LogFlow(("\n"));
885
886exit:
887
888 if (!pThis->needed_bytes)
889 pThis->cmd = -1;
890 else
891 pThis->cmd = cmd;
892
893 return;
894
895warn:
896 LogFlowFunc(("warning: command %#x,%d is not truly understood yet\n",
897 cmd, pThis->needed_bytes));
898 goto exit;
899}
900
901static uint16_t dsp_get_lohi (PSB16STATE pThis)
902{
903 uint8_t hi = dsp_get_data (pThis);
904 uint8_t lo = dsp_get_data (pThis);
905 return (hi << 8) | lo;
906}
907
908static uint16_t dsp_get_hilo (PSB16STATE pThis)
909{
910 uint8_t lo = dsp_get_data (pThis);
911 uint8_t hi = dsp_get_data (pThis);
912 return (hi << 8) | lo;
913}
914
915static void complete(PSB16STATE pThis)
916{
917 int d0, d1, d2;
918 LogFlowFunc(("complete command %#x, in_index %d, needed_bytes %d\n",
919 pThis->cmd, pThis->in_index, pThis->needed_bytes));
920
921 if (pThis->cmd > 0xaf && pThis->cmd < 0xd0)
922 {
923 d2 = dsp_get_data (pThis);
924 d1 = dsp_get_data (pThis);
925 d0 = dsp_get_data (pThis);
926
927 if (pThis->cmd & 8)
928 LogFlowFunc(("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", pThis->cmd, d0, d1, d2));
929 else
930 {
931 LogFlowFunc(("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", pThis->cmd, d0, d1, d2));
932 dma_cmd(pThis, pThis->cmd, d0, d1 + (d2 << 8));
933 }
934 }
935 else
936 {
937 switch (pThis->cmd)
938 {
939 case 0x04:
940 pThis->csp_mode = dsp_get_data (pThis);
941 pThis->csp_reg83r = 0;
942 pThis->csp_reg83w = 0;
943 LogFlowFunc(("CSP command 0x04: mode=%#x\n", pThis->csp_mode));
944 break;
945
946 case 0x05:
947 pThis->csp_param = dsp_get_data (pThis);
948 pThis->csp_value = dsp_get_data (pThis);
949 LogFlowFunc(("CSP command 0x05: param=%#x value=%#x\n",
950 pThis->csp_param,
951 pThis->csp_value));
952 break;
953
954 case 0x0e:
955 {
956 d0 = dsp_get_data(pThis);
957 d1 = dsp_get_data(pThis);
958 LogFlowFunc(("write CSP register %d <- %#x\n", d1, d0));
959 if (d1 == 0x83)
960 {
961 LogFlowFunc(("0x83[%d] <- %#x\n", pThis->csp_reg83r, d0));
962 pThis->csp_reg83[pThis->csp_reg83r % 4] = d0;
963 pThis->csp_reg83r += 1;
964 }
965 else
966 pThis->csp_regs[d1] = d0;
967 break;
968 }
969
970 case 0x0f:
971 d0 = dsp_get_data(pThis);
972 LogFlowFunc(("read CSP register %#x -> %#x, mode=%#x\n", d0, pThis->csp_regs[d0], pThis->csp_mode));
973 if (d0 == 0x83)
974 {
975 LogFlowFunc(("0x83[%d] -> %#x\n",
976 pThis->csp_reg83w,
977 pThis->csp_reg83[pThis->csp_reg83w % 4]));
978 dsp_out_data (pThis, pThis->csp_reg83[pThis->csp_reg83w % 4]);
979 pThis->csp_reg83w += 1;
980 }
981 else
982 dsp_out_data(pThis, pThis->csp_regs[d0]);
983 break;
984
985 case 0x10:
986 d0 = dsp_get_data(pThis);
987 LogFlowFunc(("cmd 0x10 d0=%#x\n", d0));
988 break;
989
990 case 0x14:
991 dma_cmd8(pThis, 0, dsp_get_lohi (pThis) + 1);
992 break;
993
994 case 0x40:
995 pThis->time_const = dsp_get_data(pThis);
996 LogFlowFunc(("set time const %d\n", pThis->time_const));
997 break;
998
999 case 0x42: /* FT2 sets output freq with this, go figure */
1000#if 0
1001 LogFlowFunc(("cmd 0x42 might not do what it think it should\n"));
1002#endif
1003 case 0x41:
1004 pThis->freq = dsp_get_hilo(pThis);
1005 LogFlowFunc(("set freq %d\n", pThis->freq));
1006 break;
1007
1008 case 0x48:
1009 pThis->block_size = dsp_get_lohi(pThis) + 1;
1010 LogFlowFunc(("set dma block len %d\n", pThis->block_size));
1011 break;
1012
1013 case 0x74:
1014 case 0x75:
1015 case 0x76:
1016 case 0x77:
1017 /* ADPCM stuff, ignore */
1018 break;
1019
1020 case 0x80:
1021 {
1022 int freq, samples, bytes;
1023 uint64_t ticks;
1024
1025 freq = pThis->freq > 0 ? pThis->freq : 11025;
1026 samples = dsp_get_lohi (pThis) + 1;
1027 bytes = samples << pThis->fmt_stereo << ((pThis->fmt_bits == 16) ? 1 : 0);
1028 ticks = (bytes * TMTimerGetFreq(pThis->pTimerIRQ)) / freq;
1029 if (ticks < TMTimerGetFreq(pThis->pTimerIRQ) / 1024)
1030 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
1031 else
1032 TMTimerSet(pThis->pTimerIRQ, TMTimerGet(pThis->pTimerIRQ) + ticks);
1033 LogFlowFunc(("mix silence %d %d % %RU64\n", samples, bytes, ticks));
1034 break;
1035 }
1036
1037 case 0xe0:
1038 d0 = dsp_get_data(pThis);
1039 pThis->out_data_len = 0;
1040 LogFlowFunc(("E0 data = %#x\n", d0));
1041 dsp_out_data(pThis, ~d0);
1042 break;
1043
1044 case 0xe2:
1045 d0 = dsp_get_data(pThis);
1046 LogFlow(("SB16:E2 = %#x\n", d0));
1047 break;
1048
1049 case 0xe4:
1050 pThis->test_reg = dsp_get_data(pThis);
1051 break;
1052
1053 case 0xf9:
1054 d0 = dsp_get_data(pThis);
1055 LogFlowFunc(("command 0xf9 with %#x\n", d0));
1056 switch (d0) {
1057 case 0x0e:
1058 dsp_out_data(pThis, 0xff);
1059 break;
1060
1061 case 0x0f:
1062 dsp_out_data(pThis, 0x07);
1063 break;
1064
1065 case 0x37:
1066 dsp_out_data(pThis, 0x38);
1067 break;
1068
1069 default:
1070 dsp_out_data(pThis, 0x00);
1071 break;
1072 }
1073 break;
1074
1075 default:
1076 LogFlowFunc(("complete: unrecognized command %#x\n", pThis->cmd));
1077 return;
1078 }
1079 }
1080
1081 LogFlow(("\n"));
1082 pThis->cmd = -1;
1083 return;
1084}
1085
1086static uint8_t sb16MixRegToVol(PSB16STATE pThis, int reg)
1087{
1088 /* The SB16 mixer has a 0 to -62dB range in 32 levels (2dB each step).
1089 * We use a 0 to -96dB range in 256 levels (0.375dB each step).
1090 * Only the top 5 bits of a mixer register are used.
1091 */
1092 uint8_t steps = 31 - (pThis->mixer_regs[reg] >> 3);
1093 uint8_t vol = 255 - steps * 16 / 3; /* (2dB*8) / (0.375dB*8) */
1094 return vol;
1095}
1096
1097static void sb16SetMasterVolume(PSB16STATE pThis)
1098{
1099 /* There's no mute switch, only volume controls. */
1100 uint8_t lvol = sb16MixRegToVol(pThis, 0x30);
1101 uint8_t rvol = sb16MixRegToVol(pThis, 0x31);
1102 PDMAUDIOVOLUME vol = { false, lvol, rvol };
1103 AudioMixerSetMasterVolume(pThis->pMixer, &vol);
1104}
1105
1106static void sb16SetPcmOutVolume(PSB16STATE pThis)
1107{
1108 /* There's no mute switch, only volume controls. */
1109 uint8_t lvol = sb16MixRegToVol(pThis, 0x32);
1110 uint8_t rvol = sb16MixRegToVol(pThis, 0x33);
1111 PDMAUDIOVOLUME vol = { false, lvol, rvol };
1112 AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol);
1113}
1114
1115static void sb16ResetLegacy(PSB16STATE pThis)
1116{
1117 pThis->freq = 11025;
1118 pThis->fmt_signed = 0;
1119 pThis->fmt_bits = 8;
1120 pThis->fmt_stereo = 0;
1121
1122 PDMAUDIOSTREAMCFG streamCfg;
1123 RT_ZERO(streamCfg);
1124 streamCfg.enmDir = PDMAUDIODIR_OUT;
1125 streamCfg.uHz = pThis->freq;
1126 streamCfg.cChannels = 1; /* Mono */
1127 streamCfg.enmFormat = PDMAUDIOFMT_U8;
1128 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
1129
1130 int rc2 = sb16OpenOut(pThis, &streamCfg);
1131 AssertRC(rc2);
1132}
1133
1134static void sb16Reset(PSB16STATE pThis)
1135{
1136 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
1137 if (pThis->dma_auto)
1138 {
1139 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
1140 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
1141 }
1142
1143 pThis->mixer_regs[0x82] = 0;
1144 pThis->dma_auto = 0;
1145 pThis->in_index = 0;
1146 pThis->out_data_len = 0;
1147 pThis->left_till_irq = 0;
1148 pThis->needed_bytes = 0;
1149 pThis->block_size = -1;
1150 pThis->nzero = 0;
1151 pThis->highspeed = 0;
1152 pThis->v2x6 = 0;
1153 pThis->cmd = -1;
1154
1155 dsp_out_data(pThis, 0xaa);
1156 sb16SpeakerControl(pThis, 0);
1157 sb16Control(pThis, 0);
1158 sb16ResetLegacy(pThis);
1159}
1160
1161static IO_WRITE_PROTO(dsp_write)
1162{
1163 PSB16STATE pThis = (PSB16STATE)opaque;
1164 int iport = nport - pThis->port;
1165
1166 LogFlowFunc(("write %#x <- %#x\n", nport, val));
1167 switch (iport)
1168 {
1169 case 0x06:
1170 switch (val)
1171 {
1172 case 0x00:
1173 {
1174 if (pThis->v2x6 == 1)
1175 {
1176 if (0 && pThis->highspeed)
1177 {
1178 pThis->highspeed = 0;
1179 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
1180 sb16Control(pThis, 0);
1181 }
1182 else
1183 sb16Reset(pThis);
1184 }
1185 pThis->v2x6 = 0;
1186 break;
1187 }
1188
1189 case 0x01:
1190 case 0x03: /* FreeBSD kludge */
1191 pThis->v2x6 = 1;
1192 break;
1193
1194 case 0xc6:
1195 pThis->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
1196 break;
1197
1198 case 0xb8: /* Panic */
1199 sb16Reset(pThis);
1200 break;
1201
1202 case 0x39:
1203 dsp_out_data(pThis, 0x38);
1204 sb16Reset(pThis);
1205 pThis->v2x6 = 0x39;
1206 break;
1207
1208 default:
1209 pThis->v2x6 = val;
1210 break;
1211 }
1212 break;
1213
1214 case 0x0c: /* Write data or command | write status */
1215#if 0
1216 if (pThis->highspeed)
1217 break;
1218#endif
1219 if (0 == pThis->needed_bytes)
1220 {
1221 sb16HandleCommand(pThis, val);
1222#if 0
1223 if (0 == pThis->needed_bytes) {
1224 log_dsp (pThis);
1225 }
1226#endif
1227 }
1228 else
1229 {
1230 if (pThis->in_index == sizeof (pThis->in2_data))
1231 {
1232 LogFlowFunc(("in data overrun\n"));
1233 }
1234 else
1235 {
1236 pThis->in2_data[pThis->in_index++] = val;
1237 if (pThis->in_index == pThis->needed_bytes)
1238 {
1239 pThis->needed_bytes = 0;
1240 complete (pThis);
1241#if 0
1242 log_dsp (pThis);
1243#endif
1244 }
1245 }
1246 }
1247 break;
1248
1249 default:
1250 LogFlowFunc(("nport=%#x, val=%#x)\n", nport, val));
1251 break;
1252 }
1253
1254 return VINF_SUCCESS;
1255}
1256
1257static IO_READ_PROTO(dsp_read)
1258{
1259 PSB16STATE pThis = (PSB16STATE)opaque;
1260 int iport, retval, ack = 0;
1261
1262 iport = nport - pThis->port;
1263
1264 /** @todo reject non-byte access?
1265 * The spec does not mention a non-byte access so we should check how real hardware behaves. */
1266
1267 switch (iport)
1268 {
1269 case 0x06: /* reset */
1270 retval = 0xff;
1271 break;
1272
1273 case 0x0a: /* read data */
1274 if (pThis->out_data_len)
1275 {
1276 retval = pThis->out_data[--pThis->out_data_len];
1277 pThis->last_read_byte = retval;
1278 }
1279 else
1280 {
1281 if (pThis->cmd != -1)
1282 LogFlowFunc(("empty output buffer for command %#x\n", pThis->cmd));
1283 retval = pThis->last_read_byte;
1284 /* goto error; */
1285 }
1286 break;
1287
1288 case 0x0c: /* 0 can write */
1289 retval = pThis->can_write ? 0 : 0x80;
1290 break;
1291
1292 case 0x0d: /* timer interrupt clear */
1293 /* LogFlowFunc(("timer interrupt clear\n")); */
1294 retval = 0;
1295 break;
1296
1297 case 0x0e: /* data available status | irq 8 ack */
1298 retval = (!pThis->out_data_len || pThis->highspeed) ? 0 : 0x80;
1299 if (pThis->mixer_regs[0x82] & 1)
1300 {
1301 ack = 1;
1302 pThis->mixer_regs[0x82] &= ~1;
1303 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
1304 }
1305 break;
1306
1307 case 0x0f: /* irq 16 ack */
1308 retval = 0xff;
1309 if (pThis->mixer_regs[0x82] & 2)
1310 {
1311 ack = 1;
1312 pThis->mixer_regs[0x82] &= ~2;
1313 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
1314 }
1315 break;
1316
1317 default:
1318 goto error;
1319 }
1320
1321 if (!ack)
1322 LogFlowFunc(("read %#x -> %#x\n", nport, retval));
1323
1324 *pu32 = retval;
1325 return VINF_SUCCESS;
1326
1327 error:
1328 LogFlowFunc(("warning: dsp_read %#x error\n", nport));
1329 return VERR_IOM_IOPORT_UNUSED;
1330}
1331
1332static void sb16MixerReset(PSB16STATE pThis)
1333{
1334 PSB16DRIVER pDrv;
1335
1336 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
1337 pDrv->Out.pMixStrm = NULL;
1338
1339 pThis->pSinkOutput = NULL;
1340
1341 if (pThis->pMixer)
1342 {
1343 AudioMixerDestroy(pThis->pMixer);
1344 pThis->pMixer = NULL;
1345 }
1346
1347 memset(pThis->mixer_regs, 0xff, 0x7f);
1348 memset(pThis->mixer_regs + 0x83, 0xff, sizeof (pThis->mixer_regs) - 0x83);
1349
1350 pThis->mixer_regs[0x02] = 4; /* master volume 3bits */
1351 pThis->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
1352 pThis->mixer_regs[0x08] = 0; /* CD volume 3bits */
1353 pThis->mixer_regs[0x0a] = 0; /* voice volume 2bits */
1354
1355 /* d5=input filt, d3=lowpass filt, d1,d2=input source */
1356 pThis->mixer_regs[0x0c] = 0;
1357
1358 /* d5=output filt, d1=stereo switch */
1359 pThis->mixer_regs[0x0e] = 0;
1360
1361 /* voice volume L d5,d7, R d1,d3 */
1362 pThis->mixer_regs[0x04] = (12 << 4) | 12;
1363 /* master ... */
1364 pThis->mixer_regs[0x22] = (12 << 4) | 12;
1365 /* MIDI ... */
1366 pThis->mixer_regs[0x26] = (12 << 4) | 12;
1367
1368 /* master/voice/MIDI L/R volume */
1369 for (int i = 0x30; i < 0x36; i++)
1370 pThis->mixer_regs[i] = 24 << 3; /* -14 dB */
1371
1372 /* treble/bass */
1373 for (int i = 0x44; i < 0x48; i++)
1374 pThis->mixer_regs[i] = 0x80;
1375
1376 int rc2 = AudioMixerCreate("SB16 Mixer", 0 /* uFlags */, &pThis->pMixer);
1377 if (RT_SUCCESS(rc2))
1378 {
1379 /* Set a default audio format for our mixer. */
1380 PDMAUDIOSTREAMCFG streamCfg;
1381 streamCfg.uHz = 44100;
1382 streamCfg.cChannels = 2;
1383 streamCfg.enmFormat = PDMAUDIOFMT_S16;
1384 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
1385
1386 rc2 = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
1387 AssertRC(rc2);
1388
1389 /* Add all required audio sinks. */
1390 rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
1391 AssertRC(rc2);
1392 }
1393
1394 /* Update the master (mixer) and PCM out volumes. */
1395 sb16SetMasterVolume(pThis);
1396 sb16SetPcmOutVolume(pThis);
1397}
1398
1399static IO_WRITE_PROTO(mixer_write_indexb)
1400{
1401 PSB16STATE pThis = (PSB16STATE)opaque;
1402 (void) nport;
1403 pThis->mixer_nreg = val;
1404
1405 return VINF_SUCCESS;
1406}
1407
1408uint32_t popcount(uint32_t u) /** @todo r=andy WTF? */
1409{
1410 u = ((u&0x55555555) + ((u>>1)&0x55555555));
1411 u = ((u&0x33333333) + ((u>>2)&0x33333333));
1412 u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
1413 u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
1414 u = ( u&0x0000ffff) + (u>>16);
1415 return u;
1416}
1417
1418uint32_t lsbindex(uint32_t u)
1419{
1420 return popcount((u & -(int32_t)u) - 1);
1421}
1422
1423/* Convert SB16 to SB Pro mixer volume (left). */
1424static inline void sb16ConvVolumeL(PSB16STATE pThis, unsigned reg, uint8_t val)
1425{
1426 /* High nibble in SBP mixer. */
1427 pThis->mixer_regs[reg] = (pThis->mixer_regs[reg] & 0x0f) | (val & 0xf0);
1428}
1429
1430/* Convert SB16 to SB Pro mixer volume (right). */
1431static inline void sb16ConvVolumeR(PSB16STATE pThis, unsigned reg, uint8_t val)
1432{
1433 /* Low nibble in SBP mixer. */
1434 pThis->mixer_regs[reg] = (pThis->mixer_regs[reg] & 0xf0) | (val >> 4);
1435}
1436
1437/* Convert SB Pro to SB16 mixer volume (left + right). */
1438static inline void sb16ConvVolumeOldToNew(PSB16STATE pThis, unsigned reg, uint8_t val)
1439{
1440 /* Left channel. */
1441 pThis->mixer_regs[reg + 0] = (val & 0xf0) | RT_BIT(3);
1442 /* Right channel (the register immediately following). */
1443 pThis->mixer_regs[reg + 1] = (val << 4) | RT_BIT(3);
1444}
1445
1446static IO_WRITE_PROTO(mixer_write_datab)
1447{
1448 PSB16STATE pThis = (PSB16STATE)opaque;
1449 bool fUpdateMaster = false;
1450 bool fUpdateStream = false;
1451
1452 (void) nport;
1453 LogFlowFunc(("mixer_write [%#x] <- %#x\n", pThis->mixer_nreg, val));
1454
1455 switch (pThis->mixer_nreg)
1456 {
1457 case 0x00:
1458 sb16MixerReset(pThis);
1459 /* And update the actual volume, too. */
1460 fUpdateMaster = true;
1461 fUpdateStream = true;
1462 break;
1463
1464 case 0x04: /* Translate from old style voice volume (L/R). */
1465 sb16ConvVolumeOldToNew(pThis, 0x32, val);
1466 fUpdateStream = true;
1467 break;
1468
1469 case 0x22: /* Translate from old style master volume (L/R). */
1470 sb16ConvVolumeOldToNew(pThis, 0x30, val);
1471 fUpdateMaster = true;
1472 break;
1473
1474 case 0x26: /* Translate from old style MIDI volume (L/R). */
1475 sb16ConvVolumeOldToNew(pThis, 0x34, val);
1476 break;
1477
1478 case 0x28: /* Translate from old style CD volume (L/R). */
1479 sb16ConvVolumeOldToNew(pThis, 0x36, val);
1480 break;
1481
1482 case 0x2E: /* Translate from old style line volume (L/R). */
1483 sb16ConvVolumeOldToNew(pThis, 0x38, val);
1484 break;
1485
1486 case 0x30: /* Translate to old style master volume (L). */
1487 sb16ConvVolumeL(pThis, 0x22, val);
1488 fUpdateMaster = true;
1489 break;
1490
1491 case 0x31: /* Translate to old style master volume (R). */
1492 sb16ConvVolumeR(pThis, 0x22, val);
1493 fUpdateMaster = true;
1494 break;
1495
1496 case 0x32: /* Translate to old style voice volume (L). */
1497 sb16ConvVolumeL(pThis, 0x04, val);
1498 fUpdateStream = true;
1499 break;
1500
1501 case 0x33: /* Translate to old style voice volume (R). */
1502 sb16ConvVolumeR(pThis, 0x04, val);
1503 fUpdateStream = true;
1504 break;
1505
1506 case 0x34: /* Translate to old style MIDI volume (L). */
1507 sb16ConvVolumeL(pThis, 0x26, val);
1508 break;
1509
1510 case 0x35: /* Translate to old style MIDI volume (R). */
1511 sb16ConvVolumeR(pThis, 0x26, val);
1512 break;
1513
1514 case 0x36: /* Translate to old style CD volume (L). */
1515 sb16ConvVolumeL(pThis, 0x28, val);
1516 break;
1517
1518 case 0x37: /* Translate to old style CD volume (R). */
1519 sb16ConvVolumeR(pThis, 0x28, val);
1520 break;
1521
1522 case 0x38: /* Translate to old style line volume (L). */
1523 sb16ConvVolumeL(pThis, 0x2E, val);
1524 break;
1525
1526 case 0x39: /* Translate to old style line volume (R). */
1527 sb16ConvVolumeR(pThis, 0x2E, val);
1528 break;
1529
1530 case 0x80:
1531 {
1532 int irq = irq_of_magic(val);
1533 LogFlowFunc(("setting irq to %d (val=%#x)\n", irq, val));
1534 if (irq > 0)
1535 pThis->irq = irq;
1536 break;
1537 }
1538
1539 case 0x81:
1540 {
1541 int dma, hdma;
1542
1543 dma = lsbindex (val & 0xf);
1544 hdma = lsbindex (val & 0xf0);
1545 if (dma != pThis->dma || hdma != pThis->hdma)
1546 LogFlow(("SB16: attempt to change DMA 8bit %d(%d), 16bit %d(%d) (val=%#x)\n",
1547 dma, pThis->dma, hdma, pThis->hdma, val));
1548#if 0
1549 pThis->dma = dma;
1550 pThis->hdma = hdma;
1551#endif
1552 break;
1553 }
1554
1555 case 0x82:
1556 LogFlowFunc(("attempt to write into IRQ status register (val=%#x)\n", val));
1557 return VINF_SUCCESS;
1558
1559 default:
1560 if (pThis->mixer_nreg >= 0x80)
1561 LogFlowFunc(("attempt to write mixer[%#x] <- %#x\n", pThis->mixer_nreg, val));
1562 break;
1563 }
1564
1565 pThis->mixer_regs[pThis->mixer_nreg] = val;
1566
1567 /* Update the master (mixer) volume. */
1568 if (fUpdateMaster)
1569 sb16SetMasterVolume(pThis);
1570
1571 /* Update the stream (PCM) volume. */
1572 if (fUpdateStream)
1573 sb16SetPcmOutVolume(pThis);
1574
1575 return VINF_SUCCESS;
1576}
1577
1578static IO_WRITE_PROTO(mixer_write)
1579{
1580 PSB16STATE pThis = (PSB16STATE)opaque;
1581 int iport = nport - pThis->port;
1582 switch (cb)
1583 {
1584 case 1:
1585 switch (iport)
1586 {
1587 case 4:
1588 mixer_write_indexb (pDevIns, opaque, nport, val, 1);
1589 break;
1590 case 5:
1591 mixer_write_datab (pDevIns, opaque, nport, val, 1);
1592 break;
1593 }
1594 break;
1595 case 2:
1596 mixer_write_indexb (pDevIns, opaque, nport, val & 0xff, 1);
1597 mixer_write_datab (pDevIns, opaque, nport, (val >> 8) & 0xff, 1);
1598 break;
1599 default:
1600 AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", nport, cb, val));
1601 break;
1602 }
1603 return VINF_SUCCESS;
1604}
1605
1606static IO_READ_PROTO(mixer_read)
1607{
1608 PSB16STATE pThis = (PSB16STATE)opaque;
1609
1610 (void) nport;
1611#ifndef DEBUG_SB16_MOST
1612 if (pThis->mixer_nreg != 0x82) {
1613 LogFlowFunc(("mixer_read[%#x] -> %#x\n",
1614 pThis->mixer_nreg, pThis->mixer_regs[pThis->mixer_nreg]));
1615 }
1616#else
1617 LogFlowFunc(("mixer_read[%#x] -> %#x\n",
1618 pThis->mixer_nreg, pThis->mixer_regs[pThis->mixer_nreg]));
1619#endif
1620 *pu32 = pThis->mixer_regs[pThis->mixer_nreg];
1621 return VINF_SUCCESS;
1622}
1623
1624static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos,
1625 uint32_t dma_len, int len)
1626{
1627 uint8_t tmpbuf[_4K]; /** @todo Have a buffer on the heap. */
1628 uint32_t cbToWrite = len;
1629 uint32_t cbWrittenTotal = 0;
1630
1631 while (cbToWrite)
1632 {
1633 uint32_t cbToRead;
1634 uint32_t cbRead;
1635
1636 cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite);
1637 if (cbToRead > sizeof(tmpbuf))
1638 cbToRead = sizeof(tmpbuf);
1639
1640 int rc = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, tmpbuf, dma_pos, cbToRead, &cbRead);
1641 AssertMsgRC(rc, ("DMAReadMemory -> %Rrc\n", rc));
1642
1643 /*
1644 * Write data to the mixer sink.
1645 */
1646 uint32_t cbWritten;
1647 rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, tmpbuf, cbToRead, &cbWritten);
1648 if (RT_FAILURE(rc))
1649 break;
1650
1651 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32, rc=%Rrc\n",
1652 cbToRead, cbToWrite, cbWritten, cbToWrite - cbWrittenTotal, rc));
1653
1654 Assert(cbToWrite >= cbToRead);
1655 cbToWrite -= cbToRead;
1656 dma_pos = (dma_pos + cbToRead) % dma_len;
1657 cbWrittenTotal += cbToRead;
1658
1659 if (!cbRead)
1660 break;
1661 }
1662
1663 return cbWrittenTotal;
1664}
1665
1666static DECLCALLBACK(uint32_t) sb16DMARead(PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len)
1667{
1668 PSB16STATE pThis = (PSB16STATE)opaque;
1669 int till, copy, written, free;
1670
1671 if (pThis->block_size <= 0)
1672 {
1673 LogFlowFunc(("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n",
1674 pThis->block_size, nchan, dma_pos, dma_len));
1675 return dma_pos;
1676 }
1677
1678 if (pThis->left_till_irq < 0)
1679 pThis->left_till_irq = pThis->block_size;
1680
1681 PSB16DRIVER pDrv;
1682
1683 uint32_t cbOutMin = UINT32_MAX;
1684 uint32_t cbOut;
1685 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
1686 {
1687 int rc2 = pDrv->pConnector->pfnStreamGetData(pDrv->pConnector, pDrv->Out.pStream, &cbOut);
1688 if (RT_SUCCESS(rc2))
1689 cbOutMin = RT_MIN(cbOutMin, cbOut);
1690 }
1691
1692 LogFlowFunc(("cbOutMin=%RU32\n", cbOutMin));
1693 if (cbOutMin == UINT32_MAX)
1694 {
1695 free = dma_len;
1696 }
1697 else
1698 {
1699 free = cbOutMin & ~pThis->align; /** @todo int vs. uint32. */
1700 if ((free <= 0) || !dma_len)
1701 return dma_pos;
1702 }
1703
1704 copy = free;
1705 till = pThis->left_till_irq;
1706
1707#ifdef DEBUG_SB16_MOST
1708 LogFlowFunc(("pos:%06d %d till:%d len:%d\n", dma_pos, free, till, dma_len));
1709#endif
1710
1711 if (copy >= till)
1712 {
1713 if (0 == pThis->dma_auto)
1714 {
1715 copy = till;
1716 }
1717 else
1718 {
1719 if (copy >= till + pThis->block_size)
1720 copy = till; /* Make sure we won't skip IRQs. */
1721 }
1722 }
1723
1724 written = sb16WriteAudio(pThis, nchan, dma_pos, dma_len, copy);
1725 dma_pos = (dma_pos + written) % dma_len;
1726 pThis->left_till_irq -= written;
1727
1728 if (pThis->left_till_irq <= 0)
1729 {
1730 pThis->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1731 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1);
1732 if (0 == pThis->dma_auto)
1733 {
1734 sb16Control(pThis, 0);
1735 sb16SpeakerControl(pThis, 0);
1736 }
1737 }
1738
1739#ifdef DEBUG_SB16_MOST
1740 LogFlowFunc(("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1741 dma_pos, free, dma_len, pThis->left_till_irq, copy, written,
1742 pThis->block_size));
1743#endif
1744
1745 while (pThis->left_till_irq <= 0)
1746 pThis->left_till_irq += pThis->block_size;
1747
1748 return dma_pos;
1749}
1750
1751#ifndef VBOX_WITH_AUDIO_CALLBACKS
1752
1753static void sb16TimerMaybeStart(PSB16STATE pThis)
1754{
1755 LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
1756
1757 if (pThis->cStreamsActive == 0) /* Only start the timer if there are no active streams. */
1758 return;
1759
1760 if (!pThis->pTimerIO)
1761 return;
1762
1763 /* Update current time timestamp. */
1764 pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO);
1765
1766 /* Fire off timer. */
1767 TMTimerSet(pThis->pTimerIO, TMTimerGet(pThis->pTimerIO) + pThis->cTimerTicksIO);
1768}
1769
1770static void sb16TimerMaybeStop(PSB16STATE pThis)
1771{
1772 LogFlowFunc(("cStreamsActive=%RU8\n", pThis->cStreamsActive));
1773
1774 if (pThis->cStreamsActive) /* Some streams still active? Bail out. */
1775 return;
1776
1777 if (!pThis->pTimerIO)
1778 return;
1779
1780 int rc2 = TMTimerStop(pThis->pTimerIO);
1781 AssertRC(rc2);
1782}
1783
1784static DECLCALLBACK(void) sb16TimerIO(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1785{
1786 PSB16STATE pThis = (PSB16STATE)pvUser;
1787 Assert(pThis == PDMINS_2_DATA(pDevIns, PSB16STATE));
1788 AssertPtr(pThis);
1789
1790 uint64_t cTicksNow = TMTimerGet(pTimer);
1791 uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTSIO;
1792 uint64_t cTicksPerSec = TMTimerGetFreq(pTimer);
1793
1794 pThis->uTimerTSIO = cTicksNow;
1795
1796 uint32_t cbOut;
1797 AudioMixerSinkTimerUpdate(pThis->pSinkOutput, cTicksPerSec, cTicksElapsed, &cbOut);
1798 if (cbOut)
1799 {
1800 /* New space available, see if we can transfer more. */
1801 PDMDevHlpDMASchedule(pThis->pDevInsR3);
1802 }
1803
1804 /* Kick the timer again. */
1805 uint64_t cTicks = pThis->cTimerTicksIO;
1806 /** @todo adjust cTicks down by now much cbOutMin represents. */
1807 TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);
1808}
1809
1810#endif /* !VBOX_WITH_AUDIO_CALLBACKS */
1811
1812static void sb16Save(PSSMHANDLE pSSM, PSB16STATE pThis)
1813{
1814 SSMR3PutS32(pSSM, pThis->irq);
1815 SSMR3PutS32(pSSM, pThis->dma);
1816 SSMR3PutS32(pSSM, pThis->hdma);
1817 SSMR3PutS32(pSSM, pThis->port);
1818 SSMR3PutS32(pSSM, pThis->ver);
1819 SSMR3PutS32(pSSM, pThis->in_index);
1820 SSMR3PutS32(pSSM, pThis->out_data_len);
1821 SSMR3PutS32(pSSM, pThis->fmt_stereo);
1822 SSMR3PutS32(pSSM, pThis->fmt_signed);
1823 SSMR3PutS32(pSSM, pThis->fmt_bits);
1824
1825 SSMR3PutU32(pSSM, pThis->fmt);
1826
1827 SSMR3PutS32(pSSM, pThis->dma_auto);
1828 SSMR3PutS32(pSSM, pThis->block_size);
1829 SSMR3PutS32(pSSM, pThis->fifo);
1830 SSMR3PutS32(pSSM, pThis->freq);
1831 SSMR3PutS32(pSSM, pThis->time_const);
1832 SSMR3PutS32(pSSM, pThis->speaker);
1833 SSMR3PutS32(pSSM, pThis->needed_bytes);
1834 SSMR3PutS32(pSSM, pThis->cmd);
1835 SSMR3PutS32(pSSM, pThis->use_hdma);
1836 SSMR3PutS32(pSSM, pThis->highspeed);
1837 SSMR3PutS32(pSSM, pThis->can_write);
1838 SSMR3PutS32(pSSM, pThis->v2x6);
1839
1840 SSMR3PutU8 (pSSM, pThis->csp_param);
1841 SSMR3PutU8 (pSSM, pThis->csp_value);
1842 SSMR3PutU8 (pSSM, pThis->csp_mode);
1843 SSMR3PutU8 (pSSM, pThis->csp_param); /* Bug compatible! */
1844 SSMR3PutMem(pSSM, pThis->csp_regs, 256);
1845 SSMR3PutU8 (pSSM, pThis->csp_index);
1846 SSMR3PutMem(pSSM, pThis->csp_reg83, 4);
1847 SSMR3PutS32(pSSM, pThis->csp_reg83r);
1848 SSMR3PutS32(pSSM, pThis->csp_reg83w);
1849
1850 SSMR3PutMem(pSSM, pThis->in2_data, sizeof (pThis->in2_data));
1851 SSMR3PutMem(pSSM, pThis->out_data, sizeof (pThis->out_data));
1852 SSMR3PutU8 (pSSM, pThis->test_reg);
1853 SSMR3PutU8 (pSSM, pThis->last_read_byte);
1854
1855 SSMR3PutS32(pSSM, pThis->nzero);
1856 SSMR3PutS32(pSSM, pThis->left_till_irq);
1857 SSMR3PutS32(pSSM, pThis->dma_running);
1858 SSMR3PutS32(pSSM, pThis->bytes_per_second);
1859 SSMR3PutS32(pSSM, pThis->align);
1860
1861 SSMR3PutS32(pSSM, pThis->mixer_nreg);
1862 SSMR3PutMem(pSSM, pThis->mixer_regs, 256);
1863
1864}
1865
1866static int sb16Load(PSSMHANDLE pSSM, PSB16STATE pThis, int version_id)
1867{
1868 SSMR3GetS32(pSSM, &pThis->irq);
1869 SSMR3GetS32(pSSM, &pThis->dma);
1870 SSMR3GetS32(pSSM, &pThis->hdma);
1871 SSMR3GetS32(pSSM, &pThis->port);
1872 SSMR3GetS32(pSSM, &pThis->ver);
1873 SSMR3GetS32(pSSM, &pThis->in_index);
1874 SSMR3GetS32(pSSM, &pThis->out_data_len);
1875 SSMR3GetS32(pSSM, &pThis->fmt_stereo);
1876 SSMR3GetS32(pSSM, &pThis->fmt_signed);
1877 SSMR3GetS32(pSSM, &pThis->fmt_bits);
1878
1879 SSMR3GetU32(pSSM, (uint32_t *)&pThis->fmt);
1880
1881 SSMR3GetS32(pSSM, &pThis->dma_auto);
1882 SSMR3GetS32(pSSM, &pThis->block_size);
1883 SSMR3GetS32(pSSM, &pThis->fifo);
1884 SSMR3GetS32(pSSM, &pThis->freq);
1885 SSMR3GetS32(pSSM, &pThis->time_const);
1886 SSMR3GetS32(pSSM, &pThis->speaker);
1887 SSMR3GetS32(pSSM, &pThis->needed_bytes);
1888 SSMR3GetS32(pSSM, &pThis->cmd);
1889 SSMR3GetS32(pSSM, &pThis->use_hdma);
1890 SSMR3GetS32(pSSM, &pThis->highspeed);
1891 SSMR3GetS32(pSSM, &pThis->can_write);
1892 SSMR3GetS32(pSSM, &pThis->v2x6);
1893
1894 SSMR3GetU8 (pSSM, &pThis->csp_param);
1895 SSMR3GetU8 (pSSM, &pThis->csp_value);
1896 SSMR3GetU8 (pSSM, &pThis->csp_mode);
1897 SSMR3GetU8 (pSSM, &pThis->csp_param); /* Bug compatible! */
1898 SSMR3GetMem(pSSM, pThis->csp_regs, 256);
1899 SSMR3GetU8 (pSSM, &pThis->csp_index);
1900 SSMR3GetMem(pSSM, pThis->csp_reg83, 4);
1901 SSMR3GetS32(pSSM, &pThis->csp_reg83r);
1902 SSMR3GetS32(pSSM, &pThis->csp_reg83w);
1903
1904 SSMR3GetMem(pSSM, pThis->in2_data, sizeof (pThis->in2_data));
1905 SSMR3GetMem(pSSM, pThis->out_data, sizeof (pThis->out_data));
1906 SSMR3GetU8 (pSSM, &pThis->test_reg);
1907 SSMR3GetU8 (pSSM, &pThis->last_read_byte);
1908
1909 SSMR3GetS32(pSSM, &pThis->nzero);
1910 SSMR3GetS32(pSSM, &pThis->left_till_irq);
1911 SSMR3GetS32(pSSM, &pThis->dma_running);
1912 SSMR3GetS32(pSSM, &pThis->bytes_per_second);
1913 SSMR3GetS32(pSSM, &pThis->align);
1914
1915 SSMR3GetS32(pSSM, &pThis->mixer_nreg);
1916 SSMR3GetMem(pSSM, pThis->mixer_regs, 256);
1917
1918#if 0
1919 PSB16DRIVER pDrv;
1920 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
1921 {
1922 if (pDrv->Out.pStream)
1923 {
1924 pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStream);
1925 pDrv->Out.pStream = NULL;
1926 }
1927 }
1928#endif
1929
1930 if (pThis->dma_running)
1931 {
1932 if (pThis->freq)
1933 {
1934 PDMAUDIOSTREAMCFG streamCfg;
1935 RT_ZERO(streamCfg);
1936 streamCfg.enmDir = PDMAUDIODIR_OUT;
1937 streamCfg.uHz = pThis->freq;
1938 streamCfg.cChannels = 1 << pThis->fmt_stereo;
1939 streamCfg.enmFormat = pThis->fmt;
1940 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
1941
1942 int rc = sb16OpenOut(pThis, &streamCfg);
1943 AssertRC(rc);
1944 }
1945
1946 sb16Control(pThis, 1);
1947 sb16SpeakerControl(pThis, pThis->speaker);
1948 }
1949
1950 /* Update the master (mixer) and PCM out volumes. */
1951 sb16SetMasterVolume(pThis);
1952 sb16SetPcmOutVolume(pThis);
1953
1954 return VINF_SUCCESS;
1955}
1956
1957static DECLCALLBACK(int) sb16LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
1958{
1959 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
1960
1961 SSMR3PutS32(pSSM, pThis->irqCfg);
1962 SSMR3PutS32(pSSM, pThis->dmaCfg);
1963 SSMR3PutS32(pSSM, pThis->hdmaCfg);
1964 SSMR3PutS32(pSSM, pThis->portCfg);
1965 SSMR3PutS32(pSSM, pThis->verCfg);
1966 return VINF_SSM_DONT_CALL_AGAIN;
1967}
1968
1969static DECLCALLBACK(int) sb16SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
1970{
1971 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
1972
1973 sb16LiveExec(pDevIns, pSSM, 0);
1974 sb16Save(pSSM, pThis);
1975 return VINF_SUCCESS;
1976}
1977
1978static DECLCALLBACK(int) sb16LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1979{
1980 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
1981
1982 AssertMsgReturn( uVersion == SB16_SAVE_STATE_VERSION
1983 || uVersion == SB16_SAVE_STATE_VERSION_VBOX_30,
1984 ("%u\n", uVersion),
1985 VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1986 if (uVersion > SB16_SAVE_STATE_VERSION_VBOX_30)
1987 {
1988 int32_t irq;
1989 SSMR3GetS32 (pSSM, &irq);
1990 int32_t dma;
1991 SSMR3GetS32 (pSSM, &dma);
1992 int32_t hdma;
1993 SSMR3GetS32 (pSSM, &hdma);
1994 int32_t port;
1995 SSMR3GetS32 (pSSM, &port);
1996 int32_t ver;
1997 int rc = SSMR3GetS32 (pSSM, &ver);
1998 AssertRCReturn (rc, rc);
1999
2000 if ( irq != pThis->irqCfg
2001 || dma != pThis->dmaCfg
2002 || hdma != pThis->hdmaCfg
2003 || port != pThis->portCfg
2004 || ver != pThis->verCfg)
2005 {
2006 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2007 N_("config changed: irq=%x/%x dma=%x/%x hdma=%x/%x port=%x/%x ver=%x/%x (saved/config)"),
2008 irq, pThis->irqCfg,
2009 dma, pThis->dmaCfg,
2010 hdma, pThis->hdmaCfg,
2011 port, pThis->portCfg,
2012 ver, pThis->verCfg);
2013 }
2014 }
2015
2016 if (uPass != SSM_PASS_FINAL)
2017 return VINF_SUCCESS;
2018
2019 sb16Load(pSSM, pThis, uVersion);
2020 return VINF_SUCCESS;
2021}
2022
2023static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg)
2024{
2025 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2026 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2027
2028 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
2029
2030 /* Update the sink's format. */
2031 PDMPCMPROPS PCMProps;
2032 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps);
2033 if (RT_SUCCESS(rc))
2034 rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps);
2035
2036 if (RT_FAILURE(rc))
2037 return rc;
2038
2039 PSB16DRIVER pDrv;
2040 uint8_t uLUN = 0;
2041
2042 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
2043 {
2044 if (!RTStrPrintf(pCfg->szName, sizeof(pCfg->szName), "[LUN#%RU8] sb16.po (%RU32Hz, %RU8 %s)",
2045 pDrv->uLUN, pCfg->uHz, pCfg->cChannels, pCfg->cChannels > 1 ? "Channels" : "Channel"))
2046 {
2047 rc = VERR_BUFFER_OVERFLOW;
2048 break;
2049 }
2050
2051 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
2052
2053 AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
2054 pDrv->Out.pMixStrm = NULL;
2055
2056 int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOutput, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
2057 if (RT_SUCCESS(rc2))
2058 {
2059 rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
2060 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
2061 }
2062
2063 if (RT_FAILURE(rc2))
2064 {
2065 if (RT_SUCCESS(rc))
2066 rc = rc2;
2067 break;
2068 }
2069
2070 uLUN++;
2071 }
2072
2073 /* Ensure volume gets propagated. */
2074 AudioMixerInvalidate(pThis->pMixer);
2075
2076 return rc;
2077}
2078
2079static void sb16CloseOut(PSB16STATE pThis)
2080{
2081 AssertPtrReturnVoid(pThis);
2082
2083 LogFlowFuncEnter();
2084
2085 PSB16DRIVER pDrv;
2086 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
2087 {
2088 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
2089 AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
2090 pDrv->Out.pMixStrm = NULL;
2091 }
2092}
2093
2094/**
2095 * @interface_method_impl{PDMDEVREG,pfnReset}
2096 */
2097static DECLCALLBACK(void) sb16DevReset(PPDMDEVINS pDevIns)
2098{
2099 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
2100
2101 /* Bring back the device to initial state, and especially make
2102 * sure there's no interrupt or DMA activity.
2103 */
2104 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 0);
2105
2106 pThis->mixer_regs[0x82] = 0;
2107 pThis->csp_regs[5] = 1;
2108 pThis->csp_regs[9] = 0xf8;
2109
2110 pThis->dma_auto = 0;
2111 pThis->in_index = 0;
2112 pThis->out_data_len = 0;
2113 pThis->left_till_irq = 0;
2114 pThis->needed_bytes = 0;
2115 pThis->block_size = -1;
2116 pThis->nzero = 0;
2117 pThis->highspeed = 0;
2118 pThis->v2x6 = 0;
2119 pThis->cmd = -1;
2120
2121 sb16MixerReset(pThis);
2122 sb16SpeakerControl(pThis, 0);
2123 sb16Control(pThis, 0);
2124 sb16ResetLegacy(pThis);
2125}
2126
2127/**
2128 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2129 */
2130static DECLCALLBACK(void *) sb16QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
2131{
2132 PSB16STATE pThis = RT_FROM_MEMBER(pInterface, SB16STATE, IBase);
2133 Assert(&pThis->IBase == pInterface);
2134
2135 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
2136 return NULL;
2137}
2138
2139/**
2140 * Powers off the device.
2141 *
2142 * @param pDevIns Device instance to power off.
2143 */
2144static DECLCALLBACK(void) sb16PowerOff(PPDMDEVINS pDevIns)
2145{
2146 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
2147
2148 LogRel2(("SB16: Powering off ...\n"));
2149
2150 /**
2151 * Note: Destroy the mixer while powering off and *not* in sb16Destruct,
2152 * giving the mixer the chance to release any references held to
2153 * PDM audio streams it maintains.
2154 */
2155 if (pThis->pMixer)
2156 {
2157 AudioMixerDestroy(pThis->pMixer);
2158 pThis->pMixer = NULL;
2159 }
2160}
2161
2162/**
2163 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2164 */
2165static DECLCALLBACK(int) sb16Destruct(PPDMDEVINS pDevIns)
2166{
2167 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
2168
2169 LogFlowFuncEnter();
2170
2171 PSB16DRIVER pDrv;
2172 while (!RTListIsEmpty(&pThis->lstDrv))
2173 {
2174 pDrv = RTListGetFirst(&pThis->lstDrv, SB16DRIVER, Node);
2175
2176 RTListNodeRemove(&pDrv->Node);
2177 RTMemFree(pDrv);
2178 }
2179
2180 sb16CloseOut(pThis);
2181
2182 return VINF_SUCCESS;
2183}
2184
2185static DECLCALLBACK(int) sb16Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
2186{
2187 PSB16STATE pThis = PDMINS_2_DATA(pDevIns, PSB16STATE);
2188
2189 /*
2190 * Validations.
2191 */
2192 Assert(iInstance == 0);
2193 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2194 if (!CFGMR3AreValuesValid(pCfg,
2195 "IRQ\0"
2196 "DMA\0"
2197 "DMA16\0"
2198 "Port\0"
2199 "Version\0"
2200 "TimerHz\0"))
2201 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2202 N_("Invalid configuration for SB16 device"));
2203
2204 /*
2205 * Read config data.
2206 */
2207 int rc = CFGMR3QuerySIntDef(pCfg, "IRQ", &pThis->irq, 5);
2208 if (RT_FAILURE(rc))
2209 return PDMDEV_SET_ERROR(pDevIns, rc,
2210 N_("SB16 configuration error: Failed to get the \"IRQ\" value"));
2211 pThis->irqCfg = pThis->irq;
2212
2213 rc = CFGMR3QuerySIntDef(pCfg, "DMA", &pThis->dma, 1);
2214 if (RT_FAILURE(rc))
2215 return PDMDEV_SET_ERROR(pDevIns, rc,
2216 N_("SB16 configuration error: Failed to get the \"DMA\" value"));
2217 pThis->dmaCfg = pThis->dma;
2218
2219 rc = CFGMR3QuerySIntDef(pCfg, "DMA16", &pThis->hdma, 5);
2220 if (RT_FAILURE(rc))
2221 return PDMDEV_SET_ERROR(pDevIns, rc,
2222 N_("SB16 configuration error: Failed to get the \"DMA16\" value"));
2223 pThis->hdmaCfg = pThis->hdma;
2224
2225 RTIOPORT Port;
2226 rc = CFGMR3QueryPortDef(pCfg, "Port", &Port, 0x220);
2227 if (RT_FAILURE(rc))
2228 return PDMDEV_SET_ERROR(pDevIns, rc,
2229 N_("SB16 configuration error: Failed to get the \"Port\" value"));
2230 pThis->port = Port;
2231 pThis->portCfg = Port;
2232
2233 uint16_t u16Version;
2234 rc = CFGMR3QueryU16Def(pCfg, "Version", &u16Version, 0x0405);
2235 if (RT_FAILURE(rc))
2236 return PDMDEV_SET_ERROR(pDevIns, rc,
2237 N_("SB16 configuration error: Failed to get the \"Version\" value"));
2238
2239#ifndef VBOX_WITH_AUDIO_CALLBACKS
2240 uint16_t uTimerHz;
2241 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 25 /* Hz */);
2242 if (RT_FAILURE(rc))
2243 return PDMDEV_SET_ERROR(pDevIns, rc,
2244 N_("SB16 configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
2245#endif
2246
2247 pThis->ver = u16Version;
2248 pThis->verCfg = u16Version;
2249
2250 /*
2251 * Init instance data.
2252 */
2253 pThis->pDevInsR3 = pDevIns;
2254 pThis->IBase.pfnQueryInterface = sb16QueryInterface;
2255 pThis->cmd = -1;
2256
2257 pThis->mixer_regs[0x80] = magic_of_irq (pThis->irq);
2258 pThis->mixer_regs[0x81] = (1 << pThis->dma) | (1 << pThis->hdma);
2259 pThis->mixer_regs[0x82] = 2 << 5;
2260
2261 pThis->csp_regs[5] = 1;
2262 pThis->csp_regs[9] = 0xf8;
2263
2264 RTListInit(&pThis->lstDrv);
2265
2266 sb16MixerReset(pThis);
2267
2268 /*
2269 * Create timer(s), register & attach stuff.
2270 */
2271 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIRQ, pThis,
2272 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IRQ timer", &pThis->pTimerIRQ);
2273 if (RT_FAILURE(rc))
2274 AssertMsgFailedReturn(("Error creating IRQ timer, rc=%Rrc\n", rc), rc);
2275
2276 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->port + 0x04, 2, pThis,
2277 mixer_write, mixer_read, NULL, NULL, "SB16");
2278 if (RT_FAILURE(rc))
2279 return rc;
2280 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->port + 0x06, 10, pThis,
2281 dsp_write, dsp_read, NULL, NULL, "SB16");
2282 if (RT_FAILURE(rc))
2283 return rc;
2284
2285 rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, sb16DMARead, pThis);
2286 if (RT_FAILURE(rc))
2287 return rc;
2288 rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, sb16DMARead, pThis);
2289 if (RT_FAILURE(rc))
2290 return rc;
2291
2292 pThis->can_write = 1;
2293
2294 rc = PDMDevHlpSSMRegister3(pDevIns, SB16_SAVE_STATE_VERSION, sizeof(SB16STATE), sb16LiveExec, sb16SaveExec, sb16LoadExec);
2295 if (RT_FAILURE(rc))
2296 return rc;
2297
2298 /*
2299 * Attach driver.
2300 */
2301 uint8_t uLUN;
2302 for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
2303 {
2304 LogFunc(("Trying to attach driver for LUN #%RU8 ...\n", uLUN));
2305 rc = sb16AttachInternal(pDevIns, NULL /* pDrv */, uLUN, 0 /* fFlags */);
2306 if (RT_FAILURE(rc))
2307 {
2308 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2309 rc = VINF_SUCCESS;
2310 else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
2311 {
2312 sb16Reattach(pThis, NULL /* pDrv */, uLUN, "NullAudio");
2313 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2314 N_("No audio devices could be opened. Selecting the NULL audio backend "
2315 "with the consequence that no sound is audible"));
2316 /* attaching to the NULL audio backend will never fail */
2317 rc = VINF_SUCCESS;
2318 }
2319 break;
2320 }
2321 }
2322
2323 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
2324
2325 sb16ResetLegacy(pThis);
2326
2327 PSB16DRIVER pDrv;
2328 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
2329 {
2330 /*
2331 * Only primary drivers are critical for the VM to run. Everything else
2332 * might not worth showing an own error message box in the GUI.
2333 */
2334 if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
2335 continue;
2336
2337 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
2338 AssertPtr(pCon);
2339
2340 /** @todo No input streams available for SB16 yet. */
2341 bool fValidOut = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
2342 if (!fValidOut)
2343 {
2344 LogRel(("SB16: Falling back to NULL backend (no sound audible)\n"));
2345
2346 sb16ResetLegacy(pThis);
2347 sb16Reattach(pThis, pDrv, pDrv->uLUN, "NullAudio");
2348
2349 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
2350 N_("No audio devices could be opened. Selecting the NULL audio backend "
2351 "with the consequence that no sound is audible"));
2352 }
2353 }
2354
2355#ifndef VBOX_WITH_AUDIO_CALLBACKS
2356 if (RT_SUCCESS(rc))
2357 {
2358 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16TimerIO, pThis,
2359 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 IO timer", &pThis->pTimerIO);
2360 if (RT_SUCCESS(rc))
2361 {
2362 pThis->cTimerTicksIO = TMTimerGetFreq(pThis->pTimerIO) / uTimerHz;
2363 pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO);
2364 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicksIO, uTimerHz));
2365
2366 sb16TimerMaybeStart(pThis);
2367 }
2368 else
2369 AssertMsgFailedReturn(("Error creating I/O timer, rc=%Rrc\n", rc), rc);
2370 }
2371#else
2372 if (RT_SUCCESS(rc))
2373 {
2374 /** @todo Merge this callback registration with the validation block above once
2375 * this becomes the standard. */
2376 PSB16DRIVER pDrv;
2377 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
2378 {
2379 /* Only register primary driver.
2380 * The device emulation does the output multiplexing then. */
2381 if (pDrv->Flags != PDMAUDIODRVFLAG_PRIMARY)
2382 continue;
2383
2384 PDMAUDIOCALLBACK AudioCallbacks[2];
2385
2386 SB16CALLBACKCTX Ctx = { pThis, pDrv };
2387
2388 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT;
2389 AudioCallbacks[0].pfnCallback = sb16CallbackInput;
2390 AudioCallbacks[0].pvCtx = &Ctx;
2391 AudioCallbacks[0].cbCtx = sizeof(SB16CALLBACKCTX);
2392
2393 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT;
2394 AudioCallbacks[1].pfnCallback = sb16CallbackOutput;
2395 AudioCallbacks[1].pvCtx = &Ctx;
2396 AudioCallbacks[1].cbCtx = sizeof(SB16CALLBACKCTX);
2397
2398 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
2399 if (RT_FAILURE(rc))
2400 break;
2401 }
2402 }
2403#endif
2404
2405 return VINF_SUCCESS;
2406}
2407
2408const PDMDEVREG g_DeviceSB16 =
2409{
2410 /* u32Version */
2411 PDM_DEVREG_VERSION,
2412 /* szName */
2413 "sb16",
2414 /* szRCMod */
2415 "",
2416 /* szR0Mod */
2417 "",
2418 /* pszDescription */
2419 "Sound Blaster 16 Controller",
2420 /* fFlags */
2421 PDM_DEVREG_FLAGS_DEFAULT_BITS,
2422 /* fClass */
2423 PDM_DEVREG_CLASS_AUDIO,
2424 /* cMaxInstances */
2425 1,
2426 /* cbInstance */
2427 sizeof(SB16STATE),
2428 /* pfnConstruct */
2429 sb16Construct,
2430 /* pfnDestruct */
2431 sb16Destruct,
2432 /* pfnRelocate */
2433 NULL,
2434 /* pfnMemSetup */
2435 NULL,
2436 /* pfnPowerOn */
2437 NULL,
2438 /* pfnReset */
2439 sb16DevReset,
2440 /* pfnSuspend */
2441 NULL,
2442 /* pfnResume */
2443 NULL,
2444 /* pfnAttach */
2445 sb16Attach,
2446 /* pfnDetach */
2447 sb16Detach,
2448 /* pfnQueryInterface */
2449 NULL,
2450 /* pfnInitComplete */
2451 NULL,
2452 /* pfnPowerOff */
2453 sb16PowerOff,
2454 /* pfnSoftReset */
2455 NULL,
2456 /* u32VersionEnd */
2457 PDM_DEVREG_VERSION
2458};
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