VirtualBox

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

Last change on this file since 70966 was 70966, checked in by vboxsync, 7 years ago

Build fix.

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