VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevHDA.cpp@ 87799

Last change on this file since 87799 was 87799, checked in by vboxsync, 4 years ago

HDA/Codec: Codec now also can run in R0 to speed up interrupt handling and therefore lowering DPC latency on Windows guests. ticketoem2ref:36

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 209.6 KB
Line 
1/* $Id: DevHDA.cpp 87799 2021-02-19 10:44:27Z vboxsync $ */
2/** @file
3 * DevHDA.cpp - VBox Intel HD Audio Controller.
4 *
5 * Implemented against the specifications found in "High Definition Audio
6 * Specification", Revision 1.0a June 17, 2010, and "Intel I/O Controller
7 * HUB 6 (ICH6) Family, Datasheet", document number 301473-002.
8 */
9
10/*
11 * Copyright (C) 2006-2020 Oracle Corporation
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License (GPL) as published by the Free Software
17 * Foundation, in version 2 as it comes in the "COPYING" file of the
18 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20 */
21
22
23/*********************************************************************************************************************************
24* Header Files *
25*********************************************************************************************************************************/
26#define LOG_GROUP LOG_GROUP_DEV_HDA
27#include <VBox/log.h>
28
29#include <VBox/vmm/pdmdev.h>
30#include <VBox/vmm/pdmaudioifs.h>
31#include <VBox/version.h>
32#include <VBox/AssertGuest.h>
33
34#include <iprt/assert.h>
35#include <iprt/asm.h>
36#include <iprt/asm-math.h>
37#include <iprt/file.h>
38#include <iprt/list.h>
39# include <iprt/string.h>
40#ifdef IN_RING3
41# include <iprt/mem.h>
42# include <iprt/semaphore.h>
43# include <iprt/uuid.h>
44#endif
45
46#include "VBoxDD.h"
47
48#include "AudioMixBuffer.h"
49#include "AudioMixer.h"
50
51#include "DevHDA.h"
52#include "DevHDACommon.h"
53
54#include "HDACodec.h"
55#include "HDAStream.h"
56#include "HDAStreamMap.h"
57#include "HDAStreamPeriod.h"
58
59#include "DrvAudio.h"
60
61
62/*********************************************************************************************************************************
63* Defined Constants And Macros *
64*********************************************************************************************************************************/
65//#define HDA_AS_PCI_EXPRESS
66
67/* Installs a DMA access handler (via PGM callback) to monitor
68 * HDA's DMA operations, that is, writing / reading audio stream data.
69 *
70 * !!! Note: Certain guests are *that* timing sensitive that when enabling !!!
71 * !!! such a handler will mess up audio completely (e.g. Windows 7). !!! */
72//#define HDA_USE_DMA_ACCESS_HANDLER
73#ifdef HDA_USE_DMA_ACCESS_HANDLER
74# include <VBox/vmm/pgm.h>
75#endif
76
77/* Uses the DMA access handler to read the written DMA audio (output) data.
78 * Only valid if HDA_USE_DMA_ACCESS_HANDLER is set.
79 *
80 * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */
81//# define HDA_USE_DMA_ACCESS_HANDLER_WRITING
82
83/* Useful to debug the device' timing. */
84//#define HDA_DEBUG_TIMING
85
86/* To debug silence coming from the guest in form of audio gaps.
87 * Very crude implementation for now. */
88//#define HDA_DEBUG_SILENCE
89
90#if defined(VBOX_WITH_HP_HDA)
91/* HP Pavilion dv4t-1300 */
92# define HDA_PCI_VENDOR_ID 0x103c
93# define HDA_PCI_DEVICE_ID 0x30f7
94#elif defined(VBOX_WITH_INTEL_HDA)
95/* Intel HDA controller */
96# define HDA_PCI_VENDOR_ID 0x8086
97# define HDA_PCI_DEVICE_ID 0x2668
98#elif defined(VBOX_WITH_NVIDIA_HDA)
99/* nVidia HDA controller */
100# define HDA_PCI_VENDOR_ID 0x10de
101# define HDA_PCI_DEVICE_ID 0x0ac0
102#else
103# error "Please specify your HDA device vendor/device IDs"
104#endif
105
106/**
107 * Acquires the HDA lock.
108 */
109#define DEVHDA_LOCK(a_pDevIns, a_pThis) \
110 do { \
111 int rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, VERR_IGNORED); \
112 AssertRC(rcLock); \
113 } while (0)
114
115/**
116 * Acquires the HDA lock or returns.
117 */
118#define DEVHDA_LOCK_RETURN(a_pDevIns, a_pThis, a_rcBusy) \
119 do { \
120 int rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, a_rcBusy); \
121 if (rcLock == VINF_SUCCESS) \
122 { /* likely */ } \
123 else \
124 { \
125 AssertRC(rcLock); \
126 return rcLock; \
127 } \
128 } while (0)
129
130/**
131 * Acquires the HDA lock or returns.
132 */
133# define DEVHDA_LOCK_RETURN_VOID(a_pDevIns, a_pThis) \
134 do { \
135 int rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, VERR_IGNORED); \
136 if (rcLock == VINF_SUCCESS) \
137 { /* likely */ } \
138 else \
139 { \
140 AssertRC(rcLock); \
141 return; \
142 } \
143 } while (0)
144
145/**
146 * Releases the HDA lock.
147 */
148#define DEVHDA_UNLOCK(a_pDevIns, a_pThis) \
149 do { PDMDevHlpCritSectLeave((a_pDevIns), &(a_pThis)->CritSect); } while (0)
150
151/**
152 * Acquires the TM lock and HDA lock, returns on failure.
153 */
154#define DEVHDA_LOCK_BOTH_RETURN(a_pDevIns, a_pThis, a_pStream, a_rcBusy) \
155 do { \
156 VBOXSTRICTRC rcLock = PDMDevHlpTimerLockClock2(pDevIns, (a_pStream)->hTimer, &(a_pThis)->CritSect, (a_rcBusy)); \
157 if (RT_LIKELY(rcLock == VINF_SUCCESS)) \
158 { /* likely */ } \
159 else \
160 return VBOXSTRICTRC_TODO(rcLock); \
161 } while (0)
162
163
164/*********************************************************************************************************************************
165* Structures and Typedefs *
166*********************************************************************************************************************************/
167
168/**
169 * Structure defining a (host backend) driver stream.
170 * Each driver has its own instances of audio mixer streams, which then
171 * can go into the same (or even different) audio mixer sinks.
172 */
173typedef struct HDADRIVERSTREAM
174{
175 /** Associated mixer handle. */
176 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
177} HDADRIVERSTREAM, *PHDADRIVERSTREAM;
178
179#ifdef HDA_USE_DMA_ACCESS_HANDLER
180/**
181 * Struct for keeping an HDA DMA access handler context.
182 */
183typedef struct HDADMAACCESSHANDLER
184{
185 /** Node for storing this handler in our list in HDASTREAMSTATE. */
186 RTLISTNODER3 Node;
187 /** Pointer to stream to which this access handler is assigned to. */
188 R3PTRTYPE(PHDASTREAM) pStream;
189 /** Access handler type handle. */
190 PGMPHYSHANDLERTYPE hAccessHandlerType;
191 /** First address this handler uses. */
192 RTGCPHYS GCPhysFirst;
193 /** Last address this handler uses. */
194 RTGCPHYS GCPhysLast;
195 /** Actual BDLE address to handle. */
196 RTGCPHYS BDLEAddr;
197 /** Actual BDLE buffer size to handle. */
198 RTGCPHYS BDLESize;
199 /** Whether the access handler has been registered or not. */
200 bool fRegistered;
201 uint8_t Padding[3];
202} HDADMAACCESSHANDLER, *PHDADMAACCESSHANDLER;
203#endif
204
205/**
206 * Struct for maintaining a host backend driver.
207 * This driver must be associated to one, and only one,
208 * HDA codec. The HDA controller does the actual multiplexing
209 * of HDA codec data to various host backend drivers then.
210 *
211 * This HDA device uses a timer in order to synchronize all
212 * read/write accesses across all attached LUNs / backends.
213 */
214typedef struct HDADRIVER
215{
216 /** Node for storing this driver in our device driver list of HDASTATE. */
217 RTLISTNODER3 Node;
218 /** Pointer to shared HDA device state. */
219 R3PTRTYPE(PHDASTATE) pHDAStateShared;
220 /** Pointer to the ring-3 HDA device state. */
221 R3PTRTYPE(PHDASTATER3) pHDAStateR3;
222 /** Driver flags. */
223 PDMAUDIODRVFLAGS fFlags;
224 uint8_t u32Padding0[2];
225 /** LUN to which this driver has been assigned. */
226 uint8_t uLUN;
227 /** Whether this driver is in an attached state or not. */
228 bool fAttached;
229 /** Pointer to attached driver base interface. */
230 R3PTRTYPE(PPDMIBASE) pDrvBase;
231 /** Audio connector interface to the underlying host backend. */
232 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
233 /** Mixer stream for line input. */
234 HDADRIVERSTREAM LineIn;
235#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
236 /** Mixer stream for mic input. */
237 HDADRIVERSTREAM MicIn;
238#endif
239 /** Mixer stream for front output. */
240 HDADRIVERSTREAM Front;
241#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
242 /** Mixer stream for center/LFE output. */
243 HDADRIVERSTREAM CenterLFE;
244 /** Mixer stream for rear output. */
245 HDADRIVERSTREAM Rear;
246#endif
247} HDADRIVER;
248
249
250/*********************************************************************************************************************************
251* Internal Functions *
252*********************************************************************************************************************************/
253#ifndef VBOX_DEVICE_STRUCT_TESTCASE
254#ifdef IN_RING3
255static void hdaR3GCTLReset(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC);
256#endif
257
258/** @name Register read/write stubs.
259 * @{
260 */
261static FNHDAREGREAD hdaRegReadUnimpl;
262static FNHDAREGWRITE hdaRegWriteUnimpl;
263/** @} */
264
265/** @name Global register set read/write functions.
266 * @{
267 */
268static FNHDAREGWRITE hdaRegWriteGCTL;
269static FNHDAREGREAD hdaRegReadLPIB;
270static FNHDAREGREAD hdaRegReadWALCLK;
271static FNHDAREGWRITE hdaRegWriteCORBWP;
272static FNHDAREGWRITE hdaRegWriteCORBRP;
273static FNHDAREGWRITE hdaRegWriteCORBCTL;
274static FNHDAREGWRITE hdaRegWriteCORBSIZE;
275static FNHDAREGWRITE hdaRegWriteCORBSTS;
276static FNHDAREGWRITE hdaRegWriteRINTCNT;
277static FNHDAREGWRITE hdaRegWriteRIRBWP;
278static FNHDAREGWRITE hdaRegWriteRIRBSTS;
279static FNHDAREGWRITE hdaRegWriteSTATESTS;
280static FNHDAREGWRITE hdaRegWriteIRS;
281static FNHDAREGREAD hdaRegReadIRS;
282static FNHDAREGWRITE hdaRegWriteBase;
283/** @} */
284
285/** @name {IOB}SDn write functions.
286 * @{
287 */
288static FNHDAREGWRITE hdaRegWriteSDCBL;
289static FNHDAREGWRITE hdaRegWriteSDCTL;
290static FNHDAREGWRITE hdaRegWriteSDSTS;
291static FNHDAREGWRITE hdaRegWriteSDLVI;
292static FNHDAREGWRITE hdaRegWriteSDFIFOW;
293static FNHDAREGWRITE hdaRegWriteSDFIFOS;
294static FNHDAREGWRITE hdaRegWriteSDFMT;
295static FNHDAREGWRITE hdaRegWriteSDBDPL;
296static FNHDAREGWRITE hdaRegWriteSDBDPU;
297/** @} */
298
299/** @name Generic register read/write functions.
300 * @{
301 */
302static FNHDAREGREAD hdaRegReadU32;
303static FNHDAREGWRITE hdaRegWriteU32;
304static FNHDAREGREAD hdaRegReadU24;
305#ifdef IN_RING3
306static FNHDAREGWRITE hdaRegWriteU24;
307#endif
308static FNHDAREGREAD hdaRegReadU16;
309static FNHDAREGWRITE hdaRegWriteU16;
310static FNHDAREGREAD hdaRegReadU8;
311static FNHDAREGWRITE hdaRegWriteU8;
312/** @} */
313
314/** @name HDA device functions.
315 * @{
316 */
317#ifdef IN_RING3
318static int hdaR3AddStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg);
319static int hdaR3RemoveStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg);
320# ifdef HDA_USE_DMA_ACCESS_HANDLER
321static DECLCALLBACK(VBOXSTRICTRC) hdaR3DmaAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
322 void *pvBuf, size_t cbBuf,
323 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser);
324# endif
325#endif /* IN_RING3 */
326/** @} */
327
328/** @name HDA mixer functions.
329 * @{
330 */
331#ifdef IN_RING3
332static int hdaR3MixerAddDrvStream(PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv);
333#endif
334/** @} */
335
336#ifdef IN_RING3
337static FNSSMFIELDGETPUT hdaR3GetPutTrans_HDABDLEDESC_fFlags_6;
338static FNSSMFIELDGETPUT hdaR3GetPutTrans_HDABDLE_Desc_fFlags_1thru4;
339#endif
340
341
342/*********************************************************************************************************************************
343* Global Variables *
344*********************************************************************************************************************************/
345
346/** No register description (RD) flags defined. */
347#define HDA_RD_F_NONE 0
348/** Writes to SD are allowed while RUN bit is set. */
349#define HDA_RD_F_SD_WRITE_RUN RT_BIT(0)
350
351/** Emits a single audio stream register set (e.g. OSD0) at a specified offset. */
352#define HDA_REG_MAP_STRM(offset, name) \
353 /* offset size read mask write mask flags read callback write callback index + abbrev description */ \
354 /* ------- ------- ---------- ---------- ------------------------- -------------- ----------------- ----------------------------- ----------- */ \
355 /* Offset 0x80 (SD0) */ \
356 { offset, 0x00003, 0x00FF001F, 0x00F0001F, HDA_RD_F_SD_WRITE_RUN, hdaRegReadU24 , hdaRegWriteSDCTL , HDA_REG_IDX_STRM(name, CTL) , #name " Stream Descriptor Control" }, \
357 /* Offset 0x83 (SD0) */ \
358 { offset + 0x3, 0x00001, 0x0000003C, 0x0000001C, HDA_RD_F_SD_WRITE_RUN, hdaRegReadU8 , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS) , #name " Status" }, \
359 /* Offset 0x84 (SD0) */ \
360 { offset + 0x4, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadLPIB, hdaRegWriteU32 , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
361 /* Offset 0x88 (SD0) */ \
362 { offset + 0x8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteSDCBL , HDA_REG_IDX_STRM(name, CBL) , #name " Cyclic Buffer Length" }, \
363 /* Offset 0x8C (SD0) -- upper 8 bits are reserved */ \
364 { offset + 0xC, 0x00002, 0x0000FFFF, 0x000000FF, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteSDLVI , HDA_REG_IDX_STRM(name, LVI) , #name " Last Valid Index" }, \
365 /* Reserved: FIFO Watermark. ** @todo Document this! */ \
366 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
367 /* Offset 0x90 (SD0) */ \
368 { offset + 0x10, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
369 /* Offset 0x92 (SD0) */ \
370 { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteSDFMT , HDA_REG_IDX_STRM(name, FMT) , #name " Stream Format" }, \
371 /* Reserved: 0x94 - 0x98. */ \
372 /* Offset 0x98 (SD0) */ \
373 { offset + 0x18, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteSDBDPL , HDA_REG_IDX_STRM(name, BDPL) , #name " Buffer Descriptor List Pointer-Lower Base Address" }, \
374 /* Offset 0x9C (SD0) */ \
375 { offset + 0x1C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteSDBDPU , HDA_REG_IDX_STRM(name, BDPU) , #name " Buffer Descriptor List Pointer-Upper Base Address" }
376
377/** Defines a single audio stream register set (e.g. OSD0). */
378#define HDA_REG_MAP_DEF_STREAM(index, name) \
379 HDA_REG_MAP_STRM(HDA_REG_DESC_SD0_BASE + (index * 32 /* 0x20 */), name)
380
381/** See 302349 p 6.2. */
382const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS] =
383{
384 /* offset size read mask write mask flags read callback write callback index + abbrev */
385 /*------- ------- ---------- ---------- ----------------- ---------------- ------------------- ------------------------ */
386 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(GCAP) }, /* Global Capabilities */
387 { 0x00002, 0x00001, 0x000000FF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMIN) }, /* Minor Version */
388 { 0x00003, 0x00001, 0x000000FF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMAJ) }, /* Major Version */
389 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTPAY) }, /* Output Payload Capabilities */
390 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INPAY) }, /* Input Payload Capabilities */
391 { 0x00008, 0x00004, 0x00000103, 0x00000103, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteGCTL , HDA_REG_IDX(GCTL) }, /* Global Control */
392 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(WAKEEN) }, /* Wake Enable */
393 { 0x0000e, 0x00002, 0x00000007, 0x00000007, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteSTATESTS, HDA_REG_IDX(STATESTS) }, /* State Change Status */
394 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadUnimpl, hdaRegWriteUnimpl , HDA_REG_IDX(GSTS) }, /* Global Status */
395 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */
396 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INSTRMPAY) }, /* Input Stream Payload Capability */
397 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(INTCTL) }, /* Interrupt Control */
398 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */
399 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_F_NONE, hdaRegReadWALCLK, hdaRegWriteUnimpl , HDA_REG_IDX_NOMEM(WALCLK) }, /* Wall Clock Counter */
400 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */
401 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBLBASE) }, /* CORB Lower Base Address */
402 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBUBASE) }, /* CORB Upper Base Address */
403 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteCORBWP , HDA_REG_IDX(CORBWP) }, /* CORB Write Pointer */
404 { 0x0004A, 0x00002, 0x000080FF, 0x00008000, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteCORBRP , HDA_REG_IDX(CORBRP) }, /* CORB Read Pointer */
405 { 0x0004C, 0x00001, 0x00000003, 0x00000003, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteCORBCTL , HDA_REG_IDX(CORBCTL) }, /* CORB Control */
406 { 0x0004D, 0x00001, 0x00000001, 0x00000001, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteCORBSTS , HDA_REG_IDX(CORBSTS) }, /* CORB Status */
407 { 0x0004E, 0x00001, 0x000000F3, 0x00000003, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteCORBSIZE, HDA_REG_IDX(CORBSIZE) }, /* CORB Size */
408 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBLBASE) }, /* RIRB Lower Base Address */
409 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBUBASE) }, /* RIRB Upper Base Address */
410 { 0x00058, 0x00002, 0x000000FF, 0x00008000, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteRIRBWP , HDA_REG_IDX(RIRBWP) }, /* RIRB Write Pointer */
411 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_F_NONE, hdaRegReadU16 , hdaRegWriteRINTCNT , HDA_REG_IDX(RINTCNT) }, /* Response Interrupt Count */
412 { 0x0005C, 0x00001, 0x00000007, 0x00000007, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteU8 , HDA_REG_IDX(RIRBCTL) }, /* RIRB Control */
413 { 0x0005D, 0x00001, 0x00000005, 0x00000005, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteRIRBSTS , HDA_REG_IDX(RIRBSTS) }, /* RIRB Status */
414 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, HDA_RD_F_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(RIRBSIZE) }, /* RIRB Size */
415 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(IC) }, /* Immediate Command */
416 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(IR) }, /* Immediate Response */
417 { 0x00068, 0x00002, 0x00000002, 0x00000002, HDA_RD_F_NONE, hdaRegReadIRS , hdaRegWriteIRS , HDA_REG_IDX(IRS) }, /* Immediate Command Status */
418 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPLBASE) }, /* DMA Position Lower Base */
419 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_F_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPUBASE) }, /* DMA Position Upper Base */
420 /* 4 Serial Data In (SDI). */
421 HDA_REG_MAP_DEF_STREAM(0, SD0),
422 HDA_REG_MAP_DEF_STREAM(1, SD1),
423 HDA_REG_MAP_DEF_STREAM(2, SD2),
424 HDA_REG_MAP_DEF_STREAM(3, SD3),
425 /* 4 Serial Data Out (SDO). */
426 HDA_REG_MAP_DEF_STREAM(4, SD4),
427 HDA_REG_MAP_DEF_STREAM(5, SD5),
428 HDA_REG_MAP_DEF_STREAM(6, SD6),
429 HDA_REG_MAP_DEF_STREAM(7, SD7)
430};
431
432const HDAREGALIAS g_aHdaRegAliases[] =
433{
434 { 0x2084, HDA_REG_SD0LPIB },
435 { 0x20a4, HDA_REG_SD1LPIB },
436 { 0x20c4, HDA_REG_SD2LPIB },
437 { 0x20e4, HDA_REG_SD3LPIB },
438 { 0x2104, HDA_REG_SD4LPIB },
439 { 0x2124, HDA_REG_SD5LPIB },
440 { 0x2144, HDA_REG_SD6LPIB },
441 { 0x2164, HDA_REG_SD7LPIB }
442};
443
444#ifdef IN_RING3
445
446/** HDABDLEDESC field descriptors for the v7 saved state. */
447static SSMFIELD const g_aSSMBDLEDescFields7[] =
448{
449 SSMFIELD_ENTRY(HDABDLEDESC, u64BufAddr),
450 SSMFIELD_ENTRY(HDABDLEDESC, u32BufSize),
451 SSMFIELD_ENTRY(HDABDLEDESC, fFlags),
452 SSMFIELD_ENTRY_TERM()
453};
454
455/** HDABDLEDESC field descriptors for the v6 saved states. */
456static SSMFIELD const g_aSSMBDLEDescFields6[] =
457{
458 SSMFIELD_ENTRY(HDABDLEDESC, u64BufAddr),
459 SSMFIELD_ENTRY(HDABDLEDESC, u32BufSize),
460 SSMFIELD_ENTRY_CALLBACK(HDABDLEDESC, fFlags, hdaR3GetPutTrans_HDABDLEDESC_fFlags_6),
461 SSMFIELD_ENTRY_TERM()
462};
463
464/** HDABDLESTATE field descriptors for the v6+ saved state. */
465static SSMFIELD const g_aSSMBDLEStateFields6[] =
466{
467 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
468 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
469 SSMFIELD_ENTRY_OLD(FIFO, HDA_FIFO_MAX), /* Deprecated; now is handled in the stream's circular buffer. */
470 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
471 SSMFIELD_ENTRY_TERM()
472};
473
474/** HDABDLESTATE field descriptors for the v7 saved state. */
475static SSMFIELD const g_aSSMBDLEStateFields7[] =
476{
477 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
478 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
479 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
480 SSMFIELD_ENTRY_TERM()
481};
482
483/** HDASTREAMSTATE field descriptors for the v6 saved state. */
484static SSMFIELD const g_aSSMStreamStateFields6[] =
485{
486 SSMFIELD_ENTRY_OLD(cBDLE, sizeof(uint16_t)), /* Deprecated. */
487 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
488 SSMFIELD_ENTRY_OLD(fStop, 1), /* Deprecated; see SSMR3PutBool(). */
489 SSMFIELD_ENTRY_OLD(fRunning, 1), /* Deprecated; using the HDA_SDCTL_RUN bit is sufficient. */
490 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
491 SSMFIELD_ENTRY_TERM()
492};
493
494/** HDASTREAMSTATE field descriptors for the v7 saved state. */
495static SSMFIELD const g_aSSMStreamStateFields7[] =
496{
497 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
498 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
499 SSMFIELD_ENTRY(HDASTREAMSTATE, tsTransferNext),
500 SSMFIELD_ENTRY_TERM()
501};
502
503/** HDASTREAMPERIOD field descriptors for the v7 saved state. */
504static SSMFIELD const g_aSSMStreamPeriodFields7[] =
505{
506 SSMFIELD_ENTRY(HDASTREAMPERIOD, u64StartWalClk),
507 SSMFIELD_ENTRY(HDASTREAMPERIOD, u64ElapsedWalClk),
508 SSMFIELD_ENTRY(HDASTREAMPERIOD, cFramesTransferred),
509 SSMFIELD_ENTRY(HDASTREAMPERIOD, cIntPending),
510 SSMFIELD_ENTRY_TERM()
511};
512
513/** HDABDLE field descriptors for the v1 thru v4 saved states. */
514static SSMFIELD const g_aSSMStreamBdleFields1234[] =
515{
516 SSMFIELD_ENTRY(HDABDLE, Desc.u64BufAddr), /* u64BdleCviAddr */
517 SSMFIELD_ENTRY_OLD(u32BdleMaxCvi, sizeof(uint32_t)), /* u32BdleMaxCvi */
518 SSMFIELD_ENTRY(HDABDLE, State.u32BDLIndex), /* u32BdleCvi */
519 SSMFIELD_ENTRY(HDABDLE, Desc.u32BufSize), /* u32BdleCviLen */
520 SSMFIELD_ENTRY(HDABDLE, State.u32BufOff), /* u32BdleCviPos */
521 SSMFIELD_ENTRY_CALLBACK(HDABDLE, Desc.fFlags, hdaR3GetPutTrans_HDABDLE_Desc_fFlags_1thru4), /* fBdleCviIoc */
522 SSMFIELD_ENTRY(HDABDLE, State.cbBelowFIFOW), /* cbUnderFifoW */
523 SSMFIELD_ENTRY_OLD(au8FIFO, 256), /* au8FIFO */
524 SSMFIELD_ENTRY_TERM()
525};
526
527#endif /* IN_RING3 */
528
529/**
530 * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
531 */
532static uint32_t const g_afMasks[5] =
533{
534 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff)
535};
536
537
538#ifdef IN_RING3
539/**
540 * Reschedules pending interrupts for all audio streams which have complete
541 * audio periods but did not have the chance to issue their (pending) interrupts yet.
542 *
543 * @param pDevIns The device instance.
544 * @param pThis The shared HDA device state.
545 * @param pThisCC The ring-3 HDA device state.
546 */
547static void hdaR3ReschedulePendingInterrupts(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
548{
549 bool fInterrupt = false;
550
551 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
552 {
553 PHDASTREAM pStream = &pThis->aStreams[i];
554 if ( hdaR3StreamPeriodIsComplete( &pStream->State.Period)
555 && hdaR3StreamPeriodNeedsInterrupt(&pStream->State.Period)
556 && hdaR3WalClkSet(pThis, pThisCC, hdaR3StreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
557 {
558 fInterrupt = true;
559 break;
560 }
561 }
562
563 LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
564
565 HDA_PROCESS_INTERRUPT(pDevIns, pThis);
566}
567#endif /* IN_RING3 */
568
569/**
570 * Looks up a register at the exact offset given by @a offReg.
571 *
572 * @returns Register index on success, -1 if not found.
573 * @param offReg The register offset.
574 */
575static int hdaRegLookup(uint32_t offReg)
576{
577 /*
578 * Aliases.
579 */
580 if (offReg >= g_aHdaRegAliases[0].offReg)
581 {
582 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
583 if (offReg == g_aHdaRegAliases[i].offReg)
584 return g_aHdaRegAliases[i].idxAlias;
585 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
586 return -1;
587 }
588
589 /*
590 * Binary search the
591 */
592 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
593 int idxLow = 0;
594 for (;;)
595 {
596 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
597 if (offReg < g_aHdaRegMap[idxMiddle].offset)
598 {
599 if (idxLow == idxMiddle)
600 break;
601 idxEnd = idxMiddle;
602 }
603 else if (offReg > g_aHdaRegMap[idxMiddle].offset)
604 {
605 idxLow = idxMiddle + 1;
606 if (idxLow >= idxEnd)
607 break;
608 }
609 else
610 return idxMiddle;
611 }
612
613#ifdef RT_STRICT
614 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
615 Assert(g_aHdaRegMap[i].offset != offReg);
616#endif
617 return -1;
618}
619
620#ifdef IN_RING3
621
622/**
623 * Looks up a register covering the offset given by @a offReg.
624 *
625 * @returns Register index on success, -1 if not found.
626 * @param offReg The register offset.
627 */
628static int hdaR3RegLookupWithin(uint32_t offReg)
629{
630 /*
631 * Aliases.
632 */
633 if (offReg >= g_aHdaRegAliases[0].offReg)
634 {
635 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
636 {
637 uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
638 if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
639 return g_aHdaRegAliases[i].idxAlias;
640 }
641 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
642 return -1;
643 }
644
645 /*
646 * Binary search the register map.
647 */
648 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
649 int idxLow = 0;
650 for (;;)
651 {
652 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
653 if (offReg < g_aHdaRegMap[idxMiddle].offset)
654 {
655 if (idxLow == idxMiddle)
656 break;
657 idxEnd = idxMiddle;
658 }
659 else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
660 {
661 idxLow = idxMiddle + 1;
662 if (idxLow >= idxEnd)
663 break;
664 }
665 else
666 return idxMiddle;
667 }
668
669# ifdef RT_STRICT
670 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
671 Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
672# endif
673 return -1;
674}
675
676#endif /* IN_RING3 */
677
678/**
679 * Synchronizes the CORB / RIRB buffers between internal <-> device state.
680 *
681 * @returns IPRT status code.
682 *
683 * @param pDevIns The device instance.
684 * @param pThis The shared HDA device state.
685 * @param fLocal Specify true to synchronize HDA state's CORB buffer with the device state,
686 * or false to synchronize the device state's RIRB buffer with the HDA state.
687 *
688 * @todo r=andy Break this up into two functions?
689 */
690static int hdaCmdSync(PPDMDEVINS pDevIns, PHDASTATE pThis, bool fLocal)
691{
692 int rc = VINF_SUCCESS;
693 if (fLocal)
694 {
695 if (pThis->u64CORBBase)
696 {
697 Assert(pThis->cbCorbBuf);
698
699/** @todo r=bird: An explanation is required why PDMDevHlpPhysRead is used with
700 * the CORB and PDMDevHlpPCIPhysWrite with RIRB below. There are
701 * similar unexplained inconsistencies in DevHDACommon.cpp. */
702 rc = PDMDevHlpPhysRead(pDevIns, pThis->u64CORBBase, pThis->au32CorbBuf,
703 RT_MIN(pThis->cbCorbBuf, sizeof(pThis->au32CorbBuf)));
704 Log3Func(("CORB: read %RGp LB %#x (%Rrc)\n", pThis->u64CORBBase, pThis->cbCorbBuf, rc));
705 AssertRCReturn(rc, rc);
706 }
707 }
708 else
709 {
710 if (pThis->u64RIRBBase)
711 {
712 Assert(pThis->cbRirbBuf);
713
714 rc = PDMDevHlpPCIPhysWrite(pDevIns, pThis->u64RIRBBase, pThis->au64RirbBuf,
715 RT_MIN(pThis->cbRirbBuf, sizeof(pThis->au64RirbBuf)));
716 Log3Func(("RIRB: phys read %RGp LB %#x (%Rrc)\n", pThis->u64RIRBBase, pThis->cbRirbBuf, rc));
717 AssertRCReturn(rc, rc);
718 }
719 }
720
721# ifdef DEBUG_CMD_BUFFER
722 LogFunc(("fLocal=%RTbool\n", fLocal));
723
724 uint8_t i = 0;
725 do
726 {
727 LogFunc(("CORB%02x: ", i));
728 uint8_t j = 0;
729 do
730 {
731 const char *pszPrefix;
732 if ((i + j) == HDA_REG(pThis, CORBRP))
733 pszPrefix = "[R]";
734 else if ((i + j) == HDA_REG(pThis, CORBWP))
735 pszPrefix = "[W]";
736 else
737 pszPrefix = " "; /* three spaces */
738 Log((" %s%08x", pszPrefix, pThis->pu32CorbBuf[i + j]));
739 j++;
740 } while (j < 8);
741 Log(("\n"));
742 i += 8;
743 } while (i != 0);
744
745 do
746 {
747 LogFunc(("RIRB%02x: ", i));
748 uint8_t j = 0;
749 do
750 {
751 const char *prefix;
752 if ((i + j) == HDA_REG(pThis, RIRBWP))
753 prefix = "[W]";
754 else
755 prefix = " ";
756 Log((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
757 } while (++j < 8);
758 Log(("\n"));
759 i += 8;
760 } while (i != 0);
761# endif
762 return rc;
763}
764
765#ifdef IN_RING3
766
767/**
768 * Processes the next CORB buffer command in the queue (ring-3).
769 *
770 * Note: This function only will be called when the ring-0 version did not have an appropriate dispatcher.
771 *
772 * This will invoke the HDA codec ring-3 verb dispatcher.
773 *
774 * @returns VBox status code suitable for MMIO write return.
775 * @param pDevIns The device instance.
776 * @param pThis The shared HDA device state.
777 * @param pThisCC The ring-0 HDA device state.
778 */
779static int hdaR3CORBCmdProcess(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
780{
781 Log3Func(("ENTER CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
782
783 if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
784 {
785 LogFunc(("CORB DMA not active, skipping\n"));
786 return VINF_SUCCESS;
787 }
788
789 /* Note: Command buffer syncing was already done in R0. */
790
791 Assert(pThis->cbCorbBuf);
792
793 int rc;
794
795 /*
796 * Prepare local copies of relevant registers.
797 */
798 uint16_t cIntCnt = HDA_REG(pThis, RINTCNT) & 0xff;
799 if (!cIntCnt) /* 0 means 256 interrupts. */
800 cIntCnt = HDA_MAX_RINTCNT;
801
802 uint32_t const cCorbEntries = RT_MIN(RT_MAX(pThis->cbCorbBuf, 1), sizeof(pThis->au32CorbBuf)) / HDA_CORB_ELEMENT_SIZE;
803 uint8_t const corbWp = HDA_REG(pThis, CORBWP) % cCorbEntries;
804 uint8_t corbRp = HDA_REG(pThis, CORBRP);
805 uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
806
807 /*
808 * The loop.
809 */
810 Log3Func(("START CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
811 while (corbRp != corbWp)
812 {
813 /* Fetch the command from the CORB. */
814 corbRp = (corbRp + 1) /* Advance +1 as the first command(s) are at CORBWP + 1. */ % cCorbEntries;
815 uint32_t const uCmd = pThis->au32CorbBuf[corbRp];
816
817 /*
818 * Execute the command.
819 */
820 uint64_t uResp = 0;
821 rc = pThisCC->pCodec->pfnLookup(&pThis->Codec, pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
822 if (RT_FAILURE(rc)) /* Can return VERR_NOT_FOUND. */
823 Log3Func(("Lookup for codec verb %08x failed: %Rrc\n", uCmd, rc));
824
825 /* Note: No return here (as we're doing for the ring-0 version);
826 we still need to do the interrupt handling below. */
827
828 Log3Func(("Codec verb %08x -> response %016RX64\n", uCmd, uResp));
829
830 if ( (uResp & CODEC_RESPONSE_UNSOLICITED)
831 && !(HDA_REG(pThis, GCTL) & HDA_GCTL_UNSOL))
832 {
833 LogFunc(("Unexpected unsolicited response.\n"));
834 HDA_REG(pThis, CORBRP) = corbRp;
835 /** @todo r=andy No RIRB syncing to guest required in that case? */
836 /** @todo r=bird: Why isn't RIRBWP updated here. The response might come
837 * after already processing several commands, can't it? (When you think
838 * about it, it is bascially the same question as Andy is asking.) */
839 return VINF_SUCCESS;
840 }
841
842 /*
843 * Store the response in the RIRB.
844 */
845 AssertCompile(HDA_RIRB_SIZE == RT_ELEMENTS(pThis->au64RirbBuf));
846 rirbWp = (rirbWp + 1) % HDA_RIRB_SIZE;
847 pThis->au64RirbBuf[rirbWp] = uResp;
848
849 /*
850 * Send interrupt if needed.
851 */
852 bool fSendInterrupt = false;
853 pThis->u16RespIntCnt++;
854 if (pThis->u16RespIntCnt >= cIntCnt) /* Response interrupt count reached? */
855 {
856 pThis->u16RespIntCnt = 0; /* Reset internal interrupt response counter. */
857
858 Log3Func(("Response interrupt count reached (%RU16)\n", pThis->u16RespIntCnt));
859 fSendInterrupt = true;
860 }
861 else if (corbRp == corbWp) /* Did we reach the end of the current command buffer? */
862 {
863 Log3Func(("Command buffer empty\n"));
864 fSendInterrupt = true;
865 }
866 if (fSendInterrupt)
867 {
868 if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RINTCTL) /* Response Interrupt Control (RINTCTL) enabled? */
869 {
870 HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
871 HDA_PROCESS_INTERRUPT(pDevIns, pThis);
872 }
873 }
874 }
875
876 /*
877 * Put register locals back.
878 */
879 Log3Func(("END CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
880 HDA_REG(pThis, CORBRP) = corbRp;
881 HDA_REG(pThis, RIRBWP) = rirbWp;
882
883 /*
884 * Write out the response.
885 */
886 rc = hdaCmdSync(pDevIns, pThis, false /* Sync to guest */);
887 AssertRC(rc);
888
889 return rc;
890}
891
892#endif /* IN_RING3 */
893
894/**
895 * Processes the next CORB buffer command in the queue (ring-0).
896 *
897 * This will invoke the HDA codec verb dispatcher.
898 *
899 * @returns VBox status code suitable for MMIO write return.
900 * @param pDevIns The device instance.
901 * @param pThis The shared HDA device state.
902 * @param pThisCC The ring-0 HDA device state.
903 */
904static int hdaR0CORBCmdProcess(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER0 pThisCC)
905{
906 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
907
908 if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
909 {
910 LogFunc(("CORB DMA not active, skipping\n"));
911 return VINF_SUCCESS;
912 }
913
914 Assert(pThis->cbCorbBuf);
915
916 int rc = hdaCmdSync(pDevIns, pThis, true /* Sync from guest */);
917 AssertRCReturn(rc, rc);
918
919 /*
920 * Prepare local copies of relevant registers.
921 */
922 uint16_t cIntCnt = HDA_REG(pThis, RINTCNT) & 0xff;
923 if (!cIntCnt) /* 0 means 256 interrupts. */
924 cIntCnt = HDA_MAX_RINTCNT;
925
926 uint32_t const cCorbEntries = RT_MIN(RT_MAX(pThis->cbCorbBuf, 1), sizeof(pThis->au32CorbBuf)) / HDA_CORB_ELEMENT_SIZE;
927 uint8_t const corbWp = HDA_REG(pThis, CORBWP) % cCorbEntries;
928 uint8_t corbRp = HDA_REG(pThis, CORBRP);
929 uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
930
931 /*
932 * The loop.
933 */
934 Log3Func(("START CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
935 while (corbRp != corbWp)
936 {
937 /* Fetch the command from the CORB. */
938 corbRp = (corbRp + 1) /* Advance +1 as the first command(s) are at CORBWP + 1. */ % cCorbEntries;
939 uint32_t const uCmd = pThis->au32CorbBuf[corbRp];
940
941 /*
942 * Execute the command.
943 */
944 uint64_t uResp = 0;
945 rc = pThisCC->Codec.pfnLookup(&pThis->Codec, &pThisCC->Codec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
946 if (RT_FAILURE(rc)) /* Can return VERR_NOT_FOUND. */
947 {
948 Log3Func(("Lookup for codec verb %08x failed: %Rrc\n", uCmd, rc));
949 return rc;
950 }
951 Log3Func(("Codec verb %08x -> response %016RX64\n", uCmd, uResp));
952
953 if ( (uResp & CODEC_RESPONSE_UNSOLICITED)
954 && !(HDA_REG(pThis, GCTL) & HDA_GCTL_UNSOL))
955 {
956 LogFunc(("Unexpected unsolicited response.\n"));
957 HDA_REG(pThis, CORBRP) = corbRp;
958 /** @todo r=andy No RIRB syncing to guest required in that case? */
959 /** @todo r=bird: Why isn't RIRBWP updated here. The response might come
960 * after already processing several commands, can't it? (When you think
961 * about it, it is bascially the same question as Andy is asking.) */
962 return VINF_SUCCESS;
963 }
964
965 /*
966 * Store the response in the RIRB.
967 */
968 AssertCompile(HDA_RIRB_SIZE == RT_ELEMENTS(pThis->au64RirbBuf));
969 rirbWp = (rirbWp + 1) % HDA_RIRB_SIZE;
970 pThis->au64RirbBuf[rirbWp] = uResp;
971
972 /*
973 * Send interrupt if needed.
974 */
975 bool fSendInterrupt = false;
976 pThis->u16RespIntCnt++;
977 if (pThis->u16RespIntCnt >= cIntCnt) /* Response interrupt count reached? */
978 {
979 pThis->u16RespIntCnt = 0; /* Reset internal interrupt response counter. */
980
981 Log3Func(("Response interrupt count reached (%RU16)\n", pThis->u16RespIntCnt));
982 fSendInterrupt = true;
983 }
984 else if (corbRp == corbWp) /* Did we reach the end of the current command buffer? */
985 {
986 Log3Func(("Command buffer empty\n"));
987 fSendInterrupt = true;
988 }
989 if (fSendInterrupt)
990 {
991 if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RINTCTL) /* Response Interrupt Control (RINTCTL) enabled? */
992 {
993 HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
994 HDA_PROCESS_INTERRUPT(pDevIns, pThis);
995 }
996 }
997 }
998
999 /*
1000 * Put register locals back.
1001 */
1002 Log3Func(("END CORB(RP:%x, WP:%x) RIRBWP:%x, RINTCNT:%RU8/%RU8\n", corbRp, corbWp, rirbWp, pThis->u16RespIntCnt, cIntCnt));
1003 HDA_REG(pThis, CORBRP) = corbRp;
1004 HDA_REG(pThis, RIRBWP) = rirbWp;
1005
1006 /*
1007 * Write out the response.
1008 */
1009 rc = hdaCmdSync(pDevIns, pThis, false /* Sync to guest */);
1010 AssertRC(rc);
1011
1012 return rc;
1013}
1014
1015/* Register access handlers. */
1016
1017static VBOXSTRICTRC hdaRegReadUnimpl(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1018{
1019 RT_NOREF(pDevIns, pThis, iReg);
1020 *pu32Value = 0;
1021 return VINF_SUCCESS;
1022}
1023
1024static VBOXSTRICTRC hdaRegWriteUnimpl(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1025{
1026 RT_NOREF(pDevIns, pThis, iReg, u32Value);
1027 return VINF_SUCCESS;
1028}
1029
1030/* U8 */
1031static VBOXSTRICTRC hdaRegReadU8(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1032{
1033 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
1034 return hdaRegReadU32(pDevIns, pThis, iReg, pu32Value);
1035}
1036
1037static VBOXSTRICTRC hdaRegWriteU8(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1038{
1039 Assert((u32Value & 0xffffff00) == 0);
1040 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
1041}
1042
1043/* U16 */
1044static VBOXSTRICTRC hdaRegReadU16(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1045{
1046 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
1047 return hdaRegReadU32(pDevIns, pThis, iReg, pu32Value);
1048}
1049
1050static VBOXSTRICTRC hdaRegWriteU16(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1051{
1052 Assert((u32Value & 0xffff0000) == 0);
1053 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
1054}
1055
1056/* U24 */
1057static VBOXSTRICTRC hdaRegReadU24(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1058{
1059 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
1060 return hdaRegReadU32(pDevIns, pThis, iReg, pu32Value);
1061}
1062
1063#ifdef IN_RING3
1064static VBOXSTRICTRC hdaRegWriteU24(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1065{
1066 Assert((u32Value & 0xff000000) == 0);
1067 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
1068}
1069#endif
1070
1071/* U32 */
1072static VBOXSTRICTRC hdaRegReadU32(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1073{
1074 RT_NOREF(pDevIns);
1075
1076 uint32_t const iRegMem = g_aHdaRegMap[iReg].mem_idx;
1077 *pu32Value = pThis->au32Regs[iRegMem] & g_aHdaRegMap[iReg].readable;
1078 return VINF_SUCCESS;
1079}
1080
1081static VBOXSTRICTRC hdaRegWriteU32(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1082{
1083 RT_NOREF(pDevIns);
1084
1085 uint32_t const iRegMem = g_aHdaRegMap[iReg].mem_idx;
1086 pThis->au32Regs[iRegMem] = (u32Value & g_aHdaRegMap[iReg].writable)
1087 | (pThis->au32Regs[iRegMem] & ~g_aHdaRegMap[iReg].writable);
1088 return VINF_SUCCESS;
1089}
1090
1091static VBOXSTRICTRC hdaRegWriteGCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1092{
1093 RT_NOREF(pDevIns, iReg);
1094
1095 if (u32Value & HDA_GCTL_CRST)
1096 {
1097 /* Set the CRST bit to indicate that we're leaving reset mode. */
1098 HDA_REG(pThis, GCTL) |= HDA_GCTL_CRST;
1099 LogFunc(("Guest leaving HDA reset\n"));
1100 }
1101 else
1102 {
1103#ifdef IN_RING3
1104 /* Enter reset state. */
1105 LogFunc(("Guest entering HDA reset with DMA(RIRB:%s, CORB:%s)\n",
1106 HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA ? "on" : "off",
1107 HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RDMAEN ? "on" : "off"));
1108
1109 /* Clear the CRST bit to indicate that we're in reset state. */
1110 HDA_REG(pThis, GCTL) &= ~HDA_GCTL_CRST;
1111
1112 hdaR3GCTLReset(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
1113#else
1114 return VINF_IOM_R3_MMIO_WRITE;
1115#endif
1116 }
1117
1118 if (u32Value & HDA_GCTL_FCNTRL)
1119 {
1120 /* Flush: GSTS:1 set, see 6.2.6. */
1121 HDA_REG(pThis, GSTS) |= HDA_GSTS_FSTS; /* Set the flush status. */
1122 /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6). */
1123 }
1124
1125 return VINF_SUCCESS;
1126}
1127
1128static VBOXSTRICTRC hdaRegWriteSTATESTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1129{
1130 RT_NOREF(pDevIns);
1131
1132 uint32_t v = HDA_REG_IND(pThis, iReg);
1133 uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK;
1134
1135 HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
1136
1137 return VINF_SUCCESS;
1138}
1139
1140static VBOXSTRICTRC hdaRegReadLPIB(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1141{
1142 RT_NOREF(pDevIns);
1143
1144 const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
1145 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, uSD);
1146 *pu32Value = u32LPIB;
1147 LogFlowFunc(("[SD%RU8] LPIB=%RU32, CBL=%RU32\n", uSD, u32LPIB, HDA_STREAM_REG(pThis, CBL, uSD)));
1148
1149 return VINF_SUCCESS;
1150}
1151
1152#ifdef IN_RING3
1153/**
1154 * Returns the current maximum value the wall clock counter can be set to.
1155 *
1156 * This maximum value depends on all currently handled HDA streams and their own current timing.
1157 *
1158 * @return Current maximum value the wall clock counter can be set to.
1159 * @param pThis The shared HDA device state.
1160 * @param pThisCC The ring-3 HDA device state.
1161 *
1162 * @remark Does not actually set the wall clock counter.
1163 *
1164 * @todo r=bird: This function is in the wrong file.
1165 */
1166static uint64_t hdaR3WalClkGetMax(PHDASTATE pThis, PHDASTATER3 pThisCC)
1167{
1168 const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
1169 const uint64_t u64FrontAbsWalClk = pThisCC->SinkFront.pStreamShared
1170 ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkFront.pStreamShared->State.Period) : 0;
1171# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
1172# error "Implement me!"
1173# endif
1174 const uint64_t u64LineInAbsWalClk = pThisCC->SinkLineIn.pStreamShared
1175 ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkLineIn.pStreamShared->State.Period) : 0;
1176# ifdef VBOX_WITH_HDA_MIC_IN
1177 const uint64_t u64MicInAbsWalClk = pThisCC->SinkMicIn.pStreamShared
1178 ? hdaR3StreamPeriodGetAbsElapsedWalClk(&pThisCC->SinkMicIn.pStreamShared->State.Period) : 0;
1179# endif
1180
1181 uint64_t u64WalClkNew = RT_MAX(u64WalClkCur, u64FrontAbsWalClk);
1182# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
1183# error "Implement me!"
1184# endif
1185 u64WalClkNew = RT_MAX(u64WalClkNew, u64LineInAbsWalClk);
1186# ifdef VBOX_WITH_HDA_MIC_IN
1187 u64WalClkNew = RT_MAX(u64WalClkNew, u64MicInAbsWalClk);
1188# endif
1189
1190 Log3Func(("%RU64 -> Front=%RU64, LineIn=%RU64 -> %RU64\n",
1191 u64WalClkCur, u64FrontAbsWalClk, u64LineInAbsWalClk, u64WalClkNew));
1192
1193 return u64WalClkNew;
1194}
1195#endif /* IN_RING3 */
1196
1197static VBOXSTRICTRC hdaRegReadWALCLK(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1198{
1199 RT_NOREF(pDevIns, iReg);
1200
1201 const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
1202 *pu32Value = RT_LO_U32(u64WalClkCur);
1203
1204 return VINF_SUCCESS;
1205}
1206
1207static VBOXSTRICTRC hdaRegWriteCORBRP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1208{
1209 RT_NOREF(pDevIns, iReg);
1210 if (u32Value & HDA_CORBRP_RST)
1211 {
1212 /* Do a CORB reset. */
1213 if (pThis->cbCorbBuf)
1214 RT_ZERO(pThis->au32CorbBuf);
1215
1216 LogRel2(("HDA: CORB reset\n"));
1217 HDA_REG(pThis, CORBRP) = HDA_CORBRP_RST; /* Clears the pointer. */
1218 }
1219 else
1220 HDA_REG(pThis, CORBRP) &= ~HDA_CORBRP_RST; /* Only CORBRP_RST bit is writable. */
1221
1222 return VINF_SUCCESS;
1223}
1224
1225static VBOXSTRICTRC hdaRegWriteCORBCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1226{
1227 VBOXSTRICTRC rc = hdaRegWriteU8(pDevIns, pThis, iReg, u32Value);
1228 AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
1229
1230 if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* DMA engine started? */
1231 {
1232#ifdef IN_RING3
1233 /* ignore rc */ hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
1234
1235#else
1236 if (hdaR0CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0)) == VERR_NOT_FOUND)
1237 return VINF_IOM_R3_MMIO_WRITE; /* Try ring-3. */
1238#endif
1239 }
1240 else
1241 LogFunc(("CORB DMA not running, skipping\n"));
1242
1243 return VINF_SUCCESS;
1244}
1245
1246static VBOXSTRICTRC hdaRegWriteCORBSIZE(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1247{
1248 RT_NOREF(pDevIns, iReg);
1249
1250 if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA)) /* Ignore request if CORB DMA engine is (still) running. */
1251 {
1252 u32Value = (u32Value & HDA_CORBSIZE_SZ);
1253
1254 uint16_t cEntries;
1255 switch (u32Value)
1256 {
1257 case 0: /* 8 byte; 2 entries. */
1258 cEntries = 2;
1259 break;
1260 case 1: /* 64 byte; 16 entries. */
1261 cEntries = 16;
1262 break;
1263 case 2: /* 1 KB; 256 entries. */
1264 cEntries = HDA_CORB_SIZE; /* default. */
1265 break;
1266 default:
1267 LogRel(("HDA: Guest tried to set an invalid CORB size (0x%x), keeping default\n", u32Value));
1268 u32Value = 2;
1269 cEntries = HDA_CORB_SIZE; /* Use default size. */
1270 break;
1271 }
1272
1273 uint32_t cbCorbBuf = cEntries * HDA_CORB_ELEMENT_SIZE;
1274 Assert(cbCorbBuf <= sizeof(pThis->au32CorbBuf)); /* paranoia */
1275
1276 if (cbCorbBuf != pThis->cbCorbBuf)
1277 {
1278 RT_ZERO(pThis->au32CorbBuf); /* Clear CORB when setting a new size. */
1279 pThis->cbCorbBuf = cbCorbBuf;
1280 }
1281
1282 LogFunc(("CORB buffer size is now %RU32 bytes (%u entries)\n", pThis->cbCorbBuf, pThis->cbCorbBuf / HDA_CORB_ELEMENT_SIZE));
1283
1284 HDA_REG(pThis, CORBSIZE) = u32Value;
1285 }
1286 else
1287 LogFunc(("CORB DMA is (still) running, skipping\n"));
1288 return VINF_SUCCESS;
1289}
1290
1291static VBOXSTRICTRC hdaRegWriteCORBSTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1292{
1293 RT_NOREF(pDevIns, iReg);
1294
1295 uint32_t v = HDA_REG(pThis, CORBSTS);
1296 HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
1297
1298 return VINF_SUCCESS;
1299}
1300
1301static VBOXSTRICTRC hdaRegWriteCORBWP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1302{
1303 VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
1304 AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
1305
1306#ifdef IN_RING3
1307 rc = hdaR3CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
1308 if (rc == VERR_NOT_FOUND)
1309 rc = VINF_SUCCESS;
1310#else
1311 rc = hdaR0CORBCmdProcess(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0));
1312 if (rc == VERR_NOT_FOUND) /* Try ring-3. */
1313 rc = VINF_IOM_R3_MMIO_WRITE;
1314#endif
1315
1316 return rc;
1317}
1318
1319static VBOXSTRICTRC hdaRegWriteSDCBL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1320{
1321 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
1322}
1323
1324static VBOXSTRICTRC hdaRegWriteSDCTL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1325{
1326#ifdef IN_RING3
1327 /* Get the stream descriptor number. */
1328 const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
1329 AssertReturn(uSD < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
1330
1331 /*
1332 * Extract the stream tag the guest wants to use for this specific
1333 * stream descriptor (SDn). This only can happen if the stream is in a non-running
1334 * state, so we're doing the lookup and assignment here.
1335 *
1336 * So depending on the guest OS, SD3 can use stream tag 4, for example.
1337 */
1338 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
1339 uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
1340 ASSERT_GUEST_MSG_RETURN(uTag < RT_ELEMENTS(pThisCC->aTags),
1341 ("SD%RU8: Invalid stream tag %RU8 (u32Value=%#x)!\n", uSD, uTag, u32Value),
1342 VINF_SUCCESS /* Always return success to the MMIO handler. */);
1343
1344 PHDASTREAM const pStreamShared = &pThis->aStreams[uSD];
1345 PHDASTREAMR3 const pStreamR3 = &pThisCC->aStreams[uSD];
1346
1347 const bool fRun = RT_BOOL(u32Value & HDA_SDCTL_RUN);
1348 const bool fReset = RT_BOOL(u32Value & HDA_SDCTL_SRST);
1349
1350 /* If the run bit is set, we take the virtual-sync clock lock as well so we
1351 can safely update timers via hdaR3TimerSet if necessary. We need to be
1352 very careful with the fInReset and fInRun indicators here, as they may
1353 change during the relocking if we need to acquire the clock lock. */
1354 const bool fNeedVirtualSyncClockLock = (u32Value & (HDA_SDCTL_RUN | HDA_SDCTL_SRST)) == HDA_SDCTL_RUN
1355 && (HDA_REG_IND(pThis, iReg) & HDA_SDCTL_RUN) == 0;
1356 if (fNeedVirtualSyncClockLock)
1357 {
1358 DEVHDA_UNLOCK(pDevIns, pThis);
1359 DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStreamShared, VINF_IOM_R3_MMIO_WRITE);
1360 }
1361
1362 const bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_RUN);
1363 const bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
1364
1365 /*LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
1366 uSD, fRun, fInRun, fReset, fInReset, u32Value));*/
1367 if (fInReset)
1368 {
1369 Assert(!fReset);
1370 Assert(!fInRun && !fRun);
1371
1372 /* Exit reset state. */
1373 ASMAtomicXchgBool(&pStreamShared->State.fInReset, false);
1374
1375 /* Report that we're done resetting this stream by clearing SRST. */
1376 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_SRST;
1377
1378 LogFunc(("[SD%RU8] Reset exit\n", uSD));
1379 }
1380 else if (fReset)
1381 {
1382 /* ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset. */
1383 Assert(!fInRun && !fRun);
1384
1385 LogFunc(("[SD%RU8] Reset enter\n", uSD));
1386
1387 hdaR3StreamLock(pStreamR3);
1388
1389# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1390 hdaR3StreamAsyncIOLock(pStreamR3);
1391# endif
1392 /* Make sure to remove the run bit before doing the actual stream reset. */
1393 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
1394
1395 hdaR3StreamReset(pThis, pThisCC, pStreamShared, pStreamR3, uSD);
1396
1397# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1398 hdaR3StreamAsyncIOUnlock(pStreamR3);
1399# endif
1400 hdaR3StreamUnlock(pStreamR3);
1401 }
1402 else
1403 {
1404 /*
1405 * We enter here to change DMA states only.
1406 */
1407 if (fInRun != fRun)
1408 {
1409 Assert(!fReset && !fInReset);
1410 LogFunc(("[SD%RU8] State changed (fRun=%RTbool)\n", uSD, fRun));
1411
1412 hdaR3StreamLock(pStreamR3);
1413
1414 int rc2 = VINF_SUCCESS;
1415
1416# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1417 if (fRun)
1418 rc2 = hdaR3StreamAsyncIOCreate(pStreamR3);
1419
1420 hdaR3StreamAsyncIOLock(pStreamR3);
1421# endif
1422 if (fRun)
1423 {
1424 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
1425 {
1426 const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1;
1427 LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl));
1428 if (uStripeCtl > 1)
1429 LogRel2(("HDA: Warning: Striping output over more than one SDO for stream #%RU8 currently is not implemented " \
1430 "(%RU8 SDOs requested)\n", uSD, uStripeCtl));
1431 }
1432
1433 /* Assign new values. */
1434 LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
1435 PHDATAG pTag = &pThisCC->aTags[uTag];
1436 pTag->uTag = uTag;
1437 pTag->pStreamR3 = &pThisCC->aStreams[uSD];
1438
1439# ifdef LOG_ENABLED
1440 PDMAUDIOPCMPROPS Props;
1441 rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &Props);
1442 AssertRC(rc2);
1443 LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
1444 uSD, Props.uHz, Props.cbSample * 8 /* Bit */, Props.cChannels));
1445# endif
1446 /* (Re-)initialize the stream with current values. */
1447 rc2 = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, uSD);
1448 if ( RT_SUCCESS(rc2)
1449 /* Any vital stream change occurred so that we need to (re-)add the stream to our setup?
1450 * Otherwise just skip this, as this costs a lot of performance. */
1451 && rc2 != VINF_NO_CHANGE)
1452 {
1453 /* Remove the old stream from the device setup. */
1454 rc2 = hdaR3RemoveStream(pThisCC, &pStreamShared->State.Cfg);
1455 AssertRC(rc2);
1456
1457 /* Add the stream to the device setup. */
1458 rc2 = hdaR3AddStream(pThisCC, &pStreamShared->State.Cfg);
1459 AssertRC(rc2);
1460 }
1461 }
1462
1463 if (RT_SUCCESS(rc2))
1464 {
1465 /* Enable/disable the stream. */
1466 rc2 = hdaR3StreamEnable(pStreamShared, pStreamR3, fRun /* fEnable */);
1467 AssertRC(rc2);
1468
1469 if (fRun)
1470 {
1471 /* Keep track of running streams. */
1472 pThisCC->cStreamsActive++;
1473
1474 /* (Re-)init the stream's period. */
1475 hdaR3StreamPeriodInit(&pStreamShared->State.Period, uSD, pStreamShared->u16LVI,
1476 pStreamShared->u32CBL, &pStreamShared->State.Cfg);
1477
1478 /* Begin a new period for this stream. */
1479 rc2 = hdaR3StreamPeriodBegin(&pStreamShared->State.Period,
1480 hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
1481 AssertRC(rc2);
1482
1483 uint64_t const tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
1484 rc2 = hdaR3TimerSet(pDevIns, pStreamShared, tsNow + pStreamShared->State.cTransferTicks, true /* fForce */, tsNow);
1485 AssertRC(rc2);
1486 }
1487 else
1488 {
1489 /* Keep track of running streams. */
1490 Assert(pThisCC->cStreamsActive);
1491 if (pThisCC->cStreamsActive)
1492 pThisCC->cStreamsActive--;
1493
1494 /* Make sure to (re-)schedule outstanding (delayed) interrupts. */
1495 hdaR3ReschedulePendingInterrupts(pDevIns, pThis, pThisCC);
1496
1497 /* Reset the period. */
1498 hdaR3StreamPeriodReset(&pStreamShared->State.Period);
1499 }
1500 }
1501
1502# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1503 hdaR3StreamAsyncIOUnlock(pStreamR3);
1504# endif
1505 /* Make sure to leave the lock before (eventually) starting the timer. */
1506 hdaR3StreamUnlock(pStreamR3);
1507 }
1508 }
1509
1510 if (fNeedVirtualSyncClockLock)
1511 PDMDevHlpTimerUnlockClock(pDevIns, pStreamShared->hTimer); /* Caller will unlock pThis->CritSect. */
1512
1513 return hdaRegWriteU24(pDevIns, pThis, iReg, u32Value);
1514#else /* !IN_RING3 */
1515 RT_NOREF(pDevIns, pThis, iReg, u32Value);
1516 return VINF_IOM_R3_MMIO_WRITE;
1517#endif /* !IN_RING3 */
1518}
1519
1520static VBOXSTRICTRC hdaRegWriteSDSTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1521{
1522#ifdef IN_RING3
1523 const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, STS, iReg);
1524 AssertReturn(uSD < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
1525 PHDASTATER3 const pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
1526 PHDASTREAMR3 const pStreamR3 = &pThisCC->aStreams[uSD];
1527 PHDASTREAM const pStreamShared = &pThis->aStreams[uSD];
1528
1529 /* We only need to take the virtual-sync lock if we want to call
1530 PDMDevHlpTimerGet or hdaR3TimerSet later. Only precondition for that
1531 is that we've got a non-zero ticks-per-transfer value. */
1532 uint64_t const cTransferTicks = pStreamShared->State.cTransferTicks;
1533 if (cTransferTicks)
1534 {
1535 DEVHDA_UNLOCK(pDevIns, pThis);
1536 DEVHDA_LOCK_BOTH_RETURN(pDevIns, pThis, pStreamShared, VINF_IOM_R3_MMIO_WRITE);
1537 }
1538
1539 hdaR3StreamLock(pStreamR3);
1540
1541 uint32_t v = HDA_REG_IND(pThis, iReg);
1542
1543 /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */
1544 HDA_REG_IND(pThis, iReg) &= ~(u32Value & v);
1545
1546/** @todo r=bird: Check if we couldn't this stuff involving hdaR3StreamPeriodLock
1547 * and IRQs after PDMDevHlpTimerUnlockClock. */
1548
1549 /*
1550 * ...
1551 */
1552 /* Some guests tend to write SDnSTS even if the stream is not running.
1553 * So make sure to check if the RUN bit is set first. */
1554 const bool fRunning = pStreamShared->State.fRunning;
1555
1556 Log3Func(("[SD%RU8] fRunning=%RTbool %R[sdsts]\n", uSD, fRunning, v));
1557
1558 PHDASTREAMPERIOD pPeriod = &pStreamShared->State.Period;
1559 hdaR3StreamPeriodLock(pPeriod);
1560 if (hdaR3StreamPeriodNeedsInterrupt(pPeriod))
1561 hdaR3StreamPeriodReleaseInterrupt(pPeriod);
1562 if (hdaR3StreamPeriodIsComplete(pPeriod))
1563 {
1564 /* Make sure to try to update the WALCLK register if a period is complete.
1565 * Use the maximum WALCLK value all (active) streams agree to. */
1566 const uint64_t uWalClkMax = hdaR3WalClkGetMax(pThis, PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3));
1567 if (uWalClkMax > hdaWalClkGetCurrent(pThis))
1568 hdaR3WalClkSet(pThis, pThisCC, uWalClkMax, false /* fForce */);
1569
1570 hdaR3StreamPeriodEnd(pPeriod);
1571
1572 if (fRunning)
1573 hdaR3StreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
1574 }
1575 hdaR3StreamPeriodUnlock(pPeriod); /* Unlock before processing interrupt. */
1576
1577 HDA_PROCESS_INTERRUPT(pDevIns, pThis);
1578
1579 /*
1580 * ...
1581 */
1582 uint64_t cTicksToNext = pStreamShared->State.cTransferTicks;
1583 if (cTicksToNext) /* Only do any calculations if the stream currently is set up for transfers. */
1584 {
1585 const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer);
1586 Assert(tsNow >= pStreamShared->State.tsTransferLast);
1587
1588 const uint64_t cTicksElapsed = tsNow - pStreamShared->State.tsTransferLast;
1589
1590 Log3Func(("[SD%RU8] cTicksElapsed=%RU64, cTicksToNext=%RU64\n",
1591 uSD, cTicksElapsed, cTicksToNext));
1592
1593 if (cTicksElapsed <= cTicksToNext)
1594 cTicksToNext = cTicksToNext - cTicksElapsed;
1595 else /* Catch up. */
1596 {
1597 Log3Func(("[SD%RU8] Warning: Lagging behind (%RU64 ticks elapsed, maximum allowed is %RU64)\n",
1598 uSD, cTicksElapsed, cTicksToNext));
1599
1600 LogRelMax2(128, ("HDA: Stream #%RU8 interrupt lagging behind (expected %RU64us, got %RU64us, %RU8 pending interrupts), trying to catch up ...\n",
1601 uSD, cTicksToNext / 1000, cTicksElapsed / 1000, pStreamShared->State.cTransferPendingInterrupts));
1602
1603 cTicksToNext = pStreamShared->State.cbTransferSize * pStreamShared->State.cTicksPerByte;
1604 }
1605
1606 Log3Func(("[SD%RU8] -> cTicksToNext=%RU64\n", uSD, cTicksToNext));
1607
1608 /* Reset processed data counter. */
1609 pStreamShared->State.tsTransferNext = tsNow + cTicksToNext;
1610
1611 /* Only re-arm the timer if there were pending transfer interrupts left
1612 * -- it could happen that we land in here if a guest writes to SDnSTS
1613 * unconditionally. */
1614 if (pStreamShared->State.cTransferPendingInterrupts)
1615 {
1616 pStreamShared->State.cTransferPendingInterrupts--;
1617
1618 /* Re-arm the timer. */
1619 LogFunc(("[SD%RU8] Timer set\n", uSD));
1620 hdaR3TimerSet(pDevIns, pStreamShared, tsNow + cTicksToNext,
1621 true /* fForce - we just set tsTransferNext*/, 0 /*tsNow*/);
1622 }
1623 }
1624
1625 if (cTransferTicks)
1626 PDMDevHlpTimerUnlockClock(pDevIns, pStreamShared->hTimer); /* Caller will unlock pThis->CritSect. */
1627 hdaR3StreamUnlock(pStreamR3);
1628 return VINF_SUCCESS;
1629#else /* !IN_RING3 */
1630 RT_NOREF(pDevIns, pThis, iReg, u32Value);
1631 return VINF_IOM_R3_MMIO_WRITE;
1632#endif /* !IN_RING3 */
1633}
1634
1635static VBOXSTRICTRC hdaRegWriteSDLVI(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1636{
1637 const size_t idxStream = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
1638 AssertReturn(idxStream < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
1639
1640#ifdef HDA_USE_DMA_ACCESS_HANDLER
1641 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
1642 {
1643 /* Try registering the DMA handlers.
1644 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
1645 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, idxStream);
1646 if ( pStream
1647 && hdaR3StreamRegisterDMAHandlers(pThis, pStream))
1648 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
1649 }
1650#endif
1651
1652 ASSERT_GUEST_LOGREL_MSG(u32Value <= UINT8_MAX, /* Should be covered by the register write mask, but just to make sure. */
1653 ("LVI for stream #%zu must not be bigger than %RU8\n", idxStream, UINT8_MAX - 1));
1654 return hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
1655}
1656
1657static VBOXSTRICTRC hdaRegWriteSDFIFOW(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1658{
1659 size_t const idxStream = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
1660 AssertReturn(idxStream < RT_ELEMENTS(pThis->aStreams), VERR_INTERNAL_ERROR_3); /* paranoia^2: Bad g_aHdaRegMap. */
1661
1662 if (RT_LIKELY(hdaGetDirFromSD((uint8_t)idxStream) == PDMAUDIODIR_IN)) /* FIFOW for input streams only. */
1663 { /* likely */ }
1664 else
1665 {
1666#ifndef IN_RING0
1667 LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", idxStream));
1668 return VINF_SUCCESS;
1669#else
1670 return VINF_IOM_R3_MMIO_WRITE; /* (Go to ring-3 for release logging.) */
1671#endif
1672 }
1673
1674 uint16_t u16FIFOW = 0;
1675 switch (u32Value)
1676 {
1677 case HDA_SDFIFOW_8B:
1678 case HDA_SDFIFOW_16B:
1679 case HDA_SDFIFOW_32B:
1680 u16FIFOW = RT_LO_U16(u32Value); /* Only bits 2:0 are used; see ICH-6, 18.2.38. */
1681 break;
1682 default:
1683 ASSERT_GUEST_LOGREL_MSG_FAILED(("Guest tried writing unsupported FIFOW (0x%zx) to stream #%RU8, defaulting to 32 bytes\n",
1684 u32Value, idxStream));
1685 u16FIFOW = HDA_SDFIFOW_32B;
1686 break;
1687 }
1688
1689 pThis->aStreams[idxStream].u8FIFOW = hdaSDFIFOWToBytes(u16FIFOW);
1690 LogFunc(("[SD%zu] Updating FIFOW to %RU8 bytes\n", idxStream, pThis->aStreams[idxStream].u8FIFOW));
1691 return hdaRegWriteU16(pDevIns, pThis, iReg, u16FIFOW);
1692}
1693
1694/**
1695 * @note This method could be called for changing value on Output Streams only (ICH6 datasheet 18.2.39).
1696 */
1697static VBOXSTRICTRC hdaRegWriteSDFIFOS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1698{
1699 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
1700
1701 ASSERT_GUEST_LOGREL_MSG_RETURN(hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT, /* FIFOS for output streams only. */
1702 ("Guest tried writing read-only FIFOS to input stream #%RU8, ignoring\n", uSD),
1703 VINF_SUCCESS);
1704
1705 uint32_t u32FIFOS;
1706 switch (u32Value)
1707 {
1708 case HDA_SDOFIFO_16B:
1709 case HDA_SDOFIFO_32B:
1710 case HDA_SDOFIFO_64B:
1711 case HDA_SDOFIFO_128B:
1712 case HDA_SDOFIFO_192B:
1713 case HDA_SDOFIFO_256B:
1714 u32FIFOS = u32Value;
1715 break;
1716
1717 default:
1718 ASSERT_GUEST_LOGREL_MSG_FAILED(("Guest tried writing unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
1719 u32Value, uSD));
1720 u32FIFOS = HDA_SDOFIFO_192B;
1721 break;
1722 }
1723
1724 return hdaRegWriteU16(pDevIns, pThis, iReg, u32FIFOS);
1725}
1726
1727#ifdef IN_RING3
1728
1729/**
1730 * Adds an audio output stream to the device setup using the given configuration.
1731 *
1732 * @returns IPRT status code.
1733 * @param pThisCC The ring-3 HDA device state.
1734 * @param pCfg Stream configuration to use for adding a stream.
1735 */
1736static int hdaR3AddStreamOut(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
1737{
1738 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
1739
1740 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
1741
1742 LogFlowFunc(("Stream=%s\n", pCfg->szName));
1743
1744 int rc = VINF_SUCCESS;
1745
1746 bool fUseFront = true; /* Always use front out by default. */
1747# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
1748 bool fUseRear;
1749 bool fUseCenter;
1750 bool fUseLFE;
1751
1752 fUseRear = fUseCenter = fUseLFE = false;
1753
1754 /*
1755 * Use commonly used setups for speaker configurations.
1756 */
1757
1758 /** @todo Make the following configurable through mixer API and/or CFGM? */
1759 switch (pCfg->Props.cChannels)
1760 {
1761 case 3: /* 2.1: Front (Stereo) + LFE. */
1762 {
1763 fUseLFE = true;
1764 break;
1765 }
1766
1767 case 4: /* Quadrophonic: Front (Stereo) + Rear (Stereo). */
1768 {
1769 fUseRear = true;
1770 break;
1771 }
1772
1773 case 5: /* 4.1: Front (Stereo) + Rear (Stereo) + LFE. */
1774 {
1775 fUseRear = true;
1776 fUseLFE = true;
1777 break;
1778 }
1779
1780 case 6: /* 5.1: Front (Stereo) + Rear (Stereo) + Center/LFE. */
1781 {
1782 fUseRear = true;
1783 fUseCenter = true;
1784 fUseLFE = true;
1785 break;
1786 }
1787
1788 default: /* Unknown; fall back to 2 front channels (stereo). */
1789 {
1790 rc = VERR_NOT_SUPPORTED;
1791 break;
1792 }
1793 }
1794# endif /* !VBOX_WITH_AUDIO_HDA_51_SURROUND */
1795
1796 if (rc == VERR_NOT_SUPPORTED)
1797 {
1798 LogRel2(("HDA: Warning: Unsupported channel count (%RU8), falling back to stereo channels (2)\n", pCfg->Props.cChannels));
1799
1800 /* Fall back to 2 channels (see below in fUseFront block). */
1801 rc = VINF_SUCCESS;
1802 }
1803
1804 do
1805 {
1806 if (RT_FAILURE(rc))
1807 break;
1808
1809 if (fUseFront)
1810 {
1811 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Front");
1812
1813 pCfg->u.enmDst = PDMAUDIOPLAYBACKDST_FRONT;
1814 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
1815
1816 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
1817
1818 rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
1819 }
1820
1821# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
1822 if ( RT_SUCCESS(rc)
1823 && (fUseCenter || fUseLFE))
1824 {
1825 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Center/LFE");
1826
1827 pCfg->u.enmDst = PDMAUDIOPLAYBACKDST_CENTER_LFE;
1828 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
1829
1830 pCfg->Props.cChannels = (fUseCenter && fUseLFE) ? 2 : 1;
1831 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
1832
1833 rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
1834 }
1835
1836 if ( RT_SUCCESS(rc)
1837 && fUseRear)
1838 {
1839 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Rear");
1840
1841 pCfg->u.enmDst = PDMAUDIOPLAYBACKDST_REAR;
1842 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
1843
1844 pCfg->Props.cChannels = 2;
1845 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cbSample, pCfg->Props.cChannels);
1846
1847 rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
1848 }
1849# endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
1850
1851 } while (0);
1852
1853 LogFlowFuncLeaveRC(rc);
1854 return rc;
1855}
1856
1857/**
1858 * Adds an audio input stream to the device setup using the given configuration.
1859 *
1860 * @returns IPRT status code.
1861 * @param pThisCC The ring-3 HDA device state.
1862 * @param pCfg Stream configuration to use for adding a stream.
1863 */
1864static int hdaR3AddStreamIn(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
1865{
1866 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
1867
1868 AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER);
1869
1870 LogFlowFunc(("Stream=%s, Source=%ld\n", pCfg->szName, pCfg->u.enmSrc));
1871
1872 int rc;
1873 switch (pCfg->u.enmSrc)
1874 {
1875 case PDMAUDIORECSRC_LINE:
1876 rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
1877 break;
1878# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
1879 case PDMAUDIORECSRC_MIC:
1880 rc = hdaR3CodecAddStream(pThisCC->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
1881 break;
1882# endif
1883 default:
1884 rc = VERR_NOT_SUPPORTED;
1885 break;
1886 }
1887
1888 LogFlowFuncLeaveRC(rc);
1889 return rc;
1890}
1891
1892/**
1893 * Adds an audio stream to the device setup using the given configuration.
1894 *
1895 * @returns IPRT status code.
1896 * @param pThisCC The ring-3 HDA device state.
1897 * @param pCfg Stream configuration to use for adding a stream.
1898 */
1899static int hdaR3AddStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
1900{
1901 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
1902
1903 LogFlowFuncEnter();
1904
1905 int rc;
1906 switch (pCfg->enmDir)
1907 {
1908 case PDMAUDIODIR_OUT:
1909 rc = hdaR3AddStreamOut(pThisCC, pCfg);
1910 break;
1911
1912 case PDMAUDIODIR_IN:
1913 rc = hdaR3AddStreamIn(pThisCC, pCfg);
1914 break;
1915
1916 default:
1917 rc = VERR_NOT_SUPPORTED;
1918 AssertFailed();
1919 break;
1920 }
1921
1922 LogFlowFunc(("Returning %Rrc\n", rc));
1923
1924 return rc;
1925}
1926
1927/**
1928 * Removes an audio stream from the device setup using the given configuration.
1929 *
1930 * @returns IPRT status code.
1931 * @param pThisCC The ring-3 HDA device state.
1932 * @param pCfg Stream configuration to use for removing a stream.
1933 */
1934static int hdaR3RemoveStream(PHDASTATER3 pThisCC, PPDMAUDIOSTREAMCFG pCfg)
1935{
1936 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
1937
1938 int rc = VINF_SUCCESS;
1939
1940 PDMAUDIOMIXERCTL enmMixerCtl = PDMAUDIOMIXERCTL_UNKNOWN;
1941 switch (pCfg->enmDir)
1942 {
1943 case PDMAUDIODIR_IN:
1944 {
1945 LogFlowFunc(("Stream=%s, Source=%ld\n", pCfg->szName, pCfg->u.enmSrc));
1946
1947 switch (pCfg->u.enmSrc)
1948 {
1949 case PDMAUDIORECSRC_UNKNOWN: break;
1950 case PDMAUDIORECSRC_LINE: enmMixerCtl = PDMAUDIOMIXERCTL_LINE_IN; break;
1951# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
1952 case PDMAUDIORECSRC_MIC: enmMixerCtl = PDMAUDIOMIXERCTL_MIC_IN; break;
1953# endif
1954 default:
1955 rc = VERR_NOT_SUPPORTED;
1956 break;
1957 }
1958
1959 break;
1960 }
1961
1962 case PDMAUDIODIR_OUT:
1963 {
1964 LogFlowFunc(("Stream=%s, Source=%ld\n", pCfg->szName, pCfg->u.enmDst));
1965
1966 switch (pCfg->u.enmDst)
1967 {
1968 case PDMAUDIOPLAYBACKDST_UNKNOWN: break;
1969 case PDMAUDIOPLAYBACKDST_FRONT: enmMixerCtl = PDMAUDIOMIXERCTL_FRONT; break;
1970# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
1971 case PDMAUDIOPLAYBACKDST_CENTER_LFE: enmMixerCtl = PDMAUDIOMIXERCTL_CENTER_LFE; break;
1972 case PDMAUDIOPLAYBACKDST_REAR: enmMixerCtl = PDMAUDIOMIXERCTL_REAR; break;
1973# endif
1974 default:
1975 rc = VERR_NOT_SUPPORTED;
1976 break;
1977 }
1978 break;
1979 }
1980
1981 default:
1982 rc = VERR_NOT_SUPPORTED;
1983 break;
1984 }
1985
1986 if ( RT_SUCCESS(rc)
1987 && enmMixerCtl != PDMAUDIOMIXERCTL_UNKNOWN)
1988 {
1989 rc = hdaR3CodecRemoveStream(pThisCC->pCodec, enmMixerCtl);
1990 }
1991
1992 LogFlowFuncLeaveRC(rc);
1993 return rc;
1994}
1995
1996#endif /* IN_RING3 */
1997
1998static VBOXSTRICTRC hdaRegWriteSDFMT(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1999{
2000#ifdef IN_RING3
2001 PDMAUDIOPCMPROPS Props;
2002 int rc2 = hdaR3SDFMTToPCMProps(RT_LO_U16(u32Value), &Props);
2003 AssertRC(rc2);
2004 LogFunc(("[SD%RU8] Set to %#x (%RU32Hz, %RU8bit, %RU8 channel(s))\n",
2005 HDA_SD_NUM_FROM_REG(pThis, FMT, iReg), u32Value, Props.uHz, Props.cbSample * 8 /* Bit */, Props.cChannels));
2006
2007 /*
2008 * Write the wanted stream format into the register in any case.
2009 *
2010 * This is important for e.g. MacOS guests, as those try to initialize streams which are not reported
2011 * by the device emulation (wants 4 channels, only have 2 channels at the moment).
2012 *
2013 * When ignoring those (invalid) formats, this leads to MacOS thinking that the device is malfunctioning
2014 * and therefore disabling the device completely.
2015 */
2016 return hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
2017#else
2018 RT_NOREF(pDevIns, pThis, iReg, u32Value);
2019 return VINF_IOM_R3_MMIO_WRITE;
2020#endif
2021}
2022
2023/**
2024 * Worker for writes to the BDPL and BDPU registers.
2025 */
2026DECLINLINE(VBOXSTRICTRC) hdaRegWriteSDBDPX(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value, uint8_t uSD)
2027{
2028#ifndef HDA_USE_DMA_ACCESS_HANDLER
2029 RT_NOREF(uSD);
2030 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
2031#else
2032# ifdef IN_RING3
2033 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
2034 {
2035 /* Try registering the DMA handlers.
2036 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
2037 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
2038 if ( pStream
2039 && hdaR3StreamRegisterDMAHandlers(pThis, pStream))
2040 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
2041 }
2042 return hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
2043# else
2044 RT_NOREF(pDevIns, pThis, iReg, u32Value, uSD);
2045 return VINF_IOM_R3_MMIO_WRITE;
2046# endif
2047#endif
2048}
2049
2050static VBOXSTRICTRC hdaRegWriteSDBDPL(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2051{
2052 return hdaRegWriteSDBDPX(pDevIns, pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPL, iReg));
2053}
2054
2055static VBOXSTRICTRC hdaRegWriteSDBDPU(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2056{
2057 return hdaRegWriteSDBDPX(pDevIns, pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPU, iReg));
2058}
2059
2060static VBOXSTRICTRC hdaRegReadIRS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2061{
2062 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
2063 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
2064 || (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
2065 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
2066
2067 return hdaRegReadU32(pDevIns, pThis, iReg, pu32Value);
2068}
2069
2070static VBOXSTRICTRC hdaRegWriteIRS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2071{
2072 RT_NOREF(pDevIns, iReg);
2073
2074 /*
2075 * If the guest set the ICB bit of IRS register, HDA should process the verb in IC register,
2076 * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
2077 */
2078 if ( (u32Value & HDA_IRS_ICB)
2079 && !(HDA_REG(pThis, IRS) & HDA_IRS_ICB))
2080 {
2081#ifdef IN_RING3
2082 uint32_t uCmd = HDA_REG(pThis, IC);
2083
2084 if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP))
2085 {
2086 /*
2087 * 3.4.3: Defines behavior of immediate Command status register.
2088 */
2089 LogRel(("HDA: Guest attempted process immediate verb (%x) with active CORB\n", uCmd));
2090 return VINF_SUCCESS;
2091 }
2092
2093 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
2094
2095 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2096 uint64_t uResp = 0;
2097 int rc2 = pThisCC->pCodec->pfnLookup(&pThis->Codec, pThisCC->pCodec, HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
2098 if (RT_FAILURE(rc2))
2099 LogFunc(("Codec lookup failed with rc2=%Rrc\n", rc2));
2100
2101 HDA_REG(pThis, IR) = (uint32_t)uResp; /** @todo r=andy Do we need a 64-bit response? */
2102 HDA_REG(pThis, IRS) = HDA_IRS_IRV; /* result is ready */
2103 /** @todo r=michaln We just set the IRS value, why are we clearing unset bits? */
2104 HDA_REG(pThis, IRS) &= ~HDA_IRS_ICB; /* busy is clear */
2105
2106 return VINF_SUCCESS;
2107#else /* !IN_RING3 */
2108 return VINF_IOM_R3_MMIO_WRITE;
2109#endif /* !IN_RING3 */
2110 }
2111
2112 /*
2113 * Once the guest read the response, it should clear the IRV bit of the IRS register.
2114 */
2115 HDA_REG(pThis, IRS) &= ~(u32Value & HDA_IRS_IRV);
2116 return VINF_SUCCESS;
2117}
2118
2119static VBOXSTRICTRC hdaRegWriteRIRBWP(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2120{
2121 RT_NOREF(pDevIns, iReg);
2122
2123 if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* Ignore request if CORB DMA engine is (still) running. */
2124 LogFunc(("CORB DMA (still) running, skipping\n"));
2125 else
2126 {
2127 if (u32Value & HDA_RIRBWP_RST)
2128 {
2129 /* Do a RIRB reset. */
2130 if (pThis->cbRirbBuf)
2131 RT_ZERO(pThis->au64RirbBuf);
2132
2133 LogRel2(("HDA: RIRB reset\n"));
2134
2135 HDA_REG(pThis, RIRBWP) = 0;
2136 }
2137 /* The remaining bits are O, see 6.2.22. */
2138 }
2139 return VINF_SUCCESS;
2140}
2141
2142static VBOXSTRICTRC hdaRegWriteRINTCNT(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2143{
2144 RT_NOREF(pDevIns);
2145 if (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA) /* Ignore request if CORB DMA engine is (still) running. */
2146 {
2147 LogFunc(("CORB DMA is (still) running, skipping\n"));
2148 return VINF_SUCCESS;
2149 }
2150
2151 VBOXSTRICTRC rc = hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
2152 AssertRC(VBOXSTRICTRC_VAL(rc));
2153
2154 /** @todo r=bird: Shouldn't we make sure the HDASTATE::u16RespIntCnt is below
2155 * the new RINTCNT value? Or alterantively, make the DMA look take
2156 * this into account instead... I'll do the later for now. */
2157
2158 LogFunc(("Response interrupt count is now %RU8\n", HDA_REG(pThis, RINTCNT) & 0xFF));
2159 return rc;
2160}
2161
2162static VBOXSTRICTRC hdaRegWriteBase(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2163{
2164 RT_NOREF(pDevIns);
2165
2166 VBOXSTRICTRC rc = hdaRegWriteU32(pDevIns, pThis, iReg, u32Value);
2167 AssertRCSuccess(VBOXSTRICTRC_VAL(rc));
2168
2169 uint32_t const iRegMem = g_aHdaRegMap[iReg].mem_idx;
2170 switch (iReg)
2171 {
2172 case HDA_REG_CORBLBASE:
2173 pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
2174 pThis->u64CORBBase |= pThis->au32Regs[iRegMem];
2175 break;
2176 case HDA_REG_CORBUBASE:
2177 pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
2178 pThis->u64CORBBase |= (uint64_t)pThis->au32Regs[iRegMem] << 32;
2179 break;
2180 case HDA_REG_RIRBLBASE:
2181 pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
2182 pThis->u64RIRBBase |= pThis->au32Regs[iRegMem];
2183 break;
2184 case HDA_REG_RIRBUBASE:
2185 pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
2186 pThis->u64RIRBBase |= (uint64_t)pThis->au32Regs[iRegMem] << 32;
2187 break;
2188 case HDA_REG_DPLBASE:
2189 pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK;
2190 Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */
2191
2192 /* Also make sure to handle the DMA position enable bit. */
2193 pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);
2194
2195#ifndef IN_RING0
2196 LogRel(("HDA: DP base (lower) set: %#RGp\n", pThis->u64DPBase));
2197 LogRel(("HDA: DMA position buffer is %s\n", pThis->fDMAPosition ? "enabled" : "disabled"));
2198#else
2199 return VINF_IOM_R3_MMIO_WRITE; /* (Go to ring-3 for release logging.) */
2200#endif
2201 break;
2202 case HDA_REG_DPUBASE:
2203 pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]);
2204#ifndef IN_RING0
2205 LogRel(("HDA: DP base (upper) set: %#RGp\n", pThis->u64DPBase));
2206#else
2207 return VINF_IOM_R3_MMIO_WRITE; /* (Go to ring-3 for release logging.) */
2208#endif
2209 break;
2210 default:
2211 AssertMsgFailed(("Invalid index\n"));
2212 break;
2213 }
2214
2215 LogFunc(("CORB base:%llx RIRB base: %llx DP base: %llx\n",
2216 pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
2217 return rc;
2218}
2219
2220static VBOXSTRICTRC hdaRegWriteRIRBSTS(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2221{
2222 RT_NOREF(pDevIns, iReg);
2223
2224 uint8_t v = HDA_REG(pThis, RIRBSTS);
2225 HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
2226
2227 HDA_PROCESS_INTERRUPT(pDevIns, pThis);
2228 return VINF_SUCCESS;
2229}
2230
2231#ifdef IN_RING3
2232
2233/**
2234 * Retrieves a corresponding sink for a given mixer control.
2235 *
2236 * @return Pointer to the sink, NULL if no sink is found.
2237 * @param pThisCC The ring-3 HDA device state.
2238 * @param enmMixerCtl Mixer control to get the corresponding sink for.
2239 */
2240static PHDAMIXERSINK hdaR3MixerControlToSink(PHDASTATER3 pThisCC, PDMAUDIOMIXERCTL enmMixerCtl)
2241{
2242 PHDAMIXERSINK pSink;
2243
2244 switch (enmMixerCtl)
2245 {
2246 case PDMAUDIOMIXERCTL_VOLUME_MASTER:
2247 /* Fall through is intentional. */
2248 case PDMAUDIOMIXERCTL_FRONT:
2249 pSink = &pThisCC->SinkFront;
2250 break;
2251# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2252 case PDMAUDIOMIXERCTL_CENTER_LFE:
2253 pSink = &pThisCC->SinkCenterLFE;
2254 break;
2255 case PDMAUDIOMIXERCTL_REAR:
2256 pSink = &pThisCC->SinkRear;
2257 break;
2258# endif
2259 case PDMAUDIOMIXERCTL_LINE_IN:
2260 pSink = &pThisCC->SinkLineIn;
2261 break;
2262# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2263 case PDMAUDIOMIXERCTL_MIC_IN:
2264 pSink = &pThisCC->SinkMicIn;
2265 break;
2266# endif
2267 default:
2268 AssertMsgFailed(("Unhandled mixer control\n"));
2269 pSink = NULL;
2270 break;
2271 }
2272
2273 return pSink;
2274}
2275
2276/**
2277 * Adds a specific HDA driver to the driver chain.
2278 *
2279 * @return IPRT status code.
2280 * @param pThisCC The ring-3 HDA device state.
2281 * @param pDrv HDA driver to add.
2282 */
2283static int hdaR3MixerAddDrv(PHDASTATER3 pThisCC, PHDADRIVER pDrv)
2284{
2285 int rc = VINF_SUCCESS;
2286
2287 PHDASTREAM pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkLineIn);
2288 if ( pStream
2289 && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
2290 {
2291 int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkLineIn.pMixSink, &pStream->State.Cfg, pDrv);
2292 if (RT_SUCCESS(rc))
2293 rc = rc2;
2294 }
2295
2296# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2297 pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkMicIn);
2298 if ( pStream
2299 && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
2300 {
2301 int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkMicIn.pMixSink, &pStream->State.Cfg, pDrv);
2302 if (RT_SUCCESS(rc))
2303 rc = rc2;
2304 }
2305# endif
2306
2307 pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkFront);
2308 if ( pStream
2309 && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
2310 {
2311 int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkFront.pMixSink, &pStream->State.Cfg, pDrv);
2312 if (RT_SUCCESS(rc))
2313 rc = rc2;
2314 }
2315
2316# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2317 pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkCenterLFE);
2318 if ( pStream
2319 && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
2320 {
2321 int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkCenterLFE.pMixSink, &pStream->State.Cfg, pDrv);
2322 if (RT_SUCCESS(rc))
2323 rc = rc2;
2324 }
2325
2326 pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkRear);
2327 if ( pStream
2328 && DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
2329 {
2330 int rc2 = hdaR3MixerAddDrvStream(pThisCC->SinkRear.pMixSink, &pStream->State.Cfg, pDrv);
2331 if (RT_SUCCESS(rc))
2332 rc = rc2;
2333 }
2334# endif
2335
2336 return rc;
2337}
2338
2339/**
2340 * Removes a specific HDA driver from the driver chain and destroys its
2341 * associated streams.
2342 *
2343 * @param pThisCC The ring-3 HDA device state.
2344 * @param pDrv HDA driver to remove.
2345 */
2346static void hdaR3MixerRemoveDrv(PHDASTATER3 pThisCC, PHDADRIVER pDrv)
2347{
2348 AssertPtrReturnVoid(pDrv);
2349
2350 if (pDrv->LineIn.pMixStrm)
2351 {
2352 if (AudioMixerSinkGetRecordingSource(pThisCC->SinkLineIn.pMixSink) == pDrv->LineIn.pMixStrm)
2353 AudioMixerSinkSetRecordingSource(pThisCC->SinkLineIn.pMixSink, NULL);
2354
2355 AudioMixerSinkRemoveStream(pThisCC->SinkLineIn.pMixSink, pDrv->LineIn.pMixStrm);
2356 AudioMixerStreamDestroy(pDrv->LineIn.pMixStrm);
2357 pDrv->LineIn.pMixStrm = NULL;
2358 }
2359
2360# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2361 if (pDrv->MicIn.pMixStrm)
2362 {
2363 if (AudioMixerSinkGetRecordingSource(pThisCC->SinkMicIn.pMixSink) == pDrv->MicIn.pMixStrm)
2364 AudioMixerSinkSetRecordingSource(&pThisCC->SinkMicIn.pMixSink, NULL);
2365
2366 AudioMixerSinkRemoveStream(pThisCC->SinkMicIn.pMixSink, pDrv->MicIn.pMixStrm);
2367 AudioMixerStreamDestroy(pDrv->MicIn.pMixStrm);
2368 pDrv->MicIn.pMixStrm = NULL;
2369 }
2370# endif
2371
2372 if (pDrv->Front.pMixStrm)
2373 {
2374 AudioMixerSinkRemoveStream(pThisCC->SinkFront.pMixSink, pDrv->Front.pMixStrm);
2375 AudioMixerStreamDestroy(pDrv->Front.pMixStrm);
2376 pDrv->Front.pMixStrm = NULL;
2377 }
2378
2379# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2380 if (pDrv->CenterLFE.pMixStrm)
2381 {
2382 AudioMixerSinkRemoveStream(pThisCC->SinkCenterLFE.pMixSink, pDrv->CenterLFE.pMixStrm);
2383 AudioMixerStreamDestroy(pDrv->CenterLFE.pMixStrm);
2384 pDrv->CenterLFE.pMixStrm = NULL;
2385 }
2386
2387 if (pDrv->Rear.pMixStrm)
2388 {
2389 AudioMixerSinkRemoveStream(pThisCC->SinkRear.pMixSink, pDrv->Rear.pMixStrm);
2390 AudioMixerStreamDestroy(pDrv->Rear.pMixStrm);
2391 pDrv->Rear.pMixStrm = NULL;
2392 }
2393# endif
2394
2395 RTListNodeRemove(&pDrv->Node);
2396}
2397
2398/**
2399 * Adds a driver stream to a specific mixer sink.
2400 *
2401 * @returns IPRT status code (ignored by caller).
2402 * @param pMixSink Audio mixer sink to add audio streams to.
2403 * @param pCfg Audio stream configuration to use for the audio streams to add.
2404 * @param pDrv Driver stream to add.
2405 */
2406static int hdaR3MixerAddDrvStream(PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PHDADRIVER pDrv)
2407{
2408 AssertPtrReturn(pMixSink, VERR_INVALID_POINTER);
2409 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2410
2411 LogFunc(("szSink=%s, szStream=%s, cChannels=%RU8\n", pMixSink->pszName, pCfg->szName, pCfg->Props.cChannels));
2412
2413 PPDMAUDIOSTREAMCFG pStreamCfg = DrvAudioHlpStreamCfgDup(pCfg);
2414 if (!pStreamCfg)
2415 return VERR_NO_MEMORY;
2416
2417 LogFunc(("[LUN#%RU8] %s\n", pDrv->uLUN, pStreamCfg->szName));
2418
2419 int rc = VINF_SUCCESS;
2420
2421 PHDADRIVERSTREAM pDrvStream = NULL;
2422
2423 if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
2424 {
2425 LogFunc(("enmRecSource=%d\n", pStreamCfg->u.enmSrc));
2426
2427 switch (pStreamCfg->u.enmSrc)
2428 {
2429 case PDMAUDIORECSRC_LINE:
2430 pDrvStream = &pDrv->LineIn;
2431 break;
2432# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2433 case PDMAUDIORECSRC_MIC:
2434 pDrvStream = &pDrv->MicIn;
2435 break;
2436# endif
2437 default:
2438 rc = VERR_NOT_SUPPORTED;
2439 break;
2440 }
2441 }
2442 else if (pStreamCfg->enmDir == PDMAUDIODIR_OUT)
2443 {
2444 LogFunc(("enmPlaybackDest=%d\n", pStreamCfg->u.enmDst));
2445
2446 switch (pStreamCfg->u.enmDst)
2447 {
2448 case PDMAUDIOPLAYBACKDST_FRONT:
2449 pDrvStream = &pDrv->Front;
2450 break;
2451# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2452 case PDMAUDIOPLAYBACKDST_CENTER_LFE:
2453 pDrvStream = &pDrv->CenterLFE;
2454 break;
2455 case PDMAUDIOPLAYBACKDST_REAR:
2456 pDrvStream = &pDrv->Rear;
2457 break;
2458# endif
2459 default:
2460 rc = VERR_NOT_SUPPORTED;
2461 break;
2462 }
2463 }
2464 else
2465 rc = VERR_NOT_SUPPORTED;
2466
2467 if (RT_SUCCESS(rc))
2468 {
2469 AssertPtr(pDrvStream);
2470 AssertMsg(pDrvStream->pMixStrm == NULL, ("[LUN#%RU8] Driver stream already present when it must not\n", pDrv->uLUN));
2471
2472 PAUDMIXSTREAM pMixStrm;
2473 rc = AudioMixerSinkCreateStream(pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, &pMixStrm);
2474 LogFlowFunc(("LUN#%RU8: Created stream \"%s\" for sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
2475 if (RT_SUCCESS(rc))
2476 {
2477 rc = AudioMixerSinkAddStream(pMixSink, pMixStrm);
2478 LogFlowFunc(("LUN#%RU8: Added stream \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
2479 if (RT_SUCCESS(rc))
2480 {
2481 /* If this is an input stream, always set the latest (added) stream
2482 * as the recording source. */
2483 /** @todo Make the recording source dynamic (CFGM?). */
2484 if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
2485 {
2486 PDMAUDIOBACKENDCFG Cfg;
2487 rc = pDrv->pConnector->pfnGetConfig(pDrv->pConnector, &Cfg);
2488 if (RT_SUCCESS(rc))
2489 {
2490 if (Cfg.cMaxStreamsIn) /* At least one input source available? */
2491 {
2492 rc = AudioMixerSinkSetRecordingSource(pMixSink, pMixStrm);
2493 LogFlowFunc(("LUN#%RU8: Recording source for '%s' -> '%s', rc=%Rrc\n",
2494 pDrv->uLUN, pStreamCfg->szName, Cfg.szName, rc));
2495
2496 if (RT_SUCCESS(rc))
2497 LogRel(("HDA: Set recording source for '%s' to '%s'\n",
2498 pStreamCfg->szName, Cfg.szName));
2499 }
2500 else
2501 LogRel(("HDA: Backend '%s' currently is not offering any recording source for '%s'\n",
2502 Cfg.szName, pStreamCfg->szName));
2503 }
2504 else if (RT_FAILURE(rc))
2505 LogFunc(("LUN#%RU8: Unable to retrieve backend configuration for '%s', rc=%Rrc\n",
2506 pDrv->uLUN, pStreamCfg->szName, rc));
2507 }
2508 }
2509 }
2510
2511 if (RT_SUCCESS(rc))
2512 pDrvStream->pMixStrm = pMixStrm;
2513 }
2514
2515 DrvAudioHlpStreamCfgFree(pStreamCfg);
2516
2517 LogFlowFuncLeaveRC(rc);
2518 return rc;
2519}
2520
2521/**
2522 * Adds all current driver streams to a specific mixer sink.
2523 *
2524 * @returns IPRT status code.
2525 * @param pThisCC The ring-3 HDA device state.
2526 * @param pMixSink Audio mixer sink to add stream to.
2527 * @param pCfg Audio stream configuration to use for the audio streams to add.
2528 */
2529static int hdaR3MixerAddDrvStreams(PHDASTATER3 pThisCC, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg)
2530{
2531 AssertPtrReturn(pMixSink, VERR_INVALID_POINTER);
2532 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2533
2534 LogFunc(("Sink=%s, Stream=%s\n", pMixSink->pszName, pCfg->szName));
2535
2536 if (!DrvAudioHlpStreamCfgIsValid(pCfg))
2537 return VERR_INVALID_PARAMETER;
2538
2539 int rc = AudioMixerSinkSetFormat(pMixSink, &pCfg->Props);
2540 if (RT_FAILURE(rc))
2541 return rc;
2542
2543 PHDADRIVER pDrv;
2544 RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
2545 {
2546 int rc2 = hdaR3MixerAddDrvStream(pMixSink, pCfg, pDrv);
2547 if (RT_FAILURE(rc2))
2548 LogFunc(("Attaching stream failed with %Rrc\n", rc2));
2549
2550 /* Do not pass failure to rc here, as there might be drivers which aren't
2551 * configured / ready yet. */
2552 }
2553
2554 return rc;
2555}
2556
2557/**
2558 * @interface_method_impl{HDACODEC,pfnCbMixerAddStream}
2559 */
2560static DECLCALLBACK(int) hdaR3MixerAddStream(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
2561{
2562 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2563 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2564 int rc;
2565
2566 PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
2567 if (pSink)
2568 {
2569 rc = hdaR3MixerAddDrvStreams(pThisCC, pSink->pMixSink, pCfg);
2570
2571 AssertPtr(pSink->pMixSink);
2572 LogFlowFunc(("Sink=%s, Mixer control=%s\n", pSink->pMixSink->pszName, DrvAudioHlpAudMixerCtlToStr(enmMixerCtl)));
2573 }
2574 else
2575 rc = VERR_NOT_FOUND;
2576
2577 LogFlowFuncLeaveRC(rc);
2578 return rc;
2579}
2580
2581/**
2582 * @interface_method_impl{HDACODEC,pfnCbMixerRemoveStream}
2583 */
2584static DECLCALLBACK(int) hdaR3MixerRemoveStream(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl)
2585{
2586 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2587 int rc;
2588
2589 PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
2590 if (pSink)
2591 {
2592 PHDADRIVER pDrv;
2593 RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
2594 {
2595 PAUDMIXSTREAM pMixStream = NULL;
2596 switch (enmMixerCtl)
2597 {
2598 /*
2599 * Input.
2600 */
2601 case PDMAUDIOMIXERCTL_LINE_IN:
2602 pMixStream = pDrv->LineIn.pMixStrm;
2603 pDrv->LineIn.pMixStrm = NULL;
2604 break;
2605# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2606 case PDMAUDIOMIXERCTL_MIC_IN:
2607 pMixStream = pDrv->MicIn.pMixStrm;
2608 pDrv->MicIn.pMixStrm = NULL;
2609 break;
2610# endif
2611 /*
2612 * Output.
2613 */
2614 case PDMAUDIOMIXERCTL_FRONT:
2615 pMixStream = pDrv->Front.pMixStrm;
2616 pDrv->Front.pMixStrm = NULL;
2617 break;
2618# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2619 case PDMAUDIOMIXERCTL_CENTER_LFE:
2620 pMixStream = pDrv->CenterLFE.pMixStrm;
2621 pDrv->CenterLFE.pMixStrm = NULL;
2622 break;
2623 case PDMAUDIOMIXERCTL_REAR:
2624 pMixStream = pDrv->Rear.pMixStrm;
2625 pDrv->Rear.pMixStrm = NULL;
2626 break;
2627# endif
2628 default:
2629 AssertMsgFailed(("Mixer control %d not implemented\n", enmMixerCtl));
2630 break;
2631 }
2632
2633 if (pMixStream)
2634 {
2635 AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
2636 AudioMixerStreamDestroy(pMixStream);
2637
2638 pMixStream = NULL;
2639 }
2640 }
2641
2642 AudioMixerSinkRemoveAllStreams(pSink->pMixSink);
2643 rc = VINF_SUCCESS;
2644 }
2645 else
2646 rc = VERR_NOT_FOUND;
2647
2648 LogFunc(("Mixer control=%s, rc=%Rrc\n", DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), rc));
2649 return rc;
2650}
2651
2652/**
2653 * @interface_method_impl{HDACODEC,pfnCbMixerControl}
2654 *
2655 * @note Is also called directly by the DevHDA code.
2656 */
2657static DECLCALLBACK(int) hdaR3MixerControl(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
2658{
2659 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
2660 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2661 LogFunc(("enmMixerCtl=%s, uSD=%RU8, uChannel=%RU8\n", DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), uSD, uChannel));
2662
2663 if (uSD == 0) /* Stream number 0 is reserved. */
2664 {
2665 Log2Func(("Invalid SDn (%RU8) number for mixer control '%s', ignoring\n", uSD, DrvAudioHlpAudMixerCtlToStr(enmMixerCtl)));
2666 return VINF_SUCCESS;
2667 }
2668 /* uChannel is optional. */
2669
2670 /* SDn0 starts as 1. */
2671 Assert(uSD);
2672 uSD--;
2673
2674# ifndef VBOX_WITH_AUDIO_HDA_MIC_IN
2675 /* Only SDI0 (Line-In) is supported. */
2676 if ( hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN
2677 && uSD >= 1)
2678 {
2679 LogRel2(("HDA: Dedicated Mic-In support not imlpemented / built-in (stream #%RU8), using Line-In (stream #0) instead\n", uSD));
2680 uSD = 0;
2681 }
2682# endif
2683
2684 int rc = VINF_SUCCESS;
2685
2686 PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
2687 if (pSink)
2688 {
2689 AssertPtr(pSink->pMixSink);
2690
2691 /* If this an output stream, determine the correct SD#. */
2692 if ( uSD < HDA_MAX_SDI
2693 && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT)
2694 uSD += HDA_MAX_SDI;
2695
2696 /* Make 100% sure we got a good stream number before continuing. */
2697 AssertLogRelReturn(uSD < RT_ELEMENTS(pThisCC->aStreams), VERR_NOT_IMPLEMENTED);
2698
2699 /* Detach the existing stream from the sink. */
2700 if ( pSink->pStreamShared
2701 && pSink->pStreamR3
2702 && ( pSink->pStreamShared->u8SD != uSD
2703 || pSink->pStreamShared->u8Channel != uChannel)
2704 )
2705 {
2706 LogFunc(("Sink '%s' was assigned to stream #%RU8 (channel %RU8) before\n",
2707 pSink->pMixSink->pszName, pSink->pStreamShared->u8SD, pSink->pStreamShared->u8Channel));
2708
2709 hdaR3StreamLock(pSink->pStreamR3);
2710
2711 /* Only disable the stream if the stream descriptor # has changed. */
2712 if (pSink->pStreamShared->u8SD != uSD)
2713 hdaR3StreamEnable(pSink->pStreamShared, pSink->pStreamR3, false /*fEnable*/);
2714
2715 pSink->pStreamR3->pMixSink = NULL;
2716
2717 hdaR3StreamUnlock(pSink->pStreamR3);
2718
2719 pSink->pStreamShared = NULL;
2720 pSink->pStreamR3 = NULL;
2721 }
2722
2723 /* Attach the new stream to the sink.
2724 * Enabling the stream will be done by the gust via a separate SDnCTL call then. */
2725 if (pSink->pStreamShared == NULL)
2726 {
2727 LogRel2(("HDA: Setting sink '%s' to stream #%RU8 (channel %RU8), mixer control=%s\n",
2728 pSink->pMixSink->pszName, uSD, uChannel, DrvAudioHlpAudMixerCtlToStr(enmMixerCtl)));
2729
2730 PHDASTREAMR3 pStreamR3 = &pThisCC->aStreams[uSD];
2731 PHDASTREAM pStreamShared = &pThis->aStreams[uSD];
2732 hdaR3StreamLock(pStreamR3);
2733
2734 pSink->pStreamR3 = pStreamR3;
2735 pSink->pStreamShared = pStreamShared;
2736
2737 pStreamShared->u8Channel = uChannel;
2738 pStreamR3->pMixSink = pSink;
2739
2740 hdaR3StreamUnlock(pStreamR3);
2741 rc = VINF_SUCCESS;
2742 }
2743 }
2744 else
2745 rc = VERR_NOT_FOUND;
2746
2747 if (RT_FAILURE(rc))
2748 LogRel(("HDA: Converter control for stream #%RU8 (channel %RU8) / mixer control '%s' failed with %Rrc, skipping\n",
2749 uSD, uChannel, DrvAudioHlpAudMixerCtlToStr(enmMixerCtl), rc));
2750
2751 LogFlowFuncLeaveRC(rc);
2752 return rc;
2753}
2754
2755/**
2756 * @interface_method_impl{HDACODEC,pfnCbMixerSetVolume}
2757 */
2758static DECLCALLBACK(int) hdaR3MixerSetVolume(PPDMDEVINS pDevIns, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)
2759{
2760 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2761 int rc;
2762
2763 PHDAMIXERSINK pSink = hdaR3MixerControlToSink(pThisCC, enmMixerCtl);
2764 if ( pSink
2765 && pSink->pMixSink)
2766 {
2767 LogRel2(("HDA: Setting volume for mixer sink '%s' to %RU8/%RU8 (%s)\n",
2768 pSink->pMixSink->pszName, pVol->uLeft, pVol->uRight, pVol->fMuted ? "Muted" : "Unmuted"));
2769
2770 /* Set the volume.
2771 * We assume that the codec already converted it to the correct range. */
2772 rc = AudioMixerSinkSetVolume(pSink->pMixSink, pVol);
2773 }
2774 else
2775 rc = VERR_NOT_FOUND;
2776
2777 LogFlowFuncLeaveRC(rc);
2778 return rc;
2779}
2780
2781/**
2782 * @callback_method_impl{FNTMTIMERDEV, Main routine for the stream's timer.}
2783 */
2784static DECLCALLBACK(void) hdaR3Timer(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser)
2785{
2786 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
2787 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
2788 uintptr_t idxStream = (uintptr_t)pvUser;
2789 AssertReturnVoid(idxStream < RT_ELEMENTS(pThis->aStreams));
2790 PHDASTREAM pStreamShared = &pThis->aStreams[idxStream];
2791 PHDASTREAMR3 pStreamR3 = &pThisCC->aStreams[idxStream];
2792 Assert(hTimer == pStreamShared->hTimer);
2793
2794 Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect));
2795 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
2796
2797 hdaR3StreamUpdate(pDevIns, pThis, pThisCC, pStreamShared, pStreamR3, true /* fInTimer */);
2798
2799 /* Flag indicating whether to kick the timer again for a new data processing round. */
2800 bool fSinkActive = false;
2801 if (pStreamR3->pMixSink)
2802 fSinkActive = AudioMixerSinkIsActive(pStreamR3->pMixSink->pMixSink);
2803
2804#ifdef LOG_ENABLED
2805 const uint8_t uSD = pStreamShared->u8SD;
2806#endif
2807
2808 if (fSinkActive)
2809 {
2810 const uint64_t tsNow = PDMDevHlpTimerGet(pDevIns, hTimer); /* (For virtual sync this remains the same for the whole callout IIRC) */
2811 const bool fTimerScheduled = hdaR3StreamTransferIsScheduled(pStreamShared, tsNow);
2812
2813 Log3Func(("[SD%RU8] fSinksActive=%RTbool, fTimerScheduled=%RTbool\n", uSD, fSinkActive, fTimerScheduled));
2814
2815 if (!fTimerScheduled)
2816 {
2817 if (!pStreamShared->State.tsTransferLast) /* Never did a transfer before? Initialize with current time. */
2818 pStreamShared->State.tsTransferLast = tsNow;
2819
2820 Assert(tsNow >= pStreamShared->State.tsTransferLast);
2821
2822 /* How many ticks have passed since the last transfer? */
2823 const uint64_t cTicksElapsed = tsNow - pStreamShared->State.tsTransferLast;
2824
2825 uint64_t cTicksToNext;
2826 if (cTicksElapsed == 0) /* We just ran in the same timing slot? */
2827 {
2828 /* Schedule a transfer at the next regular timing slot. */
2829 cTicksToNext = pStreamShared->State.cTransferTicks;
2830 }
2831 else
2832 {
2833 /* Some time since the last transfer has passed already; take this into account. */
2834 if (pStreamShared->State.cTransferTicks >= cTicksElapsed)
2835 {
2836 cTicksToNext = pStreamShared->State.cTransferTicks - cTicksElapsed;
2837 }
2838 else /* Catch up as soon as possible. */
2839 cTicksToNext = 0;
2840 }
2841
2842 Log3Func(("[SD%RU8] tsNow=%RU64, tsTransferLast=%RU64, cTicksElapsed=%RU64 -> cTicksToNext=%RU64\n",
2843 uSD, tsNow, pStreamShared->State.tsTransferLast, cTicksElapsed, cTicksToNext));
2844
2845 /* Note: cTicksToNext can be 0, which means we have to run *now*. */
2846 hdaR3TimerSet(pDevIns, pStreamShared, tsNow + cTicksToNext,
2847 true /*fForce*/, 0 /* tsNow */);
2848 }
2849 }
2850 else
2851 Log3Func(("[SD%RU8] fSinksActive=%RTbool\n", uSD, fSinkActive));
2852}
2853
2854# ifdef HDA_USE_DMA_ACCESS_HANDLER
2855/**
2856 * HC access handler for the FIFO.
2857 *
2858 * @returns VINF_SUCCESS if the handler have carried out the operation.
2859 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2860 * @param pVM VM Handle.
2861 * @param pVCpu The cross context CPU structure for the calling EMT.
2862 * @param GCPhys The physical address the guest is writing to.
2863 * @param pvPhys The HC mapping of that address.
2864 * @param pvBuf What the guest is reading/writing.
2865 * @param cbBuf How much it's reading/writing.
2866 * @param enmAccessType The access type.
2867 * @param enmOrigin Who is making the access.
2868 * @param pvUser User argument.
2869 */
2870static DECLCALLBACK(VBOXSTRICTRC) hdaR3DmaAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
2871 void *pvBuf, size_t cbBuf,
2872 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2873{
2874 RT_NOREF(pVM, pVCpu, pvPhys, pvBuf, enmOrigin);
2875
2876 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)pvUser;
2877 AssertPtr(pHandler);
2878
2879 PHDASTREAM pStream = pHandler->pStream;
2880 AssertPtr(pStream);
2881
2882 Assert(GCPhys >= pHandler->GCPhysFirst);
2883 Assert(GCPhys <= pHandler->GCPhysLast);
2884 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
2885
2886 /* Not within BDLE range? Bail out. */
2887 if ( (GCPhys < pHandler->BDLEAddr)
2888 || (GCPhys + cbBuf > pHandler->BDLEAddr + pHandler->BDLESize))
2889 {
2890 return VINF_PGM_HANDLER_DO_DEFAULT;
2891 }
2892
2893 switch (enmAccessType)
2894 {
2895 case PGMACCESSTYPE_WRITE:
2896 {
2897# ifdef DEBUG
2898 PHDASTREAMDEBUG pStreamDbg = &pStream->Dbg;
2899
2900 const uint64_t tsNowNs = RTTimeNanoTS();
2901 const uint32_t tsElapsedMs = (tsNowNs - pStreamDbg->tsWriteSlotBegin) / 1000 / 1000;
2902
2903 uint64_t cWritesHz = ASMAtomicReadU64(&pStreamDbg->cWritesHz);
2904 uint64_t cbWrittenHz = ASMAtomicReadU64(&pStreamDbg->cbWrittenHz);
2905
2906 if (tsElapsedMs >= (1000 / HDA_TIMER_HZ_DEFAULT))
2907 {
2908 LogFunc(("[SD%RU8] %RU32ms elapsed, cbWritten=%RU64, cWritten=%RU64 -- %RU32 bytes on average per time slot (%zums)\n",
2909 pStream->u8SD, tsElapsedMs, cbWrittenHz, cWritesHz,
2910 ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ_DEFAULT));
2911
2912 pStreamDbg->tsWriteSlotBegin = tsNowNs;
2913
2914 cWritesHz = 0;
2915 cbWrittenHz = 0;
2916 }
2917
2918 cWritesHz += 1;
2919 cbWrittenHz += cbBuf;
2920
2921 ASMAtomicIncU64(&pStreamDbg->cWritesTotal);
2922 ASMAtomicAddU64(&pStreamDbg->cbWrittenTotal, cbBuf);
2923
2924 ASMAtomicWriteU64(&pStreamDbg->cWritesHz, cWritesHz);
2925 ASMAtomicWriteU64(&pStreamDbg->cbWrittenHz, cbWrittenHz);
2926
2927 LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n",
2928 pStream->u8SD, cbBuf, GCPhys, GCPhys - pHandler->BDLEAddr));
2929
2930 LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n",
2931 pStream->u8SD, pStreamDbg->cWritesTotal, pStreamDbg->cbWrittenTotal,
2932 ASMDivU64ByU32RetU32(pStreamDbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));
2933# endif
2934
2935 if (pThis->fDebugEnabled)
2936 {
2937 RTFILE fh;
2938 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessWrite.pcm",
2939 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
2940 RTFileWrite(fh, pvBuf, cbBuf, NULL);
2941 RTFileClose(fh);
2942 }
2943
2944# ifdef HDA_USE_DMA_ACCESS_HANDLER_WRITING
2945 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
2946 AssertPtr(pCircBuf);
2947
2948 uint8_t *pbBuf = (uint8_t *)pvBuf;
2949 while (cbBuf)
2950 {
2951 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
2952 void *pvChunk;
2953 size_t cbChunk;
2954 RTCircBufAcquireWriteBlock(pCircBuf, cbBuf, &pvChunk, &cbChunk);
2955
2956 if (cbChunk)
2957 {
2958 memcpy(pvChunk, pbBuf, cbChunk);
2959
2960 pbBuf += cbChunk;
2961 Assert(cbBuf >= cbChunk);
2962 cbBuf -= cbChunk;
2963 }
2964 else
2965 {
2966 //AssertMsg(RTCircBufFree(pCircBuf), ("No more space but still %zu bytes to write\n", cbBuf));
2967 break;
2968 }
2969
2970 LogFunc(("[SD%RU8] cbChunk=%zu\n", pStream->u8SD, cbChunk));
2971
2972 RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
2973 }
2974# endif /* HDA_USE_DMA_ACCESS_HANDLER_WRITING */
2975 break;
2976 }
2977
2978 default:
2979 AssertMsgFailed(("Access type not implemented\n"));
2980 break;
2981 }
2982
2983 return VINF_PGM_HANDLER_DO_DEFAULT;
2984}
2985# endif /* HDA_USE_DMA_ACCESS_HANDLER */
2986
2987/**
2988 * Soft reset of the device triggered via GCTL.
2989 *
2990 * @param pDevIns The device instance.
2991 * @param pThis The shared HDA device state.
2992 * @param pThisCC The ring-3 HDA device state.
2993 */
2994static void hdaR3GCTLReset(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
2995{
2996 LogFlowFuncEnter();
2997
2998 pThisCC->cStreamsActive = 0;
2999
3000 HDA_REG(pThis, GCAP) = HDA_MAKE_GCAP(HDA_MAX_SDO, HDA_MAX_SDI, 0, 0, 1); /* see 6.2.1 */
3001 HDA_REG(pThis, VMIN) = 0x00; /* see 6.2.2 */
3002 HDA_REG(pThis, VMAJ) = 0x01; /* see 6.2.3 */
3003 HDA_REG(pThis, OUTPAY) = 0x003C; /* see 6.2.4 */
3004 HDA_REG(pThis, INPAY) = 0x001D; /* see 6.2.5 */
3005 HDA_REG(pThis, CORBSIZE) = 0x42; /* Up to 256 CORB entries see 6.2.1 */
3006 HDA_REG(pThis, RIRBSIZE) = 0x42; /* Up to 256 RIRB entries see 6.2.1 */
3007 HDA_REG(pThis, CORBRP) = 0x0;
3008 HDA_REG(pThis, CORBWP) = 0x0;
3009 HDA_REG(pThis, RIRBWP) = 0x0;
3010 /* Some guests (like Haiku) don't set RINTCNT explicitly but expect an interrupt after each
3011 * RIRB response -- so initialize RINTCNT to 1 by default. */
3012 HDA_REG(pThis, RINTCNT) = 0x1;
3013
3014 /*
3015 * Stop any audio currently playing and/or recording.
3016 */
3017 pThisCC->SinkFront.pStreamShared = NULL;
3018 pThisCC->SinkFront.pStreamR3 = NULL;
3019 if (pThisCC->SinkFront.pMixSink)
3020 AudioMixerSinkReset(pThisCC->SinkFront.pMixSink);
3021# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3022 pThisCC->SinkMicIn.pStreamShared = NULL;
3023 pThisCC->SinkMicIn.pStreamR3 = NULL;
3024 if (pThisCC->SinkMicIn.pMixSink)
3025 AudioMixerSinkReset(pThisCC->SinkMicIn.pMixSink);
3026# endif
3027 pThisCC->SinkLineIn.pStreamShared = NULL;
3028 pThisCC->SinkLineIn.pStreamR3 = NULL;
3029 if (pThisCC->SinkLineIn.pMixSink)
3030 AudioMixerSinkReset(pThisCC->SinkLineIn.pMixSink);
3031# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3032 pThisCC->SinkCenterLFE = NULL;
3033 if (pThisCC->SinkCenterLFE.pMixSink)
3034 AudioMixerSinkReset(pThisCC->SinkCenterLFE.pMixSink);
3035 pThisCC->SinkRear.pStreamShared = NULL;
3036 pThisCC->SinkRear.pStreamR3 = NULL;
3037 if (pThisCC->SinkRear.pMixSink)
3038 AudioMixerSinkReset(pThisCC->SinkRear.pMixSink);
3039# endif
3040
3041 /*
3042 * Reset the codec.
3043 */
3044 hdaCodecReset(&pThis->Codec);
3045
3046 /*
3047 * Set some sensible defaults for which HDA sinks
3048 * are connected to which stream number.
3049 *
3050 * We use SD0 for input and SD4 for output by default.
3051 * These stream numbers can be changed by the guest dynamically lateron.
3052 */
3053 ASMCompilerBarrier(); /* paranoia */
3054# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3055 hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_MIC_IN , 1 /* SD0 */, 0 /* Channel */);
3056# endif
3057 hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_LINE_IN , 1 /* SD0 */, 0 /* Channel */);
3058
3059 hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_FRONT , 5 /* SD4 */, 0 /* Channel */);
3060# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3061 hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
3062 hdaR3MixerControl(pDevIns, PDMAUDIOMIXERCTL_REAR , 5 /* SD4 */, 0 /* Channel */);
3063# endif
3064 ASMCompilerBarrier(); /* paranoia */
3065
3066 /* Reset CORB. */
3067 pThis->cbCorbBuf = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE;
3068 RT_ZERO(pThis->au32CorbBuf);
3069
3070 /* Reset RIRB. */
3071 pThis->cbRirbBuf = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE;
3072 RT_ZERO(pThis->au64RirbBuf);
3073
3074 /* Clear our internal response interrupt counter. */
3075 pThis->u16RespIntCnt = 0;
3076
3077 for (size_t idxStream = 0; idxStream < RT_ELEMENTS(pThis->aStreams); idxStream++)
3078 {
3079 int rc2 = hdaR3StreamEnable(&pThis->aStreams[idxStream], &pThisCC->aStreams[idxStream], false /* fEnable */);
3080 if (RT_SUCCESS(rc2))
3081 {
3082 /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
3083 HDA_STREAM_REG(pThis, CTL, idxStream) &= ~HDA_SDCTL_RUN;
3084 hdaR3StreamReset(pThis, pThisCC, &pThis->aStreams[idxStream], &pThisCC->aStreams[idxStream], (uint8_t)idxStream);
3085 }
3086 }
3087
3088 /* Clear stream tags <-> objects mapping table. */
3089 RT_ZERO(pThisCC->aTags);
3090
3091 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
3092 HDA_REG(pThis, STATESTS) = 0x1;
3093
3094 LogFlowFuncLeave();
3095 LogRel(("HDA: Reset\n"));
3096}
3097
3098#else /* !IN_RING3 */
3099
3100/**
3101 * Checks if a dword read starting with @a idxRegDsc is safe.
3102 *
3103 * We can guarentee it only standard reader callbacks are used.
3104 * @returns true if it will always succeed, false if it may return back to
3105 * ring-3 or we're just not sure.
3106 * @param idxRegDsc The first register descriptor in the DWORD being read.
3107 */
3108DECLINLINE(bool) hdaIsMultiReadSafeInRZ(unsigned idxRegDsc)
3109{
3110 int32_t cbLeft = 4; /* signed on purpose */
3111 do
3112 {
3113 if ( g_aHdaRegMap[idxRegDsc].pfnRead == hdaRegReadU24
3114 || g_aHdaRegMap[idxRegDsc].pfnRead == hdaRegReadU16
3115 || g_aHdaRegMap[idxRegDsc].pfnRead == hdaRegReadU8
3116 || g_aHdaRegMap[idxRegDsc].pfnRead == hdaRegReadUnimpl)
3117 { /* okay */ }
3118 else
3119 {
3120 Log4(("hdaIsMultiReadSafeInRZ: idxRegDsc=%u %s\n", idxRegDsc, g_aHdaRegMap[idxRegDsc].abbrev));
3121 return false;
3122 }
3123
3124 idxRegDsc++;
3125 if (idxRegDsc < RT_ELEMENTS(g_aHdaRegMap))
3126 cbLeft -= g_aHdaRegMap[idxRegDsc].offset - g_aHdaRegMap[idxRegDsc - 1].offset;
3127 else
3128 break;
3129 } while (cbLeft > 0);
3130 return true;
3131}
3132
3133
3134#endif /* !IN_RING3 */
3135
3136
3137/* MMIO callbacks */
3138
3139/**
3140 * @callback_method_impl{FNIOMMMIONEWREAD, Looks up and calls the appropriate handler.}
3141 *
3142 * @note During implementation, we discovered so-called "forgotten" or "hole"
3143 * registers whose description is not listed in the RPM, datasheet, or
3144 * spec.
3145 */
3146static DECLCALLBACK(VBOXSTRICTRC) hdaMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
3147{
3148 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
3149 VBOXSTRICTRC rc;
3150 RT_NOREF_PV(pvUser);
3151 Assert(pThis->uAlignmentCheckMagic == HDASTATE_ALIGNMENT_CHECK_MAGIC);
3152
3153 /*
3154 * Look up and log.
3155 */
3156 int idxRegDsc = hdaRegLookup(off); /* Register descriptor index. */
3157#ifdef LOG_ENABLED
3158 unsigned const cbLog = cb;
3159 uint32_t offRegLog = (uint32_t)off;
3160#endif
3161
3162 Log3Func(("off=%#x cb=%#x\n", offRegLog, cb));
3163 Assert(cb == 4); Assert((off & 3) == 0);
3164
3165 rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_MMIO_READ);
3166 if (rc == VINF_SUCCESS)
3167 {
3168 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
3169 LogFunc(("Access to registers except GCTL is blocked while resetting\n"));
3170
3171 if (idxRegDsc >= 0)
3172 {
3173 /* ASSUMES gapless DWORD at end of map. */
3174 if (g_aHdaRegMap[idxRegDsc].size == 4)
3175 {
3176 /*
3177 * Straight forward DWORD access.
3178 */
3179 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pDevIns, pThis, idxRegDsc, (uint32_t *)pv);
3180 Log3Func(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, VBOXSTRICTRC_VAL(rc)));
3181 STAM_COUNTER_INC(&pThis->aStatRegReads[idxRegDsc]);
3182 }
3183#ifndef IN_RING3
3184 else if (!hdaIsMultiReadSafeInRZ(idxRegDsc))
3185
3186 {
3187 STAM_COUNTER_INC(&pThis->aStatRegReadsToR3[idxRegDsc]);
3188 rc = VINF_IOM_R3_MMIO_READ;
3189 }
3190#endif
3191 else
3192 {
3193 /*
3194 * Multi register read (unless there are trailing gaps).
3195 * ASSUMES that only DWORD reads have sideeffects.
3196 */
3197 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatRegMultiReads));
3198 Log4(("hdaMmioRead: multi read: %#x LB %#x %s\n", off, cb, g_aHdaRegMap[idxRegDsc].abbrev));
3199 uint32_t u32Value = 0;
3200 unsigned cbLeft = 4;
3201 do
3202 {
3203 uint32_t const cbReg = g_aHdaRegMap[idxRegDsc].size;
3204 uint32_t u32Tmp = 0;
3205
3206 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pDevIns, pThis, idxRegDsc, &u32Tmp);
3207 Log4Func(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, VBOXSTRICTRC_VAL(rc)));
3208 STAM_COUNTER_INC(&pThis->aStatRegReads[idxRegDsc]);
3209#ifdef IN_RING3
3210 if (rc != VINF_SUCCESS)
3211 break;
3212#else
3213 AssertMsgBreak(rc == VINF_SUCCESS, ("rc=%Rrc - impossible, we sanitized the readers!\n", VBOXSTRICTRC_VAL(rc)));
3214#endif
3215 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
3216
3217 cbLeft -= cbReg;
3218 off += cbReg;
3219 idxRegDsc++;
3220 } while (cbLeft > 0 && g_aHdaRegMap[idxRegDsc].offset == off);
3221
3222 if (rc == VINF_SUCCESS)
3223 *(uint32_t *)pv = u32Value;
3224 else
3225 Assert(!IOM_SUCCESS(rc));
3226 }
3227 }
3228 else
3229 {
3230 LogRel(("HDA: Invalid read access @0x%x (bytes=%u)\n", (uint32_t)off, cb));
3231 Log3Func(("\tHole at %x is accessed for read\n", offRegLog));
3232 STAM_COUNTER_INC(&pThis->StatRegUnknownReads);
3233 rc = VINF_IOM_MMIO_UNUSED_FF;
3234 }
3235
3236 DEVHDA_UNLOCK(pDevIns, pThis);
3237
3238 /*
3239 * Log the outcome.
3240 */
3241#ifdef LOG_ENABLED
3242 if (cbLog == 4)
3243 Log3Func(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, VBOXSTRICTRC_VAL(rc)));
3244 else if (cbLog == 2)
3245 Log3Func(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, VBOXSTRICTRC_VAL(rc)));
3246 else if (cbLog == 1)
3247 Log3Func(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, VBOXSTRICTRC_VAL(rc)));
3248#endif
3249 }
3250 else
3251 {
3252 if (idxRegDsc >= 0)
3253 STAM_COUNTER_INC(&pThis->aStatRegReadsToR3[idxRegDsc]);
3254 }
3255 return rc;
3256}
3257
3258
3259DECLINLINE(VBOXSTRICTRC) hdaWriteReg(PPDMDEVINS pDevIns, PHDASTATE pThis, int idxRegDsc, uint32_t u32Value, char const *pszLog)
3260{
3261 DEVHDA_LOCK_RETURN(pDevIns, pThis, VINF_IOM_R3_MMIO_WRITE);
3262
3263 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
3264 {
3265 Log(("hdaWriteReg: Warning: Access to %s is blocked while controller is in reset mode\n", g_aHdaRegMap[idxRegDsc].abbrev));
3266 LogRel2(("HDA: Warning: Access to register %s is blocked while controller is in reset mode\n",
3267 g_aHdaRegMap[idxRegDsc].abbrev));
3268 STAM_COUNTER_INC(&pThis->StatRegWritesBlockedByReset);
3269
3270 DEVHDA_UNLOCK(pDevIns, pThis);
3271 return VINF_SUCCESS;
3272 }
3273
3274 /*
3275 * Handle RD (register description) flags.
3276 */
3277
3278 /* For SDI / SDO: Check if writes to those registers are allowed while SDCTL's RUN bit is set. */
3279 if (idxRegDsc >= HDA_NUM_GENERAL_REGS)
3280 {
3281 const uint32_t uSDCTL = HDA_STREAM_REG(pThis, CTL, HDA_SD_NUM_FROM_REG(pThis, CTL, idxRegDsc));
3282
3283 /*
3284 * Some OSes (like Win 10 AU) violate the spec by writing stuff to registers which are not supposed to be be touched
3285 * while SDCTL's RUN bit is set. So just ignore those values.
3286 */
3287
3288 /* Is the RUN bit currently set? */
3289 if ( RT_BOOL(uSDCTL & HDA_SDCTL_RUN)
3290 /* Are writes to the register denied if RUN bit is set? */
3291 && !(g_aHdaRegMap[idxRegDsc].fFlags & HDA_RD_F_SD_WRITE_RUN))
3292 {
3293 Log(("hdaWriteReg: Warning: Access to %s is blocked! %R[sdctl]\n", g_aHdaRegMap[idxRegDsc].abbrev, uSDCTL));
3294 LogRel2(("HDA: Warning: Access to register %s is blocked while the stream's RUN bit is set\n",
3295 g_aHdaRegMap[idxRegDsc].abbrev));
3296 STAM_COUNTER_INC(&pThis->StatRegWritesBlockedByRun);
3297
3298 DEVHDA_UNLOCK(pDevIns, pThis);
3299 return VINF_SUCCESS;
3300 }
3301 }
3302
3303#ifdef LOG_ENABLED
3304 uint32_t const idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3305 uint32_t const u32OldValue = pThis->au32Regs[idxRegMem];
3306#endif
3307 VBOXSTRICTRC rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pDevIns, pThis, idxRegDsc, u32Value);
3308 Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s, rc=%d\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
3309 g_aHdaRegMap[idxRegDsc].size, u32OldValue, pThis->au32Regs[idxRegMem], pszLog, VBOXSTRICTRC_VAL(rc)));
3310#ifndef IN_RING3
3311 if (rc == VINF_IOM_R3_MMIO_WRITE)
3312 STAM_COUNTER_INC(&pThis->aStatRegWritesToR3[idxRegDsc]);
3313 else
3314#endif
3315 STAM_COUNTER_INC(&pThis->aStatRegWrites[idxRegDsc]);
3316
3317 DEVHDA_UNLOCK(pDevIns, pThis);
3318 RT_NOREF(pszLog);
3319 return rc;
3320}
3321
3322
3323/**
3324 * @callback_method_impl{FNIOMMMIONEWWRITE,
3325 * Looks up and calls the appropriate handler.}
3326 */
3327static DECLCALLBACK(VBOXSTRICTRC) hdaMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
3328{
3329 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
3330 RT_NOREF_PV(pvUser);
3331 Assert(pThis->uAlignmentCheckMagic == HDASTATE_ALIGNMENT_CHECK_MAGIC);
3332
3333 /*
3334 * Look up and log the access.
3335 */
3336 int idxRegDsc = hdaRegLookup(off);
3337#if defined(IN_RING3) || defined(LOG_ENABLED)
3338 uint32_t idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
3339#endif
3340 uint64_t u64Value;
3341 if (cb == 4) u64Value = *(uint32_t const *)pv;
3342 else if (cb == 2) u64Value = *(uint16_t const *)pv;
3343 else if (cb == 1) u64Value = *(uint8_t const *)pv;
3344 else if (cb == 8) u64Value = *(uint64_t const *)pv;
3345 else
3346 ASSERT_GUEST_MSG_FAILED_RETURN(("cb=%u %.*Rhxs\n", cb, cb, pv),
3347 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "odd write size: off=%RGp cb=%u\n", off, cb));
3348
3349 /*
3350 * The behavior of accesses that aren't aligned on natural boundraries is
3351 * undefined. Just reject them outright.
3352 */
3353 ASSERT_GUEST_MSG_RETURN((off & (cb - 1)) == 0, ("off=%RGp cb=%u %.*Rhxs\n", off, cb, cb, pv),
3354 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: off=%RGp cb=%u\n", off, cb));
3355
3356#ifdef LOG_ENABLED
3357 uint32_t const u32LogOldValue = idxRegDsc >= 0 ? pThis->au32Regs[idxRegMem] : UINT32_MAX;
3358#endif
3359
3360 /*
3361 * Try for a direct hit first.
3362 */
3363 VBOXSTRICTRC rc;
3364 if (idxRegDsc >= 0 && g_aHdaRegMap[idxRegDsc].size == cb)
3365 {
3366 Log3Func(("@%#05x u%u=%#0*RX64 %s\n", (uint32_t)off, cb * 8, 2 + cb * 2, u64Value, g_aHdaRegMap[idxRegDsc].abbrev));
3367 rc = hdaWriteReg(pDevIns, pThis, idxRegDsc, u64Value, "");
3368 Log3Func(("\t%#x -> %#x\n", u32LogOldValue, idxRegMem != UINT32_MAX ? pThis->au32Regs[idxRegMem] : UINT32_MAX));
3369 }
3370 /*
3371 * Sub-register access. Supply missing bits as needed.
3372 */
3373 else if ( idxRegDsc >= 0
3374 && cb < g_aHdaRegMap[idxRegDsc].size)
3375 {
3376 u64Value |= pThis->au32Regs[g_aHdaRegMap[idxRegDsc].mem_idx]
3377 & g_afMasks[g_aHdaRegMap[idxRegDsc].size]
3378 & ~g_afMasks[cb];
3379 Log4Func(("@%#05x u%u=%#0*RX64 cb=%#x cbReg=%x %s\n"
3380 "\tSupplying missing bits (%#x): %#llx -> %#llx ...\n",
3381 (uint32_t)off, cb * 8, 2 + cb * 2, u64Value, cb, g_aHdaRegMap[idxRegDsc].size, g_aHdaRegMap[idxRegDsc].abbrev,
3382 g_afMasks[g_aHdaRegMap[idxRegDsc].size] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
3383 rc = hdaWriteReg(pDevIns, pThis, idxRegDsc, u64Value, "");
3384 Log4Func(("\t%#x -> %#x\n", u32LogOldValue, idxRegMem != UINT32_MAX ? pThis->au32Regs[idxRegMem] : UINT32_MAX));
3385 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatRegSubWrite));
3386 }
3387 /*
3388 * Partial or multiple register access, loop thru the requested memory.
3389 */
3390 else
3391 {
3392#ifdef IN_RING3
3393 if (idxRegDsc == -1)
3394 Log4Func(("@%#05x u32=%#010x cb=%d\n", (uint32_t)off, *(uint32_t const *)pv, cb));
3395 else if (g_aHdaRegMap[idxRegDsc].size == cb)
3396 Log4Func(("@%#05x u%u=%#0*RX64 %s\n", (uint32_t)off, cb * 8, 2 + cb * 2, u64Value, g_aHdaRegMap[idxRegDsc].abbrev));
3397 else
3398 Log4Func(("@%#05x u%u=%#0*RX64 %s - mismatch cbReg=%u\n", (uint32_t)off, cb * 8, 2 + cb * 2, u64Value,
3399 g_aHdaRegMap[idxRegDsc].abbrev, g_aHdaRegMap[idxRegDsc].size));
3400
3401 /*
3402 * If it's an access beyond the start of the register, shift the input
3403 * value and fill in missing bits. Natural alignment rules means we
3404 * will only see 1 or 2 byte accesses of this kind, so no risk of
3405 * shifting out input values.
3406 */
3407 if (idxRegDsc < 0)
3408 {
3409 idxRegDsc = hdaR3RegLookupWithin(off);
3410 if (idxRegDsc != -1)
3411 {
3412 uint32_t const cbBefore = (uint32_t)off - g_aHdaRegMap[idxRegDsc].offset;
3413 Assert(cbBefore > 0 && cbBefore < 4);
3414 off -= cbBefore;
3415 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3416 u64Value <<= cbBefore * 8;
3417 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbBefore];
3418 Log4Func(("\tWithin register, supplied %u leading bits: %#llx -> %#llx ...\n",
3419 cbBefore * 8, ~(uint64_t)g_afMasks[cbBefore] & u64Value, u64Value));
3420 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatRegMultiWrites));
3421 }
3422 else
3423 STAM_COUNTER_INC(&pThis->StatRegUnknownWrites);
3424 }
3425 else
3426 {
3427 Log4(("hdaMmioWrite: multi write: %s\n", g_aHdaRegMap[idxRegDsc].abbrev));
3428 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatRegMultiWrites));
3429 }
3430
3431 /* Loop thru the write area, it may cover multiple registers. */
3432 rc = VINF_SUCCESS;
3433 for (;;)
3434 {
3435 uint32_t cbReg;
3436 if (idxRegDsc >= 0)
3437 {
3438 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3439 cbReg = g_aHdaRegMap[idxRegDsc].size;
3440 if (cb < cbReg)
3441 {
3442 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbReg] & ~g_afMasks[cb];
3443 Log4Func(("\tSupplying missing bits (%#x): %#llx -> %#llx ...\n",
3444 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
3445 }
3446# ifdef LOG_ENABLED
3447 uint32_t uLogOldVal = pThis->au32Regs[idxRegMem];
3448# endif
3449 rc = hdaWriteReg(pDevIns, pThis, idxRegDsc, u64Value & g_afMasks[cbReg], "*");
3450 Log4Func(("\t%#x -> %#x\n", uLogOldVal, pThis->au32Regs[idxRegMem]));
3451 }
3452 else
3453 {
3454 LogRel(("HDA: Invalid write access @0x%x\n", (uint32_t)off));
3455 cbReg = 1;
3456 }
3457 if (rc != VINF_SUCCESS)
3458 break;
3459 if (cbReg >= cb)
3460 break;
3461
3462 /* Advance. */
3463 off += cbReg;
3464 cb -= cbReg;
3465 u64Value >>= cbReg * 8;
3466 if (idxRegDsc == -1)
3467 idxRegDsc = hdaRegLookup(off);
3468 else
3469 {
3470 idxRegDsc++;
3471 if ( (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
3472 || g_aHdaRegMap[idxRegDsc].offset != off)
3473 idxRegDsc = -1;
3474 }
3475 }
3476
3477#else /* !IN_RING3 */
3478 /* Take the simple way out. */
3479 rc = VINF_IOM_R3_MMIO_WRITE;
3480#endif /* !IN_RING3 */
3481 }
3482
3483 return rc;
3484}
3485
3486#ifdef IN_RING3
3487
3488
3489/*********************************************************************************************************************************
3490* Saved state *
3491*********************************************************************************************************************************/
3492
3493/**
3494 * @callback_method_impl{FNSSMFIELDGETPUT,
3495 * Version 6 saves the IOC flag in HDABDLEDESC::fFlags as a bool}
3496 */
3497static DECLCALLBACK(int)
3498hdaR3GetPutTrans_HDABDLEDESC_fFlags_6(PSSMHANDLE pSSM, const struct SSMFIELD *pField, void *pvStruct,
3499 uint32_t fFlags, bool fGetOrPut, void *pvUser)
3500{
3501 PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;
3502 RT_NOREF(pSSM, pField, pvStruct, fFlags);
3503 AssertReturn(fGetOrPut, VERR_INTERNAL_ERROR_4);
3504 bool fIoc;
3505 int rc = pDevIns->pHlpR3->pfnSSMGetBool(pSSM, &fIoc);
3506 if (RT_SUCCESS(rc))
3507 {
3508 PHDABDLEDESC pDesc = (PHDABDLEDESC)pvStruct;
3509 pDesc->fFlags = fIoc ? HDA_BDLE_F_IOC : 0;
3510 }
3511 return rc;
3512}
3513
3514
3515/**
3516 * @callback_method_impl{FNSSMFIELDGETPUT,
3517 * Versions 1 thru 4 save the IOC flag in HDASTREAMSTATE::DescfFlags as a bool}
3518 */
3519static DECLCALLBACK(int)
3520hdaR3GetPutTrans_HDABDLE_Desc_fFlags_1thru4(PSSMHANDLE pSSM, const struct SSMFIELD *pField, void *pvStruct,
3521 uint32_t fFlags, bool fGetOrPut, void *pvUser)
3522{
3523 PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;
3524 RT_NOREF(pSSM, pField, pvStruct, fFlags);
3525 AssertReturn(fGetOrPut, VERR_INTERNAL_ERROR_4);
3526 bool fIoc;
3527 int rc = pDevIns->pHlpR3->pfnSSMGetBool(pSSM, &fIoc);
3528 if (RT_SUCCESS(rc))
3529 {
3530 PHDABDLE pState = (PHDABDLE)pvStruct;
3531 pState->Desc.fFlags = fIoc ? HDA_BDLE_F_IOC : 0;
3532 }
3533 return rc;
3534}
3535
3536
3537static int hdaR3SaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStreamShared, PHDASTREAMR3 pStreamR3)
3538{
3539 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
3540# ifdef LOG_ENABLED
3541 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
3542# endif
3543
3544 Log2Func(("[SD%RU8]\n", pStreamShared->u8SD));
3545
3546 /* Save stream ID. */
3547 Assert(pStreamShared->u8SD < HDA_MAX_STREAMS);
3548 int rc = pHlp->pfnSSMPutU8(pSSM, pStreamShared->u8SD);
3549 AssertRCReturn(rc, rc);
3550
3551 rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State, sizeof(pStreamShared->State),
3552 0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
3553 AssertRCReturn(rc, rc);
3554
3555 rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(pStreamShared->State.BDLE.Desc),
3556 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
3557 AssertRCReturn(rc, rc);
3558
3559 rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(pStreamShared->State.BDLE.State),
3560 0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
3561 AssertRCReturn(rc, rc);
3562
3563 rc = pHlp->pfnSSMPutStructEx(pSSM, &pStreamShared->State.Period, sizeof(pStreamShared->State.Period),
3564 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
3565 AssertRCReturn(rc, rc);
3566
3567 uint32_t cbCircBufSize = 0;
3568 uint32_t cbCircBufUsed = 0;
3569
3570 if (pStreamR3->State.pCircBuf)
3571 {
3572 cbCircBufSize = (uint32_t)RTCircBufSize(pStreamR3->State.pCircBuf);
3573 cbCircBufUsed = (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf);
3574 }
3575
3576 rc = pHlp->pfnSSMPutU32(pSSM, cbCircBufSize);
3577 AssertRCReturn(rc, rc);
3578
3579 rc = pHlp->pfnSSMPutU32(pSSM, cbCircBufUsed);
3580 AssertRCReturn(rc, rc);
3581
3582 if (cbCircBufUsed)
3583 {
3584 /*
3585 * We now need to get the circular buffer's data without actually modifying
3586 * the internal read / used offsets -- otherwise we would end up with broken audio
3587 * data after saving the state.
3588 *
3589 * So get the current read offset and serialize the buffer data manually based on that.
3590 */
3591 size_t const offBuf = RTCircBufOffsetRead(pStreamR3->State.pCircBuf);
3592 void *pvBuf;
3593 size_t cbBuf;
3594 RTCircBufAcquireReadBlock(pStreamR3->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
3595 Assert(cbBuf);
3596 if (cbBuf)
3597 {
3598 rc = pHlp->pfnSSMPutMem(pSSM, pvBuf, cbBuf);
3599 AssertRC(rc);
3600 if ( RT_SUCCESS(rc)
3601 && cbBuf < cbCircBufUsed)
3602 {
3603 rc = pHlp->pfnSSMPutMem(pSSM, (uint8_t *)pvBuf - offBuf, cbCircBufUsed - cbBuf);
3604 }
3605 }
3606 RTCircBufReleaseReadBlock(pStreamR3->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
3607 }
3608
3609 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n", pStreamR3->u8SD, HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD),
3610 HDA_STREAM_REG(pThis, CBL, pStreamShared->u8SD), HDA_STREAM_REG(pThis, LVI, pStreamShared->u8SD)));
3611
3612#ifdef LOG_ENABLED
3613 hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
3614#endif
3615
3616 return rc;
3617}
3618
3619/**
3620 * @callback_method_impl{FNSSMDEVSAVEEXEC}
3621 */
3622static DECLCALLBACK(int) hdaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
3623{
3624 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
3625 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
3626 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
3627
3628 /* Save Codec nodes states. */
3629 hdaCodecSaveState(pDevIns, &pThis->Codec, pSSM);
3630
3631 /* Save MMIO registers. */
3632 pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
3633 pHlp->pfnSSMPutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3634
3635 /* Save controller-specifc internals. */
3636 pHlp->pfnSSMPutU64(pSSM, pThis->u64WalClk);
3637 pHlp->pfnSSMPutU8(pSSM, pThis->u8IRQL);
3638
3639 /* Save number of streams. */
3640 pHlp->pfnSSMPutU32(pSSM, HDA_MAX_STREAMS);
3641
3642 /* Save stream states. */
3643 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
3644 {
3645 int rc = hdaR3SaveStream(pDevIns, pSSM, &pThis->aStreams[i], &pThisCC->aStreams[i]);
3646 AssertRCReturn(rc, rc);
3647 }
3648
3649 return VINF_SUCCESS;
3650}
3651
3652/**
3653 * Does required post processing when loading a saved state.
3654 *
3655 * @param pDevIns The device instance.
3656 * @param pThis Pointer to the shared HDA state.
3657 * @param pThisCC Pointer to the ring-3 HDA state.
3658 */
3659static int hdaR3LoadExecPost(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC)
3660{
3661 int rc = VINF_SUCCESS; /** @todo r=bird: Really, what's the point of this? */
3662
3663 /*
3664 * Enable all previously active streams.
3665 */
3666 for (size_t i = 0; i < HDA_MAX_STREAMS; i++)
3667 {
3668 PHDASTREAM pStreamShared = &pThis->aStreams[i];
3669
3670 bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
3671 if (fActive)
3672 {
3673 PHDASTREAMR3 pStreamR3 = &pThisCC->aStreams[i];
3674
3675 int rc2;
3676#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
3677 /* Make sure to also create the async I/O thread before actually enabling the stream. */
3678 rc2 = hdaR3StreamAsyncIOCreate(pStreamR3);
3679 AssertRC(rc2);
3680
3681 /* ... and enabling it. */
3682 hdaR3StreamAsyncIOEnable(pStreamR3, true /* fEnable */);
3683#endif
3684 /* Resume the stream's period. */
3685 hdaR3StreamPeriodResume(&pStreamShared->State.Period);
3686
3687 /* (Re-)enable the stream. */
3688 rc2 = hdaR3StreamEnable(pStreamShared, pStreamR3, true /* fEnable */);
3689 AssertRC(rc2);
3690
3691 /* Add the stream to the device setup. */
3692 rc2 = hdaR3AddStream(pThisCC, &pStreamShared->State.Cfg);
3693 AssertRC(rc2);
3694
3695#ifdef HDA_USE_DMA_ACCESS_HANDLER
3696 /* (Re-)install the DMA handler. */
3697 hdaR3StreamRegisterDMAHandlers(pThis, pStreamShared);
3698#endif
3699 if (hdaR3StreamTransferIsScheduled(pStreamShared, PDMDevHlpTimerGet(pDevIns, pStreamShared->hTimer)))
3700 hdaR3TimerSet(pDevIns, pStreamShared, hdaR3StreamTransferGetNext(pStreamShared), true /*fForce*/, 0 /*tsNow*/);
3701
3702 /* Also keep track of the currently active streams. */
3703 pThisCC->cStreamsActive++;
3704 }
3705 }
3706
3707 LogFlowFuncLeaveRC(rc);
3708 return rc;
3709}
3710
3711
3712/**
3713 * Handles loading of all saved state versions older than the current one.
3714 *
3715 * @param pDevIns The device instance.
3716 * @param pThis Pointer to the shared HDA state.
3717 * @param pThisCC Pointer to the ring-3 HDA state.
3718 * @param pSSM Pointer to SSM handle.
3719 * @param uVersion Saved state version to load.
3720 */
3721static int hdaR3LoadExecLegacy(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PSSMHANDLE pSSM, uint32_t uVersion)
3722{
3723 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
3724 int rc;
3725
3726 /*
3727 * Load MMIO registers.
3728 */
3729 uint32_t cRegs;
3730 switch (uVersion)
3731 {
3732 case HDA_SAVED_STATE_VERSION_1:
3733 /* Starting with r71199, we would save 112 instead of 113
3734 registers due to some code cleanups. This only affected trunk
3735 builds in the 4.1 development period. */
3736 cRegs = 113;
3737 if (pHlp->pfnSSMHandleRevision(pSSM) >= 71199)
3738 {
3739 uint32_t uVer = pHlp->pfnSSMHandleVersion(pSSM);
3740 if ( VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
3741 && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
3742 && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
3743 cRegs = 112;
3744 }
3745 break;
3746
3747 case HDA_SAVED_STATE_VERSION_2:
3748 case HDA_SAVED_STATE_VERSION_3:
3749 cRegs = 112;
3750 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= 112);
3751 break;
3752
3753 /* Since version 4 we store the register count to stay flexible. */
3754 case HDA_SAVED_STATE_VERSION_4:
3755 case HDA_SAVED_STATE_VERSION_5:
3756 case HDA_SAVED_STATE_VERSION_6:
3757 rc = pHlp->pfnSSMGetU32(pSSM, &cRegs);
3758 AssertRCReturn(rc, rc);
3759 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
3760 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
3761 break;
3762
3763 default:
3764 AssertLogRelMsgFailedReturn(("HDA: Internal Error! Didn't expect saved state version %RU32 ending up in hdaR3LoadExecLegacy!\n",
3765 uVersion), VERR_INTERNAL_ERROR_5);
3766 }
3767
3768 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
3769 {
3770 pHlp->pfnSSMGetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3771 pHlp->pfnSSMSkip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
3772 }
3773 else
3774 pHlp->pfnSSMGetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
3775
3776 /* Make sure to update the base addresses first before initializing any streams down below. */
3777 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
3778 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
3779 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
3780
3781 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
3782 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
3783
3784 /*
3785 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
3786 *
3787 * Note: Saved states < v5 store LVI (u32BdleMaxCvi) for
3788 * *every* BDLE state, whereas it only needs to be stored
3789 * *once* for every stream. Most of the BDLE state we can
3790 * get out of the registers anyway, so just ignore those values.
3791 *
3792 * Also, only the current BDLE was saved, regardless whether
3793 * there were more than one (and there are at least two entries,
3794 * according to the spec).
3795 */
3796 switch (uVersion)
3797 {
3798 case HDA_SAVED_STATE_VERSION_1:
3799 case HDA_SAVED_STATE_VERSION_2:
3800 case HDA_SAVED_STATE_VERSION_3:
3801 case HDA_SAVED_STATE_VERSION_4:
3802 {
3803 /* Only load the internal states.
3804 * The rest will be initialized from the saved registers later. */
3805
3806 /* Note 1: Only the *current* BDLE for a stream was saved! */
3807 /* Note 2: The stream's saving order is/was fixed, so don't touch! */
3808
3809 /* Output */
3810 PHDASTREAM pStreamShared = &pThis->aStreams[4];
3811 rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[4], 4 /* Stream descriptor, hardcoded */);
3812 AssertRCReturn(rc, rc);
3813 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
3814 0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
3815 AssertRCReturn(rc, rc);
3816 pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
3817
3818 /* Microphone-In */
3819 pStreamShared = &pThis->aStreams[2];
3820 rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[2], 2 /* Stream descriptor, hardcoded */);
3821 AssertRCReturn(rc, rc);
3822 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
3823 0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
3824 AssertRCReturn(rc, rc);
3825 pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
3826
3827 /* Line-In */
3828 pStreamShared = &pThis->aStreams[0];
3829 rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, &pThisCC->aStreams[0], 0 /* Stream descriptor, hardcoded */);
3830 AssertRCReturn(rc, rc);
3831 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE, sizeof(pStreamShared->State.BDLE),
3832 0 /* fFlags */, g_aSSMStreamBdleFields1234, pDevIns);
3833 AssertRCReturn(rc, rc);
3834 pStreamShared->State.uCurBDLE = pStreamShared->State.BDLE.State.u32BDLIndex;
3835 break;
3836 }
3837
3838 /*
3839 * v5 & v6 - Since v5 we support flexible stream and BDLE counts.
3840 */
3841 default:
3842 {
3843 /* Stream count. */
3844 uint32_t cStreams;
3845 rc = pHlp->pfnSSMGetU32(pSSM, &cStreams);
3846 AssertRCReturn(rc, rc);
3847 if (cStreams > HDA_MAX_STREAMS)
3848 return pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
3849 N_("State contains %u streams while %u is the maximum supported"),
3850 cStreams, HDA_MAX_STREAMS);
3851
3852 /* Load stream states. */
3853 for (uint32_t i = 0; i < cStreams; i++)
3854 {
3855 uint8_t idStream;
3856 rc = pHlp->pfnSSMGetU8(pSSM, &idStream);
3857 AssertRCReturn(rc, rc);
3858
3859 HDASTREAM StreamDummyShared;
3860 HDASTREAMR3 StreamDummyR3;
3861 PHDASTREAM pStreamShared = idStream < RT_ELEMENTS(pThis->aStreams) ? &pThis->aStreams[idStream] : &StreamDummyShared;
3862 PHDASTREAMR3 pStreamR3 = idStream < RT_ELEMENTS(pThisCC->aStreams) ? &pThisCC->aStreams[idStream] : &StreamDummyR3;
3863 AssertLogRelMsgStmt(idStream < RT_ELEMENTS(pThisCC->aStreams),
3864 ("HDA stream ID=%RU8 not supported, skipping loadingit ...\n", idStream),
3865 RT_ZERO(StreamDummyShared); RT_ZERO(StreamDummyR3));
3866
3867 rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, idStream);
3868 if (RT_FAILURE(rc))
3869 {
3870 LogRel(("HDA: Stream #%RU32: Setting up of stream %RU8 failed, rc=%Rrc\n", i, idStream, rc));
3871 break;
3872 }
3873
3874 /*
3875 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
3876 */
3877 if (uVersion == HDA_SAVED_STATE_VERSION_5)
3878 {
3879 struct V5HDASTREAMSTATE /* HDASTREAMSTATE + HDABDLE */
3880 {
3881 uint16_t cBLDEs;
3882 uint16_t uCurBDLE;
3883 uint32_t u32BDLEIndex;
3884 uint32_t cbBelowFIFOW;
3885 uint32_t u32BufOff;
3886 } Tmp;
3887 static SSMFIELD const g_aV5State1Fields[] =
3888 {
3889 SSMFIELD_ENTRY(V5HDASTREAMSTATE, cBLDEs),
3890 SSMFIELD_ENTRY(V5HDASTREAMSTATE, uCurBDLE),
3891 SSMFIELD_ENTRY_TERM()
3892 };
3893 rc = pHlp->pfnSSMGetStructEx(pSSM, &Tmp, sizeof(Tmp), 0 /* fFlags */, g_aV5State1Fields, NULL);
3894 AssertRCReturn(rc, rc);
3895 pStreamShared->State.uCurBDLE = Tmp.uCurBDLE;
3896
3897 for (uint16_t a = 0; a < Tmp.cBLDEs; a++)
3898 {
3899 static SSMFIELD const g_aV5State2Fields[] =
3900 {
3901 SSMFIELD_ENTRY(V5HDASTREAMSTATE, u32BDLEIndex),
3902 SSMFIELD_ENTRY_OLD(au8FIFO, 256),
3903 SSMFIELD_ENTRY(V5HDASTREAMSTATE, cbBelowFIFOW),
3904 SSMFIELD_ENTRY_TERM()
3905 };
3906 rc = pHlp->pfnSSMGetStructEx(pSSM, &Tmp, sizeof(Tmp), 0 /* fFlags */, g_aV5State2Fields, NULL);
3907 AssertRCReturn(rc, rc);
3908 if (Tmp.u32BDLEIndex == pStreamShared->State.uCurBDLE)
3909 {
3910 pStreamShared->State.BDLE.State.cbBelowFIFOW = Tmp.cbBelowFIFOW;
3911 pStreamShared->State.BDLE.State.u32BufOff = Tmp.u32BufOff;
3912 }
3913 }
3914 }
3915 else
3916 {
3917 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State, sizeof(HDASTREAMSTATE),
3918 0 /* fFlags */, g_aSSMStreamStateFields6, NULL);
3919 AssertRCReturn(rc, rc);
3920
3921 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(pStreamShared->State.BDLE.Desc),
3922 0 /* fFlags */, g_aSSMBDLEDescFields6, pDevIns);
3923 AssertRCReturn(rc, rc);
3924
3925 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(HDABDLESTATE),
3926 0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
3927 AssertRCReturn(rc, rc);
3928
3929 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n", idStream, HDA_STREAM_REG(pThis, LPIB, idStream),
3930 HDA_STREAM_REG(pThis, CBL, idStream), HDA_STREAM_REG(pThis, LVI, idStream)));
3931#ifdef LOG_ENABLED
3932 hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
3933#endif
3934 }
3935
3936 } /* for cStreams */
3937 break;
3938 } /* default */
3939 }
3940
3941 return rc;
3942}
3943
3944/**
3945 * @callback_method_impl{FNSSMDEVLOADEXEC}
3946 */
3947static DECLCALLBACK(int) hdaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3948{
3949 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
3950 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
3951 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
3952
3953 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3954
3955 LogRel2(("hdaR3LoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
3956
3957 /*
3958 * Load Codec nodes states.
3959 */
3960 int rc = hdaR3CodecLoadState(pDevIns, &pThis->Codec, pThisCC->pCodec, pSSM, uVersion);
3961 if (RT_FAILURE(rc))
3962 {
3963 LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
3964 return rc;
3965 }
3966
3967 if (uVersion <= HDA_SAVED_STATE_VERSION_6) /* Handle older saved states? */
3968 {
3969 rc = hdaR3LoadExecLegacy(pDevIns, pThis, pThisCC, pSSM, uVersion);
3970 if (RT_SUCCESS(rc))
3971 rc = hdaR3LoadExecPost(pDevIns, pThis, pThisCC);
3972 return rc;
3973 }
3974
3975 /*
3976 * Load MMIO registers.
3977 */
3978 uint32_t cRegs;
3979 rc = pHlp->pfnSSMGetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
3980 AssertRCReturn(rc, rc);
3981 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
3982 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
3983
3984 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
3985 {
3986 pHlp->pfnSSMGetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3987 rc = pHlp->pfnSSMSkip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
3988 AssertRCReturn(rc, rc);
3989 }
3990 else
3991 {
3992 rc = pHlp->pfnSSMGetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
3993 AssertRCReturn(rc, rc);
3994 }
3995
3996 /* Make sure to update the base addresses first before initializing any streams down below. */
3997 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
3998 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
3999 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
4000
4001 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
4002 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
4003
4004 /*
4005 * Load controller-specifc internals.
4006 * Don't annoy other team mates (forgot this for state v7).
4007 */
4008 if ( pHlp->pfnSSMHandleRevision(pSSM) >= 116273
4009 || pHlp->pfnSSMHandleVersion(pSSM) >= VBOX_FULL_VERSION_MAKE(5, 2, 0))
4010 {
4011 pHlp->pfnSSMGetU64(pSSM, &pThis->u64WalClk);
4012 rc = pHlp->pfnSSMGetU8(pSSM, &pThis->u8IRQL);
4013 AssertRCReturn(rc, rc);
4014 }
4015
4016 /*
4017 * Load streams.
4018 */
4019 uint32_t cStreams;
4020 rc = pHlp->pfnSSMGetU32(pSSM, &cStreams);
4021 AssertRCReturn(rc, rc);
4022 if (cStreams > HDA_MAX_STREAMS)
4023 return pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
4024 N_("State contains %u streams while %u is the maximum supported"),
4025 cStreams, HDA_MAX_STREAMS);
4026 Log2Func(("cStreams=%RU32\n", cStreams));
4027
4028 /* Load stream states. */
4029 for (uint32_t i = 0; i < cStreams; i++)
4030 {
4031 uint8_t idStream;
4032 rc = pHlp->pfnSSMGetU8(pSSM, &idStream);
4033 AssertRCReturn(rc, rc);
4034
4035 /* Paranoia. */
4036 AssertLogRelMsgReturn(idStream < HDA_MAX_STREAMS,
4037 ("HDA: Saved state contains bogus stream ID %RU8 for stream #%RU8", idStream, i),
4038 VERR_SSM_INVALID_STATE);
4039
4040 HDASTREAM StreamDummyShared;
4041 HDASTREAMR3 StreamDummyR3;
4042 PHDASTREAM pStreamShared = idStream < RT_ELEMENTS(pThis->aStreams) ? &pThis->aStreams[idStream] : &StreamDummyShared;
4043 PHDASTREAMR3 pStreamR3 = idStream < RT_ELEMENTS(pThisCC->aStreams) ? &pThisCC->aStreams[idStream] : &StreamDummyR3;
4044 AssertLogRelMsgStmt(idStream < RT_ELEMENTS(pThisCC->aStreams),
4045 ("HDA stream ID=%RU8 not supported, skipping loadingit ...\n", idStream),
4046 RT_ZERO(StreamDummyShared); RT_ZERO(StreamDummyR3));
4047
4048 rc = hdaR3StreamSetUp(pDevIns, pThis, pStreamShared, pStreamR3, idStream);
4049 if (RT_FAILURE(rc))
4050 {
4051 LogRel(("HDA: Stream #%RU8: Setting up failed, rc=%Rrc\n", idStream, rc));
4052 /* Continue. */
4053 }
4054
4055 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State, sizeof(HDASTREAMSTATE),
4056 0 /* fFlags */, g_aSSMStreamStateFields7, NULL);
4057 AssertRCReturn(rc, rc);
4058
4059 /*
4060 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
4061 */
4062 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.Desc, sizeof(HDABDLEDESC),
4063 0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
4064 AssertRCReturn(rc, rc);
4065
4066 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.BDLE.State, sizeof(HDABDLESTATE),
4067 0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
4068 AssertRCReturn(rc, rc);
4069
4070 Log2Func(("[SD%RU8] %R[bdle]\n", pStreamShared->u8SD, &pStreamShared->State.BDLE));
4071
4072 /*
4073 * Load period state.
4074 */
4075 hdaR3StreamPeriodInit(&pStreamShared->State.Period, pStreamShared->u8SD, pStreamShared->u16LVI,
4076 pStreamShared->u32CBL, &pStreamShared->State.Cfg);
4077
4078 rc = pHlp->pfnSSMGetStructEx(pSSM, &pStreamShared->State.Period, sizeof(pStreamShared->State.Period),
4079 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
4080 AssertRCReturn(rc, rc);
4081
4082 /*
4083 * Load internal (FIFO) buffer.
4084 */
4085 uint32_t cbCircBufSize = 0;
4086 pHlp->pfnSSMGetU32(pSSM, &cbCircBufSize); /* cbCircBuf */
4087 uint32_t cbCircBufUsed = 0;
4088 rc = pHlp->pfnSSMGetU32(pSSM, &cbCircBufUsed); /* cbCircBuf */
4089 AssertRCReturn(rc, rc);
4090
4091 if (cbCircBufSize) /* If 0, skip the buffer. */
4092 {
4093 /* Paranoia. */
4094 AssertLogRelMsgReturn(cbCircBufSize <= _32M,
4095 ("HDA: Saved state contains bogus DMA buffer size (%RU32) for stream #%RU8",
4096 cbCircBufSize, idStream),
4097 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
4098 AssertLogRelMsgReturn(cbCircBufUsed <= cbCircBufSize,
4099 ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
4100 cbCircBufUsed, cbCircBufSize, idStream),
4101 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
4102
4103 /* Do we need to cre-create the circular buffer do fit the data size? */
4104 if ( pStreamR3->State.pCircBuf
4105 && cbCircBufSize != (uint32_t)RTCircBufSize(pStreamR3->State.pCircBuf))
4106 {
4107 RTCircBufDestroy(pStreamR3->State.pCircBuf);
4108 pStreamR3->State.pCircBuf = NULL;
4109 }
4110
4111 rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBufSize);
4112 AssertRCReturn(rc, rc);
4113
4114 if (cbCircBufUsed)
4115 {
4116 void *pvBuf;
4117 size_t cbBuf;
4118 RTCircBufAcquireWriteBlock(pStreamR3->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
4119
4120 AssertLogRelMsgReturn(cbBuf == cbCircBufUsed, ("cbBuf=%zu cbCircBufUsed=%zu\n", cbBuf, cbCircBufUsed),
4121 VERR_INTERNAL_ERROR_3);
4122 rc = pHlp->pfnSSMGetMem(pSSM, pvBuf, cbBuf);
4123 AssertRCReturn(rc, rc);
4124
4125 RTCircBufReleaseWriteBlock(pStreamR3->State.pCircBuf, cbBuf);
4126
4127 Assert(cbBuf == cbCircBufUsed);
4128 }
4129 }
4130
4131 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n", idStream, HDA_STREAM_REG(pThis, LPIB, idStream),
4132 HDA_STREAM_REG(pThis, CBL, idStream), HDA_STREAM_REG(pThis, LVI, idStream)));
4133#ifdef LOG_ENABLED
4134 hdaR3BDLEDumpAll(pDevIns, pThis, pStreamShared->u64BDLBase, pStreamShared->u16LVI + 1);
4135#endif
4136 /** @todo (Re-)initialize active periods? */
4137
4138 } /* for cStreams */
4139
4140 rc = hdaR3LoadExecPost(pDevIns, pThis, pThisCC);
4141 AssertRC(rc);
4142
4143 LogFlowFuncLeaveRC(rc);
4144 return rc;
4145}
4146
4147
4148/*********************************************************************************************************************************
4149* IPRT format type handlers *
4150*********************************************************************************************************************************/
4151
4152/**
4153 * @callback_method_impl{FNRTSTRFORMATTYPE}
4154 */
4155static DECLCALLBACK(size_t) hdaR3StrFmtBDLE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4156 const char *pszType, void const *pvValue,
4157 int cchWidth, int cchPrecision, unsigned fFlags,
4158 void *pvUser)
4159{
4160 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4161 PHDABDLE pBDLE = (PHDABDLE)pvValue;
4162 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4163 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])",
4164 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,
4165 pBDLE->Desc.fFlags & HDA_BDLE_F_IOC, pBDLE->Desc.u32BufSize, pBDLE->Desc.u64BufAddr);
4166}
4167
4168/**
4169 * @callback_method_impl{FNRTSTRFORMATTYPE}
4170 */
4171static DECLCALLBACK(size_t) hdaR3StrFmtSDCTL(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4172 const char *pszType, void const *pvValue,
4173 int cchWidth, int cchPrecision, unsigned fFlags,
4174 void *pvUser)
4175{
4176 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4177 uint32_t uSDCTL = (uint32_t)(uintptr_t)pvValue;
4178 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4179 "SDCTL(raw:%#x, DIR:%s, TP:%RTbool, STRIPE:%x, DEIE:%RTbool, FEIE:%RTbool, IOCE:%RTbool, RUN:%RTbool, RESET:%RTbool)",
4180 uSDCTL,
4181 uSDCTL & HDA_SDCTL_DIR ? "OUT" : "IN",
4182 RT_BOOL(uSDCTL & HDA_SDCTL_TP),
4183 (uSDCTL & HDA_SDCTL_STRIPE_MASK) >> HDA_SDCTL_STRIPE_SHIFT,
4184 RT_BOOL(uSDCTL & HDA_SDCTL_DEIE),
4185 RT_BOOL(uSDCTL & HDA_SDCTL_FEIE),
4186 RT_BOOL(uSDCTL & HDA_SDCTL_IOCE),
4187 RT_BOOL(uSDCTL & HDA_SDCTL_RUN),
4188 RT_BOOL(uSDCTL & HDA_SDCTL_SRST));
4189}
4190
4191/**
4192 * @callback_method_impl{FNRTSTRFORMATTYPE}
4193 */
4194static DECLCALLBACK(size_t) hdaR3StrFmtSDFIFOS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4195 const char *pszType, void const *pvValue,
4196 int cchWidth, int cchPrecision, unsigned fFlags,
4197 void *pvUser)
4198{
4199 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4200 uint32_t uSDFIFOS = (uint32_t)(uintptr_t)pvValue;
4201 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw:%#x, sdfifos:%RU8 B)", uSDFIFOS, uSDFIFOS ? uSDFIFOS + 1 : 0);
4202}
4203
4204/**
4205 * @callback_method_impl{FNRTSTRFORMATTYPE}
4206 */
4207static DECLCALLBACK(size_t) hdaR3StrFmtSDFIFOW(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4208 const char *pszType, void const *pvValue,
4209 int cchWidth, int cchPrecision, unsigned fFlags,
4210 void *pvUser)
4211{
4212 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4213 uint32_t uSDFIFOW = (uint32_t)(uintptr_t)pvValue;
4214 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSDFIFOW, hdaSDFIFOWToBytes(uSDFIFOW));
4215}
4216
4217/**
4218 * @callback_method_impl{FNRTSTRFORMATTYPE}
4219 */
4220static DECLCALLBACK(size_t) hdaR3StrFmtSDSTS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4221 const char *pszType, void const *pvValue,
4222 int cchWidth, int cchPrecision, unsigned fFlags,
4223 void *pvUser)
4224{
4225 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4226 uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
4227 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4228 "SDSTS(raw:%#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
4229 uSdSts,
4230 RT_BOOL(uSdSts & HDA_SDSTS_FIFORDY),
4231 RT_BOOL(uSdSts & HDA_SDSTS_DESE),
4232 RT_BOOL(uSdSts & HDA_SDSTS_FIFOE),
4233 RT_BOOL(uSdSts & HDA_SDSTS_BCIS));
4234}
4235
4236
4237/*********************************************************************************************************************************
4238* Debug Info Item Handlers *
4239*********************************************************************************************************************************/
4240
4241static int hdaR3DbgLookupRegByName(const char *pszArgs)
4242{
4243 int iReg = 0;
4244 for (; iReg < HDA_NUM_REGS; ++iReg)
4245 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
4246 return iReg;
4247 return -1;
4248}
4249
4250
4251static void hdaR3DbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
4252{
4253 Assert( pThis
4254 && iHdaIndex >= 0
4255 && iHdaIndex < HDA_NUM_REGS);
4256 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
4257}
4258
4259/**
4260 * @callback_method_impl{FNDBGFHANDLERDEV}
4261 */
4262static DECLCALLBACK(void) hdaR3DbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4263{
4264 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4265 int iHdaRegisterIndex = hdaR3DbgLookupRegByName(pszArgs);
4266 if (iHdaRegisterIndex != -1)
4267 hdaR3DbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
4268 else
4269 {
4270 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NUM_REGS; ++iHdaRegisterIndex)
4271 hdaR3DbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
4272 }
4273}
4274
4275static void hdaR3DbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
4276{
4277 Assert( pThis
4278 && iIdx >= 0
4279 && iIdx < HDA_MAX_STREAMS);
4280
4281 const PHDASTREAM pStream = &pThis->aStreams[iIdx];
4282
4283 pHlp->pfnPrintf(pHlp, "Stream #%d:\n", iIdx);
4284 pHlp->pfnPrintf(pHlp, "\tSD%dCTL : %R[sdctl]\n", iIdx, HDA_STREAM_REG(pThis, CTL, iIdx));
4285 pHlp->pfnPrintf(pHlp, "\tSD%dCTS : %R[sdsts]\n", iIdx, HDA_STREAM_REG(pThis, STS, iIdx));
4286 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOS: %R[sdfifos]\n", iIdx, HDA_STREAM_REG(pThis, FIFOS, iIdx));
4287 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOW: %R[sdfifow]\n", iIdx, HDA_STREAM_REG(pThis, FIFOW, iIdx));
4288 pHlp->pfnPrintf(pHlp, "\tBDLE : %R[bdle]\n", &pStream->State.BDLE);
4289}
4290
4291static void hdaR3DbgPrintBDLE(PPDMDEVINS pDevIns, PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
4292{
4293 Assert( pThis
4294 && iIdx >= 0
4295 && iIdx < HDA_MAX_STREAMS);
4296
4297 const PHDASTREAM pStream = &pThis->aStreams[iIdx];
4298 const PHDABDLE pBDLE = &pStream->State.BDLE;
4299
4300 pHlp->pfnPrintf(pHlp, "Stream #%d BDLE:\n", iIdx);
4301
4302 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, iIdx),
4303 HDA_STREAM_REG(pThis, BDPU, iIdx));
4304 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, iIdx);
4305 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, iIdx);
4306
4307 if (!u64BaseDMA)
4308 return;
4309
4310 pHlp->pfnPrintf(pHlp, "\tCurrent: %R[bdle]\n\n", pBDLE);
4311
4312 pHlp->pfnPrintf(pHlp, "\tMemory:\n");
4313
4314 uint32_t cbBDLE = 0;
4315 for (uint16_t i = 0; i < u16LVI + 1; i++)
4316 {
4317 HDABDLEDESC bd;
4318 PDMDevHlpPhysRead(pDevIns, u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
4319
4320 pHlp->pfnPrintf(pHlp, "\t\t%s #%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
4321 pBDLE->State.u32BDLIndex == i ? "*" : " ", i, bd.u64BufAddr, bd.u32BufSize, bd.fFlags & HDA_BDLE_F_IOC);
4322
4323 cbBDLE += bd.u32BufSize;
4324 }
4325
4326 pHlp->pfnPrintf(pHlp, "Total: %RU32 bytes\n", cbBDLE);
4327
4328 if (cbBDLE != u32CBL)
4329 pHlp->pfnPrintf(pHlp, "Warning: %RU32 bytes does not match CBL (%RU32)!\n", cbBDLE, u32CBL);
4330
4331 pHlp->pfnPrintf(pHlp, "DMA counters (base @ 0x%llx):\n", u64BaseDMA);
4332 if (!u64BaseDMA) /* No DMA base given? Bail out. */
4333 {
4334 pHlp->pfnPrintf(pHlp, "\tNo counters found\n");
4335 return;
4336 }
4337
4338 for (int i = 0; i < u16LVI + 1; i++)
4339 {
4340 uint32_t uDMACnt;
4341 PDMDevHlpPhysRead(pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
4342 &uDMACnt, sizeof(uDMACnt));
4343
4344 pHlp->pfnPrintf(pHlp, "\t#%03d DMA @ 0x%x\n", i , uDMACnt);
4345 }
4346}
4347
4348static int hdaR3DbgLookupStrmIdx(PHDASTATE pThis, const char *pszArgs)
4349{
4350 RT_NOREF(pThis, pszArgs);
4351 /** @todo Add args parsing. */
4352 return -1;
4353}
4354
4355/**
4356 * @callback_method_impl{FNDBGFHANDLERDEV, hdastream}
4357 */
4358static DECLCALLBACK(void) hdaR3DbgInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4359{
4360 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4361 int iHdaStreamdex = hdaR3DbgLookupStrmIdx(pThis, pszArgs);
4362 if (iHdaStreamdex != -1)
4363 hdaR3DbgPrintStream(pThis, pHlp, iHdaStreamdex);
4364 else
4365 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
4366 hdaR3DbgPrintStream(pThis, pHlp, iHdaStreamdex);
4367}
4368
4369/**
4370 * @callback_method_impl{FNDBGFHANDLERDEV, hdabdle}
4371 */
4372static DECLCALLBACK(void) hdaR3DbgInfoBDLE(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4373{
4374 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4375 int iHdaStreamdex = hdaR3DbgLookupStrmIdx(pThis, pszArgs);
4376 if (iHdaStreamdex != -1)
4377 hdaR3DbgPrintBDLE(pDevIns, pThis, pHlp, iHdaStreamdex);
4378 else
4379 for (iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
4380 hdaR3DbgPrintBDLE(pDevIns, pThis, pHlp, iHdaStreamdex);
4381}
4382
4383/**
4384 * @callback_method_impl{FNDBGFHANDLERDEV, hdcnodes}
4385 */
4386static DECLCALLBACK(void) hdaR3DbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4387{
4388 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4389 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4390
4391 if (pThisCC->pCodec->pfnDbgListNodes)
4392 pThisCC->pCodec->pfnDbgListNodes(&pThis->Codec, pThisCC->pCodec, pHlp, pszArgs);
4393 else
4394 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
4395}
4396
4397/**
4398 * @callback_method_impl{FNDBGFHANDLERDEV, hdcselector}
4399 */
4400static DECLCALLBACK(void) hdaR3DbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4401{
4402 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4403 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4404
4405 if (pThisCC->pCodec->pfnDbgSelector)
4406 pThisCC->pCodec->pfnDbgSelector(&pThis->Codec, pThisCC->pCodec, pHlp, pszArgs);
4407 else
4408 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
4409}
4410
4411/**
4412 * @callback_method_impl{FNDBGFHANDLERDEV, hdamixer}
4413 */
4414static DECLCALLBACK(void) hdaR3DbgInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4415{
4416 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4417
4418 if (pThisCC->pMixer)
4419 AudioMixerDebug(pThisCC->pMixer, pHlp, pszArgs);
4420 else
4421 pHlp->pfnPrintf(pHlp, "Mixer not available\n");
4422}
4423
4424
4425/*********************************************************************************************************************************
4426* PDMIBASE *
4427*********************************************************************************************************************************/
4428
4429/**
4430 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
4431 */
4432static DECLCALLBACK(void *) hdaR3QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
4433{
4434 PHDASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, HDASTATER3, IBase);
4435
4436 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
4437 return NULL;
4438}
4439
4440
4441/*********************************************************************************************************************************
4442* PDMDEVREGR3 *
4443*********************************************************************************************************************************/
4444
4445/**
4446 * Attach command, internal version.
4447 *
4448 * This is called to let the device attach to a driver for a specified LUN
4449 * during runtime. This is not called during VM construction, the device
4450 * constructor has to attach to all the available drivers.
4451 *
4452 * @returns VBox status code.
4453 * @param pDevIns The device instance.
4454 * @param pThis The shared HDA device state.
4455 * @param pThisCC The ring-3 HDA device state.
4456 * @param uLUN The logical unit which is being detached.
4457 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
4458 * @param ppDrv Attached driver instance on success. Optional.
4459 */
4460static int hdaR3AttachInternal(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, unsigned uLUN, uint32_t fFlags, PHDADRIVER *ppDrv)
4461{
4462 RT_NOREF(fFlags);
4463
4464 /*
4465 * Attach driver.
4466 */
4467 char *pszDesc;
4468 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
4469 AssertLogRelFailedReturn(VERR_NO_MEMORY);
4470
4471 PPDMIBASE pDrvBase;
4472 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN, &pThisCC->IBase, &pDrvBase, pszDesc);
4473 if (RT_SUCCESS(rc))
4474 {
4475 PHDADRIVER pDrv = (PHDADRIVER)RTMemAllocZ(sizeof(HDADRIVER));
4476 if (pDrv)
4477 {
4478 pDrv->pDrvBase = pDrvBase;
4479 pDrv->pHDAStateShared = pThis;
4480 pDrv->pHDAStateR3 = pThisCC;
4481 pDrv->uLUN = uLUN;
4482 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
4483 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
4484
4485 /*
4486 * For now we always set the driver at LUN 0 as our primary
4487 * host backend. This might change in the future.
4488 */
4489 if (pDrv->uLUN == 0)
4490 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
4491
4492 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
4493
4494 /* Attach to driver list if not attached yet. */
4495 if (!pDrv->fAttached)
4496 {
4497 RTListAppend(&pThisCC->lstDrv, &pDrv->Node);
4498 pDrv->fAttached = true;
4499 }
4500
4501 if (ppDrv)
4502 *ppDrv = pDrv;
4503 }
4504 else
4505 rc = VERR_NO_MEMORY;
4506 }
4507 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
4508 LogFunc(("No attached driver for LUN #%u\n", uLUN));
4509
4510 if (RT_FAILURE(rc))
4511 {
4512 /* Only free this string on failure;
4513 * must remain valid for the live of the driver instance. */
4514 RTStrFree(pszDesc);
4515 }
4516
4517 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
4518 return rc;
4519}
4520
4521/**
4522 * Detach command, internal version.
4523 *
4524 * This is called to let the device detach from a driver for a specified LUN
4525 * during runtime.
4526 *
4527 * @returns VBox status code.
4528 * @param pThisCC The ring-3 HDA device state.
4529 * @param pDrv Driver to detach from device.
4530 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
4531 */
4532static int hdaR3DetachInternal(PHDASTATER3 pThisCC, PHDADRIVER pDrv, uint32_t fFlags)
4533{
4534 RT_NOREF(fFlags);
4535
4536 /* First, remove the driver from our list and destory it's associated streams.
4537 * This also will un-set the driver as a recording source (if associated). */
4538 hdaR3MixerRemoveDrv(pThisCC, pDrv);
4539
4540 /* Next, search backwards for a capable (attached) driver which now will be the
4541 * new recording source. */
4542 PHDADRIVER pDrvCur;
4543 RTListForEachReverse(&pThisCC->lstDrv, pDrvCur, HDADRIVER, Node)
4544 {
4545 if (!pDrvCur->pConnector)
4546 continue;
4547
4548 PDMAUDIOBACKENDCFG Cfg;
4549 int rc2 = pDrvCur->pConnector->pfnGetConfig(pDrvCur->pConnector, &Cfg);
4550 if (RT_FAILURE(rc2))
4551 continue;
4552
4553 PHDADRIVERSTREAM pDrvStrm;
4554# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4555 pDrvStrm = &pDrvCur->MicIn;
4556 if ( pDrvStrm
4557 && pDrvStrm->pMixStrm)
4558 {
4559 rc2 = AudioMixerSinkSetRecordingSource(pThisCC->SinkMicIn.pMixSink, pDrvStrm->pMixStrm);
4560 if (RT_SUCCESS(rc2))
4561 LogRel2(("HDA: Set new recording source for 'Mic In' to '%s'\n", Cfg.szName));
4562 }
4563# endif
4564 pDrvStrm = &pDrvCur->LineIn;
4565 if ( pDrvStrm
4566 && pDrvStrm->pMixStrm)
4567 {
4568 rc2 = AudioMixerSinkSetRecordingSource(pThisCC->SinkLineIn.pMixSink, pDrvStrm->pMixStrm);
4569 if (RT_SUCCESS(rc2))
4570 LogRel2(("HDA: Set new recording source for 'Line In' to '%s'\n", Cfg.szName));
4571 }
4572 }
4573
4574 LogFunc(("uLUN=%u, fFlags=0x%x\n", pDrv->uLUN, fFlags));
4575 return VINF_SUCCESS;
4576}
4577
4578/**
4579 * @interface_method_impl{PDMDEVREG,pfnAttach}
4580 */
4581static DECLCALLBACK(int) hdaR3Attach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
4582{
4583 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4584 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4585
4586 DEVHDA_LOCK_RETURN(pDevIns, pThis, VERR_IGNORED);
4587
4588 LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
4589
4590 PHDADRIVER pDrv;
4591 int rc2 = hdaR3AttachInternal(pDevIns, pThis, pThisCC, uLUN, fFlags, &pDrv);
4592 if (RT_SUCCESS(rc2))
4593 rc2 = hdaR3MixerAddDrv(pThisCC, pDrv);
4594
4595 if (RT_FAILURE(rc2))
4596 LogFunc(("Failed with %Rrc\n", rc2));
4597
4598 DEVHDA_UNLOCK(pDevIns, pThis);
4599
4600 return VINF_SUCCESS;
4601}
4602
4603/**
4604 * @interface_method_impl{PDMDEVREG,pfnDetach}
4605 */
4606static DECLCALLBACK(void) hdaR3Detach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
4607{
4608 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4609 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4610
4611 DEVHDA_LOCK(pDevIns, pThis);
4612
4613 LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
4614
4615 PHDADRIVER pDrv, pDrvNext;
4616 RTListForEachSafe(&pThisCC->lstDrv, pDrv, pDrvNext, HDADRIVER, Node)
4617 {
4618 if (pDrv->uLUN == uLUN)
4619 {
4620 int rc2 = hdaR3DetachInternal(pThisCC, pDrv, fFlags);
4621 if (RT_SUCCESS(rc2))
4622 {
4623 RTMemFree(pDrv);
4624 pDrv = NULL;
4625 }
4626
4627 break;
4628 }
4629 }
4630
4631 DEVHDA_UNLOCK(pDevIns, pThis);
4632}
4633
4634/**
4635 * Powers off the device.
4636 *
4637 * @param pDevIns Device instance to power off.
4638 */
4639static DECLCALLBACK(void) hdaR3PowerOff(PPDMDEVINS pDevIns)
4640{
4641 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4642 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4643
4644 DEVHDA_LOCK_RETURN_VOID(pDevIns, pThis);
4645
4646 LogRel2(("HDA: Powering off ...\n"));
4647
4648 /* Ditto goes for the codec, which in turn uses the mixer. */
4649 hdaR3CodecPowerOff(pThisCC->pCodec);
4650
4651 /*
4652 * Note: Destroy the mixer while powering off and *not* in hdaR3Destruct,
4653 * giving the mixer the chance to release any references held to
4654 * PDM audio streams it maintains.
4655 */
4656 if (pThisCC->pMixer)
4657 {
4658 AudioMixerDestroy(pThisCC->pMixer);
4659 pThisCC->pMixer = NULL;
4660 }
4661
4662 DEVHDA_UNLOCK(pDevIns, pThis);
4663}
4664
4665/**
4666 * Replaces a driver with a the NullAudio drivers.
4667 *
4668 * @returns VBox status code.
4669 * @param pDevIns The device instance.
4670 * @param pThis The shared HDA device state.
4671 * @param pThisCC The ring-3 HDA device state.
4672 * @param iLun The logical unit which is being replaced.
4673 */
4674static int hdaR3ReconfigLunWithNullAudio(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, unsigned iLun)
4675{
4676 int rc = PDMDevHlpDriverReconfigure2(pDevIns, iLun, "AUDIO", "NullAudio");
4677 if (RT_SUCCESS(rc))
4678 rc = hdaR3AttachInternal(pDevIns, pThis, pThisCC, iLun, 0 /* fFlags */, NULL /* ppDrv */);
4679 LogFunc(("pThis=%p, iLun=%u, rc=%Rrc\n", pThis, iLun, rc));
4680 return rc;
4681}
4682
4683
4684/**
4685 * @interface_method_impl{PDMDEVREG,pfnReset}
4686 */
4687static DECLCALLBACK(void) hdaR3Reset(PPDMDEVINS pDevIns)
4688{
4689 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4690 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4691
4692 LogFlowFuncEnter();
4693
4694 DEVHDA_LOCK_RETURN_VOID(pDevIns, pThis);
4695
4696 /*
4697 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
4698 * hdaR3Reset shouldn't affects these registers.
4699 */
4700 HDA_REG(pThis, WAKEEN) = 0x0;
4701
4702 hdaR3GCTLReset(pDevIns, pThis, pThisCC);
4703
4704 /* Indicate that HDA is not in reset. The firmware is supposed to (un)reset HDA,
4705 * but we can take a shortcut.
4706 */
4707 HDA_REG(pThis, GCTL) = HDA_GCTL_CRST;
4708
4709 DEVHDA_UNLOCK(pDevIns, pThis);
4710}
4711
4712
4713/**
4714 * @interface_method_impl{PDMDEVREG,pfnDestruct}
4715 */
4716static DECLCALLBACK(int) hdaR3Destruct(PPDMDEVINS pDevIns)
4717{
4718 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); /* this shall come first */
4719 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4720 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4721 DEVHDA_LOCK(pDevIns, pThis); /** @todo r=bird: this will fail on early constructor failure. */
4722
4723 PHDADRIVER pDrv;
4724 while (!RTListIsEmpty(&pThisCC->lstDrv))
4725 {
4726 pDrv = RTListGetFirst(&pThisCC->lstDrv, HDADRIVER, Node);
4727
4728 RTListNodeRemove(&pDrv->Node);
4729 RTMemFree(pDrv);
4730 }
4731
4732 if (pThisCC->pCodec)
4733 {
4734 RTMemFree(pThisCC->pCodec);
4735 pThisCC->pCodec = NULL;
4736 }
4737
4738 hdaCodecDestruct(&pThis->Codec);
4739
4740 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
4741 hdaR3StreamDestroy(&pThis->aStreams[i], &pThisCC->aStreams[i]);
4742
4743 DEVHDA_UNLOCK(pDevIns, pThis);
4744 return VINF_SUCCESS;
4745}
4746
4747
4748/**
4749 * @interface_method_impl{PDMDEVREG,pfnConstruct}
4750 */
4751static DECLCALLBACK(int) hdaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
4752{
4753 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* this shall come first */
4754 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
4755 PHDASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER3);
4756 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
4757 Assert(iInstance == 0); RT_NOREF(iInstance);
4758
4759 /*
4760 * Initialize the state sufficently to make the destructor work.
4761 */
4762 pThis->uAlignmentCheckMagic = HDASTATE_ALIGNMENT_CHECK_MAGIC;
4763 RTListInit(&pThisCC->lstDrv);
4764 pThis->cbCorbBuf = HDA_CORB_SIZE * HDA_CORB_ELEMENT_SIZE;
4765 pThis->cbRirbBuf = HDA_RIRB_SIZE * HDA_RIRB_ELEMENT_SIZE;
4766
4767 /** @todo r=bird: There are probably other things which should be
4768 * initialized here before we start failing. */
4769
4770 /*
4771 * Validate and read configuration.
4772 */
4773 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "BufSizeInMs|BufSizeOutMs|TimerHz|PosAdjustEnabled|PosAdjustFrames|TransferHeuristicsEnabled|DebugEnabled|DebugPathOut", "");
4774
4775 /* Note: Error checking of this value happens in hdaR3StreamSetUp(). */
4776 int rc = pHlp->pfnCFGMQueryU16Def(pCfg, "BufSizeInMs", &pThis->cbCircBufInMs, 0 /* Default value, if not set. */);
4777 if (RT_FAILURE(rc))
4778 return PDMDEV_SET_ERROR(pDevIns, rc,
4779 N_("HDA configuration error: failed to read input buffer size (ms) as unsigned integer"));
4780
4781 /* Note: Error checking of this value happens in hdaR3StreamSetUp(). */
4782 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "BufSizeOutMs", &pThis->cbCircBufOutMs, 0 /* Default value, if not set. */);
4783 if (RT_FAILURE(rc))
4784 return PDMDEV_SET_ERROR(pDevIns, rc,
4785 N_("HDA configuration error: failed to read output buffer size (ms) as unsigned integer"));
4786
4787 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "TimerHz", &pThis->uTimerHz, HDA_TIMER_HZ_DEFAULT /* Default value, if not set. */);
4788 if (RT_FAILURE(rc))
4789 return PDMDEV_SET_ERROR(pDevIns, rc,
4790 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
4791
4792 if (pThis->uTimerHz != HDA_TIMER_HZ_DEFAULT)
4793 LogRel(("HDA: Using custom device timer rate (%RU16Hz)\n", pThis->uTimerHz));
4794
4795 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "PosAdjustEnabled", &pThis->fPosAdjustEnabled, true);
4796 if (RT_FAILURE(rc))
4797 return PDMDEV_SET_ERROR(pDevIns, rc,
4798 N_("HDA configuration error: failed to read position adjustment enabled as boolean"));
4799
4800 if (!pThis->fPosAdjustEnabled)
4801 LogRel(("HDA: Position adjustment is disabled\n"));
4802
4803 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "PosAdjustFrames", &pThis->cPosAdjustFrames, HDA_POS_ADJUST_DEFAULT);
4804 if (RT_FAILURE(rc))
4805 return PDMDEV_SET_ERROR(pDevIns, rc,
4806 N_("HDA configuration error: failed to read position adjustment frames as unsigned integer"));
4807
4808 if (pThis->cPosAdjustFrames)
4809 LogRel(("HDA: Using custom position adjustment (%RU16 audio frames)\n", pThis->cPosAdjustFrames));
4810
4811 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "TransferHeuristicsEnabled", &pThis->fTransferHeuristicsEnabled, true);
4812 if (RT_FAILURE(rc))
4813 return PDMDEV_SET_ERROR(pDevIns, rc,
4814 N_("HDA configuration error: failed to read data transfer heuristics enabled as boolean"));
4815
4816 if (!pThis->fTransferHeuristicsEnabled)
4817 LogRel(("HDA: Data transfer heuristics are disabled\n"));
4818
4819 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "DebugEnabled", &pThisCC->Dbg.fEnabled, false);
4820 if (RT_FAILURE(rc))
4821 return PDMDEV_SET_ERROR(pDevIns, rc,
4822 N_("HDA configuration error: failed to read debugging enabled flag as boolean"));
4823
4824 rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "DebugPathOut", &pThisCC->Dbg.pszOutPath, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
4825 if (RT_FAILURE(rc))
4826 return PDMDEV_SET_ERROR(pDevIns, rc,
4827 N_("HDA configuration error: failed to read debugging output path flag as string"));
4828
4829 if (pThisCC->Dbg.fEnabled)
4830 LogRel2(("HDA: Debug output will be saved to '%s'\n", pThisCC->Dbg.pszOutPath));
4831
4832 /*
4833 * Use our own critical section for the device instead of the default
4834 * one provided by PDM. This allows fine-grained locking in combination
4835 * with TM when timer-specific stuff is being called in e.g. the MMIO handlers.
4836 */
4837 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "HDA");
4838 AssertRCReturn(rc, rc);
4839
4840 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
4841 AssertRCReturn(rc, rc);
4842
4843 /*
4844 * Initialize data (most of it anyway).
4845 */
4846 pThisCC->pDevIns = pDevIns;
4847 /* IBase */
4848 pThisCC->IBase.pfnQueryInterface = hdaR3QueryInterface;
4849
4850 /* PCI Device */
4851 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
4852 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
4853
4854 PDMPciDevSetVendorId( pPciDev, HDA_PCI_VENDOR_ID); /* nVidia */
4855 PDMPciDevSetDeviceId( pPciDev, HDA_PCI_DEVICE_ID); /* HDA */
4856
4857 PDMPciDevSetCommand( pPciDev, 0x0000); /* 04 rw,ro - pcicmd. */
4858 PDMPciDevSetStatus( pPciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
4859 PDMPciDevSetRevisionId( pPciDev, 0x01); /* 08 ro - rid. */
4860 PDMPciDevSetClassProg( pPciDev, 0x00); /* 09 ro - pi. */
4861 PDMPciDevSetClassSub( pPciDev, 0x03); /* 0a ro - scc; 03 == HDA. */
4862 PDMPciDevSetClassBase( pPciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
4863 PDMPciDevSetHeaderType( pPciDev, 0x00); /* 0e ro - headtyp. */
4864 PDMPciDevSetBaseAddress( pPciDev, 0, /* 10 rw - MMIO */
4865 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
4866 PDMPciDevSetInterruptLine( pPciDev, 0x00); /* 3c rw. */
4867 PDMPciDevSetInterruptPin( pPciDev, 0x01); /* 3d ro - INTA#. */
4868
4869# if defined(HDA_AS_PCI_EXPRESS)
4870 PDMPciDevSetCapabilityList(pPciDev, 0x80);
4871# elif defined(VBOX_WITH_MSI_DEVICES)
4872 PDMPciDevSetCapabilityList(pPciDev, 0x60);
4873# else
4874 PDMPciDevSetCapabilityList(pPciDev, 0x50); /* ICH6 datasheet 18.1.16 */
4875# endif
4876
4877 /// @todo r=michaln: If there are really no PDMPciDevSetXx for these, the
4878 /// meaning of these values needs to be properly documented!
4879 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
4880 PDMPciDevSetByte( pPciDev, 0x40, 0x01);
4881
4882 /* Power Management */
4883 PDMPciDevSetByte( pPciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
4884 PDMPciDevSetByte( pPciDev, 0x50 + 1, 0x0); /* next */
4885 PDMPciDevSetWord( pPciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
4886
4887# ifdef HDA_AS_PCI_EXPRESS
4888 /* PCI Express */
4889 PDMPciDevSetByte( pPciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
4890 PDMPciDevSetByte( pPciDev, 0x80 + 1, 0x60); /* next */
4891 /* Device flags */
4892 PDMPciDevSetWord( pPciDev, 0x80 + 2,
4893 1 /* version */
4894 | (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) /* Root Complex Integrated Endpoint */
4895 | (100 << 9) /* MSI */ );
4896 /* Device capabilities */
4897 PDMPciDevSetDWord( pPciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
4898 /* Device control */
4899 PDMPciDevSetWord( pPciDev, 0x80 + 8, 0);
4900 /* Device status */
4901 PDMPciDevSetWord( pPciDev, 0x80 + 10, 0);
4902 /* Link caps */
4903 PDMPciDevSetDWord( pPciDev, 0x80 + 12, 0);
4904 /* Link control */
4905 PDMPciDevSetWord( pPciDev, 0x80 + 16, 0);
4906 /* Link status */
4907 PDMPciDevSetWord( pPciDev, 0x80 + 18, 0);
4908 /* Slot capabilities */
4909 PDMPciDevSetDWord( pPciDev, 0x80 + 20, 0);
4910 /* Slot control */
4911 PDMPciDevSetWord( pPciDev, 0x80 + 24, 0);
4912 /* Slot status */
4913 PDMPciDevSetWord( pPciDev, 0x80 + 26, 0);
4914 /* Root control */
4915 PDMPciDevSetWord( pPciDev, 0x80 + 28, 0);
4916 /* Root capabilities */
4917 PDMPciDevSetWord( pPciDev, 0x80 + 30, 0);
4918 /* Root status */
4919 PDMPciDevSetDWord( pPciDev, 0x80 + 32, 0);
4920 /* Device capabilities 2 */
4921 PDMPciDevSetDWord( pPciDev, 0x80 + 36, 0);
4922 /* Device control 2 */
4923 PDMPciDevSetQWord( pPciDev, 0x80 + 40, 0);
4924 /* Link control 2 */
4925 PDMPciDevSetQWord( pPciDev, 0x80 + 48, 0);
4926 /* Slot control 2 */
4927 PDMPciDevSetWord( pPciDev, 0x80 + 56, 0);
4928# endif /* HDA_AS_PCI_EXPRESS */
4929
4930 /*
4931 * Register the PCI device.
4932 */
4933 rc = PDMDevHlpPCIRegister(pDevIns, pPciDev);
4934 AssertRCReturn(rc, rc);
4935
4936 /** @todo r=bird: The IOMMMIO_FLAGS_READ_DWORD flag isn't entirely optimal,
4937 * as several frequently used registers aren't dword sized. 6.0 and earlier
4938 * will go to ring-3 to handle accesses to any such register, where-as 6.1 and
4939 * later will do trivial register reads in ring-0. Real optimal code would use
4940 * IOMMMIO_FLAGS_READ_PASSTHRU and do the necessary extra work to deal with
4941 * anything the guest may throw at us. */
4942 rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaMmioWrite, hdaMmioRead, NULL /*pvUser*/,
4943 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU, "HDA", &pThis->hMmio);
4944 AssertRCReturn(rc, rc);
4945
4946# ifdef VBOX_WITH_MSI_DEVICES
4947 PDMMSIREG MsiReg;
4948 RT_ZERO(MsiReg);
4949 MsiReg.cMsiVectors = 1;
4950 MsiReg.iMsiCapOffset = 0x60;
4951 MsiReg.iMsiNextOffset = 0x50;
4952 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
4953 if (RT_FAILURE(rc))
4954 {
4955 /* That's OK, we can work without MSI */
4956 PDMPciDevSetCapabilityList(pPciDev, 0x50);
4957 }
4958# endif
4959
4960 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SAVED_STATE_VERSION, sizeof(*pThis), hdaR3SaveExec, hdaR3LoadExec);
4961 AssertRCReturn(rc, rc);
4962
4963# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
4964 LogRel(("HDA: Asynchronous I/O enabled\n"));
4965# endif
4966
4967 /*
4968 * Attach drivers. We ASSUME they are configured consecutively without any
4969 * gaps, so we stop when we hit the first LUN w/o a driver configured.
4970 */
4971 for (unsigned iLun = 0; ; iLun++)
4972 {
4973 AssertBreak(iLun < UINT8_MAX);
4974 LogFunc(("Trying to attach driver for LUN#%u ...\n", iLun));
4975 rc = hdaR3AttachInternal(pDevIns, pThis, pThisCC, iLun, 0 /* fFlags */, NULL /* ppDrv */);
4976 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
4977 {
4978 LogFunc(("cLUNs=%u\n", iLun));
4979 break;
4980 }
4981 if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
4982 {
4983 hdaR3ReconfigLunWithNullAudio(pDevIns, pThis, pThisCC, iLun); /* Pretend attaching to the NULL audio backend will never fail. */
4984 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
4985 N_("Host audio backend initialization has failed. Selecting the NULL audio backend with the consequence that no sound is audible"));
4986 }
4987 else
4988 AssertLogRelMsgReturn(RT_SUCCESS(rc), ("LUN#%u: rc=%Rrc\n", iLun, rc), rc);
4989 }
4990
4991 /*
4992 * Create the mixer.
4993 */
4994 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThisCC->pMixer);
4995 AssertRCReturn(rc, rc);
4996
4997 /*
4998 * Add mixer output sinks.
4999 */
5000# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
5001 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Front", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
5002 AssertRCReturn(rc, rc);
5003 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Center / Subwoofer", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkCenterLFE.pMixSink);
5004 AssertRCReturn(rc, rc);
5005 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] Rear", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkRear.pMixSink);
5006 AssertRCReturn(rc, rc);
5007# else
5008 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThisCC->SinkFront.pMixSink);
5009 AssertRCReturn(rc, rc);
5010# endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
5011
5012 /*
5013 * Add mixer input sinks.
5014 */
5015 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Line In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkLineIn.pMixSink);
5016 AssertRCReturn(rc, rc);
5017# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5018 rc = AudioMixerCreateSink(pThisCC->pMixer, "[Recording] Microphone In", AUDMIXSINKDIR_INPUT, &pThisCC->SinkMicIn.pMixSink);
5019 AssertRCReturn(rc, rc);
5020# endif
5021
5022 /* There is no master volume control. Set the master to max. */
5023 PDMAUDIOVOLUME vol = { false, 255, 255 };
5024 rc = AudioMixerSetMasterVolume(pThisCC->pMixer, &vol);
5025 AssertRCReturn(rc, rc);
5026
5027 /* Allocate codec. */
5028 PHDACODECR3 pCodecR3 = (PHDACODECR3)RTMemAllocZ(sizeof(HDACODECR3));
5029 AssertPtrReturn(pCodecR3, VERR_NO_MEMORY);
5030
5031 /* Set codec callbacks to this controller. */
5032 pCodecR3->pDevIns = pDevIns;
5033 pCodecR3->pfnCbMixerAddStream = hdaR3MixerAddStream;
5034 pCodecR3->pfnCbMixerRemoveStream = hdaR3MixerRemoveStream;
5035 pCodecR3->pfnCbMixerControl = hdaR3MixerControl;
5036 pCodecR3->pfnCbMixerSetVolume = hdaR3MixerSetVolume;
5037
5038 /* Construct the common + R3 codec part. */
5039 rc = hdaR3CodecConstruct(pDevIns, &pThis->Codec, pCodecR3, 0 /* Codec index */, pCfg);
5040 AssertRCReturn(rc, rc);
5041
5042 pThisCC->pCodec = pCodecR3;
5043
5044 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
5045 verb F20 should provide device/codec recognition. */
5046 Assert(pThis->Codec.u16VendorId);
5047 Assert(pThis->Codec.u16DeviceId);
5048 PDMPciDevSetSubSystemVendorId(pPciDev, pThis->Codec.u16VendorId); /* 2c ro - intel.) */
5049 PDMPciDevSetSubSystemId( pPciDev, pThis->Codec.u16DeviceId); /* 2e ro. */
5050
5051 /*
5052 * Create the per stream timers and the asso.
5053 *
5054 * We must the critical section for the timers as the device has a
5055 * noop section associated with it.
5056 *
5057 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver relies
5058 * on exact (virtual) DMA timing and uses DMA Position Buffers
5059 * instead of the LPIB registers.
5060 */
5061 /** @todo r=bird: The need to use virtual sync is perhaps because TM
5062 * doesn't schedule regular TMCLOCK_VIRTUAL timers as accurately as it
5063 * should (VT-x preemption timer, etc). Hope to address that before
5064 * long. @bugref{9943}. */
5065 static const char * const s_apszNames[] =
5066 { "HDA SD0", "HDA SD1", "HDA SD2", "HDA SD3", "HDA SD4", "HDA SD5", "HDA SD6", "HDA SD7", };
5067 AssertCompile(RT_ELEMENTS(s_apszNames) == HDA_MAX_STREAMS);
5068 for (size_t i = 0; i < HDA_MAX_STREAMS; i++)
5069 {
5070 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaR3Timer, (void *)(uintptr_t)i,
5071 TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_NO_RING0,
5072 s_apszNames[i], &pThis->aStreams[i].hTimer);
5073 AssertRCReturn(rc, rc);
5074
5075 rc = PDMDevHlpTimerSetCritSect(pDevIns, pThis->aStreams[i].hTimer, &pThis->CritSect);
5076 AssertRCReturn(rc, rc);
5077 }
5078
5079 /*
5080 * Create all hardware streams.
5081 */
5082 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
5083 {
5084 rc = hdaR3StreamConstruct(&pThis->aStreams[i], &pThisCC->aStreams[i], pThis, pThisCC, i /* u8SD */);
5085 AssertRCReturn(rc, rc);
5086 }
5087
5088# ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
5089 /*
5090 * Initialize the driver chain.
5091 */
5092 PHDADRIVER pDrv;
5093 RTListForEach(&pThisCC->lstDrv, pDrv, HDADRIVER, Node)
5094 {
5095 /*
5096 * Only primary drivers are critical for the VM to run. Everything else
5097 * might not worth showing an own error message box in the GUI.
5098 */
5099 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
5100 continue;
5101
5102 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
5103 AssertPtr(pCon);
5104
5105 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
5106# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5107 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
5108# endif
5109 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
5110# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
5111 /** @todo Anything to do here? */
5112# endif
5113
5114 if ( !fValidLineIn
5115# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5116 && !fValidMicIn
5117# endif
5118 && !fValidOut)
5119 {
5120 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
5121 hdaR3Reset(pDevIns);
5122 hdaR3ReconfigLunWithNullAudio(pThis, pDrv->uLUN);
5123 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
5124 N_("No audio devices could be opened. "
5125 "Selecting the NULL audio backend with the consequence that no sound is audible"));
5126 }
5127 else
5128 {
5129 bool fWarn = false;
5130
5131 PDMAUDIOBACKENDCFG BackendCfg;
5132 int rc2 = pCon->pfnGetConfig(pCon, &BackendCfg);
5133 if (RT_SUCCESS(rc2))
5134 {
5135 if (BackendCfg.cMaxStreamsIn)
5136 {
5137# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5138 /* If the audio backend supports two or more input streams at once,
5139 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
5140 if (BackendCfg.cMaxStreamsIn >= 2)
5141 fWarn = !fValidLineIn || !fValidMicIn;
5142 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
5143 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
5144 * One of the two simply is not in use then. */
5145 else if (BackendCfg.cMaxStreamsIn == 1)
5146 fWarn = !fValidLineIn && !fValidMicIn;
5147 /* Don't warn if our backend is not able of supporting any input streams at all. */
5148# else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
5149 /* We only have line-in as input source. */
5150 fWarn = !fValidLineIn;
5151# endif /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
5152 }
5153
5154 if ( !fWarn
5155 && BackendCfg.cMaxStreamsOut)
5156 fWarn = !fValidOut;
5157 }
5158 else
5159 {
5160 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
5161 fWarn = true;
5162 }
5163
5164 if (fWarn)
5165 {
5166 char szMissingStreams[255];
5167 size_t len = 0;
5168 if (!fValidLineIn)
5169 {
5170 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
5171 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
5172 }
5173# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5174 if (!fValidMicIn)
5175 {
5176 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
5177 len += RTStrPrintf(szMissingStreams + len,
5178 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
5179 }
5180# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
5181 if (!fValidOut)
5182 {
5183 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
5184 len += RTStrPrintf(szMissingStreams + len,
5185 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
5186 }
5187
5188 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
5189 N_("Some HDA audio streams (%s) could not be opened. "
5190 "Guest applications generating audio output or depending on audio input may hang. "
5191 "Make sure your host audio device is working properly. "
5192 "Check the logfile for error messages of the audio subsystem"), szMissingStreams);
5193 }
5194 }
5195 }
5196# endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
5197
5198 hdaR3Reset(pDevIns);
5199
5200 /*
5201 * Info items and string formatter types. The latter is non-optional as
5202 * the info handles use (at least some of) the custom types and we cannot
5203 * accept screwing formatting.
5204 */
5205 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaR3DbgInfo);
5206 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaR3DbgInfoBDLE);
5207 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaR3DbgInfoStream);
5208 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaR3DbgInfoCodecNodes);
5209 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaR3DbgInfoCodecSelector);
5210 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaR3DbgInfoMixer);
5211
5212 rc = RTStrFormatTypeRegister("bdle", hdaR3StrFmtBDLE, NULL);
5213 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
5214 rc = RTStrFormatTypeRegister("sdctl", hdaR3StrFmtSDCTL, NULL);
5215 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
5216 rc = RTStrFormatTypeRegister("sdsts", hdaR3StrFmtSDSTS, NULL);
5217 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
5218 rc = RTStrFormatTypeRegister("sdfifos", hdaR3StrFmtSDFIFOS, NULL);
5219 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
5220 rc = RTStrFormatTypeRegister("sdfifow", hdaR3StrFmtSDFIFOW, NULL);
5221 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
5222
5223 /*
5224 * Asserting sanity.
5225 */
5226 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
5227 {
5228 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
5229 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
5230
5231 /* binary search order. */
5232 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
5233 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5234 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
5235
5236 /* alignment. */
5237 AssertReleaseMsg( pReg->size == 1
5238 || (pReg->size == 2 && (pReg->offset & 1) == 0)
5239 || (pReg->size == 3 && (pReg->offset & 3) == 0)
5240 || (pReg->size == 4 && (pReg->offset & 3) == 0),
5241 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5242
5243 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
5244 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
5245 if (pReg->offset & 3)
5246 {
5247 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL;
5248 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5249 if (pPrevReg)
5250 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
5251 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5252 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
5253 }
5254#if 0
5255 if ((pReg->offset + pReg->size) & 3)
5256 {
5257 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5258 if (pNextReg)
5259 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
5260 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5261 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
5262 }
5263#endif
5264 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */
5265 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
5266 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5267 }
5268
5269# ifdef VBOX_WITH_STATISTICS
5270 /*
5271 * Register statistics.
5272 */
5273 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "Input", STAMUNIT_TICKS_PER_CALL, "Profiling input.");
5274 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "Output", STAMUNIT_TICKS_PER_CALL, "Profiling output.");
5275 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation.");
5276 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation.");
5277
5278 AssertCompile(RT_ELEMENTS(g_aHdaRegMap) == HDA_NUM_REGS);
5279 AssertCompile(RT_ELEMENTS(pThis->aStatRegReads) == HDA_NUM_REGS);
5280 AssertCompile(RT_ELEMENTS(pThis->aStatRegReadsToR3) == HDA_NUM_REGS);
5281 AssertCompile(RT_ELEMENTS(pThis->aStatRegWrites) == HDA_NUM_REGS);
5282 AssertCompile(RT_ELEMENTS(pThis->aStatRegWritesToR3) == HDA_NUM_REGS);
5283 for (size_t i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
5284 {
5285 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStatRegReads[i], STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
5286 g_aHdaRegMap[i].desc, "Regs/%03x-%s-Reads", g_aHdaRegMap[i].offset, g_aHdaRegMap[i].abbrev);
5287 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStatRegReadsToR3[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
5288 g_aHdaRegMap[i].desc, "Regs/%03x-%s-Reads-ToR3", g_aHdaRegMap[i].offset, g_aHdaRegMap[i].abbrev);
5289 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStatRegWrites[i], STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
5290 g_aHdaRegMap[i].desc, "Regs/%03x-%s-Writes", g_aHdaRegMap[i].offset, g_aHdaRegMap[i].abbrev);
5291 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStatRegWritesToR3[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
5292 g_aHdaRegMap[i].desc, "Regs/%03x-%s-Writes-ToR3", g_aHdaRegMap[i].offset, g_aHdaRegMap[i].abbrev);
5293 }
5294 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegMultiReadsR3, STAMTYPE_COUNTER, "RegMultiReadsR3", STAMUNIT_OCCURENCES, "Register read not targeting just one register, handled in ring-3");
5295 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegMultiReadsRZ, STAMTYPE_COUNTER, "RegMultiReadsRZ", STAMUNIT_OCCURENCES, "Register read not targeting just one register, handled in ring-0");
5296 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegMultiWritesR3, STAMTYPE_COUNTER, "RegMultiWritesR3", STAMUNIT_OCCURENCES, "Register writes not targeting just one register, handled in ring-3");
5297 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegMultiWritesRZ, STAMTYPE_COUNTER, "RegMultiWritesRZ", STAMUNIT_OCCURENCES, "Register writes not targeting just one register, handled in ring-0");
5298 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegSubWriteR3, STAMTYPE_COUNTER, "RegSubWritesR3", STAMUNIT_OCCURENCES, "Trucated register writes, handled in ring-3");
5299 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegSubWriteRZ, STAMTYPE_COUNTER, "RegSubWritesRZ", STAMUNIT_OCCURENCES, "Trucated register writes, handled in ring-0");
5300 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegUnknownReads, STAMTYPE_COUNTER, "RegUnknownReads", STAMUNIT_OCCURENCES, "Reads of unknown registers.");
5301 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegUnknownWrites, STAMTYPE_COUNTER, "RegUnknownWrites", STAMUNIT_OCCURENCES, "Writes to unknown registers.");
5302 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegWritesBlockedByReset, STAMTYPE_COUNTER, "RegWritesBlockedByReset", STAMUNIT_OCCURENCES, "Writes blocked by pending reset (GCTL/CRST)");
5303 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRegWritesBlockedByRun, STAMTYPE_COUNTER, "RegWritesBlockedByRun", STAMUNIT_OCCURENCES, "Writes blocked by byte RUN bit.");
5304# endif
5305
5306 return VINF_SUCCESS;
5307}
5308
5309#else /* !IN_RING3 */
5310
5311/**
5312 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
5313 */
5314static DECLCALLBACK(int) hdaRZConstruct(PPDMDEVINS pDevIns)
5315{
5316 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); /* this shall come first */
5317 PHDASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PHDASTATE);
5318 PHDASTATER0 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PHDASTATER0);
5319
5320 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
5321 AssertRCReturn(rc, rc);
5322
5323 rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, hdaMmioWrite, hdaMmioRead, NULL /*pvUser*/);
5324 AssertRCReturn(rc, rc);
5325
5326 /* Construct the R0 codec part. */
5327 rc = hdaR0CodecConstruct(pDevIns, &pThis->Codec, &pThisCC->Codec);
5328 AssertRCReturn(rc, rc);
5329
5330 return VINF_SUCCESS;
5331}
5332
5333#endif /* !IN_RING3 */
5334
5335/**
5336 * The device registration structure.
5337 */
5338const PDMDEVREG g_DeviceHDA =
5339{
5340 /* .u32Version = */ PDM_DEVREG_VERSION,
5341 /* .uReserved0 = */ 0,
5342 /* .szName = */ "hda",
5343 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
5344 /* .fClass = */ PDM_DEVREG_CLASS_AUDIO,
5345 /* .cMaxInstances = */ 1,
5346 /* .uSharedVersion = */ 42,
5347 /* .cbInstanceShared = */ sizeof(HDASTATE),
5348 /* .cbInstanceCC = */ CTX_EXPR(sizeof(HDASTATER3), sizeof(HDASTATER0), 0),
5349 /* .cbInstanceRC = */ 0,
5350 /* .cMaxPciDevices = */ 1,
5351 /* .cMaxMsixVectors = */ 0,
5352 /* .pszDescription = */ "Intel HD Audio Controller",
5353#if defined(IN_RING3)
5354 /* .pszRCMod = */ "VBoxDDRC.rc",
5355 /* .pszR0Mod = */ "VBoxDDR0.r0",
5356 /* .pfnConstruct = */ hdaR3Construct,
5357 /* .pfnDestruct = */ hdaR3Destruct,
5358 /* .pfnRelocate = */ NULL,
5359 /* .pfnMemSetup = */ NULL,
5360 /* .pfnPowerOn = */ NULL,
5361 /* .pfnReset = */ hdaR3Reset,
5362 /* .pfnSuspend = */ NULL,
5363 /* .pfnResume = */ NULL,
5364 /* .pfnAttach = */ hdaR3Attach,
5365 /* .pfnDetach = */ hdaR3Detach,
5366 /* .pfnQueryInterface = */ NULL,
5367 /* .pfnInitComplete = */ NULL,
5368 /* .pfnPowerOff = */ hdaR3PowerOff,
5369 /* .pfnSoftReset = */ NULL,
5370 /* .pfnReserved0 = */ NULL,
5371 /* .pfnReserved1 = */ NULL,
5372 /* .pfnReserved2 = */ NULL,
5373 /* .pfnReserved3 = */ NULL,
5374 /* .pfnReserved4 = */ NULL,
5375 /* .pfnReserved5 = */ NULL,
5376 /* .pfnReserved6 = */ NULL,
5377 /* .pfnReserved7 = */ NULL,
5378#elif defined(IN_RING0)
5379 /* .pfnEarlyConstruct = */ NULL,
5380 /* .pfnConstruct = */ hdaRZConstruct,
5381 /* .pfnDestruct = */ NULL,
5382 /* .pfnFinalDestruct = */ NULL,
5383 /* .pfnRequest = */ NULL,
5384 /* .pfnReserved0 = */ NULL,
5385 /* .pfnReserved1 = */ NULL,
5386 /* .pfnReserved2 = */ NULL,
5387 /* .pfnReserved3 = */ NULL,
5388 /* .pfnReserved4 = */ NULL,
5389 /* .pfnReserved5 = */ NULL,
5390 /* .pfnReserved6 = */ NULL,
5391 /* .pfnReserved7 = */ NULL,
5392#elif defined(IN_RC)
5393 /* .pfnConstruct = */ hdaRZConstruct,
5394 /* .pfnReserved0 = */ NULL,
5395 /* .pfnReserved1 = */ NULL,
5396 /* .pfnReserved2 = */ NULL,
5397 /* .pfnReserved3 = */ NULL,
5398 /* .pfnReserved4 = */ NULL,
5399 /* .pfnReserved5 = */ NULL,
5400 /* .pfnReserved6 = */ NULL,
5401 /* .pfnReserved7 = */ NULL,
5402#else
5403# error "Not in IN_RING3, IN_RING0 or IN_RC!"
5404#endif
5405 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
5406};
5407
5408#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
5409
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