VirtualBox

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

Last change on this file since 68725 was 68719, checked in by vboxsync, 8 years ago

Audio: TMTimerStop() not needed in hdaTimerStop() / ichac97TimerStop().

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

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