VirtualBox

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

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

Audio/HDA: Disable audio streams before doing a stream reset in hdaGCTLReset().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 187.5 KB
Line 
1/* $Id: DevHDA.cpp 70975 2018-02-12 16:42:51Z 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 int rc2 = hdaStreamEnable(&pThis->aStreams[uSD], false /* fEnable */);
3042 if (RT_SUCCESS(rc2))
3043 {
3044 /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
3045 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
3046 hdaStreamReset(pThis, &pThis->aStreams[uSD], uSD);
3047 }
3048 }
3049
3050 /* Clear stream tags <-> objects mapping table. */
3051 RT_ZERO(pThis->aTags);
3052
3053 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
3054 HDA_REG(pThis, STATESTS) = 0x1;
3055
3056 LogFlowFuncLeave();
3057 LogRel(("HDA: Reset\n"));
3058}
3059
3060#ifdef DEBUG_andy
3061# define HDA_DEBUG_DMA
3062#endif
3063
3064#endif /* IN_RING3 */
3065
3066/* MMIO callbacks */
3067
3068/**
3069 * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
3070 *
3071 * @note During implementation, we discovered so-called "forgotten" or "hole"
3072 * registers whose description is not listed in the RPM, datasheet, or
3073 * spec.
3074 */
3075PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
3076{
3077 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3078 int rc;
3079 RT_NOREF_PV(pvUser);
3080
3081 /*
3082 * Look up and log.
3083 */
3084 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
3085 int idxRegDsc = hdaRegLookup(offReg); /* Register descriptor index. */
3086#ifdef LOG_ENABLED
3087 unsigned const cbLog = cb;
3088 uint32_t offRegLog = offReg;
3089#endif
3090
3091 Log3Func(("offReg=%#x cb=%#x\n", offReg, cb));
3092 Assert(cb == 4); Assert((offReg & 3) == 0);
3093
3094 DEVHDA_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
3095
3096 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
3097 LogFunc(("Access to registers except GCTL is blocked while reset\n"));
3098
3099 if (idxRegDsc == -1)
3100 LogRel(("HDA: Invalid read access @0x%x (bytes=%u)\n", offReg, cb));
3101
3102 if (idxRegDsc != -1)
3103 {
3104 /* Leave lock before calling read function. */
3105 DEVHDA_UNLOCK(pThis);
3106
3107 /* ASSUMES gapless DWORD at end of map. */
3108 if (g_aHdaRegMap[idxRegDsc].size == 4)
3109 {
3110 /*
3111 * Straight forward DWORD access.
3112 */
3113 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, (uint32_t *)pv);
3114 Log3Func(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
3115 }
3116 else
3117 {
3118 /*
3119 * Multi register read (unless there are trailing gaps).
3120 * ASSUMES that only DWORD reads have sideeffects.
3121 */
3122 uint32_t u32Value = 0;
3123 unsigned cbLeft = 4;
3124 do
3125 {
3126 uint32_t const cbReg = g_aHdaRegMap[idxRegDsc].size;
3127 uint32_t u32Tmp = 0;
3128
3129 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Tmp);
3130 Log3Func(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
3131 if (rc != VINF_SUCCESS)
3132 break;
3133 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
3134
3135 cbLeft -= cbReg;
3136 offReg += cbReg;
3137 idxRegDsc++;
3138 } while (cbLeft > 0 && g_aHdaRegMap[idxRegDsc].offset == offReg);
3139
3140 if (rc == VINF_SUCCESS)
3141 *(uint32_t *)pv = u32Value;
3142 else
3143 Assert(!IOM_SUCCESS(rc));
3144 }
3145 }
3146 else
3147 {
3148 DEVHDA_UNLOCK(pThis);
3149
3150 rc = VINF_IOM_MMIO_UNUSED_FF;
3151 Log3Func(("\tHole at %x is accessed for read\n", offReg));
3152 }
3153
3154 /*
3155 * Log the outcome.
3156 */
3157#ifdef LOG_ENABLED
3158 if (cbLog == 4)
3159 Log3Func(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
3160 else if (cbLog == 2)
3161 Log3Func(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
3162 else if (cbLog == 1)
3163 Log3Func(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
3164#endif
3165 return rc;
3166}
3167
3168
3169DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxRegDsc, uint32_t u32Value, char const *pszLog)
3170{
3171 DEVHDA_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
3172
3173 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
3174 {
3175 Log(("hdaWriteReg: Warning: Access to %s is blocked while controller is in reset mode\n", g_aHdaRegMap[idxRegDsc].abbrev));
3176 LogRel2(("HDA: Warning: Access to register %s is blocked while controller is in reset mode\n",
3177 g_aHdaRegMap[idxRegDsc].abbrev));
3178
3179 DEVHDA_UNLOCK(pThis);
3180 return VINF_SUCCESS;
3181 }
3182
3183 /*
3184 * Handle RD (register description) flags.
3185 */
3186
3187 /* For SDI / SDO: Check if writes to those registers are allowed while SDCTL's RUN bit is set. */
3188 if (idxRegDsc >= HDA_NUM_GENERAL_REGS)
3189 {
3190 const uint32_t uSDCTL = HDA_STREAM_REG(pThis, CTL, HDA_SD_NUM_FROM_REG(pThis, CTL, idxRegDsc));
3191
3192 /*
3193 * Some OSes (like Win 10 AU) violate the spec by writing stuff to registers which are not supposed to be be touched
3194 * while SDCTL's RUN bit is set. So just ignore those values.
3195 */
3196
3197 /* Is the RUN bit currently set? */
3198 if ( RT_BOOL(uSDCTL & HDA_SDCTL_RUN)
3199 /* Are writes to the register denied if RUN bit is set? */
3200 && !(g_aHdaRegMap[idxRegDsc].fFlags & HDA_RD_FLAG_SD_WRITE_RUN))
3201 {
3202 Log(("hdaWriteReg: Warning: Access to %s is blocked! %R[sdctl]\n", g_aHdaRegMap[idxRegDsc].abbrev, uSDCTL));
3203 LogRel2(("HDA: Warning: Access to register %s is blocked while the stream's RUN bit is set\n",
3204 g_aHdaRegMap[idxRegDsc].abbrev));
3205
3206 DEVHDA_UNLOCK(pThis);
3207 return VINF_SUCCESS;
3208 }
3209 }
3210
3211 /* Leave the lock before calling write function. */
3212 DEVHDA_UNLOCK(pThis);
3213
3214#ifdef LOG_ENABLED
3215 uint32_t const idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3216 uint32_t const u32OldValue = pThis->au32Regs[idxRegMem];
3217#endif
3218 int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value);
3219 Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
3220 g_aHdaRegMap[idxRegDsc].size, u32OldValue, pThis->au32Regs[idxRegMem], pszLog));
3221 RT_NOREF(pszLog);
3222 return rc;
3223}
3224
3225
3226/**
3227 * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
3228 */
3229PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
3230{
3231 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3232 int rc;
3233 RT_NOREF_PV(pvUser);
3234
3235 /*
3236 * The behavior of accesses that aren't aligned on natural boundraries is
3237 * undefined. Just reject them outright.
3238 */
3239 /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
3240 Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
3241 if (GCPhysAddr & (cb - 1))
3242 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
3243
3244 /*
3245 * Look up and log the access.
3246 */
3247 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
3248 int idxRegDsc = hdaRegLookup(offReg);
3249 uint32_t idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
3250 uint64_t u64Value;
3251 if (cb == 4) u64Value = *(uint32_t const *)pv;
3252 else if (cb == 2) u64Value = *(uint16_t const *)pv;
3253 else if (cb == 1) u64Value = *(uint8_t const *)pv;
3254 else if (cb == 8) u64Value = *(uint64_t const *)pv;
3255 else
3256 {
3257 u64Value = 0; /* shut up gcc. */
3258 AssertReleaseMsgFailed(("%u\n", cb));
3259 }
3260
3261#ifdef LOG_ENABLED
3262 uint32_t const u32LogOldValue = idxRegDsc >= 0 ? pThis->au32Regs[idxRegMem] : UINT32_MAX;
3263 if (idxRegDsc == -1)
3264 Log3Func(("@%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
3265 else if (cb == 4)
3266 Log3Func(("@%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
3267 else if (cb == 2)
3268 Log3Func(("@%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
3269 else if (cb == 1)
3270 Log3Func(("@%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
3271
3272 if (idxRegDsc >= 0 && g_aHdaRegMap[idxRegDsc].size != cb)
3273 Log3Func(("\tsize=%RU32 != cb=%u!!\n", g_aHdaRegMap[idxRegDsc].size, cb));
3274#endif
3275
3276 /*
3277 * Try for a direct hit first.
3278 */
3279 if (idxRegDsc != -1 && g_aHdaRegMap[idxRegDsc].size == cb)
3280 {
3281 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "");
3282 Log3Func(("\t%#x -> %#x\n", u32LogOldValue, idxRegMem != UINT32_MAX ? pThis->au32Regs[idxRegMem] : UINT32_MAX));
3283 }
3284 /*
3285 * Partial or multiple register access, loop thru the requested memory.
3286 */
3287 else
3288 {
3289 /*
3290 * If it's an access beyond the start of the register, shift the input
3291 * value and fill in missing bits. Natural alignment rules means we
3292 * will only see 1 or 2 byte accesses of this kind, so no risk of
3293 * shifting out input values.
3294 */
3295 if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(offReg)) != -1)
3296 {
3297 uint32_t const cbBefore = offReg - g_aHdaRegMap[idxRegDsc].offset; Assert(cbBefore > 0 && cbBefore < 4);
3298 offReg -= cbBefore;
3299 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3300 u64Value <<= cbBefore * 8;
3301 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbBefore];
3302 Log3Func(("\tWithin register, supplied %u leading bits: %#llx -> %#llx ...\n",
3303 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
3304 }
3305
3306 /* Loop thru the write area, it may cover multiple registers. */
3307 rc = VINF_SUCCESS;
3308 for (;;)
3309 {
3310 uint32_t cbReg;
3311 if (idxRegDsc != -1)
3312 {
3313 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
3314 cbReg = g_aHdaRegMap[idxRegDsc].size;
3315 if (cb < cbReg)
3316 {
3317 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbReg] & ~g_afMasks[cb];
3318 Log3Func(("\tSupplying missing bits (%#x): %#llx -> %#llx ...\n",
3319 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
3320 }
3321#ifdef LOG_ENABLED
3322 uint32_t uLogOldVal = pThis->au32Regs[idxRegMem];
3323#endif
3324 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "*");
3325 Log3Func(("\t%#x -> %#x\n", uLogOldVal, pThis->au32Regs[idxRegMem]));
3326 }
3327 else
3328 {
3329 LogRel(("HDA: Invalid write access @0x%x\n", offReg));
3330 cbReg = 1;
3331 }
3332 if (rc != VINF_SUCCESS)
3333 break;
3334 if (cbReg >= cb)
3335 break;
3336
3337 /* Advance. */
3338 offReg += cbReg;
3339 cb -= cbReg;
3340 u64Value >>= cbReg * 8;
3341 if (idxRegDsc == -1)
3342 idxRegDsc = hdaRegLookup(offReg);
3343 else
3344 {
3345 idxRegDsc++;
3346 if ( (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
3347 || g_aHdaRegMap[idxRegDsc].offset != offReg)
3348 {
3349 idxRegDsc = -1;
3350 }
3351 }
3352 }
3353 }
3354
3355 return rc;
3356}
3357
3358
3359/* PCI callback. */
3360
3361#ifdef IN_RING3
3362/**
3363 * @callback_method_impl{FNPCIIOREGIONMAP}
3364 */
3365static DECLCALLBACK(int) hdaPciIoRegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
3366 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
3367{
3368 RT_NOREF(iRegion, enmType);
3369 PHDASTATE pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
3370
3371 /*
3372 * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
3373 *
3374 * Let IOM talk DWORDs when reading, saves a lot of complications. On
3375 * writing though, we have to do it all ourselves because of sideeffects.
3376 */
3377 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
3378 int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
3379 IOMMMIO_FLAGS_READ_DWORD
3380 | IOMMMIO_FLAGS_WRITE_PASSTHRU,
3381 hdaMMIOWrite, hdaMMIORead, "HDA");
3382
3383 if (RT_FAILURE(rc))
3384 return rc;
3385
3386 if (pThis->fR0Enabled)
3387 {
3388 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
3389 "hdaMMIOWrite", "hdaMMIORead");
3390 if (RT_FAILURE(rc))
3391 return rc;
3392 }
3393
3394 if (pThis->fRCEnabled)
3395 {
3396 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
3397 "hdaMMIOWrite", "hdaMMIORead");
3398 if (RT_FAILURE(rc))
3399 return rc;
3400 }
3401
3402 pThis->MMIOBaseAddr = GCPhysAddress;
3403 return VINF_SUCCESS;
3404}
3405
3406
3407/* Saved state callbacks. */
3408
3409static int hdaSaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStream)
3410{
3411 RT_NOREF(pDevIns);
3412#ifdef VBOX_STRICT
3413 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3414#endif
3415
3416 Log2Func(("[SD%RU8]\n", pStream->u8SD));
3417
3418 /* Save stream ID. */
3419 int rc = SSMR3PutU8(pSSM, pStream->u8SD);
3420 AssertRCReturn(rc, rc);
3421 Assert(pStream->u8SD < HDA_MAX_STREAMS);
3422
3423 rc = SSMR3PutStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
3424 AssertRCReturn(rc, rc);
3425
3426#ifdef VBOX_STRICT /* Sanity checks. */
3427 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
3428 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
3429 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
3430 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
3431
3432 Assert(u64BaseDMA == pStream->u64BDLBase);
3433 Assert(u16LVI == pStream->u16LVI);
3434 Assert(u32CBL == pStream->u32CBL);
3435#endif
3436
3437 rc = SSMR3PutStructEx(pSSM, &pStream->State.BDLE.Desc, sizeof(HDABDLEDESC),
3438 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
3439 AssertRCReturn(rc, rc);
3440
3441 rc = SSMR3PutStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE),
3442 0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
3443 AssertRCReturn(rc, rc);
3444
3445 rc = SSMR3PutStructEx(pSSM, &pStream->State.Period, sizeof(HDASTREAMPERIOD),
3446 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
3447 AssertRCReturn(rc, rc);
3448
3449#ifdef VBOX_STRICT /* Sanity checks. */
3450 PHDABDLE pBDLE = &pStream->State.BDLE;
3451 if (u64BaseDMA)
3452 {
3453 Assert(pStream->State.uCurBDLE <= u16LVI + 1);
3454
3455 HDABDLE curBDLE;
3456 rc = hdaBDLEFetch(pThis, &curBDLE, u64BaseDMA, pStream->State.uCurBDLE);
3457 AssertRC(rc);
3458
3459 Assert(curBDLE.Desc.u32BufSize == pBDLE->Desc.u32BufSize);
3460 Assert(curBDLE.Desc.u64BufAdr == pBDLE->Desc.u64BufAdr);
3461 Assert(curBDLE.Desc.fFlags == pBDLE->Desc.fFlags);
3462 }
3463 else
3464 {
3465 Assert(pBDLE->Desc.u64BufAdr == 0);
3466 Assert(pBDLE->Desc.u32BufSize == 0);
3467 }
3468#endif
3469
3470 uint32_t cbCircBufSize = 0;
3471 uint32_t cbCircBufUsed = 0;
3472
3473 if (pStream->State.pCircBuf)
3474 {
3475 cbCircBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf);
3476 cbCircBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
3477 }
3478
3479 rc = SSMR3PutU32(pSSM, cbCircBufSize);
3480 AssertRCReturn(rc, rc);
3481
3482 rc = SSMR3PutU32(pSSM, cbCircBufUsed);
3483 AssertRCReturn(rc, rc);
3484
3485 if (cbCircBufUsed)
3486 {
3487 /*
3488 * We now need to get the circular buffer's data without actually modifying
3489 * the internal read / used offsets -- otherwise we would end up with broken audio
3490 * data after saving the state.
3491 *
3492 * So get the current read offset and serialize the buffer data manually based on that.
3493 */
3494 size_t cbCircBufOffRead = RTCircBufOffsetRead(pStream->State.pCircBuf);
3495
3496 void *pvBuf;
3497 size_t cbBuf;
3498 RTCircBufAcquireReadBlock(pStream->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
3499
3500 if (cbBuf)
3501 {
3502 size_t cbToRead = cbCircBufUsed;
3503 size_t cbEnd = 0;
3504
3505 if (cbCircBufUsed > cbCircBufOffRead)
3506 cbEnd = cbCircBufUsed - cbCircBufOffRead;
3507
3508 if (cbEnd) /* Save end of buffer first. */
3509 {
3510 rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf + cbCircBufSize - cbEnd /* End of buffer */, cbEnd);
3511 AssertRCReturn(rc, rc);
3512
3513 Assert(cbToRead >= cbEnd);
3514 cbToRead -= cbEnd;
3515 }
3516
3517 if (cbToRead) /* Save remaining stuff at start of buffer (if any). */
3518 {
3519 rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf - cbCircBufUsed /* Start of buffer */, cbToRead);
3520 AssertRCReturn(rc, rc);
3521 }
3522 }
3523
3524 RTCircBufReleaseReadBlock(pStream->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
3525 }
3526
3527 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
3528 pStream->u8SD,
3529 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), HDA_STREAM_REG(pThis, CBL, pStream->u8SD), HDA_STREAM_REG(pThis, LVI, pStream->u8SD)));
3530
3531#ifdef LOG_ENABLED
3532 hdaBDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
3533#endif
3534
3535 return rc;
3536}
3537
3538/**
3539 * @callback_method_impl{FNSSMDEVSAVEEXEC}
3540 */
3541static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
3542{
3543 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3544
3545 /* Save Codec nodes states. */
3546 hdaCodecSaveState(pThis->pCodec, pSSM);
3547
3548 /* Save MMIO registers. */
3549 SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
3550 SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3551
3552 /* Save controller-specifc internals. */
3553 SSMR3PutU64(pSSM, pThis->u64WalClk);
3554 SSMR3PutU8(pSSM, pThis->u8IRQL);
3555
3556 /* Save number of streams. */
3557 SSMR3PutU32(pSSM, HDA_MAX_STREAMS);
3558
3559 /* Save stream states. */
3560 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
3561 {
3562 int rc = hdaSaveStream(pDevIns, pSSM, &pThis->aStreams[i]);
3563 AssertRCReturn(rc, rc);
3564 }
3565
3566 return VINF_SUCCESS;
3567}
3568
3569/**
3570 * Does required post processing when loading a saved state.
3571 *
3572 * @param pThis Pointer to HDA state.
3573 */
3574static int hdaLoadExecPost(PHDASTATE pThis)
3575{
3576 int rc = VINF_SUCCESS;
3577
3578 /*
3579 * Enable all previously active streams.
3580 */
3581 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
3582 {
3583 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, i);
3584 if (pStream)
3585 {
3586 int rc2;
3587
3588 bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
3589 if (fActive)
3590 {
3591#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
3592 /* Make sure to also create the async I/O thread before actually enabling the stream. */
3593 rc2 = hdaStreamAsyncIOCreate(pStream);
3594 AssertRC(rc2);
3595
3596 /* ... and enabling it. */
3597 hdaStreamAsyncIOEnable(pStream, true /* fEnable */);
3598#endif
3599 /* Resume the stream's period. */
3600 hdaStreamPeriodResume(&pStream->State.Period);
3601
3602 /* (Re-)enable the stream. */
3603 rc2 = hdaStreamEnable(pStream, true /* fEnable */);
3604 AssertRC(rc2);
3605
3606 /* Add the stream to the device setup. */
3607 rc2 = hdaAddStream(pThis, &pStream->State.Cfg);
3608 AssertRC(rc2);
3609
3610#ifdef HDA_USE_DMA_ACCESS_HANDLER
3611 /* (Re-)install the DMA handler. */
3612 hdaStreamRegisterDMAHandlers(pThis, pStream);
3613#endif
3614 if (hdaStreamTransferIsScheduled(pStream))
3615 hdaTimerSet(pThis, pStream, hdaStreamTransferGetNext(pStream), true /* fForce */);
3616
3617 /* Also keep track of the currently active streams. */
3618 pThis->cStreamsActive++;
3619 }
3620 }
3621 }
3622
3623 LogFlowFuncLeaveRC(rc);
3624 return rc;
3625}
3626
3627
3628/**
3629 * Handles loading of all saved state versions older than the current one.
3630 *
3631 * @param pThis Pointer to HDA state.
3632 * @param pSSM Pointer to SSM handle.
3633 * @param uVersion Saved state version to load.
3634 * @param uPass Loading stage to handle.
3635 */
3636static int hdaLoadExecLegacy(PHDASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3637{
3638 RT_NOREF(uPass);
3639
3640 int rc = VINF_SUCCESS;
3641
3642 /*
3643 * Load MMIO registers.
3644 */
3645 uint32_t cRegs;
3646 switch (uVersion)
3647 {
3648 case HDA_SSM_VERSION_1:
3649 /* Starting with r71199, we would save 112 instead of 113
3650 registers due to some code cleanups. This only affected trunk
3651 builds in the 4.1 development period. */
3652 cRegs = 113;
3653 if (SSMR3HandleRevision(pSSM) >= 71199)
3654 {
3655 uint32_t uVer = SSMR3HandleVersion(pSSM);
3656 if ( VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
3657 && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
3658 && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
3659 cRegs = 112;
3660 }
3661 break;
3662
3663 case HDA_SSM_VERSION_2:
3664 case HDA_SSM_VERSION_3:
3665 cRegs = 112;
3666 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= 112);
3667 break;
3668
3669 /* Since version 4 we store the register count to stay flexible. */
3670 case HDA_SSM_VERSION_4:
3671 case HDA_SSM_VERSION_5:
3672 case HDA_SSM_VERSION_6:
3673 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
3674 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
3675 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
3676 break;
3677
3678 default:
3679 LogRel(("HDA: Warning: Unsupported / too new saved state version (%RU32)\n", uVersion));
3680 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3681 }
3682
3683 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
3684 {
3685 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3686 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
3687 }
3688 else
3689 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
3690
3691 /* Make sure to update the base addresses first before initializing any streams down below. */
3692 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
3693 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
3694 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
3695
3696 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
3697 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
3698
3699 /*
3700 * Note: Saved states < v5 store LVI (u32BdleMaxCvi) for
3701 * *every* BDLE state, whereas it only needs to be stored
3702 * *once* for every stream. Most of the BDLE state we can
3703 * get out of the registers anyway, so just ignore those values.
3704 *
3705 * Also, only the current BDLE was saved, regardless whether
3706 * there were more than one (and there are at least two entries,
3707 * according to the spec).
3708 */
3709#define HDA_SSM_LOAD_BDLE_STATE_PRE_V5(v, x) \
3710 { \
3711 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */ \
3712 AssertRCReturn(rc, rc); \
3713 rc = SSMR3GetU64(pSSM, &x.Desc.u64BufAdr); /* u64BdleCviAddr */ \
3714 AssertRCReturn(rc, rc); \
3715 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* u32BdleMaxCvi */ \
3716 AssertRCReturn(rc, rc); \
3717 rc = SSMR3GetU32(pSSM, &x.State.u32BDLIndex); /* u32BdleCvi */ \
3718 AssertRCReturn(rc, rc); \
3719 rc = SSMR3GetU32(pSSM, &x.Desc.u32BufSize); /* u32BdleCviLen */ \
3720 AssertRCReturn(rc, rc); \
3721 rc = SSMR3GetU32(pSSM, &x.State.u32BufOff); /* u32BdleCviPos */ \
3722 AssertRCReturn(rc, rc); \
3723 bool fIOC; \
3724 rc = SSMR3GetBool(pSSM, &fIOC); /* fBdleCviIoc */ \
3725 AssertRCReturn(rc, rc); \
3726 x.Desc.fFlags = fIOC ? HDA_BDLE_FLAG_IOC : 0; \
3727 rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */ \
3728 AssertRCReturn(rc, rc); \
3729 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO */ \
3730 AssertRCReturn(rc, rc); \
3731 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */ \
3732 AssertRCReturn(rc, rc); \
3733 }
3734
3735 /*
3736 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
3737 */
3738 switch (uVersion)
3739 {
3740 case HDA_SSM_VERSION_1:
3741 case HDA_SSM_VERSION_2:
3742 case HDA_SSM_VERSION_3:
3743 case HDA_SSM_VERSION_4:
3744 {
3745 /* Only load the internal states.
3746 * The rest will be initialized from the saved registers later. */
3747
3748 /* Note 1: Only the *current* BDLE for a stream was saved! */
3749 /* Note 2: The stream's saving order is/was fixed, so don't touch! */
3750
3751 /* Output */
3752 PHDASTREAM pStream = &pThis->aStreams[4];
3753 rc = hdaStreamInit(pStream, 4 /* Stream descriptor, hardcoded */);
3754 if (RT_FAILURE(rc))
3755 break;
3756 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
3757 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
3758
3759 /* Microphone-In */
3760 pStream = &pThis->aStreams[2];
3761 rc = hdaStreamInit(pStream, 2 /* Stream descriptor, hardcoded */);
3762 if (RT_FAILURE(rc))
3763 break;
3764 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
3765 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
3766
3767 /* Line-In */
3768 pStream = &pThis->aStreams[0];
3769 rc = hdaStreamInit(pStream, 0 /* Stream descriptor, hardcoded */);
3770 if (RT_FAILURE(rc))
3771 break;
3772 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
3773 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
3774 break;
3775 }
3776
3777#undef HDA_SSM_LOAD_BDLE_STATE_PRE_V5
3778
3779 default: /* Since v5 we support flexible stream and BDLE counts. */
3780 {
3781 uint32_t cStreams;
3782 rc = SSMR3GetU32(pSSM, &cStreams);
3783 if (RT_FAILURE(rc))
3784 break;
3785
3786 if (cStreams > HDA_MAX_STREAMS)
3787 cStreams = HDA_MAX_STREAMS; /* Sanity. */
3788
3789 /* Load stream states. */
3790 for (uint32_t i = 0; i < cStreams; i++)
3791 {
3792 uint8_t uStreamID;
3793 rc = SSMR3GetU8(pSSM, &uStreamID);
3794 if (RT_FAILURE(rc))
3795 break;
3796
3797 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uStreamID);
3798 HDASTREAM StreamDummy;
3799
3800 if (!pStream)
3801 {
3802 pStream = &StreamDummy;
3803 LogRel2(("HDA: Warning: Stream ID=%RU32 not supported, skipping to load ...\n", uStreamID));
3804 }
3805
3806 rc = hdaStreamInit(pStream, uStreamID);
3807 if (RT_FAILURE(rc))
3808 {
3809 LogRel(("HDA: Stream #%RU32: Initialization of stream %RU8 failed, rc=%Rrc\n", i, uStreamID, rc));
3810 break;
3811 }
3812
3813 /*
3814 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
3815 */
3816
3817 if (uVersion == HDA_SSM_VERSION_5)
3818 {
3819 /* Get the current BDLE entry and skip the rest. */
3820 uint16_t cBDLE;
3821
3822 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
3823 AssertRC(rc);
3824 rc = SSMR3GetU16(pSSM, &cBDLE); /* cBDLE */
3825 AssertRC(rc);
3826 rc = SSMR3GetU16(pSSM, &pStream->State.uCurBDLE); /* uCurBDLE */
3827 AssertRC(rc);
3828 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
3829 AssertRC(rc);
3830
3831 uint32_t u32BDLEIndex;
3832 for (uint16_t a = 0; a < cBDLE; a++)
3833 {
3834 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
3835 AssertRC(rc);
3836 rc = SSMR3GetU32(pSSM, &u32BDLEIndex); /* u32BDLIndex */
3837 AssertRC(rc);
3838
3839 /* Does the current BDLE index match the current BDLE to process? */
3840 if (u32BDLEIndex == pStream->State.uCurBDLE)
3841 {
3842 rc = SSMR3GetU32(pSSM, &pStream->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */
3843 AssertRC(rc);
3844 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO, deprecated */
3845 AssertRC(rc);
3846 rc = SSMR3GetU32(pSSM, &pStream->State.BDLE.State.u32BufOff); /* u32BufOff */
3847 AssertRC(rc);
3848 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
3849 AssertRC(rc);
3850 }
3851 else /* Skip not current BDLEs. */
3852 {
3853 rc = SSMR3Skip(pSSM, sizeof(uint32_t) /* cbBelowFIFOW */
3854 + sizeof(uint8_t) * 256 /* au8FIFO */
3855 + sizeof(uint32_t) /* u32BufOff */
3856 + sizeof(uint32_t)); /* End marker */
3857 AssertRC(rc);
3858 }
3859 }
3860 }
3861 else
3862 {
3863 rc = SSMR3GetStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE),
3864 0 /* fFlags */, g_aSSMStreamStateFields6, NULL);
3865 if (RT_FAILURE(rc))
3866 break;
3867
3868 /* Get HDABDLEDESC. */
3869 uint32_t uMarker;
3870 rc = SSMR3GetU32(pSSM, &uMarker); /* Begin marker. */
3871 AssertRC(rc);
3872 Assert(uMarker == UINT32_C(0x19200102) /* SSMR3STRUCT_BEGIN */);
3873 rc = SSMR3GetU64(pSSM, &pStream->State.BDLE.Desc.u64BufAdr);
3874 AssertRC(rc);
3875 rc = SSMR3GetU32(pSSM, &pStream->State.BDLE.Desc.u32BufSize);
3876 AssertRC(rc);
3877 bool fFlags = false;
3878 rc = SSMR3GetBool(pSSM, &fFlags); /* Saved states < v7 only stored the IOC as boolean flag. */
3879 AssertRC(rc);
3880 pStream->State.BDLE.Desc.fFlags = fFlags ? HDA_BDLE_FLAG_IOC : 0;
3881 rc = SSMR3GetU32(pSSM, &uMarker); /* End marker. */
3882 AssertRC(rc);
3883 Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */);
3884
3885 rc = SSMR3GetStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE),
3886 0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
3887 if (RT_FAILURE(rc))
3888 break;
3889
3890 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
3891 uStreamID,
3892 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
3893#ifdef LOG_ENABLED
3894 hdaBDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
3895#endif
3896 }
3897
3898 } /* for cStreams */
3899 break;
3900 } /* default */
3901 }
3902
3903 return rc;
3904}
3905
3906/**
3907 * @callback_method_impl{FNSSMDEVLOADEXEC}
3908 */
3909static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3910{
3911 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3912
3913 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3914
3915 LogRel2(("hdaLoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
3916
3917 /*
3918 * Load Codec nodes states.
3919 */
3920 int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
3921 if (RT_FAILURE(rc))
3922 {
3923 LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
3924 return rc;
3925 }
3926
3927 if (uVersion < HDA_SSM_VERSION) /* Handle older saved states? */
3928 {
3929 rc = hdaLoadExecLegacy(pThis, pSSM, uVersion, uPass);
3930 if (RT_SUCCESS(rc))
3931 rc = hdaLoadExecPost(pThis);
3932
3933 return rc;
3934 }
3935
3936 /*
3937 * Load MMIO registers.
3938 */
3939 uint32_t cRegs;
3940 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
3941 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
3942 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
3943
3944 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
3945 {
3946 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3947 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
3948 }
3949 else
3950 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
3951
3952 /* Make sure to update the base addresses first before initializing any streams down below. */
3953 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
3954 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
3955 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
3956
3957 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
3958 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
3959
3960 /*
3961 * Load controller-specifc internals.
3962 * Don't annoy other team mates (forgot this for state v7).
3963 */
3964 if ( SSMR3HandleRevision(pSSM) >= 116273
3965 || SSMR3HandleVersion(pSSM) >= VBOX_FULL_VERSION_MAKE(5, 2, 0))
3966 {
3967 rc = SSMR3GetU64(pSSM, &pThis->u64WalClk);
3968 AssertRC(rc);
3969
3970 rc = SSMR3GetU8(pSSM, &pThis->u8IRQL);
3971 AssertRC(rc);
3972 }
3973
3974 /*
3975 * Load streams.
3976 */
3977 uint32_t cStreams;
3978 rc = SSMR3GetU32(pSSM, &cStreams);
3979 AssertRC(rc);
3980
3981 if (cStreams > HDA_MAX_STREAMS)
3982 cStreams = HDA_MAX_STREAMS; /* Sanity. */
3983
3984 Log2Func(("cStreams=%RU32\n", cStreams));
3985
3986 /* Load stream states. */
3987 for (uint32_t i = 0; i < cStreams; i++)
3988 {
3989 uint8_t uStreamID;
3990 rc = SSMR3GetU8(pSSM, &uStreamID);
3991 AssertRC(rc);
3992
3993 PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uStreamID);
3994 HDASTREAM StreamDummy;
3995
3996 if (!pStream)
3997 {
3998 pStream = &StreamDummy;
3999 LogRel2(("HDA: Warning: Loading of stream #%RU8 not supported, skipping to load ...\n", uStreamID));
4000 }
4001
4002 rc = hdaStreamInit(pStream, uStreamID);
4003 if (RT_FAILURE(rc))
4004 {
4005 LogRel(("HDA: Stream #%RU8: Loading initialization failed, rc=%Rrc\n", uStreamID, rc));
4006 /* Continue. */
4007 }
4008
4009 rc = SSMR3GetStructEx(pSSM, &pStream->State, sizeof(HDASTREAMSTATE),
4010 0 /* fFlags */, g_aSSMStreamStateFields7,
4011 NULL);
4012 AssertRC(rc);
4013
4014 /*
4015 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
4016 */
4017 rc = SSMR3GetStructEx(pSSM, &pStream->State.BDLE.Desc, sizeof(HDABDLEDESC),
4018 0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
4019 AssertRC(rc);
4020
4021 rc = SSMR3GetStructEx(pSSM, &pStream->State.BDLE.State, sizeof(HDABDLESTATE),
4022 0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
4023 AssertRC(rc);
4024
4025 Log2Func(("[SD%RU8] %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));
4026
4027 /*
4028 * Load period state.
4029 * Don't annoy other team mates (forgot this for state v7).
4030 */
4031 hdaStreamPeriodInit(&pStream->State.Period,
4032 pStream->u8SD, pStream->u16LVI, pStream->u32CBL, &pStream->State.Cfg);
4033
4034 if ( SSMR3HandleRevision(pSSM) >= 116273
4035 || SSMR3HandleVersion(pSSM) >= VBOX_FULL_VERSION_MAKE(5, 2, 0))
4036 {
4037 rc = SSMR3GetStructEx(pSSM, &pStream->State.Period, sizeof(HDASTREAMPERIOD),
4038 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
4039 AssertRC(rc);
4040 }
4041
4042 /*
4043 * Load internal (FIFO) buffer.
4044 */
4045 uint32_t cbCircBufSize = 0;
4046 rc = SSMR3GetU32(pSSM, &cbCircBufSize); /* cbCircBuf */
4047 AssertRC(rc);
4048
4049 uint32_t cbCircBufUsed = 0;
4050 rc = SSMR3GetU32(pSSM, &cbCircBufUsed); /* cbCircBuf */
4051 AssertRC(rc);
4052
4053 if (cbCircBufSize) /* If 0, skip the buffer. */
4054 {
4055 /* Paranoia. */
4056 AssertReleaseMsg(cbCircBufSize <= _1M,
4057 ("HDA: Saved state contains bogus DMA buffer size (%RU32) for stream #%RU8",
4058 cbCircBufSize, uStreamID));
4059 AssertReleaseMsg(cbCircBufUsed <= cbCircBufSize,
4060 ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
4061 cbCircBufUsed, cbCircBufSize, uStreamID));
4062 AssertPtr(pStream->State.pCircBuf);
4063
4064 /* Do we need to cre-create the circular buffer do fit the data size? */
4065 if (cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
4066 {
4067 RTCircBufDestroy(pStream->State.pCircBuf);
4068 pStream->State.pCircBuf = NULL;
4069
4070 rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
4071 AssertRC(rc);
4072 }
4073
4074 if ( RT_SUCCESS(rc)
4075 && cbCircBufUsed)
4076 {
4077 void *pvBuf;
4078 size_t cbBuf;
4079
4080 RTCircBufAcquireWriteBlock(pStream->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
4081
4082 if (cbBuf)
4083 {
4084 rc = SSMR3GetMem(pSSM, pvBuf, cbBuf);
4085 AssertRC(rc);
4086 }
4087
4088 RTCircBufReleaseWriteBlock(pStream->State.pCircBuf, cbBuf);
4089
4090 Assert(cbBuf == cbCircBufUsed);
4091 }
4092 }
4093
4094 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
4095 uStreamID,
4096 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
4097#ifdef LOG_ENABLED
4098 hdaBDLEDumpAll(pThis, pStream->u64BDLBase, pStream->u16LVI + 1);
4099#endif
4100 /** @todo (Re-)initialize active periods? */
4101
4102 } /* for cStreams */
4103
4104 rc = hdaLoadExecPost(pThis);
4105 AssertRC(rc);
4106
4107 LogFlowFuncLeaveRC(rc);
4108 return rc;
4109}
4110
4111/* Debug and log type formatters. */
4112
4113/**
4114 * @callback_method_impl{FNRTSTRFORMATTYPE}
4115 */
4116static DECLCALLBACK(size_t) hdaDbgFmtBDLE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4117 const char *pszType, void const *pvValue,
4118 int cchWidth, int cchPrecision, unsigned fFlags,
4119 void *pvUser)
4120{
4121 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4122 PHDABDLE pBDLE = (PHDABDLE)pvValue;
4123 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4124 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])",
4125 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,
4126 pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC, pBDLE->Desc.u32BufSize, pBDLE->Desc.u64BufAdr);
4127}
4128
4129/**
4130 * @callback_method_impl{FNRTSTRFORMATTYPE}
4131 */
4132static DECLCALLBACK(size_t) hdaDbgFmtSDCTL(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4133 const char *pszType, void const *pvValue,
4134 int cchWidth, int cchPrecision, unsigned fFlags,
4135 void *pvUser)
4136{
4137 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4138 uint32_t uSDCTL = (uint32_t)(uintptr_t)pvValue;
4139 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4140 "SDCTL(raw:%#x, DIR:%s, TP:%RTbool, STRIPE:%x, DEIE:%RTbool, FEIE:%RTbool, IOCE:%RTbool, RUN:%RTbool, RESET:%RTbool)",
4141 uSDCTL,
4142 uSDCTL & HDA_SDCTL_DIR ? "OUT" : "IN",
4143 RT_BOOL(uSDCTL & HDA_SDCTL_TP),
4144 (uSDCTL & HDA_SDCTL_STRIPE_MASK) >> HDA_SDCTL_STRIPE_SHIFT,
4145 RT_BOOL(uSDCTL & HDA_SDCTL_DEIE),
4146 RT_BOOL(uSDCTL & HDA_SDCTL_FEIE),
4147 RT_BOOL(uSDCTL & HDA_SDCTL_IOCE),
4148 RT_BOOL(uSDCTL & HDA_SDCTL_RUN),
4149 RT_BOOL(uSDCTL & HDA_SDCTL_SRST));
4150}
4151
4152/**
4153 * @callback_method_impl{FNRTSTRFORMATTYPE}
4154 */
4155static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4156 const char *pszType, void const *pvValue,
4157 int cchWidth, int cchPrecision, unsigned fFlags,
4158 void *pvUser)
4159{
4160 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4161 uint32_t uSDFIFOS = (uint32_t)(uintptr_t)pvValue;
4162 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw:%#x, sdfifos:%RU8 B)", uSDFIFOS, uSDFIFOS ? uSDFIFOS + 1 : 0);
4163}
4164
4165/**
4166 * @callback_method_impl{FNRTSTRFORMATTYPE}
4167 */
4168static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOW(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4169 const char *pszType, void const *pvValue,
4170 int cchWidth, int cchPrecision, unsigned fFlags,
4171 void *pvUser)
4172{
4173 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4174 uint32_t uSDFIFOW = (uint32_t)(uintptr_t)pvValue;
4175 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSDFIFOW, hdaSDFIFOWToBytes(uSDFIFOW));
4176}
4177
4178/**
4179 * @callback_method_impl{FNRTSTRFORMATTYPE}
4180 */
4181static DECLCALLBACK(size_t) hdaDbgFmtSDSTS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
4182 const char *pszType, void const *pvValue,
4183 int cchWidth, int cchPrecision, unsigned fFlags,
4184 void *pvUser)
4185{
4186 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
4187 uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
4188 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
4189 "SDSTS(raw:%#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
4190 uSdSts,
4191 RT_BOOL(uSdSts & HDA_SDSTS_FIFORDY),
4192 RT_BOOL(uSdSts & HDA_SDSTS_DESE),
4193 RT_BOOL(uSdSts & HDA_SDSTS_FIFOE),
4194 RT_BOOL(uSdSts & HDA_SDSTS_BCIS));
4195}
4196
4197static int hdaDbgLookupRegByName(const char *pszArgs)
4198{
4199 int iReg = 0;
4200 for (; iReg < HDA_NUM_REGS; ++iReg)
4201 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
4202 return iReg;
4203 return -1;
4204}
4205
4206
4207static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
4208{
4209 Assert( pThis
4210 && iHdaIndex >= 0
4211 && iHdaIndex < HDA_NUM_REGS);
4212 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
4213}
4214
4215/**
4216 * @callback_method_impl{FNDBGFHANDLERDEV}
4217 */
4218static DECLCALLBACK(void) hdaDbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4219{
4220 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4221 int iHdaRegisterIndex = hdaDbgLookupRegByName(pszArgs);
4222 if (iHdaRegisterIndex != -1)
4223 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
4224 else
4225 {
4226 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NUM_REGS; ++iHdaRegisterIndex)
4227 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
4228 }
4229}
4230
4231static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
4232{
4233 Assert( pThis
4234 && iIdx >= 0
4235 && iIdx < HDA_MAX_STREAMS);
4236
4237 const PHDASTREAM pStream = &pThis->aStreams[iIdx];
4238
4239 pHlp->pfnPrintf(pHlp, "Stream #%d:\n", iIdx);
4240 pHlp->pfnPrintf(pHlp, "\tSD%dCTL : %R[sdctl]\n", iIdx, HDA_STREAM_REG(pThis, CTL, iIdx));
4241 pHlp->pfnPrintf(pHlp, "\tSD%dCTS : %R[sdsts]\n", iIdx, HDA_STREAM_REG(pThis, STS, iIdx));
4242 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOS: %R[sdfifos]\n", iIdx, HDA_STREAM_REG(pThis, FIFOS, iIdx));
4243 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOW: %R[sdfifow]\n", iIdx, HDA_STREAM_REG(pThis, FIFOW, iIdx));
4244 pHlp->pfnPrintf(pHlp, "\tBDLE : %R[bdle]\n", &pStream->State.BDLE);
4245}
4246
4247static void hdaDbgPrintBDLE(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
4248{
4249 Assert( pThis
4250 && iIdx >= 0
4251 && iIdx < HDA_MAX_STREAMS);
4252
4253 const PHDASTREAM pStream = &pThis->aStreams[iIdx];
4254 const PHDABDLE pBDLE = &pStream->State.BDLE;
4255
4256 pHlp->pfnPrintf(pHlp, "Stream #%d BDLE:\n", iIdx);
4257
4258 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, iIdx),
4259 HDA_STREAM_REG(pThis, BDPU, iIdx));
4260 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, iIdx);
4261 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, iIdx);
4262
4263 if (!u64BaseDMA)
4264 return;
4265
4266 pHlp->pfnPrintf(pHlp, "\tCurrent: %R[bdle]\n\n", pBDLE);
4267
4268 pHlp->pfnPrintf(pHlp, "\tMemory:\n");
4269
4270 uint32_t cbBDLE = 0;
4271 for (uint16_t i = 0; i < u16LVI + 1; i++)
4272 {
4273 HDABDLEDESC bd;
4274 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
4275
4276 pHlp->pfnPrintf(pHlp, "\t\t%s #%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
4277 pBDLE->State.u32BDLIndex == i ? "*" : " ", i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC);
4278
4279 cbBDLE += bd.u32BufSize;
4280 }
4281
4282 pHlp->pfnPrintf(pHlp, "Total: %RU32 bytes\n", cbBDLE);
4283
4284 if (cbBDLE != u32CBL)
4285 pHlp->pfnPrintf(pHlp, "Warning: %RU32 bytes does not match CBL (%RU32)!\n", cbBDLE, u32CBL);
4286
4287 pHlp->pfnPrintf(pHlp, "DMA counters (base @ 0x%llx):\n", u64BaseDMA);
4288 if (!u64BaseDMA) /* No DMA base given? Bail out. */
4289 {
4290 pHlp->pfnPrintf(pHlp, "\tNo counters found\n");
4291 return;
4292 }
4293
4294 for (int i = 0; i < u16LVI + 1; i++)
4295 {
4296 uint32_t uDMACnt;
4297 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
4298 &uDMACnt, sizeof(uDMACnt));
4299
4300 pHlp->pfnPrintf(pHlp, "\t#%03d DMA @ 0x%x\n", i , uDMACnt);
4301 }
4302}
4303
4304static int hdaDbgLookupStrmIdx(PHDASTATE pThis, const char *pszArgs)
4305{
4306 RT_NOREF(pThis, pszArgs);
4307 /** @todo Add args parsing. */
4308 return -1;
4309}
4310
4311/**
4312 * @callback_method_impl{FNDBGFHANDLERDEV}
4313 */
4314static DECLCALLBACK(void) hdaDbgInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4315{
4316 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4317 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
4318 if (iHdaStreamdex != -1)
4319 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
4320 else
4321 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
4322 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
4323}
4324
4325/**
4326 * @callback_method_impl{FNDBGFHANDLERDEV}
4327 */
4328static DECLCALLBACK(void) hdaDbgInfoBDLE(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4329{
4330 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4331 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
4332 if (iHdaStreamdex != -1)
4333 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
4334 else
4335 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
4336 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
4337}
4338
4339/**
4340 * @callback_method_impl{FNDBGFHANDLERDEV}
4341 */
4342static DECLCALLBACK(void) hdaDbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4343{
4344 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4345
4346 if (pThis->pCodec->pfnDbgListNodes)
4347 pThis->pCodec->pfnDbgListNodes(pThis->pCodec, pHlp, pszArgs);
4348 else
4349 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
4350}
4351
4352/**
4353 * @callback_method_impl{FNDBGFHANDLERDEV}
4354 */
4355static DECLCALLBACK(void) hdaDbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4356{
4357 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4358
4359 if (pThis->pCodec->pfnDbgSelector)
4360 pThis->pCodec->pfnDbgSelector(pThis->pCodec, pHlp, pszArgs);
4361 else
4362 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
4363}
4364
4365/**
4366 * @callback_method_impl{FNDBGFHANDLERDEV}
4367 */
4368static DECLCALLBACK(void) hdaDbgInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4369{
4370 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4371
4372 if (pThis->pMixer)
4373 AudioMixerDebug(pThis->pMixer, pHlp, pszArgs);
4374 else
4375 pHlp->pfnPrintf(pHlp, "Mixer not available\n");
4376}
4377
4378
4379/* PDMIBASE */
4380
4381/**
4382 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
4383 */
4384static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
4385{
4386 PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
4387 Assert(&pThis->IBase == pInterface);
4388
4389 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
4390 return NULL;
4391}
4392
4393
4394/* PDMDEVREG */
4395
4396
4397/**
4398 * @interface_method_impl{PDMDEVREG,pfnReset}
4399 */
4400static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
4401{
4402 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4403
4404 LogFlowFuncEnter();
4405
4406 DEVHDA_LOCK_RETURN_VOID(pThis);
4407
4408 /*
4409 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
4410 * hdaReset shouldn't affects these registers.
4411 */
4412 HDA_REG(pThis, WAKEEN) = 0x0;
4413
4414 hdaGCTLReset(pThis);
4415
4416 /* Indicate that HDA is not in reset. The firmware is supposed to (un)reset HDA,
4417 * but we can take a shortcut.
4418 */
4419 HDA_REG(pThis, GCTL) = HDA_GCTL_CRST;
4420
4421 DEVHDA_UNLOCK(pThis);
4422}
4423
4424/**
4425 * @interface_method_impl{PDMDEVREG,pfnDestruct}
4426 */
4427static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
4428{
4429 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4430
4431 DEVHDA_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
4432
4433 PHDADRIVER pDrv;
4434 while (!RTListIsEmpty(&pThis->lstDrv))
4435 {
4436 pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node);
4437
4438 RTListNodeRemove(&pDrv->Node);
4439 RTMemFree(pDrv);
4440 }
4441
4442 if (pThis->pCodec)
4443 {
4444 hdaCodecDestruct(pThis->pCodec);
4445
4446 RTMemFree(pThis->pCodec);
4447 pThis->pCodec = NULL;
4448 }
4449
4450 RTMemFree(pThis->pu32CorbBuf);
4451 pThis->pu32CorbBuf = NULL;
4452
4453 RTMemFree(pThis->pu64RirbBuf);
4454 pThis->pu64RirbBuf = NULL;
4455
4456 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
4457 hdaStreamDestroy(&pThis->aStreams[i]);
4458
4459 DEVHDA_UNLOCK(pThis);
4460
4461 return VINF_SUCCESS;
4462}
4463
4464
4465/**
4466 * Attach command, internal version.
4467 *
4468 * This is called to let the device attach to a driver for a specified LUN
4469 * during runtime. This is not called during VM construction, the device
4470 * constructor has to attach to all the available drivers.
4471 *
4472 * @returns VBox status code.
4473 * @param pThis HDA state.
4474 * @param uLUN The logical unit which is being detached.
4475 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
4476 * @param ppDrv Attached driver instance on success. Optional.
4477 */
4478static int hdaAttachInternal(PHDASTATE pThis, unsigned uLUN, uint32_t fFlags, PHDADRIVER *ppDrv)
4479{
4480 RT_NOREF(fFlags);
4481
4482 /*
4483 * Attach driver.
4484 */
4485 char *pszDesc;
4486 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
4487 AssertLogRelFailedReturn(VERR_NO_MEMORY);
4488
4489 PPDMIBASE pDrvBase;
4490 int rc = PDMDevHlpDriverAttach(pThis->pDevInsR3, uLUN,
4491 &pThis->IBase, &pDrvBase, pszDesc);
4492 if (RT_SUCCESS(rc))
4493 {
4494 PHDADRIVER pDrv = (PHDADRIVER)RTMemAllocZ(sizeof(HDADRIVER));
4495 if (pDrv)
4496 {
4497 pDrv->pDrvBase = pDrvBase;
4498 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
4499 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
4500 pDrv->pHDAState = pThis;
4501 pDrv->uLUN = uLUN;
4502
4503 /*
4504 * For now we always set the driver at LUN 0 as our primary
4505 * host backend. This might change in the future.
4506 */
4507 if (pDrv->uLUN == 0)
4508 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
4509
4510 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
4511
4512 /* Attach to driver list if not attached yet. */
4513 if (!pDrv->fAttached)
4514 {
4515 RTListAppend(&pThis->lstDrv, &pDrv->Node);
4516 pDrv->fAttached = true;
4517 }
4518
4519 if (ppDrv)
4520 *ppDrv = pDrv;
4521 }
4522 else
4523 rc = VERR_NO_MEMORY;
4524 }
4525 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
4526 LogFunc(("No attached driver for LUN #%u\n", uLUN));
4527
4528 if (RT_FAILURE(rc))
4529 {
4530 /* Only free this string on failure;
4531 * must remain valid for the live of the driver instance. */
4532 RTStrFree(pszDesc);
4533 }
4534
4535 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
4536 return rc;
4537}
4538
4539/**
4540 * Detach command, internal version.
4541 *
4542 * This is called to let the device detach from a driver for a specified LUN
4543 * during runtime.
4544 *
4545 * @returns VBox status code.
4546 * @param pThis HDA state.
4547 * @param pDrv Driver to detach device from.
4548 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
4549 */
4550static int hdaDetachInternal(PHDASTATE pThis, PHDADRIVER pDrv, uint32_t fFlags)
4551{
4552 RT_NOREF(fFlags);
4553
4554 AudioMixerSinkRemoveStream(pThis->SinkFront.pMixSink, pDrv->Front.pMixStrm);
4555 AudioMixerStreamDestroy(pDrv->Front.pMixStrm);
4556 pDrv->Front.pMixStrm = NULL;
4557
4558#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4559 AudioMixerSinkRemoveStream(pThis->SinkCenterLFE.pMixSink, pDrv->CenterLFE.pMixStrm);
4560 AudioMixerStreamDestroy(pDrv->CenterLFE.pMixStrm);
4561 pDrv->CenterLFE.pMixStrm = NULL;
4562
4563 AudioMixerSinkRemoveStream(pThis->SinkRear.pMixSink, pDrv->Rear.pMixStrm);
4564 AudioMixerStreamDestroy(pDrv->Rear.pMixStrm);
4565 pDrv->Rear.pMixStrm = NULL;
4566#endif
4567
4568 AudioMixerSinkRemoveStream(pThis->SinkLineIn.pMixSink, pDrv->LineIn.pMixStrm);
4569 AudioMixerStreamDestroy(pDrv->LineIn.pMixStrm);
4570 pDrv->LineIn.pMixStrm = NULL;
4571
4572#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4573 AudioMixerSinkRemoveStream(pThis->SinkMicIn.pMixSink, pDrv->MicIn.pMixStrm);
4574 AudioMixerStreamDestroy(pDrv->MicIn.pMixStrm);
4575 pDrv->MicIn.pMixStrm = NULL;
4576#endif
4577
4578 RTListNodeRemove(&pDrv->Node);
4579
4580 LogFunc(("uLUN=%u, fFlags=0x%x\n", pDrv->uLUN, fFlags));
4581 return VINF_SUCCESS;
4582}
4583
4584/**
4585 * @interface_method_impl{PDMDEVREG,pfnAttach}
4586 */
4587static DECLCALLBACK(int) hdaAttach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
4588{
4589 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4590
4591 DEVHDA_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
4592
4593 LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
4594
4595 PHDADRIVER pDrv;
4596 int rc2 = hdaAttachInternal(pThis, uLUN, fFlags, &pDrv);
4597 if (RT_SUCCESS(rc2))
4598 {
4599 PHDASTREAM pStream = hdaGetStreamFromSink(pThis, &pThis->SinkFront);
4600 if (DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
4601 hdaMixerAddDrvStream(pThis, pThis->SinkFront.pMixSink, &pStream->State.Cfg, pDrv);
4602
4603#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4604 pStream = hdaGetStreamFromSink(pThis, &pThis->SinkCenterLFE);
4605 if (DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
4606 hdaMixerAddDrvStream(pThis, pThis->SinkCenterLFE.pMixSink, &pStream->State.Cfg, pDrv);
4607
4608 pStream = hdaGetStreamFromSink(pThis, &pThis->SinkRear);
4609 if (DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
4610 hdaMixerAddDrvStream(pThis, pThis->SinkRear.pMixSink, &pStream->State.Cfg, pDrv);
4611#endif
4612 pStream = hdaGetStreamFromSink(pThis, &pThis->SinkLineIn);
4613 if (DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
4614 hdaMixerAddDrvStream(pThis, pThis->SinkLineIn.pMixSink, &pStream->State.Cfg, pDrv);
4615
4616#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4617 pStream = hdaGetStreamFromSink(pThis, &pThis->SinkMicIn);
4618 if (DrvAudioHlpStreamCfgIsValid(&pStream->State.Cfg))
4619 hdaMixerAddDrvStream(pThis, pThis->SinkMicIn.pMixSink, &pStream->State.Cfg, pDrv);
4620#endif
4621 }
4622
4623 DEVHDA_UNLOCK(pThis);
4624
4625 return VINF_SUCCESS;
4626}
4627
4628/**
4629 * @interface_method_impl{PDMDEVREG,pfnDetach}
4630 */
4631static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
4632{
4633 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4634
4635 DEVHDA_LOCK(pThis);
4636
4637 LogFunc(("uLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
4638
4639 PHDADRIVER pDrv, pDrvNext;
4640 RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, HDADRIVER, Node)
4641 {
4642 if (pDrv->uLUN == uLUN)
4643 {
4644 int rc2 = hdaDetachInternal(pThis, pDrv, fFlags);
4645 if (RT_SUCCESS(rc2))
4646 {
4647 RTMemFree(pDrv);
4648 pDrv = NULL;
4649 }
4650
4651 break;
4652 }
4653 }
4654
4655 DEVHDA_UNLOCK(pThis);
4656}
4657
4658/**
4659 * Re-attaches (replaces) a driver with a new driver.
4660 *
4661 * @returns VBox status code.
4662 * @param pThis Device instance to re-attach driver to.
4663 * @param pDrv Driver instance used for attaching to.
4664 * If NULL is specified, a new driver will be created and appended
4665 * to the driver list.
4666 * @param uLUN The logical unit which is being re-detached.
4667 * @param pszDriver New driver name to attach.
4668 */
4669static int hdaReattachInternal(PHDASTATE pThis, PHDADRIVER pDrv, uint8_t uLUN, const char *pszDriver)
4670{
4671 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
4672 AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
4673
4674 int rc;
4675
4676 if (pDrv)
4677 {
4678 rc = hdaDetachInternal(pThis, pDrv, 0 /* fFlags */);
4679 if (RT_SUCCESS(rc))
4680 rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
4681
4682 if (RT_FAILURE(rc))
4683 return rc;
4684
4685 pDrv = NULL;
4686 }
4687
4688 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
4689 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
4690 PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/hda/0/");
4691
4692 /* Remove LUN branch. */
4693 CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
4694
4695#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
4696
4697 do
4698 {
4699 PCFGMNODE pLunL0;
4700 rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN); RC_CHECK();
4701 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
4702 rc = CFGMR3InsertNode(pLunL0, "Config/", NULL); RC_CHECK();
4703
4704 PCFGMNODE pLunL1, pLunL2;
4705 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver/", &pLunL1); RC_CHECK();
4706 rc = CFGMR3InsertNode (pLunL1, "Config/", &pLunL2); RC_CHECK();
4707 rc = CFGMR3InsertString(pLunL1, "Driver", pszDriver); RC_CHECK();
4708
4709 rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver); RC_CHECK();
4710
4711 } while (0);
4712
4713 if (RT_SUCCESS(rc))
4714 rc = hdaAttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
4715
4716 LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
4717
4718#undef RC_CHECK
4719
4720 return rc;
4721}
4722
4723/**
4724 * Powers off the device.
4725 *
4726 * @param pDevIns Device instance to power off.
4727 */
4728static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns)
4729{
4730 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4731
4732 DEVHDA_LOCK_RETURN_VOID(pThis);
4733
4734 LogRel2(("HDA: Powering off ...\n"));
4735
4736 /* Ditto goes for the codec, which in turn uses the mixer. */
4737 hdaCodecPowerOff(pThis->pCodec);
4738
4739 /**
4740 * Note: Destroy the mixer while powering off and *not* in hdaDestruct,
4741 * giving the mixer the chance to release any references held to
4742 * PDM audio streams it maintains.
4743 */
4744 if (pThis->pMixer)
4745 {
4746 AudioMixerDestroy(pThis->pMixer);
4747 pThis->pMixer = NULL;
4748 }
4749
4750 DEVHDA_UNLOCK(pThis);
4751}
4752
4753/**
4754 * @interface_method_impl{PDMDEVREG,pfnConstruct}
4755 */
4756static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
4757{
4758 RT_NOREF(iInstance);
4759 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
4760 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
4761 Assert(iInstance == 0);
4762
4763 /*
4764 * Validations.
4765 */
4766 if (!CFGMR3AreValuesValid(pCfg, "R0Enabled\0"
4767 "RCEnabled\0"
4768 "TimerHz\0"
4769 "PosAdjustEnabled\0"
4770 "PosAdjustFrames\0"
4771 "DebugEnabled\0"
4772 "DebugPathOut\0"))
4773 {
4774 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
4775 N_ ("Invalid configuration for the Intel HDA device"));
4776 }
4777
4778 int rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &pThis->fRCEnabled, false);
4779 if (RT_FAILURE(rc))
4780 return PDMDEV_SET_ERROR(pDevIns, rc,
4781 N_("HDA configuration error: failed to read RCEnabled as boolean"));
4782 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, false);
4783 if (RT_FAILURE(rc))
4784 return PDMDEV_SET_ERROR(pDevIns, rc,
4785 N_("HDA configuration error: failed to read R0Enabled as boolean"));
4786
4787 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &pThis->u16TimerHz, HDA_TIMER_HZ_DEFAULT /* Default value, if not set. */);
4788 if (RT_FAILURE(rc))
4789 return PDMDEV_SET_ERROR(pDevIns, rc,
4790 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
4791
4792 if (pThis->u16TimerHz != HDA_TIMER_HZ_DEFAULT)
4793 LogRel(("HDA: Using custom device timer rate (%RU16Hz)\n", pThis->u16TimerHz));
4794
4795 rc = CFGMR3QueryBoolDef(pCfg, "PosAdjustEnabled", &pThis->fPosAdjustEnabled, true);
4796 if (RT_FAILURE(rc))
4797 return PDMDEV_SET_ERROR(pDevIns, rc,
4798 N_("HDA configuration error: failed to read position adjustment enabled as boolean"));
4799
4800 if (!pThis->fPosAdjustEnabled)
4801 LogRel(("HDA: Position adjustment is disabled\n"));
4802
4803 rc = CFGMR3QueryU16Def(pCfg, "PosAdjustFrames", &pThis->cPosAdjustFrames, HDA_POS_ADJUST_DEFAULT);
4804 if (RT_FAILURE(rc))
4805 return PDMDEV_SET_ERROR(pDevIns, rc,
4806 N_("HDA configuration error: failed to read position adjustment frames as unsigned integer"));
4807
4808 if (pThis->cPosAdjustFrames)
4809 LogRel(("HDA: Using custom position adjustment (%RU16 audio frames)\n", pThis->cPosAdjustFrames));
4810
4811 rc = CFGMR3QueryBoolDef(pCfg, "DebugEnabled", &pThis->Dbg.fEnabled, false);
4812 if (RT_FAILURE(rc))
4813 return PDMDEV_SET_ERROR(pDevIns, rc,
4814 N_("HDA configuration error: failed to read debugging enabled flag as boolean"));
4815
4816 rc = CFGMR3QueryStringDef(pCfg, "DebugPathOut", pThis->Dbg.szOutPath, sizeof(pThis->Dbg.szOutPath),
4817 VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
4818 if (RT_FAILURE(rc))
4819 return PDMDEV_SET_ERROR(pDevIns, rc,
4820 N_("HDA configuration error: failed to read debugging output path flag as string"));
4821
4822 if (!strlen(pThis->Dbg.szOutPath))
4823 RTStrPrintf(pThis->Dbg.szOutPath, sizeof(pThis->Dbg.szOutPath), VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH);
4824
4825 if (pThis->Dbg.fEnabled)
4826 LogRel2(("HDA: Debug output will be saved to '%s'\n", pThis->Dbg.szOutPath));
4827
4828 /*
4829 * Use an own critical section for the device instead of the default
4830 * one provided by PDM. This allows fine-grained locking in combination
4831 * with TM when timer-specific stuff is being called in e.g. the MMIO handlers.
4832 */
4833 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "HDA");
4834 AssertRCReturn(rc, rc);
4835
4836 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
4837 AssertRCReturn(rc, rc);
4838
4839 /*
4840 * Initialize data (most of it anyway).
4841 */
4842 pThis->pDevInsR3 = pDevIns;
4843 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
4844 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
4845 /* IBase */
4846 pThis->IBase.pfnQueryInterface = hdaQueryInterface;
4847
4848 /* PCI Device */
4849 PCIDevSetVendorId (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
4850 PCIDevSetDeviceId (&pThis->PciDev, HDA_PCI_DEVICE_ID); /* HDA */
4851
4852 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
4853 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
4854 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */
4855 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */
4856 PCIDevSetClassSub (&pThis->PciDev, 0x03); /* 0a ro - scc; 03 == HDA. */
4857 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
4858 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */
4859 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - MMIO */
4860 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
4861 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */
4862 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */
4863
4864#if defined(HDA_AS_PCI_EXPRESS)
4865 PCIDevSetCapabilityList (&pThis->PciDev, 0x80);
4866#elif defined(VBOX_WITH_MSI_DEVICES)
4867 PCIDevSetCapabilityList (&pThis->PciDev, 0x60);
4868#else
4869 PCIDevSetCapabilityList (&pThis->PciDev, 0x50); /* ICH6 datasheet 18.1.16 */
4870#endif
4871
4872 /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
4873 /// of these values needs to be properly documented!
4874 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
4875 PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
4876
4877 /* Power Management */
4878 PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
4879 PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
4880 PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
4881
4882#ifdef HDA_AS_PCI_EXPRESS
4883 /* PCI Express */
4884 PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
4885 PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
4886 /* Device flags */
4887 PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
4888 /* version */ 0x1 |
4889 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
4890 /* MSI */ (100) << 9 );
4891 /* Device capabilities */
4892 PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
4893 /* Device control */
4894 PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
4895 /* Device status */
4896 PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
4897 /* Link caps */
4898 PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
4899 /* Link control */
4900 PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
4901 /* Link status */
4902 PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
4903 /* Slot capabilities */
4904 PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
4905 /* Slot control */
4906 PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
4907 /* Slot status */
4908 PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
4909 /* Root control */
4910 PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
4911 /* Root capabilities */
4912 PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
4913 /* Root status */
4914 PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
4915 /* Device capabilities 2 */
4916 PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
4917 /* Device control 2 */
4918 PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
4919 /* Link control 2 */
4920 PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
4921 /* Slot control 2 */
4922 PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
4923#endif
4924
4925 /*
4926 * Register the PCI device.
4927 */
4928 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
4929 if (RT_FAILURE(rc))
4930 return rc;
4931
4932 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
4933 if (RT_FAILURE(rc))
4934 return rc;
4935
4936#ifdef VBOX_WITH_MSI_DEVICES
4937 PDMMSIREG MsiReg;
4938 RT_ZERO(MsiReg);
4939 MsiReg.cMsiVectors = 1;
4940 MsiReg.iMsiCapOffset = 0x60;
4941 MsiReg.iMsiNextOffset = 0x50;
4942 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
4943 if (RT_FAILURE(rc))
4944 {
4945 /* That's OK, we can work without MSI */
4946 PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
4947 }
4948#endif
4949
4950 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
4951 if (RT_FAILURE(rc))
4952 return rc;
4953
4954 RTListInit(&pThis->lstDrv);
4955
4956#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
4957 LogRel(("HDA: Asynchronous I/O enabled\n"));
4958#endif
4959
4960 uint8_t uLUN;
4961 for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
4962 {
4963 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
4964 rc = hdaAttachInternal(pThis, uLUN, 0 /* fFlags */, NULL /* ppDrv */);
4965 if (RT_FAILURE(rc))
4966 {
4967 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
4968 rc = VINF_SUCCESS;
4969 else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
4970 {
4971 hdaReattachInternal(pThis, NULL /* pDrv */, uLUN, "NullAudio");
4972 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
4973 N_("Host audio backend initialization has failed. Selecting the NULL audio backend "
4974 "with the consequence that no sound is audible"));
4975 /* Attaching to the NULL audio backend will never fail. */
4976 rc = VINF_SUCCESS;
4977 }
4978 break;
4979 }
4980 }
4981
4982 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
4983
4984 if (RT_SUCCESS(rc))
4985 {
4986 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer);
4987 if (RT_SUCCESS(rc))
4988 {
4989 /*
4990 * Add mixer output sinks.
4991 */
4992#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4993 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front",
4994 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
4995 AssertRC(rc);
4996 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer",
4997 AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink);
4998 AssertRC(rc);
4999 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear",
5000 AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink);
5001 AssertRC(rc);
5002#else
5003 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output",
5004 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
5005 AssertRC(rc);
5006#endif
5007 /*
5008 * Add mixer input sinks.
5009 */
5010 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",
5011 AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink);
5012 AssertRC(rc);
5013#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5014 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In",
5015 AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink);
5016 AssertRC(rc);
5017#endif
5018 /* There is no master volume control. Set the master to max. */
5019 PDMAUDIOVOLUME vol = { false, 255, 255 };
5020 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
5021 AssertRC(rc);
5022 }
5023 }
5024
5025 if (RT_SUCCESS(rc))
5026 {
5027 /* Construct codec. */
5028 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
5029 if (!pThis->pCodec)
5030 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state"));
5031
5032 /* Set codec callbacks to this controller. */
5033 pThis->pCodec->pfnCbMixerAddStream = hdaMixerAddStream;
5034 pThis->pCodec->pfnCbMixerRemoveStream = hdaMixerRemoveStream;
5035 pThis->pCodec->pfnCbMixerControl = hdaMixerControl;
5036 pThis->pCodec->pfnCbMixerSetVolume = hdaMixerSetVolume;
5037
5038 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */
5039
5040 /* Construct the codec. */
5041 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg);
5042 if (RT_FAILURE(rc))
5043 AssertRCReturn(rc, rc);
5044
5045 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
5046 verb F20 should provide device/codec recognition. */
5047 Assert(pThis->pCodec->u16VendorId);
5048 Assert(pThis->pCodec->u16DeviceId);
5049 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
5050 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
5051 }
5052
5053 if (RT_SUCCESS(rc))
5054 {
5055 /*
5056 * Create all hardware streams.
5057 */
5058 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
5059 {
5060 /* Create the emulation timer (per stream).
5061 *
5062 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
5063 * relies on exact (virtual) DMA timing and uses DMA Position Buffers
5064 * instead of the LPIB registers.
5065 */
5066 char szTimer[16];
5067 RTStrPrintf2(szTimer, sizeof(szTimer), "HDA SD%RU8", i);
5068
5069 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, &pThis->aStreams[i],
5070 TMTIMER_FLAGS_NO_CRIT_SECT, szTimer, &pThis->pTimer[i]);
5071 AssertRCReturn(rc, rc);
5072
5073 /* Use our own critcal section for the device timer.
5074 * That way we can control more fine-grained when to lock what. */
5075 rc = TMR3TimerSetCritSect(pThis->pTimer[i], &pThis->CritSect);
5076 AssertRCReturn(rc, rc);
5077
5078 rc = hdaStreamCreate(&pThis->aStreams[i], pThis, i /* u8SD */);
5079 AssertRC(rc);
5080 }
5081
5082#ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
5083 /*
5084 * Initialize the driver chain.
5085 */
5086 PHDADRIVER pDrv;
5087 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
5088 {
5089 /*
5090 * Only primary drivers are critical for the VM to run. Everything else
5091 * might not worth showing an own error message box in the GUI.
5092 */
5093 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
5094 continue;
5095
5096 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
5097 AssertPtr(pCon);
5098
5099 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
5100# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5101 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
5102# endif
5103 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
5104# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
5105 /** @todo Anything to do here? */
5106# endif
5107
5108 if ( !fValidLineIn
5109# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5110 && !fValidMicIn
5111# endif
5112 && !fValidOut)
5113 {
5114 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
5115
5116 hdaReset(pDevIns);
5117 hdaReattachInternal(pThis, pDrv, pDrv->uLUN, "NullAudio");
5118
5119 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
5120 N_("No audio devices could be opened. Selecting the NULL audio backend "
5121 "with the consequence that no sound is audible"));
5122 }
5123 else
5124 {
5125 bool fWarn = false;
5126
5127 PDMAUDIOBACKENDCFG backendCfg;
5128 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
5129 if (RT_SUCCESS(rc2))
5130 {
5131 if (backendCfg.cMaxStreamsIn)
5132 {
5133# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5134 /* If the audio backend supports two or more input streams at once,
5135 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
5136 if (backendCfg.cMaxStreamsIn >= 2)
5137 fWarn = !fValidLineIn || !fValidMicIn;
5138 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
5139 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
5140 * One of the two simply is not in use then. */
5141 else if (backendCfg.cMaxStreamsIn == 1)
5142 fWarn = !fValidLineIn && !fValidMicIn;
5143 /* Don't warn if our backend is not able of supporting any input streams at all. */
5144# else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
5145 /* We only have line-in as input source. */
5146 fWarn = !fValidLineIn;
5147# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
5148 }
5149
5150 if ( !fWarn
5151 && backendCfg.cMaxStreamsOut)
5152 {
5153 fWarn = !fValidOut;
5154 }
5155 }
5156 else
5157 {
5158 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
5159 fWarn = true;
5160 }
5161
5162 if (fWarn)
5163 {
5164 char szMissingStreams[255];
5165 size_t len = 0;
5166 if (!fValidLineIn)
5167 {
5168 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
5169 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
5170 }
5171# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
5172 if (!fValidMicIn)
5173 {
5174 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
5175 len += RTStrPrintf(szMissingStreams + len,
5176 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
5177 }
5178# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
5179 if (!fValidOut)
5180 {
5181 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
5182 len += RTStrPrintf(szMissingStreams + len,
5183 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
5184 }
5185
5186 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
5187 N_("Some HDA audio streams (%s) could not be opened. Guest applications generating audio "
5188 "output or depending on audio input may hang. Make sure your host audio device "
5189 "is working properly. Check the logfile for error messages of the audio "
5190 "subsystem"), szMissingStreams);
5191 }
5192 }
5193 }
5194#endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
5195 }
5196
5197 if (RT_SUCCESS(rc))
5198 {
5199 hdaReset(pDevIns);
5200
5201 /*
5202 * Debug and string formatter types.
5203 */
5204 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaDbgInfo);
5205 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaDbgInfoBDLE);
5206 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaDbgInfoStream);
5207 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaDbgInfoCodecNodes);
5208 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaDbgInfoCodecSelector);
5209 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaDbgInfoMixer);
5210
5211 rc = RTStrFormatTypeRegister("bdle", hdaDbgFmtBDLE, NULL);
5212 AssertRC(rc);
5213 rc = RTStrFormatTypeRegister("sdctl", hdaDbgFmtSDCTL, NULL);
5214 AssertRC(rc);
5215 rc = RTStrFormatTypeRegister("sdsts", hdaDbgFmtSDSTS, NULL);
5216 AssertRC(rc);
5217 rc = RTStrFormatTypeRegister("sdfifos", hdaDbgFmtSDFIFOS, NULL);
5218 AssertRC(rc);
5219 rc = RTStrFormatTypeRegister("sdfifow", hdaDbgFmtSDFIFOW, NULL);
5220 AssertRC(rc);
5221
5222 /*
5223 * Some debug assertions.
5224 */
5225 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
5226 {
5227 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
5228 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
5229
5230 /* binary search order. */
5231 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
5232 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5233 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
5234
5235 /* alignment. */
5236 AssertReleaseMsg( pReg->size == 1
5237 || (pReg->size == 2 && (pReg->offset & 1) == 0)
5238 || (pReg->size == 3 && (pReg->offset & 3) == 0)
5239 || (pReg->size == 4 && (pReg->offset & 3) == 0),
5240 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5241
5242 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
5243 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
5244 if (pReg->offset & 3)
5245 {
5246 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL;
5247 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5248 if (pPrevReg)
5249 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
5250 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5251 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
5252 }
5253#if 0
5254 if ((pReg->offset + pReg->size) & 3)
5255 {
5256 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5257 if (pNextReg)
5258 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
5259 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
5260 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
5261 }
5262#endif
5263 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */
5264 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
5265 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
5266 }
5267 }
5268
5269# ifdef VBOX_WITH_STATISTICS
5270 if (RT_SUCCESS(rc))
5271 {
5272 /*
5273 * Register statistics.
5274 */
5275 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer.");
5276 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "/Devices/HDA/Input", STAMUNIT_TICKS_PER_CALL, "Profiling input.");
5277 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "/Devices/HDA/Output", STAMUNIT_TICKS_PER_CALL, "Profiling output.");
5278 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation.");
5279 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation.");
5280 }
5281# endif
5282
5283 LogFlowFuncLeaveRC(rc);
5284 return rc;
5285}
5286
5287/**
5288 * The device registration structure.
5289 */
5290const PDMDEVREG g_DeviceHDA =
5291{
5292 /* u32Version */
5293 PDM_DEVREG_VERSION,
5294 /* szName */
5295 "hda",
5296 /* szRCMod */
5297 "VBoxDDRC.rc",
5298 /* szR0Mod */
5299 "VBoxDDR0.r0",
5300 /* pszDescription */
5301 "Intel HD Audio Controller",
5302 /* fFlags */
5303 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
5304 /* fClass */
5305 PDM_DEVREG_CLASS_AUDIO,
5306 /* cMaxInstances */
5307 1,
5308 /* cbInstance */
5309 sizeof(HDASTATE),
5310 /* pfnConstruct */
5311 hdaConstruct,
5312 /* pfnDestruct */
5313 hdaDestruct,
5314 /* pfnRelocate */
5315 NULL,
5316 /* pfnMemSetup */
5317 NULL,
5318 /* pfnPowerOn */
5319 NULL,
5320 /* pfnReset */
5321 hdaReset,
5322 /* pfnSuspend */
5323 NULL,
5324 /* pfnResume */
5325 NULL,
5326 /* pfnAttach */
5327 hdaAttach,
5328 /* pfnDetach */
5329 hdaDetach,
5330 /* pfnQueryInterface. */
5331 NULL,
5332 /* pfnInitComplete */
5333 NULL,
5334 /* pfnPowerOff */
5335 hdaPowerOff,
5336 /* pfnSoftReset */
5337 NULL,
5338 /* u32VersionEnd */
5339 PDM_DEVREG_VERSION
5340};
5341
5342#endif /* IN_RING3 */
5343#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
5344
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