VirtualBox

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

Last change on this file since 67751 was 67710, checked in by vboxsync, 8 years ago

HDA: Fixed HDA detection with Linux 3.13 (ROIC/RINTCTL mix-up), avoided assertions by using stricter CORBRP/WP comparisons.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 269.1 KB
Line 
1/* $Id: DevHDA.cpp 67710 2017-06-29 18:43:32Z vboxsync $ */
2/** @file
3 * DevHDA - 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#include "HDACodec.h"
50# if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)
51# include "HDAStreamChannel.h"
52# endif
53#include "HDAStreamMap.h"
54#include "HDAStreamPeriod.h"
55#include "DevHDACommon.h"
56#include "DrvAudio.h"
57
58
59/*********************************************************************************************************************************
60* Defined Constants And Macros *
61*********************************************************************************************************************************/
62//#define HDA_AS_PCI_EXPRESS
63#define VBOX_WITH_INTEL_HDA
64
65/* Installs a DMA access handler (via PGM callback) to monitor
66 * HDA's DMA operations, that is, writing / reading audio stream data.
67 *
68 * !!! Note: Certain guests are *that* timing sensitive that when enabling !!!
69 * !!! such a handler will mess up audio completely (e.g. Windows 7). !!! */
70//#define HDA_USE_DMA_ACCESS_HANDLER
71#ifdef HDA_USE_DMA_ACCESS_HANDLER
72# include <VBox/vmm/pgm.h>
73#endif
74
75/* Uses the DMA access handler to read the written DMA audio (output) data.
76 * Only valid if HDA_USE_DMA_ACCESS_HANDLER is set.
77 *
78 * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */
79//# define HDA_USE_DMA_ACCESS_HANDLER_WRITING
80
81/* Useful to debug the device' timing. */
82//#define HDA_DEBUG_TIMING
83
84/* To debug silence coming from the guest in form of audio gaps.
85 * Very crude implementation for now. */
86//#define HDA_DEBUG_SILENCE
87
88#if defined(VBOX_WITH_HP_HDA)
89/* HP Pavilion dv4t-1300 */
90# define HDA_PCI_VENDOR_ID 0x103c
91# define HDA_PCI_DEVICE_ID 0x30f7
92#elif defined(VBOX_WITH_INTEL_HDA)
93/* Intel HDA controller */
94# define HDA_PCI_VENDOR_ID 0x8086
95# define HDA_PCI_DEVICE_ID 0x2668
96#elif defined(VBOX_WITH_NVIDIA_HDA)
97/* nVidia HDA controller */
98# define HDA_PCI_VENDOR_ID 0x10de
99# define HDA_PCI_DEVICE_ID 0x0ac0
100#else
101# error "Please specify your HDA device vendor/device IDs"
102#endif
103
104/* Make sure that interleaving streams support is enabled if the 5.1 surround code is being used. */
105#if defined (VBOX_WITH_AUDIO_HDA_51_SURROUND) && !defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT)
106# define VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT
107#endif
108
109/** Default timer frequency (in Hz).
110 *
111 * Note: Keep in mind that the Hz rate has nothing to do with samples rates
112 * or DMA / interrupt timing -- it's purely needed in order to drive
113 * the data flow at a constant (and sufficient) rate.
114 *
115 * Lowering this value can ask for trouble, as backends then can run
116 * into data underruns. */
117#define HDA_TIMER_HZ 200
118
119/** HDA's (fixed) audio frame size in bytes.
120 * We only support 16-bit stereo frames at the moment. */
121#define HDA_FRAME_SIZE 4
122
123/**
124 * At the moment we support 4 input + 4 output streams max, which is 8 in total.
125 * Bidirectional streams are currently *not* supported.
126 *
127 * Note: When changing any of those values, be prepared for some saved state
128 * fixups / trouble!
129 */
130#define HDA_MAX_SDI 4
131#define HDA_MAX_SDO 4
132#define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO)
133AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);
134
135/** Number of general registers. */
136#define HDA_NUM_GENERAL_REGS 34
137/** Number of total registers in the HDA's register map. */
138#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
139/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
140#define HDA_MAX_TAGS 16
141
142/**
143 * NB: Register values stored in memory (au32Regs[]) are indexed through
144 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
145 * register descriptors in g_aHdaRegMap[] are indexed through the
146 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
147 *
148 * The au32Regs[] layout is kept unchanged for saved state
149 * compatibility.
150 */
151
152/* Registers */
153#define HDA_REG_IND_NAME(x) HDA_REG_##x
154#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
155#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
156#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
157
158
159#define HDA_REG_GCAP 0 /* range 0x00-0x01*/
160#define HDA_RMX_GCAP 0
161/* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
162 * oss (15:12) - number of output streams supported
163 * iss (11:8) - number of input streams supported
164 * bss (7:3) - number of bidirectional streams supported
165 * bds (2:1) - number of serial data out (SDO) signals supported
166 * b64sup (0) - 64 bit addressing supported.
167 */
168#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
169 ( (((oss) & 0xF) << 12) \
170 | (((iss) & 0xF) << 8) \
171 | (((bss) & 0x1F) << 3) \
172 | (((bds) & 0x3) << 2) \
173 | ((b64sup) & 1))
174
175#define HDA_REG_VMIN 1 /* 0x02 */
176#define HDA_RMX_VMIN 1
177
178#define HDA_REG_VMAJ 2 /* 0x03 */
179#define HDA_RMX_VMAJ 2
180
181#define HDA_REG_OUTPAY 3 /* 0x04-0x05 */
182#define HDA_RMX_OUTPAY 3
183
184#define HDA_REG_INPAY 4 /* 0x06-0x07 */
185#define HDA_RMX_INPAY 4
186
187#define HDA_REG_GCTL 5 /* 0x08-0x0B */
188#define HDA_RMX_GCTL 5
189#define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */
190#define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */
191#define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */
192
193#define HDA_REG_WAKEEN 6 /* 0x0C */
194#define HDA_RMX_WAKEEN 6
195
196#define HDA_REG_STATESTS 7 /* 0x0E */
197#define HDA_RMX_STATESTS 7
198#define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */
199
200#define HDA_REG_GSTS 8 /* 0x10-0x11*/
201#define HDA_RMX_GSTS 8
202#define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */
203
204#define HDA_REG_OUTSTRMPAY 9 /* 0x18 */
205#define HDA_RMX_OUTSTRMPAY 112
206
207#define HDA_REG_INSTRMPAY 10 /* 0x1a */
208#define HDA_RMX_INSTRMPAY 113
209
210#define HDA_REG_INTCTL 11 /* 0x20 */
211#define HDA_RMX_INTCTL 9
212#define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */
213#define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */
214/* Bits 0-29 correspond to streams 0-29. */
215#define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
216
217#define HDA_REG_INTSTS 12 /* 0x24 */
218#define HDA_RMX_INTSTS 10
219#define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */
220#define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */
221/* Bits 0-29 correspond to streams 0-29. */
222
223#define HDA_REG_WALCLK 13 /* 0x30 */
224/* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
225
226/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
227 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
228 * the datasheet.
229 */
230#define HDA_REG_SSYNC 14 /* 0x34 */
231#define HDA_RMX_SSYNC 12
232
233#define HDA_REG_CORBLBASE 15 /* 0x40 */
234#define HDA_RMX_CORBLBASE 13
235
236#define HDA_REG_CORBUBASE 16 /* 0x44 */
237#define HDA_RMX_CORBUBASE 14
238
239#define HDA_REG_CORBWP 17 /* 0x48 */
240#define HDA_RMX_CORBWP 15
241
242#define HDA_REG_CORBRP 18 /* 0x4A */
243#define HDA_RMX_CORBRP 16
244#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
245
246#define HDA_REG_CORBCTL 19 /* 0x4C */
247#define HDA_RMX_CORBCTL 17
248#define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */
249#define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */
250
251#define HDA_REG_CORBSTS 20 /* 0x4D */
252#define HDA_RMX_CORBSTS 18
253
254#define HDA_REG_CORBSIZE 21 /* 0x4E */
255#define HDA_RMX_CORBSIZE 19
256/* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */
257
258#define HDA_REG_RIRBLBASE 22 /* 0x50 */
259#define HDA_RMX_RIRBLBASE 20
260
261#define HDA_REG_RIRBUBASE 23 /* 0x54 */
262#define HDA_RMX_RIRBUBASE 21
263
264#define HDA_REG_RIRBWP 24 /* 0x58 */
265#define HDA_RMX_RIRBWP 22
266#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
267
268#define HDA_REG_RINTCNT 25 /* 0x5A */
269#define HDA_RMX_RINTCNT 23
270#define RINTCNT_N(pThis) (HDA_REG(pThis, RINTCNT) & 0xff)
271
272#define HDA_REG_RIRBCTL 26 /* 0x5C */
273#define HDA_RMX_RIRBCTL 24
274#define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */
275#define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */
276#define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */
277
278#define HDA_REG_RIRBSTS 27 /* 0x5D */
279#define HDA_RMX_RIRBSTS 25
280#define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */
281#define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */
282
283#define HDA_REG_RIRBSIZE 28 /* 0x5E */
284#define HDA_RMX_RIRBSIZE 26
285
286#define HDA_REG_IC 29 /* 0x60 */
287#define HDA_RMX_IC 27
288
289#define HDA_REG_IR 30 /* 0x64 */
290#define HDA_RMX_IR 28
291
292#define HDA_REG_IRS 31 /* 0x68 */
293#define HDA_RMX_IRS 29
294#define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */
295#define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */
296
297#define HDA_REG_DPLBASE 32 /* 0x70 */
298#define HDA_RMX_DPLBASE 30
299
300#define HDA_REG_DPUBASE 33 /* 0x74 */
301#define HDA_RMX_DPUBASE 31
302
303#define DPBASE_ADDR_MASK (~(uint64_t)0x7f)
304
305#define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)
306#define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)
307/* Note: sdnum here _MUST_ be stream reg number [0,7]. */
308#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
309
310#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
311
312/** @todo Condense marcos! */
313
314#define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
315#define HDA_RMX_SD0CTL 32
316#define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
317#define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
318#define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
319#define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
320#define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
321#define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
322#define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
323
324#define HDA_SDCTL_NUM_MASK 0xF
325#define HDA_SDCTL_NUM_SHIFT 20
326#define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */
327#define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */
328#define HDA_SDCTL_STRIPE_MASK 0x3
329#define HDA_SDCTL_STRIPE_SHIFT 16
330#define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */
331#define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */
332#define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */
333#define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */
334#define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */
335
336#define HDA_REG_SD0STS 35 /* 0x83; other streams offset by 0x20 */
337#define HDA_RMX_SD0STS 33
338#define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)
339#define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)
340#define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)
341#define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)
342#define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)
343#define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)
344#define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)
345
346#define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */
347#define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */
348#define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */
349#define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */
350
351#define HDA_REG_SD0LPIB 36 /* 0x84; other streams offset by 0x20 */
352#define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
353#define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
354#define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
355#define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
356#define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
357#define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
358#define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
359#define HDA_RMX_SD0LPIB 34
360#define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
361#define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
362#define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
363#define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
364#define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
365#define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
366#define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
367
368#define HDA_REG_SD0CBL 37 /* 0x88; other streams offset by 0x20 */
369#define HDA_RMX_SD0CBL 35
370#define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
371#define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
372#define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
373#define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
374#define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
375#define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
376#define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
377
378#define HDA_REG_SD0LVI 38 /* 0x8C; other streams offset by 0x20 */
379#define HDA_RMX_SD0LVI 36
380#define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
381#define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
382#define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
383#define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
384#define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
385#define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
386#define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
387
388#define HDA_REG_SD0FIFOW 39 /* 0x8E; other streams offset by 0x20 */
389#define HDA_RMX_SD0FIFOW 37
390#define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
391#define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
392#define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
393#define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
394#define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
395#define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
396#define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
397
398/*
399 * ICH6 datasheet defined limits for FIFOW values (18.2.38).
400 */
401#define HDA_SDFIFOW_8B 0x2
402#define HDA_SDFIFOW_16B 0x3
403#define HDA_SDFIFOW_32B 0x4
404
405#define HDA_REG_SD0FIFOS 40 /* 0x90; other streams offset by 0x20 */
406#define HDA_RMX_SD0FIFOS 38
407#define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
408#define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
409#define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
410#define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
411#define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
412#define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
413#define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
414
415/*
416 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
417 * formula: size - 1
418 * Other values not listed are not supported.
419 */
420/** Maximum FIFO size (in bytes). */
421#define HDA_FIFO_MAX 256
422
423#define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
424#define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */
425
426#define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
427#define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
428#define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
429#define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
430#define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
431#define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */
432
433#define HDA_REG_SD0FMT 41 /* 0x92; other streams offset by 0x20 */
434#define HDA_RMX_SD0FMT 39
435#define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
436#define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
437#define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
438#define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
439#define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
440#define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
441#define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
442
443#define HDA_REG_SD0BDPL 42 /* 0x98; other streams offset by 0x20 */
444#define HDA_RMX_SD0BDPL 40
445#define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
446#define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
447#define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
448#define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
449#define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
450#define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
451#define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
452
453#define HDA_REG_SD0BDPU 43 /* 0x9C; other streams offset by 0x20 */
454#define HDA_RMX_SD0BDPU 41
455#define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
456#define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
457#define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
458#define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
459#define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
460#define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
461#define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
462
463#define HDA_BDLE_FLAG_IOC RT_BIT(0) /* Interrupt on completion (IOC). */
464
465#define HDA_CODEC_CAD_SHIFT 28
466/* Encodes the (required) LUN into a codec command. */
467#define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
468
469
470
471/*********************************************************************************************************************************
472* Structures and Typedefs *
473*********************************************************************************************************************************/
474
475/**
476 * Internal state of a Buffer Descriptor List Entry (BDLE),
477 * needed to keep track of the data needed for the actual device
478 * emulation.
479 */
480typedef struct HDABDLESTATE
481{
482 /** Own index within the BDL (Buffer Descriptor List). */
483 uint32_t u32BDLIndex;
484 /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
485 * Used to check if we need fill up the FIFO again. */
486 uint32_t cbBelowFIFOW;
487 /** Current offset in DMA buffer (in bytes).*/
488 uint32_t u32BufOff;
489 uint32_t Padding;
490} HDABDLESTATE, *PHDABDLESTATE;
491
492/**
493 * BDL description structure.
494 * Do not touch this, as this must match to the HDA specs.
495 */
496typedef struct HDABDLEDESC
497{
498 /** Starting address of the actual buffer. Must be 128-bit aligned. */
499 uint64_t u64BufAdr;
500 /** Size of the actual buffer (in bytes). */
501 uint32_t u32BufSize;
502 /** Bit 0: Interrupt on completion; the controller will generate
503 * an interrupt when the last byte of the buffer has been
504 * fetched by the DMA engine.
505 *
506 * Rest is reserved for further use and must be 0. */
507 uint32_t fFlags;
508} HDABDLEDESC, *PHDABDLEDESC;
509AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
510
511/**
512 * Buffer Descriptor List Entry (BDLE) (3.6.3).
513 */
514typedef struct HDABDLE
515{
516 /** The actual BDL description. */
517 HDABDLEDESC Desc;
518 /** Internal state of this BDLE.
519 * Not part of the actual BDLE registers. */
520 HDABDLESTATE State;
521} HDABDLE, *PHDABDLE;
522
523#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
524/**
525 * Structure keeping the HDA stream's state for asynchronous I/O.
526 */
527typedef struct HDASTREAMSTATEAIO
528{
529 /** Thread handle for the actual I/O thread. */
530 RTTHREAD Thread;
531 /** Event for letting the thread know there is some data to process. */
532 RTSEMEVENT Event;
533 /** Critical section for synchronizing access. */
534 RTCRITSECT CritSect;
535 /** Started indicator. */
536 volatile bool fStarted;
537 /** Shutdown indicator. */
538 volatile bool fShutdown;
539 /** Whether the thread should do any data processing or not. */
540 volatile bool fEnabled;
541 uint32_t Padding1;
542} HDASTREAMSTATEAIO, *PHDASTREAMSTATEAIO;
543#endif
544
545/**
546 * Internal state of a HDA stream.
547 */
548typedef struct HDASTREAMSTATE
549{
550 /** Current BDLE to use. Wraps around to 0 if
551 * maximum (cBDLE) is reached. */
552 uint16_t uCurBDLE;
553 /** Flag indicating whether this stream currently is
554 * in reset mode and therefore not acccessible by the guest. */
555 volatile bool fInReset;
556 /** Unused, padding. */
557 uint32_t Padding0;
558 /** Critical section to serialize access. */
559 RTCRITSECT CritSect;
560#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
561 /** Asynchronous I/O state members. */
562 HDASTREAMSTATEAIO AIO;
563#endif
564 /** This stream's data mapping. */
565 HDASTREAMMAPPING Mapping;
566 /** Current BDLE (Buffer Descriptor List Entry). */
567 HDABDLE BDLE;
568 /** Circular buffer (FIFO) for holding DMA'ed data. */
569 R3PTRTYPE(PRTCIRCBUF) pCircBuf;
570 /** Timestamp of the last success DMA data transfer.
571 * Used to calculate the time actually elapsed between two transfers. */
572 uint64_t uTimerTS;
573 /** The stream's period. Need for timing. */
574 HDASTREAMPERIOD Period;
575 /** The stream's current configuration.
576 * Should match SDFMT. */
577 PDMAUDIOSTREAMCFG strmCfg;
578#ifdef HDA_USE_DMA_ACCESS_HANDLER
579 /** List of DMA handlers. */
580 RTLISTANCHORR3 lstDMAHandlers;
581#endif
582 /** Unused, padding. */
583 uint8_t Padding1[3];
584} HDASTREAMSTATE, *PHDASTREAMSTATE;
585
586/**
587 * Structure defining an HDA mixer sink.
588 * Its purpose is to know which audio mixer sink is bound to
589 * which SDn (SDI/SDO) device stream.
590 *
591 * This is needed in order to handle interleaved streams
592 * (that is, multiple channels in one stream) or non-interleaved
593 * streams (each channel has a dedicated stream).
594 *
595 * This is only known to the actual device emulation level.
596 */
597typedef struct HDAMIXERSINK
598{
599 /** SDn ID this sink is assigned to. 0 if not assigned. */
600 uint8_t uSD;
601 /** Channel ID of SDn ID. Only valid if SDn ID is valid. */
602 uint8_t uChannel;
603 uint8_t Padding[3];
604 /** Pointer to the actual audio mixer sink. */
605 R3PTRTYPE(PAUDMIXSINK) pMixSink;
606} HDAMIXERSINK, *PHDAMIXERSINK;
607
608#if defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER)
609typedef struct HDASTREAMDBGINFO
610{
611 /** Critical section to serialize access if needed. */
612 RTCRITSECT CritSect;
613 uint32_t Padding1[2];
614 /** Number of total read accesses. */
615 uint64_t cReadsTotal;
616 /** Number of total DMA bytes read. */
617 uint64_t cbReadTotal;
618 /** Timestamp (in ns) of last read access. */
619 uint64_t tsLastReadNs;
620 /** Number of total write accesses. */
621 uint64_t cWritesTotal;
622 /** Number of total DMA bytes written. */
623 uint64_t cbWrittenTotal;
624 /** Number of total write accesses since last iteration (Hz). */
625 uint64_t cWritesHz;
626 /** Number of total DMA bytes written since last iteration (Hz). */
627 uint64_t cbWrittenHz;
628 /** Timestamp (in ns) of beginning a new write slot. */
629 uint64_t tsWriteSlotBegin;
630 /** Number of current silence samples in a (consecutive) row. */
631 uint64_t csSilence;
632 /** Number of silent samples in a row to consider an audio block as audio gap (silence). */
633 uint64_t cSilenceThreshold;
634 /** How many bytes to skip in an audio stream before detecting silence.
635 * (useful for intros and silence at the beginning of a song). */
636 uint64_t cbSilenceReadMin;
637} HDASTREAMDBGINFO ,*PHDASTREAMDBGINFO;
638#endif /* defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER) */
639
640/**
641 * Structure for keeping a HDA stream (SDI / SDO).
642 *
643 * Note: This HDA stream has nothing to do with a regular audio stream handled
644 * by the audio connector or the audio mixer. This HDA stream is a serial data in/out
645 * stream (SDI/SDO) defined in hardware and can contain multiple audio streams
646 * in one single SDI/SDO (interleaving streams).
647 *
648 * How a specific SDI/SDO is mapped to our internal audio streams relies on the
649 * stream channel mappings.
650 *
651 * Contains only register values which do *not* change until a
652 * stream reset occurs.
653 */
654typedef struct HDASTREAM
655{
656 /** Stream descriptor number (SDn). */
657 uint8_t u8SD;
658 uint8_t Padding0[7];
659 /** DMA base address (SDnBDPU - SDnBDPL). */
660 uint64_t u64BDLBase;
661 /** Cyclic Buffer Length (SDnCBL).
662 * Represents the size of the ring buffer. */
663 uint32_t u32CBL;
664 /** Format (SDnFMT). */
665 uint16_t u16FMT;
666 /** FIFO Size (FIFOS).
667 * Maximum number of bytes that may have been DMA'd into
668 * memory but not yet transmitted on the link. */
669 uint16_t u16FIFOS;
670 /** FIFO Watermark. */
671 uint16_t u16FIFOW;
672 /** Last Valid Index (SDnLVI). */
673 uint16_t u16LVI;
674 uint16_t Padding1[2];
675 /** Pointer to HDA sink this stream is attached to. */
676 R3PTRTYPE(PHDAMIXERSINK) pMixSink;
677 /** Internal state of this stream. */
678 HDASTREAMSTATE State;
679#ifdef DEBUG
680 /** Debug information. */
681 HDASTREAMDBGINFO Dbg;
682#endif
683} HDASTREAM, *PHDASTREAM;
684
685#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
686/**
687 * Structure for keeping a HDA stream thread context.
688 */
689typedef struct HDASTREAMTHREADCTX
690{
691 PHDASTATE pThis;
692 PHDASTREAM pStream;
693} HDASTREAMTHREADCTX, *PHDASTREAMTHREADCTX;
694#endif
695
696/**
697 * Structure for mapping a stream tag to an HDA stream.
698 */
699typedef struct HDATAG
700{
701 /** Own stream tag. */
702 uint8_t uTag;
703 uint8_t Padding[7];
704 /** Pointer to associated stream. */
705 R3PTRTYPE(PHDASTREAM) pStream;
706} HDATAG, *PHDATAG;
707
708/**
709 * Structure defining a (host backend) driver stream.
710 * Each driver has its own instances of audio mixer streams, which then
711 * can go into the same (or even different) audio mixer sinks.
712 */
713typedef struct HDADRIVERSTREAM
714{
715 union
716 {
717 /** Desired playback destination (for an output stream). */
718 PDMAUDIOPLAYBACKDEST Dest;
719 /** Desired recording source (for an input stream). */
720 PDMAUDIORECSOURCE Source;
721 } DestSource;
722 uint8_t Padding1[4];
723 /** Associated mixer handle. */
724 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
725} HDADRIVERSTREAM, *PHDADRIVERSTREAM;
726
727#ifdef HDA_USE_DMA_ACCESS_HANDLER
728typedef struct HDADMAACCESSHANDLER
729{
730 /** Node for storing this handler in our list in HDASTREAMSTATE. */
731 RTLISTNODER3 Node;
732 /** Pointer to stream to which this access handler is assigned to. */
733 R3PTRTYPE(PHDASTREAM) pStream;
734 /** Access handler type handle. */
735 PGMPHYSHANDLERTYPE hAccessHandlerType;
736 /** First address this handler uses. */
737 RTGCPHYS GCPhysFirst;
738 /** Last address this handler uses. */
739 RTGCPHYS GCPhysLast;
740 /** Actual BDLE address to handle. */
741 RTGCPHYS BDLEAddr;
742 /** Actual BDLE buffer size to handle. */
743 RTGCPHYS BDLESize;
744 /** Whether the access handler has been registered or not. */
745 bool fRegistered;
746 uint8_t Padding[3];
747} HDADMAACCESSHANDLER, *PHDADMAACCESSHANDLER;
748#endif
749
750/**
751 * Struct for maintaining a host backend driver.
752 * This driver must be associated to one, and only one,
753 * HDA codec. The HDA controller does the actual multiplexing
754 * of HDA codec data to various host backend drivers then.
755 *
756 * This HDA device uses a timer in order to synchronize all
757 * read/write accesses across all attached LUNs / backends.
758 */
759typedef struct HDADRIVER
760{
761 /** Node for storing this driver in our device driver list of HDASTATE. */
762 RTLISTNODER3 Node;
763 /** Pointer to HDA controller (state). */
764 R3PTRTYPE(PHDASTATE) pHDAState;
765 /** Driver flags. */
766 PDMAUDIODRVFLAGS fFlags;
767 uint8_t u32Padding0[2];
768 /** LUN to which this driver has been assigned. */
769 uint8_t uLUN;
770 /** Whether this driver is in an attached state or not. */
771 bool fAttached;
772 /** Pointer to attached driver base interface. */
773 R3PTRTYPE(PPDMIBASE) pDrvBase;
774 /** Audio connector interface to the underlying host backend. */
775 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
776 /** Mixer stream for line input. */
777 HDADRIVERSTREAM LineIn;
778#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
779 /** Mixer stream for mic input. */
780 HDADRIVERSTREAM MicIn;
781#endif
782 /** Mixer stream for front output. */
783 HDADRIVERSTREAM Front;
784#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
785 /** Mixer stream for center/LFE output. */
786 HDADRIVERSTREAM CenterLFE;
787 /** Mixer stream for rear output. */
788 HDADRIVERSTREAM Rear;
789#endif
790} HDADRIVER;
791
792#ifdef DEBUG
793/** @todo Make STAM values out of this? */
794typedef struct HDASTATEDBGINFO
795{
796 /** Timestamp (in ns) of the last timer callback (hdaTimer).
797 * Used to calculate the time actually elapsed between two timer callbacks. */
798 uint64_t tsTimerLastCalledNs;
799 /** IRQ debugging information. */
800 struct
801 {
802 /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
803 uint64_t tsProcessedLastNs;
804 /** Timestamp (in ns) of last asserted IRQ. */
805 uint64_t tsAssertedNs;
806 /** How many IRQs have been asserted already. */
807 uint64_t cAsserted;
808 /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
809 uint64_t tsAssertedTotalNs;
810 /** Timestamp (in ns) of last deasserted IRQ. */
811 uint64_t tsDeassertedNs;
812 /** How many IRQs have been deasserted already. */
813 uint64_t cDeasserted;
814 /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
815 uint64_t tsDeassertedTotalNs;
816 } IRQ;
817} HDASTATEDBGINFO, *PHDASTATEDBGINFO;
818#endif
819
820/**
821 * ICH Intel HD Audio Controller state.
822 */
823typedef struct HDASTATE
824{
825 /** The PCI device structure. */
826 PDMPCIDEV PciDev;
827 /** R3 Pointer to the device instance. */
828 PPDMDEVINSR3 pDevInsR3;
829 /** R0 Pointer to the device instance. */
830 PPDMDEVINSR0 pDevInsR0;
831 /** R0 Pointer to the device instance. */
832 PPDMDEVINSRC pDevInsRC;
833 /** Padding for alignment. */
834 uint32_t u32Padding;
835 /** The base interface for LUN\#0. */
836 PDMIBASE IBase;
837 RTGCPHYS MMIOBaseAddr;
838 /** The HDA's register set. */
839 uint32_t au32Regs[HDA_NUM_REGS];
840 /** Internal stream states. */
841 HDASTREAM aStreams[HDA_MAX_STREAMS];
842 /** Mapping table between stream tags and stream states. */
843 HDATAG aTags[HDA_MAX_TAGS];
844 /** CORB buffer base address. */
845 uint64_t u64CORBBase;
846 /** RIRB buffer base address. */
847 uint64_t u64RIRBBase;
848 /** DMA base address.
849 * Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */
850 uint64_t u64DPBase;
851 /** Pointer to CORB buffer. */
852 R3PTRTYPE(uint32_t *) pu32CorbBuf;
853 /** Size in bytes of CORB buffer. */
854 uint32_t cbCorbBuf;
855 /** Padding for alignment. */
856 uint32_t u32Padding1;
857 /** Pointer to RIRB buffer. */
858 R3PTRTYPE(uint64_t *) pu64RirbBuf;
859 /** Size in bytes of RIRB buffer. */
860 uint32_t cbRirbBuf;
861 /** DMA position buffer enable bit. */
862 bool fDMAPosition;
863 /** Flag whether the R0 part is enabled. */
864 bool fR0Enabled;
865 /** Flag whether the RC part is enabled. */
866 bool fRCEnabled;
867 /** Number of active (running) SDn streams. */
868 uint8_t cStreamsActive;
869#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
870 /** The timer for pumping data thru the attached LUN drivers. */
871 PTMTIMERR3 pTimer;
872 /** Flag indicating whether the timer is active or not. */
873 bool fTimerActive;
874 uint8_t u8Padding1[7];
875 /** Timer ticks per Hz. */
876 uint64_t cTimerTicks;
877 /** The current timer expire time (in timer ticks). */
878 uint64_t tsTimerExpire;
879#endif
880#ifdef VBOX_WITH_STATISTICS
881# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
882 STAMPROFILE StatTimer;
883# endif
884 STAMPROFILE StatIn;
885 STAMPROFILE StatOut;
886 STAMCOUNTER StatBytesRead;
887 STAMCOUNTER StatBytesWritten;
888#endif
889 /** Pointer to HDA codec to use. */
890 R3PTRTYPE(PHDACODEC) pCodec;
891 /** List of associated LUN drivers (HDADRIVER). */
892 RTLISTANCHORR3 lstDrv;
893 /** The device' software mixer. */
894 R3PTRTYPE(PAUDIOMIXER) pMixer;
895 /** HDA sink for (front) output. */
896 HDAMIXERSINK SinkFront;
897#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
898 /** HDA sink for center / LFE output. */
899 HDAMIXERSINK SinkCenterLFE;
900 /** HDA sink for rear output. */
901 HDAMIXERSINK SinkRear;
902#endif
903 /** HDA mixer sink for line input. */
904 HDAMIXERSINK SinkLineIn;
905#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
906 /** Audio mixer sink for microphone input. */
907 HDAMIXERSINK SinkMicIn;
908#endif
909 /** Last updated WALCLK counter. */
910 uint64_t u64WalClk;
911 /** Response Interrupt Count (RINTCNT). */
912 uint8_t u8RespIntCnt;
913 /** Current IRQ level. */
914 uint8_t u8IRQL;
915 /** Padding for alignment. */
916 uint8_t au8Padding2[6];
917#ifdef DEBUG
918 HDASTATEDBGINFO Dbg;
919#endif
920} HDASTATE;
921/** Pointer to the ICH Intel HD Audio Controller state. */
922typedef HDASTATE *PHDASTATE;
923
924#ifdef VBOX_WITH_AUDIO_HDA_CALLBACKS
925typedef struct HDACALLBACKCTX
926{
927 PHDASTATE pThis;
928 PHDADRIVER pDriver;
929} HDACALLBACKCTX, *PHDACALLBACKCTX;
930#endif
931
932
933/*********************************************************************************************************************************
934* Internal Functions *
935*********************************************************************************************************************************/
936#ifndef VBOX_DEVICE_STRUCT_TESTCASE
937#ifdef IN_RING3
938static void hdaGctlReset(PHDASTATE pThis);
939#endif
940
941/** @name Register read/write stubs.
942 * @{
943 */
944static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
945static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
946/** @} */
947
948/** @name Global register set read/write functions.
949 * @{
950 */
951static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
952static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
953static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
954static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
955static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
956static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
957static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
958static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
959static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
960static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
961static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
962static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
963static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
964/** @} */
965
966/** @name {IOB}SDn write functions.
967 * @{
968 */
969static int hdaRegWriteSDCBL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
970static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
971static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
972static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
973static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
974static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
975static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
976static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
977static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
978/** @} */
979
980/** @name {IOB}SDn utility functions.
981 * @{
982 */
983#ifdef IN_RING3
984static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps);
985#endif
986/** @} */
987
988/** @name Generic register read/write functions.
989 * @{
990 */
991static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
992static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
993static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
994#ifdef IN_RING3
995static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
996#endif
997static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
998static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
999static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
1000static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
1001/** @} */
1002
1003/** @name Stream functions.
1004 * @{
1005 */
1006#ifdef IN_RING3
1007static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream);
1008static int hdaStreamEnable(PHDASTATE pThis, PHDASTREAM pStream, bool fEnable);
1009static uint32_t hdaStreamGetUsed(PHDASTREAM pStream);
1010static uint32_t hdaStreamGetFree(PHDASTREAM pStream);
1011static int hdaStreamTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcessMax);
1012DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);
1013static void hdaStreamLock(PHDASTREAM pStream);
1014static void hdaStreamUnlock(PHDASTREAM pStream);
1015static int hdaStreamRead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead);
1016static int hdaStreamWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten);
1017static void hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fAsync);
1018# ifdef HDA_USE_DMA_ACCESS_HANDLER
1019static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
1020static void hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
1021# endif
1022#endif /* IN_RING3 */
1023/** @} */
1024
1025/** @name Async I/O stream functions.
1026 * @{
1027 */
1028#ifdef IN_RING3
1029# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1030static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
1031static int hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream);
1032static int hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream);
1033static int hdaStreamAsyncIONotify(PHDASTATE pThis, PHDASTREAM pStream);
1034static void hdaStreamAsyncIOLock(PHDASTREAM pStream);
1035static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream);
1036static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable);
1037# endif
1038#endif
1039/** @} */
1040
1041/** @name HDA device functions.
1042 * @{
1043 */
1044#ifdef IN_RING3
1045# ifdef HDA_USE_DMA_ACCESS_HANDLER
1046static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser);
1047# endif
1048static void hdaDoTransfers(PHDASTATE pThis);
1049#endif /* IN_RING3 */
1050/** @} */
1051
1052/** @name BDLE (Buffer Descriptor List Entry) functions.
1053 * @{
1054 */
1055#ifdef IN_RING3
1056static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
1057# ifdef LOG_ENABLED
1058static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
1059# endif
1060#endif /* IN_RING3 */
1061/** @} */
1062
1063/** @name Timer functions.
1064 * @{
1065 */
1066#if !defined(VBOX_WITH_AUDIO_HDA_CALLBACKS) && defined(IN_RING3)
1067static void hdaTimerMaybeStart(PHDASTATE pThis);
1068static void hdaTimerMaybeStop(PHDASTATE pThis);
1069static void hdaTimerMain(PHDASTATE pThis);
1070#endif
1071/** @} */
1072
1073/** @name Wall clock (WALCLK) functions.
1074 * @{
1075 */
1076uint64_t hdaWalClkGetCurrent(PHDASTATE pThis);
1077#ifdef IN_RING3
1078bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce);
1079#endif
1080/** @} */
1081
1082/*********************************************************************************************************************************
1083* Global Variables *
1084*********************************************************************************************************************************/
1085
1086/** Offset of the SD0 register map. */
1087#define HDA_REG_DESC_SD0_BASE 0x80
1088
1089/** Turn a short global register name into an memory index and a stringized name. */
1090#define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
1091
1092/** Turns a short stream register name into an memory index and a stringized name. */
1093#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
1094
1095/** Same as above for a register *not* stored in memory. */
1096#define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev
1097
1098/** No register description (RD) flags defined. */
1099#define HDA_RD_FLAG_NONE 0
1100/** Writes to SD are allowed while RUN bit is set. */
1101#define HDA_RD_FLAG_SD_WRITE_RUN RT_BIT(0)
1102
1103/** Emits a single audio stream register set (e.g. OSD0) at a specified offset. */
1104#define HDA_REG_MAP_STRM(offset, name) \
1105 /* offset size read mask write mask flags read callback write callback index + abbrev description */ \
1106 /* ------- ------- ---------- ---------- ------------------------- -------------- ----------------- ----------------------------- ----------- */ \
1107 /* Offset 0x80 (SD0) */ \
1108 { offset, 0x00003, 0x00FF001F, 0x00F0001F, HDA_RD_FLAG_SD_WRITE_RUN, hdaRegReadU24 , hdaRegWriteSDCTL , HDA_REG_IDX_STRM(name, CTL) , #name " Stream Descriptor Control" }, \
1109 /* Offset 0x83 (SD0) */ \
1110 { offset + 0x3, 0x00001, 0x0000003C, 0x0000001C, HDA_RD_FLAG_SD_WRITE_RUN, hdaRegReadU8 , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS) , #name " Status" }, \
1111 /* Offset 0x84 (SD0) */ \
1112 { offset + 0x4, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadLPIB, hdaRegWriteU32 , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
1113 /* Offset 0x88 (SD0) */ \
1114 { offset + 0x8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteSDCBL , HDA_REG_IDX_STRM(name, CBL) , #name " Cyclic Buffer Length" }, \
1115 /* Offset 0x8C (SD0) */ \
1116 { offset + 0xC, 0x00002, 0x0000FFFF, 0x0000FFFF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDLVI , HDA_REG_IDX_STRM(name, LVI) , #name " Last Valid Index" }, \
1117 /* Reserved: FIFO Watermark. ** @todo Document this! */ \
1118 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
1119 /* Offset 0x90 (SD0) */ \
1120 { offset + 0x10, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
1121 /* Offset 0x92 (SD0) */ \
1122 { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFMT , HDA_REG_IDX_STRM(name, FMT) , #name " Stream Format" }, \
1123 /* Reserved: 0x94 - 0x98. */ \
1124 /* Offset 0x98 (SD0) */ \
1125 { 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" }, \
1126 /* Offset 0x9C (SD0) */ \
1127 { 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" }
1128
1129/** Defines a single audio stream register set (e.g. OSD0). */
1130#define HDA_REG_MAP_DEF_STREAM(index, name) \
1131 HDA_REG_MAP_STRM(HDA_REG_DESC_SD0_BASE + (index * 32 /* 0x20 */), name)
1132
1133/* See 302349 p 6.2. */
1134static const struct HDAREGDESC
1135{
1136 /** Register offset in the register space. */
1137 uint32_t offset;
1138 /** Size in bytes. Registers of size > 4 are in fact tables. */
1139 uint32_t size;
1140 /** Readable bits. */
1141 uint32_t readable;
1142 /** Writable bits. */
1143 uint32_t writable;
1144 /** Register descriptor (RD) flags of type HDA_RD_FLAG_.
1145 * These are used to specify the handling (read/write)
1146 * policy of the register. */
1147 uint32_t fFlags;
1148 /** Read callback. */
1149 int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
1150 /** Write callback. */
1151 int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
1152 /** Index into the register storage array. */
1153 uint32_t mem_idx;
1154 /** Abbreviated name. */
1155 const char *abbrev;
1156 /** Descripton. */
1157 const char *desc;
1158} g_aHdaRegMap[HDA_NUM_REGS] =
1159
1160{
1161 /* offset size read mask write mask flags read callback write callback index + abbrev */
1162 /*------- ------- ---------- ---------- ----------------- ---------------- ------------------- ------------------------ */
1163 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(GCAP) }, /* Global Capabilities */
1164 { 0x00002, 0x00001, 0x000000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMIN) }, /* Minor Version */
1165 { 0x00003, 0x00001, 0x000000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMAJ) }, /* Major Version */
1166 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTPAY) }, /* Output Payload Capabilities */
1167 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INPAY) }, /* Input Payload Capabilities */
1168 { 0x00008, 0x00004, 0x00000103, 0x00000103, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteGCTL , HDA_REG_IDX(GCTL) }, /* Global Control */
1169 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(WAKEEN) }, /* Wake Enable */
1170 { 0x0000e, 0x00002, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteSTATESTS, HDA_REG_IDX(STATESTS) }, /* State Change Status */
1171 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadUnimpl, hdaRegWriteUnimpl , HDA_REG_IDX(GSTS) }, /* Global Status */
1172 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */
1173 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INSTRMPAY) }, /* Input Stream Payload Capability */
1174 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(INTCTL) }, /* Interrupt Control */
1175 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */
1176 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadWALCLK, hdaRegWriteUnimpl , HDA_REG_IDX_NOMEM(WALCLK) }, /* Wall Clock Counter */
1177 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */
1178 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBLBASE) }, /* CORB Lower Base Address */
1179 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBUBASE) }, /* CORB Upper Base Address */
1180 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteCORBWP , HDA_REG_IDX(CORBWP) }, /* CORB Write Pointer */
1181 { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteCORBRP , HDA_REG_IDX(CORBRP) }, /* CORB Read Pointer */
1182 { 0x0004C, 0x00001, 0x00000003, 0x00000003, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteCORBCTL , HDA_REG_IDX(CORBCTL) }, /* CORB Control */
1183 { 0x0004D, 0x00001, 0x00000001, 0x00000001, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteCORBSTS , HDA_REG_IDX(CORBSTS) }, /* CORB Status */
1184 { 0x0004E, 0x00001, 0x000000F3, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(CORBSIZE) }, /* CORB Size */
1185 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBLBASE) }, /* RIRB Lower Base Address */
1186 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBUBASE) }, /* RIRB Upper Base Address */
1187 { 0x00058, 0x00002, 0x000000FF, 0x00008000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteRIRBWP , HDA_REG_IDX(RIRBWP) }, /* RIRB Write Pointer */
1188 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(RINTCNT) }, /* Response Interrupt Count */
1189 { 0x0005C, 0x00001, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteU8 , HDA_REG_IDX(RIRBCTL) }, /* RIRB Control */
1190 { 0x0005D, 0x00001, 0x00000005, 0x00000005, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteRIRBSTS , HDA_REG_IDX(RIRBSTS) }, /* RIRB Status */
1191 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(RIRBSIZE) }, /* RIRB Size */
1192 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(IC) }, /* Immediate Command */
1193 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(IR) }, /* Immediate Response */
1194 { 0x00068, 0x00002, 0x00000002, 0x00000002, HDA_RD_FLAG_NONE, hdaRegReadIRS , hdaRegWriteIRS , HDA_REG_IDX(IRS) }, /* Immediate Command Status */
1195 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPLBASE) }, /* DMA Position Lower Base */
1196 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPUBASE) }, /* DMA Position Upper Base */
1197 /* 4 Serial Data In (SDI). */
1198 HDA_REG_MAP_DEF_STREAM(0, SD0),
1199 HDA_REG_MAP_DEF_STREAM(1, SD1),
1200 HDA_REG_MAP_DEF_STREAM(2, SD2),
1201 HDA_REG_MAP_DEF_STREAM(3, SD3),
1202 /* 4 Serial Data Out (SDO). */
1203 HDA_REG_MAP_DEF_STREAM(4, SD4),
1204 HDA_REG_MAP_DEF_STREAM(5, SD5),
1205 HDA_REG_MAP_DEF_STREAM(6, SD6),
1206 HDA_REG_MAP_DEF_STREAM(7, SD7)
1207};
1208
1209/**
1210 * HDA register aliases (HDA spec 3.3.45).
1211 * @remarks Sorted by offReg.
1212 */
1213static const struct
1214{
1215 /** The alias register offset. */
1216 uint32_t offReg;
1217 /** The register index. */
1218 int idxAlias;
1219} g_aHdaRegAliases[] =
1220{
1221 { 0x2084, HDA_REG_SD0LPIB },
1222 { 0x20a4, HDA_REG_SD1LPIB },
1223 { 0x20c4, HDA_REG_SD2LPIB },
1224 { 0x20e4, HDA_REG_SD3LPIB },
1225 { 0x2104, HDA_REG_SD4LPIB },
1226 { 0x2124, HDA_REG_SD5LPIB },
1227 { 0x2144, HDA_REG_SD6LPIB },
1228 { 0x2164, HDA_REG_SD7LPIB },
1229};
1230
1231#ifdef IN_RING3
1232/** HDABDLEDESC field descriptors for the v7 saved state. */
1233static SSMFIELD const g_aSSMBDLEDescFields7[] =
1234{
1235 SSMFIELD_ENTRY(HDABDLEDESC, u64BufAdr),
1236 SSMFIELD_ENTRY(HDABDLEDESC, u32BufSize),
1237 SSMFIELD_ENTRY(HDABDLEDESC, fFlags),
1238 SSMFIELD_ENTRY_TERM()
1239};
1240
1241/** HDABDLESTATE field descriptors for the v6+ saved state. */
1242static SSMFIELD const g_aSSMBDLEStateFields6[] =
1243{
1244 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
1245 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
1246 SSMFIELD_ENTRY_OLD(FIFO, HDA_FIFO_MAX), /* Deprecated; now is handled in the stream's circular buffer. */
1247 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
1248 SSMFIELD_ENTRY_TERM()
1249};
1250
1251/** HDABDLESTATE field descriptors for the v7 saved state. */
1252static SSMFIELD const g_aSSMBDLEStateFields7[] =
1253{
1254 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
1255 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
1256 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
1257 SSMFIELD_ENTRY_TERM()
1258};
1259
1260/** HDASTREAMSTATE field descriptors for the v6 saved state. */
1261static SSMFIELD const g_aSSMStreamStateFields6[] =
1262{
1263 SSMFIELD_ENTRY_OLD(cBDLE, sizeof(uint16_t)), /* Deprecated. */
1264 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
1265 SSMFIELD_ENTRY_OLD(fStop, 1), /* Deprecated; see SSMR3PutBool(). */
1266 SSMFIELD_ENTRY_OLD(fRunning, 1), /* Deprecated; using the HDA_SDCTL_RUN bit is sufficient. */
1267 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
1268 SSMFIELD_ENTRY_TERM()
1269};
1270
1271/** HDASTREAMSTATE field descriptors for the v7 saved state. */
1272static SSMFIELD const g_aSSMStreamStateFields7[] =
1273{
1274 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
1275 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
1276 SSMFIELD_ENTRY(HDASTREAMSTATE, uTimerTS),
1277 SSMFIELD_ENTRY_TERM()
1278};
1279
1280/** HDASTREAMPERIOD field descriptors for the v7 saved state. */
1281static SSMFIELD const g_aSSMStreamPeriodFields7[] =
1282{
1283 SSMFIELD_ENTRY(HDASTREAMPERIOD, u64StartWalClk),
1284 SSMFIELD_ENTRY(HDASTREAMPERIOD, u64ElapsedWalClk),
1285 SSMFIELD_ENTRY(HDASTREAMPERIOD, framesTransferred),
1286 SSMFIELD_ENTRY(HDASTREAMPERIOD, cIntPending),
1287 SSMFIELD_ENTRY_TERM()
1288};
1289#endif
1290
1291/**
1292 * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
1293 */
1294static uint32_t const g_afMasks[5] =
1295{
1296 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff)
1297};
1298
1299
1300#ifdef IN_RING3
1301/**
1302 * Retrieves the number of bytes of a FIFOW register.
1303 *
1304 * @return Number of bytes of a given FIFOW register.
1305 */
1306DECLINLINE(uint8_t) hdaSDFIFOWToBytes(uint32_t u32RegFIFOW)
1307{
1308 uint32_t cb;
1309 switch (u32RegFIFOW)
1310 {
1311 case HDA_SDFIFOW_8B: cb = 8; break;
1312 case HDA_SDFIFOW_16B: cb = 16; break;
1313 case HDA_SDFIFOW_32B: cb = 32; break;
1314 default: cb = 0; break;
1315 }
1316
1317 Assert(RT_IS_POWER_OF_TWO(cb));
1318 return cb;
1319}
1320
1321/**
1322 * Updates an HDA stream's current read or write buffer position (depending on the stream type) by
1323 * updating its associated LPIB register and DMA position buffer (if enabled).
1324 *
1325 * @returns Set LPIB value.
1326 * @param pThis HDA state.
1327 * @param pStream HDA stream to update read / write position for.
1328 * @param u32LPIB New LPIB (position) value to set.
1329 */
1330DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
1331{
1332 AssertPtrReturn(pThis, 0);
1333 AssertPtrReturn(pStream, 0);
1334
1335 AssertMsg(u32LPIB <= pStream->u32CBL,
1336 ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));
1337
1338 u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
1339
1340 LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
1341 pStream->u8SD, u32LPIB, pThis->fDMAPosition));
1342
1343 /* Update LPIB in any case. */
1344 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
1345
1346 /* Do we need to tell the current DMA position? */
1347 if (pThis->fDMAPosition)
1348 {
1349 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
1350 pThis->u64DPBase + (pStream->u8SD * 2 * sizeof(uint32_t)),
1351 (void *)&u32LPIB, sizeof(uint32_t));
1352 AssertRC(rc2);
1353 }
1354
1355 return u32LPIB;
1356}
1357
1358
1359/**
1360 * Locks an HDA stream for serialized access.
1361 *
1362 * @returns IPRT status code.
1363 * @param pStream HDA stream to lock.
1364 */
1365static void hdaStreamLock(PHDASTREAM pStream)
1366{
1367 AssertPtrReturnVoid(pStream);
1368 int rc2 = RTCritSectEnter(&pStream->State.CritSect);
1369 AssertRC(rc2);
1370}
1371
1372
1373/**
1374 * Unlocks a formerly locked HDA stream.
1375 *
1376 * @returns IPRT status code.
1377 * @param pStream HDA stream to unlock.
1378 */
1379static void hdaStreamUnlock(PHDASTREAM pStream)
1380{
1381 AssertPtrReturnVoid(pStream);
1382 int rc2 = RTCritSectLeave(&pStream->State.CritSect);
1383 AssertRC(rc2);
1384}
1385
1386
1387/**
1388 * Returns the HDA stream of specified stream descriptor number.
1389 *
1390 * @return Pointer to HDA stream, or NULL if none found.
1391 */
1392DECLINLINE(PHDASTREAM) hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD)
1393{
1394 AssertPtrReturn(pThis, NULL);
1395 AssertReturn(uSD < HDA_MAX_STREAMS, NULL);
1396
1397 if (uSD >= HDA_MAX_STREAMS)
1398 {
1399 AssertMsgFailed(("Invalid / non-handled SD%RU8\n", uSD));
1400 return NULL;
1401 }
1402
1403 return &pThis->aStreams[uSD];
1404}
1405
1406
1407/**
1408 * Returns the HDA stream of specified HDA sink.
1409 *
1410 * @return Pointer to HDA stream, or NULL if none found.
1411 */
1412DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink)
1413{
1414 AssertPtrReturn(pThis, NULL);
1415 AssertPtrReturn(pSink, NULL);
1416
1417 /** @todo Do something with the channel mapping here? */
1418 return hdaStreamGetFromSD(pThis, pSink->uSD);
1419}
1420
1421
1422/**
1423 * Returns the audio direction of a specified stream descriptor.
1424 *
1425 * The register layout specifies that input streams (SDI) come first,
1426 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
1427 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
1428 *
1429 * Note: SDnFMT register does not provide that information, so we have to judge
1430 * for ourselves.
1431 *
1432 * @return Audio direction.
1433 */
1434DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)
1435{
1436 AssertReturn(uSD < HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
1437
1438 if (uSD < HDA_MAX_SDI)
1439 return PDMAUDIODIR_IN;
1440
1441 return PDMAUDIODIR_OUT;
1442}
1443#endif /* IN_RING3 */
1444
1445static uint32_t hdaGetINTSTS(PHDASTATE pThis)
1446{
1447 uint32_t intSts = 0;
1448
1449 /* Check controller interrupts (RIRB, STATEST). */
1450 if ( (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
1451 /* SDIN State Change Status Flags (SCSF). */
1452 || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
1453 {
1454 intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
1455 }
1456
1457 if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
1458 {
1459 intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */
1460 }
1461
1462 /* For each stream, check if any interrupt status bit is set and enabled. */
1463 for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)
1464 {
1465 if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE | HDA_SDCTL_IOCE))
1466 {
1467 Log3Func(("[SD%d] interrupt status set\n", iStrm));
1468 intSts |= RT_BIT(iStrm);
1469 }
1470 }
1471
1472 if (intSts)
1473 intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
1474
1475 Log3Func(("-> 0x%x\n", intSts));
1476
1477 return intSts;
1478}
1479
1480#ifndef DEBUG
1481static int hdaProcessInterrupt(PHDASTATE pThis)
1482#else
1483static int hdaProcessInterrupt(PHDASTATE pThis, const char *pszSource)
1484#endif
1485{
1486 HDA_REG(pThis, INTSTS) = hdaGetINTSTS(pThis);
1487
1488 Log3Func(("IRQL=%RU8\n", pThis->u8IRQL));
1489
1490 /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
1491 * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
1492 */
1493
1494 /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */
1495 if ( (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
1496 && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))
1497 {
1498 if (!pThis->u8IRQL)
1499 {
1500#ifdef DEBUG
1501 if (!pThis->Dbg.IRQ.tsProcessedLastNs)
1502 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
1503
1504 const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
1505
1506 if (!pThis->Dbg.IRQ.tsAssertedNs)
1507 pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
1508
1509 const uint64_t tsAssertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsAssertedNs;
1510
1511 pThis->Dbg.IRQ.cAsserted++;
1512 pThis->Dbg.IRQ.tsAssertedTotalNs += tsAssertedElapsedNs;
1513
1514 const uint64_t avgAssertedUs = (pThis->Dbg.IRQ.tsAssertedTotalNs / pThis->Dbg.IRQ.cAsserted) / 1000;
1515
1516 if (avgAssertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
1517 Log3Func(("Asserted (%s): %zuus elapsed (%zuus on average) -- %zuus alternation delay\n",
1518 pszSource, tsAssertedElapsedNs / 1000,
1519 avgAssertedUs,
1520 (pThis->Dbg.IRQ.tsDeassertedNs - pThis->Dbg.IRQ.tsAssertedNs) / 1000));
1521#endif
1522 Log3Func(("Asserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
1523 pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
1524
1525 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1 /* Assert */);
1526 pThis->u8IRQL = 1;
1527
1528#ifdef DEBUG
1529 pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
1530 pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
1531#endif
1532 }
1533 }
1534 else
1535 {
1536 if (pThis->u8IRQL)
1537 {
1538#ifdef DEBUG
1539 if (!pThis->Dbg.IRQ.tsProcessedLastNs)
1540 pThis->Dbg.IRQ.tsProcessedLastNs = RTTimeNanoTS();
1541
1542 const uint64_t tsLastElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsProcessedLastNs;
1543
1544 if (!pThis->Dbg.IRQ.tsDeassertedNs)
1545 pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();
1546
1547 const uint64_t tsDeassertedElapsedNs = RTTimeNanoTS() - pThis->Dbg.IRQ.tsDeassertedNs;
1548
1549 pThis->Dbg.IRQ.cDeasserted++;
1550 pThis->Dbg.IRQ.tsDeassertedTotalNs += tsDeassertedElapsedNs;
1551
1552 const uint64_t avgDeassertedUs = (pThis->Dbg.IRQ.tsDeassertedTotalNs / pThis->Dbg.IRQ.cDeasserted) / 1000;
1553
1554 if (avgDeassertedUs > (1000 / HDA_TIMER_HZ) /* ms */ * 1000) /* Exceeds time slot? */
1555 Log3Func(("Deasserted (%s): %zuus elapsed (%zuus on average)\n",
1556 pszSource, tsDeassertedElapsedNs / 1000, avgDeassertedUs));
1557
1558 Log3Func(("Deasserted (%s): %RU64us between alternation (WALCLK=%RU64)\n",
1559 pszSource, tsLastElapsedNs / 1000, pThis->u64WalClk));
1560#endif
1561 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0 /* Deassert */);
1562 pThis->u8IRQL = 0;
1563
1564#ifdef DEBUG
1565 pThis->Dbg.IRQ.tsDeassertedNs = RTTimeNanoTS();
1566 pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsDeassertedNs;
1567#endif
1568 }
1569 }
1570
1571 return VINF_SUCCESS;
1572}
1573
1574#ifdef IN_RING3
1575/**
1576 * Reschedules pending interrupts for all audio streams which have complete
1577 * audio periods but did not have the chance to issue their (pending) interrupts yet.
1578 *
1579 * @param pThis The HDA device state.
1580 */
1581static void hdaReschedulePendingInterrupts(PHDASTATE pThis)
1582{
1583 bool fInterrupt = false;
1584
1585 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
1586 {
1587 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
1588 if (!pStream)
1589 continue;
1590
1591 if ( hdaStreamPeriodIsComplete (&pStream->State.Period)
1592 && hdaStreamPeriodNeedsInterrupt(&pStream->State.Period)
1593 && hdaWalClkSet(pThis, hdaStreamPeriodGetAbsElapsedWalClk(&pStream->State.Period), false /* fForce */))
1594 {
1595 fInterrupt = true;
1596 break;
1597 }
1598 }
1599
1600 LogFunc(("fInterrupt=%RTbool\n", fInterrupt));
1601
1602#ifndef DEBUG
1603 hdaProcessInterrupt(pThis);
1604#else
1605 hdaProcessInterrupt(pThis, __FUNCTION__);
1606#endif
1607}
1608#endif
1609
1610/**
1611 * Looks up a register at the exact offset given by @a offReg.
1612 *
1613 * @returns Register index on success, -1 if not found.
1614 * @param offReg The register offset.
1615 */
1616static int hdaRegLookup(uint32_t offReg)
1617{
1618 /*
1619 * Aliases.
1620 */
1621 if (offReg >= g_aHdaRegAliases[0].offReg)
1622 {
1623 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1624 if (offReg == g_aHdaRegAliases[i].offReg)
1625 return g_aHdaRegAliases[i].idxAlias;
1626 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1627 return -1;
1628 }
1629
1630 /*
1631 * Binary search the
1632 */
1633 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1634 int idxLow = 0;
1635 for (;;)
1636 {
1637 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1638 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1639 {
1640 if (idxLow == idxMiddle)
1641 break;
1642 idxEnd = idxMiddle;
1643 }
1644 else if (offReg > g_aHdaRegMap[idxMiddle].offset)
1645 {
1646 idxLow = idxMiddle + 1;
1647 if (idxLow >= idxEnd)
1648 break;
1649 }
1650 else
1651 return idxMiddle;
1652 }
1653
1654#ifdef RT_STRICT
1655 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1656 Assert(g_aHdaRegMap[i].offset != offReg);
1657#endif
1658 return -1;
1659}
1660
1661/**
1662 * Looks up a register covering the offset given by @a offReg.
1663 *
1664 * @returns Register index on success, -1 if not found.
1665 * @param offReg The register offset.
1666 */
1667static int hdaRegLookupWithin(uint32_t offReg)
1668{
1669 /*
1670 * Aliases.
1671 */
1672 if (offReg >= g_aHdaRegAliases[0].offReg)
1673 {
1674 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1675 {
1676 uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
1677 if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
1678 return g_aHdaRegAliases[i].idxAlias;
1679 }
1680 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1681 return -1;
1682 }
1683
1684 /*
1685 * Binary search the register map.
1686 */
1687 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1688 int idxLow = 0;
1689 for (;;)
1690 {
1691 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1692 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1693 {
1694 if (idxLow == idxMiddle)
1695 break;
1696 idxEnd = idxMiddle;
1697 }
1698 else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
1699 {
1700 idxLow = idxMiddle + 1;
1701 if (idxLow >= idxEnd)
1702 break;
1703 }
1704 else
1705 return idxMiddle;
1706 }
1707
1708#ifdef RT_STRICT
1709 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1710 Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
1711#endif
1712 return -1;
1713}
1714
1715#ifdef IN_RING3
1716
1717static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
1718{
1719 int rc = VINF_SUCCESS;
1720 if (fLocal)
1721 {
1722 Assert((HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA));
1723 Assert(pThis->u64CORBBase);
1724 AssertPtr(pThis->pu32CorbBuf);
1725 Assert(pThis->cbCorbBuf);
1726
1727 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
1728 if (RT_FAILURE(rc))
1729 AssertRCReturn(rc, rc);
1730# ifdef DEBUG_CMD_BUFFER
1731 uint8_t i = 0;
1732 do
1733 {
1734 LogFunc(("CORB%02x: ", i));
1735 uint8_t j = 0;
1736 do
1737 {
1738 const char *pszPrefix;
1739 if ((i + j) == HDA_REG(pThis, CORBRP));
1740 pszPrefix = "[R]";
1741 else if ((i + j) == HDA_REG(pThis, CORBWP));
1742 pszPrefix = "[W]";
1743 else
1744 pszPrefix = " "; /* three spaces */
1745 LogFunc(("%s%08x", pszPrefix, pThis->pu32CorbBuf[i + j]));
1746 j++;
1747 } while (j < 8);
1748 LogFunc(("\n"));
1749 i += 8;
1750 } while(i != 0);
1751# endif
1752 }
1753 else
1754 {
1755 Assert((HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RDMAEN));
1756 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
1757 if (RT_FAILURE(rc))
1758 AssertRCReturn(rc, rc);
1759# ifdef DEBUG_CMD_BUFFER
1760 uint8_t i = 0;
1761 do {
1762 LogFunc(("RIRB%02x: ", i));
1763 uint8_t j = 0;
1764 do {
1765 const char *prefix;
1766 if ((i + j) == HDA_REG(pThis, RIRBWP))
1767 prefix = "[W]";
1768 else
1769 prefix = " ";
1770 LogFunc((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
1771 } while (++j < 8);
1772 LogFunc(("\n"));
1773 i += 8;
1774 } while (i != 0);
1775# endif
1776 }
1777 return rc;
1778}
1779
1780static int hdaCORBCmdProcess(PHDASTATE pThis)
1781{
1782 int rc = hdaCmdSync(pThis, true);
1783 if (RT_FAILURE(rc))
1784 AssertRCReturn(rc, rc);
1785
1786 uint8_t corbRp = HDA_REG(pThis, CORBRP);
1787 uint8_t corbWp = HDA_REG(pThis, CORBWP);
1788 uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
1789
1790 Assert((corbWp != corbRp));
1791 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1792
1793 while (corbRp != corbWp)
1794 {
1795 uint64_t uResp;
1796 uint32_t uCmd = pThis->pu32CorbBuf[++corbRp];
1797
1798 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
1799 if (RT_FAILURE(rc2))
1800 LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2));
1801
1802 (rirbWp)++;
1803
1804 if ( (uResp & CODEC_RESPONSE_UNSOLICITED)
1805 && !(HDA_REG(pThis, GCTL) & HDA_GCTL_UNSOL))
1806 {
1807 LogFunc(("Unexpected unsolicited response\n"));
1808 HDA_REG(pThis, CORBRP) = corbRp;
1809 return rc;
1810 }
1811
1812 pThis->pu64RirbBuf[rirbWp] = uResp;
1813
1814 pThis->u8RespIntCnt++;
1815 if (pThis->u8RespIntCnt == RINTCNT_N(pThis))
1816 break;
1817 }
1818
1819 HDA_REG(pThis, CORBRP) = corbRp;
1820 HDA_REG(pThis, RIRBWP) = rirbWp;
1821
1822 rc = hdaCmdSync(pThis, false);
1823
1824 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n",
1825 HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1826
1827 if (HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RINTCTL) /* Response Interrupt Control (RINTCTL) enabled? */
1828 {
1829 if (pThis->u8RespIntCnt)
1830 {
1831 pThis->u8RespIntCnt = 0;
1832
1833 HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
1834
1835#ifndef DEBUG
1836 rc = hdaProcessInterrupt(pThis);
1837#else
1838 rc = hdaProcessInterrupt(pThis, __FUNCTION__);
1839#endif
1840 }
1841 }
1842
1843 if (RT_FAILURE(rc))
1844 AssertRCReturn(rc, rc);
1845
1846 return rc;
1847}
1848
1849static int hdaStreamCreate(PHDASTATE pThis, PHDASTREAM pStream)
1850{
1851 RT_NOREF(pThis);
1852 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1853
1854 pStream->u8SD = UINT8_MAX;
1855 pStream->pMixSink = NULL;
1856
1857 pStream->State.fInReset = false;
1858#ifdef HDA_USE_DMA_ACCESS_HANDLER
1859 RTListInit(&pStream->State.lstDMAHandlers);
1860#endif
1861
1862 int rc = RTCircBufCreate(&pStream->State.pCircBuf, _64K); /** @todo Make this configurable. */
1863 if (RT_SUCCESS(rc))
1864 {
1865 rc = hdaStreamPeriodCreate(&pStream->State.Period);
1866 if (RT_SUCCESS(rc))
1867 rc = RTCritSectInit(&pStream->State.CritSect);
1868 }
1869
1870#ifdef DEBUG
1871 int rc2 = RTCritSectInit(&pStream->Dbg.CritSect);
1872 AssertRC(rc2);
1873#endif
1874
1875 return rc;
1876}
1877
1878static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream)
1879{
1880 AssertPtrReturnVoid(pStream);
1881
1882 LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
1883
1884 hdaStreamMapDestroy(&pStream->State.Mapping);
1885
1886 int rc2;
1887
1888#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1889 rc2 = hdaStreamAsyncIODestroy(pThis, pStream);
1890 AssertRC(rc2);
1891#else
1892 RT_NOREF(pThis);
1893#endif
1894
1895 rc2 = RTCritSectDelete(&pStream->State.CritSect);
1896 AssertRC(rc2);
1897
1898 if (pStream->State.pCircBuf)
1899 {
1900 RTCircBufDestroy(pStream->State.pCircBuf);
1901 pStream->State.pCircBuf = NULL;
1902 }
1903
1904 hdaStreamPeriodDestroy(&pStream->State.Period);
1905
1906#ifdef DEBUG
1907 rc2 = RTCritSectDelete(&pStream->Dbg.CritSect);
1908 AssertRC(rc2);
1909#endif
1910
1911 LogFlowFuncLeave();
1912}
1913
1914static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
1915{
1916 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1917 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1918
1919 pStream->u8SD = uSD;
1920 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
1921 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
1922 pStream->u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
1923 pStream->u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
1924 pStream->u16FIFOS = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
1925
1926 /* Make sure to also update the stream's DMA counter (based on its current LPIB value). */
1927 hdaStreamUpdateLPIB(pThis, pStream, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
1928
1929 PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;
1930
1931 int rc = hdaSDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &pCfg->Props);
1932 if (RT_FAILURE(rc))
1933 {
1934 LogRel(("HDA: Warning: Format 0x%x for stream #%RU8 not supported\n", HDA_STREAM_REG(pThis, FMT, uSD), uSD));
1935 return rc;
1936 }
1937
1938 /* Set the stream's direction. */
1939 pCfg->enmDir = hdaGetDirFromSD(pStream->u8SD);
1940
1941 /* The the stream's name, based on the direction. */
1942 switch (pCfg->enmDir)
1943 {
1944 case PDMAUDIODIR_IN:
1945# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
1946# error "Implement me!"
1947# else
1948 pCfg->DestSource.Source = PDMAUDIORECSOURCE_LINE;
1949 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
1950 RTStrCopy(pCfg->szName, sizeof(pCfg->szName), "Line In");
1951# endif
1952 break;
1953
1954 case PDMAUDIODIR_OUT:
1955 /* Destination(s) will be set in hdaAddStreamOut(),
1956 * based on the channels / stream layout. */
1957 break;
1958
1959 default:
1960 rc = VERR_NOT_SUPPORTED;
1961 break;
1962 }
1963
1964 /*
1965 * Initialize the stream mapping in any case, regardless if
1966 * we support surround audio or not. This is needed to handle
1967 * the supported channels within a single audio stream, e.g. mono/stereo.
1968 *
1969 * In other words, the stream mapping *always* knows the real
1970 * number of channels in a single audio stream.
1971 */
1972 rc = hdaStreamMapInit(&pStream->State.Mapping, &pCfg->Props);
1973 AssertRCReturn(rc, rc);
1974
1975 LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, rc=%Rrc\n",
1976 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS, rc));
1977
1978 return rc;
1979}
1980
1981/**
1982 * Resets an HDA stream.
1983 *
1984 * @param pThis HDA state.
1985 * @param pStream HDA stream to reset.
1986 * @param uSD Stream descriptor (SD) number to use for this stream.
1987 */
1988static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
1989{
1990 AssertPtrReturnVoid(pThis);
1991 AssertPtrReturnVoid(pStream);
1992 AssertReturnVoid(uSD < HDA_MAX_STREAMS);
1993
1994# ifdef VBOX_STRICT
1995 AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_RUN),
1996 ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
1997# endif
1998
1999 LogFunc(("[SD%RU8]: Reset\n", uSD));
2000
2001 /*
2002 * Set reset state.
2003 */
2004 Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
2005 ASMAtomicXchgBool(&pStream->State.fInReset, true);
2006
2007 /*
2008 * Second, initialize the registers.
2009 */
2010 HDA_STREAM_REG(pThis, STS, uSD) = HDA_SDSTS_FIFORDY;
2011 /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
2012 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
2013 HDA_STREAM_REG(pThis, CTL, uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_SRST);
2014 /* ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39. */
2015 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_192B;
2016 /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
2017 HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
2018 HDA_STREAM_REG(pThis, LPIB, uSD) = 0;
2019 HDA_STREAM_REG(pThis, CBL, uSD) = 0;
2020 HDA_STREAM_REG(pThis, LVI, uSD) = 0;
2021 HDA_STREAM_REG(pThis, FMT, uSD) = 0;
2022 HDA_STREAM_REG(pThis, BDPU, uSD) = 0;
2023 HDA_STREAM_REG(pThis, BDPL, uSD) = 0;
2024
2025#ifdef HDA_USE_DMA_ACCESS_HANDLER
2026 hdaStreamUnregisterDMAHandlers(pThis, pStream);
2027#endif
2028
2029 RT_ZERO(pStream->State.BDLE);
2030 pStream->State.uCurBDLE = 0;
2031
2032 if (pStream->State.pCircBuf)
2033 RTCircBufReset(pStream->State.pCircBuf);
2034
2035 /* Reset stream map. */
2036 hdaStreamMapReset(&pStream->State.Mapping);
2037
2038 /* (Re-)initialize the stream with current values. */
2039 int rc2 = hdaStreamInit(pThis, pStream, uSD);
2040 AssertRC(rc2);
2041
2042 /* Reset the stream's period. */
2043 hdaStreamPeriodReset(&pStream->State.Period);
2044
2045#ifdef DEBUG
2046 pStream->Dbg.cReadsTotal = 0;
2047 pStream->Dbg.cbReadTotal = 0;
2048 pStream->Dbg.tsLastReadNs = 0;
2049 pStream->Dbg.cWritesTotal = 0;
2050 pStream->Dbg.cbWrittenTotal = 0;
2051 pStream->Dbg.cWritesHz = 0;
2052 pStream->Dbg.cbWrittenHz = 0;
2053 pStream->Dbg.tsWriteSlotBegin = 0;
2054#endif
2055
2056 /* Report that we're done resetting this stream. */
2057 HDA_STREAM_REG(pThis, CTL, uSD) = 0;
2058
2059 LogFunc(("[SD%RU8] Reset\n", uSD));
2060
2061 /* Exit reset mode. */
2062 ASMAtomicXchgBool(&pStream->State.fInReset, false);
2063}
2064
2065/**
2066 * Enables or disables an HDA audio stream.
2067 *
2068 * @returns IPRT status code.
2069 * @param pThis HDA state.
2070 * @param pStream HDA stream to enable or disable.
2071 * @param fEnable Whether to enable or disble the stream.
2072 */
2073static int hdaStreamEnable(PHDASTATE pThis, PHDASTREAM pStream, bool fEnable)
2074{
2075 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2076 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
2077
2078 LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
2079
2080 int rc = VINF_SUCCESS;
2081
2082 if (pStream->pMixSink) /* Stream attached to a sink? */
2083 {
2084 AUDMIXSINKCMD enmCmd = fEnable
2085 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
2086
2087 /* First, enable or disable the stream and the stream's sink, if any. */
2088 if (pStream->pMixSink->pMixSink)
2089 rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
2090 }
2091
2092 LogFunc(("[SD%RU8] rc=%Rrc\n", pStream->u8SD, rc));
2093 return rc;
2094}
2095#endif /* IN_RING3 */
2096
2097/* Register access handlers. */
2098
2099static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2100{
2101 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg);
2102 *pu32Value = 0;
2103 return VINF_SUCCESS;
2104}
2105
2106static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2107{
2108 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2109 return VINF_SUCCESS;
2110}
2111
2112/* U8 */
2113static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2114{
2115 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
2116 return hdaRegReadU32(pThis, iReg, pu32Value);
2117}
2118
2119static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2120{
2121 Assert((u32Value & 0xffffff00) == 0);
2122 return hdaRegWriteU32(pThis, iReg, u32Value);
2123}
2124
2125/* U16 */
2126static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2127{
2128 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
2129 return hdaRegReadU32(pThis, iReg, pu32Value);
2130}
2131
2132static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2133{
2134 Assert((u32Value & 0xffff0000) == 0);
2135 return hdaRegWriteU32(pThis, iReg, u32Value);
2136}
2137
2138/* U24 */
2139static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2140{
2141 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
2142 return hdaRegReadU32(pThis, iReg, pu32Value);
2143}
2144
2145#ifdef IN_RING3
2146static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2147{
2148 Assert((u32Value & 0xff000000) == 0);
2149 return hdaRegWriteU32(pThis, iReg, u32Value);
2150}
2151#endif
2152
2153/* U32 */
2154static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2155{
2156 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
2157
2158 *pu32Value = pThis->au32Regs[iRegMem] & g_aHdaRegMap[iReg].readable;
2159 return VINF_SUCCESS;
2160}
2161
2162static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2163{
2164 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
2165
2166 pThis->au32Regs[iRegMem] = (u32Value & g_aHdaRegMap[iReg].writable)
2167 | (pThis->au32Regs[iRegMem] & ~g_aHdaRegMap[iReg].writable);
2168 return VINF_SUCCESS;
2169}
2170
2171static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2172{
2173 RT_NOREF_PV(iReg);
2174
2175 if (u32Value & HDA_GCTL_CRST)
2176 {
2177 /* Set the CRST bit to indicate that we're leaving reset mode. */
2178 HDA_REG(pThis, GCTL) |= HDA_GCTL_CRST;
2179 LogFunc(("Guest leaving HDA reset\n"));
2180 }
2181 else
2182 {
2183#ifdef IN_RING3
2184 /* Enter reset state. */
2185 LogFunc(("Guest entering HDA reset with DMA(RIRB:%s, CORB:%s)\n",
2186 HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA ? "on" : "off",
2187 HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RDMAEN ? "on" : "off"));
2188
2189 /* Clear the CRST bit to indicate that we're in reset state. */
2190 HDA_REG(pThis, GCTL) &= ~HDA_GCTL_CRST;
2191
2192 hdaGctlReset(pThis);
2193#else
2194 return VINF_IOM_R3_MMIO_WRITE;
2195#endif
2196 }
2197
2198 if (u32Value & HDA_GCTL_FCNTRL)
2199 {
2200 /* Flush: GSTS:1 set, see 6.2.6. */
2201 HDA_REG(pThis, GSTS) |= HDA_GSTS_FSTS; /* Set the flush status. */
2202 /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6). */
2203 }
2204 return VINF_SUCCESS;
2205}
2206
2207static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2208{
2209 uint32_t v = HDA_REG_IND(pThis, iReg);
2210 uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK;
2211
2212 HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
2213
2214 return VINF_SUCCESS;
2215}
2216
2217static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2218{
2219 const uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
2220 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, uSD);
2221#ifdef LOG_ENABLED
2222 const uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, uSD);
2223 LogFlowFunc(("[SD%RU8] LPIB=%RU32, CBL=%RU32\n", uSD, u32LPIB, u32CBL));
2224#endif
2225
2226 *pu32Value = u32LPIB;
2227 return VINF_SUCCESS;
2228}
2229
2230/**
2231 * Retrieves the currently set value for the wall clock.
2232 *
2233 * @return IPRT status code.
2234 * @return Currently set wall clock value.
2235 * @param pThis HDA state.
2236 *
2237 * @remark Operation is atomic.
2238 */
2239uint64_t hdaWalClkGetCurrent(PHDASTATE pThis)
2240{
2241 return ASMAtomicReadU64(&pThis->u64WalClk);
2242}
2243
2244#ifdef IN_RING3
2245/**
2246 * Returns the current maximum value the wall clock counter can be set to.
2247 * This maximum value depends on all currently handled HDA streams and their own current timing.
2248 *
2249 * @return Current maximum value the wall clock counter can be set to.
2250 * @param pThis HDA state.
2251 *
2252 * @remark Does not actually set the wall clock counter.
2253 */
2254uint64_t hdaWalClkGetMax(PHDASTATE pThis)
2255{
2256 const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
2257 const uint64_t u64FrontAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);
2258#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2259# error "Implement me!"
2260#endif
2261 const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);
2262#ifdef VBOX_WITH_HDA_MIC_IN
2263 const uint64_t u64MicInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);
2264#endif
2265
2266 uint64_t u64WalClkNew = RT_MAX(u64WalClkCur, u64FrontAbsWalClk);
2267#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2268# error "Implement me!"
2269#endif
2270 u64WalClkNew = RT_MAX(u64WalClkNew, u64LineInAbsWalClk);
2271#ifdef VBOX_WITH_HDA_MIC_IN
2272 u64WalClkNew = RT_MAX(u64WalClkNew, u64MicInAbsWalClk);
2273#endif
2274
2275 Log3Func(("%RU64 -> Front=%RU64, LineIn=%RU64 -> %RU64\n",
2276 u64WalClkCur, u64FrontAbsWalClk, u64LineInAbsWalClk, u64WalClkNew));
2277
2278 return u64WalClkNew;
2279}
2280
2281/**
2282 * Sets the actual WALCLK register to the specified wall clock value.
2283 * The specified wall clock value only will be set (unless fForce is set to true) if all
2284 * handled HDA streams have passed (in time) that value. This guarantees that the WALCLK
2285 * register stays in sync with all handled HDA streams.
2286 *
2287 * @return true if the WALCLK register has been updated, false if not.
2288 * @param pThis HDA state.
2289 * @param u64WalClk Wall clock value to set WALCLK register to.
2290 * @param fForce Whether to force setting the wall clock value or not.
2291 */
2292bool hdaWalClkSet(PHDASTATE pThis, uint64_t u64WalClk, bool fForce)
2293{
2294 const bool fFrontPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period,
2295 u64WalClk);
2296 const uint64_t u64FrontAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkFront)->State.Period);
2297#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2298# error "Implement me!"
2299#endif
2300
2301 const bool fLineInPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period, u64WalClk);
2302 const uint64_t u64LineInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkLineIn)->State.Period);
2303#ifdef VBOX_WITH_HDA_MIC_IN
2304 const bool fMicInPassed = hdaStreamPeriodHasPassedAbsWalClk (&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period, u64WalClk);
2305 const uint64_t u64MicInAbsWalClk = hdaStreamPeriodGetAbsElapsedWalClk(&hdaSinkGetStream(pThis, &pThis->SinkMicIn)->State.Period);
2306#endif
2307
2308#ifdef VBOX_STRICT
2309 const uint64_t u64WalClkCur = ASMAtomicReadU64(&pThis->u64WalClk);
2310#endif
2311 uint64_t u64WalClkSet = u64WalClk;
2312
2313 /* Only drive the WALCLK register forward if all (active) stream periods have passed
2314 * the specified point in time given by u64WalClk. */
2315 if ( ( fFrontPassed
2316#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2317# error "Implement me!"
2318#endif
2319 && fLineInPassed
2320#ifdef VBOX_WITH_HDA_MIC_IN
2321 && fMicInPassed
2322#endif
2323 )
2324 || fForce)
2325 {
2326 if (!fForce)
2327 {
2328 /* Get the maximum value of all periods we need to handle.
2329 * Not the most elegant solution, but works for now ... */
2330 u64WalClk = RT_MAX(u64WalClkSet, u64FrontAbsWalClk);
2331#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2332# error "Implement me!"
2333#endif
2334 u64WalClk = RT_MAX(u64WalClkSet, u64LineInAbsWalClk);
2335#ifdef VBOX_WITH_HDA_MIC_IN
2336 u64WalClk = RT_MAX(u64WalClkSet, u64MicInAbsWalClk);
2337#endif
2338 AssertMsg(u64WalClkSet > u64WalClkCur,
2339 ("Setting WALCLK to a stale or backward value (%RU64 -> %RU64) isn't a good idea really. "
2340 "Good luck with stuck audio stuff.\n", u64WalClkCur, u64WalClkSet));
2341 }
2342
2343 /* Set the new WALCLK value. */
2344 ASMAtomicWriteU64(&pThis->u64WalClk, u64WalClkSet);
2345 }
2346
2347 const uint64_t u64WalClkNew = hdaWalClkGetCurrent(pThis);
2348
2349 Log3Func(("Cur: %RU64, New: %RU64 (force %RTbool) -> %RU64 %s\n",
2350 u64WalClkCur, u64WalClk, fForce,
2351 u64WalClkNew, u64WalClkNew == u64WalClk ? "[OK]" : "[DELAYED]"));
2352
2353 return (u64WalClkNew == u64WalClk);
2354}
2355#endif /* IN_RING3 */
2356
2357static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2358{
2359#ifdef IN_RING3
2360 RT_NOREF(iReg);
2361
2362 *pu32Value = RT_LO_U32(ASMAtomicReadU64(&pThis->u64WalClk));
2363
2364 Log3Func(("%RU32 (max @ %RU64)\n",*pu32Value, hdaWalClkGetMax(pThis)));
2365
2366 return VINF_SUCCESS;
2367#else
2368 RT_NOREF(pThis, iReg, pu32Value);
2369 return VINF_IOM_R3_MMIO_WRITE;
2370#endif
2371}
2372
2373static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2374{
2375 RT_NOREF_PV(iReg);
2376
2377 if (u32Value & HDA_CORBRP_RST)
2378 HDA_REG(pThis, CORBRP) = HDA_CORBRP_RST; /* Clears the pointer. */
2379 else
2380 HDA_REG(pThis, CORBRP) &= ~HDA_CORBRP_RST; /* Only CORBRP_RST bit is writable. */
2381
2382 return VINF_SUCCESS;
2383}
2384
2385static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2386{
2387#ifdef IN_RING3
2388 int rc = hdaRegWriteU8(pThis, iReg, u32Value);
2389 AssertRC(rc);
2390 if ( (uint8_t)HDA_REG(pThis, CORBWP) != (uint8_t)HDA_REG(pThis, CORBRP)
2391 && (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
2392 {
2393 return hdaCORBCmdProcess(pThis);
2394 }
2395 return rc;
2396#else
2397 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2398 return VINF_IOM_R3_MMIO_WRITE;
2399#endif
2400}
2401
2402static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2403{
2404 RT_NOREF_PV(iReg);
2405
2406 uint32_t v = HDA_REG(pThis, CORBSTS);
2407 HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
2408 return VINF_SUCCESS;
2409}
2410
2411static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2412{
2413#ifdef IN_RING3
2414 int rc;
2415 rc = hdaRegWriteU16(pThis, iReg, u32Value);
2416 if (RT_FAILURE(rc))
2417 AssertRCReturn(rc, rc);
2418 if ((uint8_t)HDA_REG(pThis, CORBWP) == (uint8_t)HDA_REG(pThis, CORBRP))
2419 return VINF_SUCCESS;
2420 if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
2421 return VINF_SUCCESS;
2422 rc = hdaCORBCmdProcess(pThis);
2423 return rc;
2424#else /* !IN_RING3 */
2425 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2426 return VINF_IOM_R3_MMIO_WRITE;
2427#endif /* IN_RING3 */
2428}
2429
2430static int hdaRegWriteSDCBL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2431{
2432#ifdef IN_RING3
2433 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, CBL, iReg));
2434 if (!pStream)
2435 {
2436 LogFunc(("[SD%RU8]: Warning: Changing SDCBL on non-attached stream (0x%x)\n",
2437 HDA_SD_NUM_FROM_REG(pThis, CTL, iReg), u32Value));
2438 return hdaRegWriteU32(pThis, iReg, u32Value);
2439 }
2440
2441 pStream->u32CBL = u32Value;
2442
2443 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
2444 AssertRC(rc2);
2445
2446 LogFlowFunc(("[SD%RU8]: CBL=%RU32\n", pStream->u8SD, u32Value));
2447
2448 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2449#else /* !IN_RING3 */
2450 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2451 return VINF_IOM_R3_MMIO_WRITE;
2452#endif /* IN_RING3 */
2453}
2454
2455static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2456{
2457#ifdef IN_RING3
2458 /*
2459 * Some guests write too much (that is, 32-bit with the top 8 bit being junk)
2460 * instead of 24-bit required for SDCTL. So just mask this here to be safe.
2461 */
2462 u32Value = (u32Value & 0x00ffffff);
2463
2464 bool fRun = RT_BOOL(u32Value & HDA_SDCTL_RUN);
2465 bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_RUN);
2466
2467 bool fReset = RT_BOOL(u32Value & HDA_SDCTL_SRST);
2468 bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
2469
2470 /* Get the stream descriptor. */
2471 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
2472
2473 LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
2474 uSD, fRun, fInRun, fReset, fInReset, u32Value));
2475
2476 /*
2477 * Extract the stream tag the guest wants to use for this specific
2478 * stream descriptor (SDn). This only can happen if the stream is in a non-running
2479 * state, so we're doing the lookup and assignment here.
2480 *
2481 * So depending on the guest OS, SD3 can use stream tag 4, for example.
2482 */
2483 uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
2484 if (uTag > HDA_MAX_TAGS)
2485 {
2486 LogFunc(("[SD%RU8]: Warning: Invalid stream tag %RU8 specified!\n", uSD, uTag));
2487 return hdaRegWriteU24(pThis, iReg, u32Value);
2488 }
2489
2490 PHDATAG pTag = &pThis->aTags[uTag];
2491 AssertPtr(pTag);
2492
2493 LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag));
2494
2495 /* Assign new values. */
2496 pTag->uTag = uTag;
2497 pTag->pStream = hdaStreamGetFromSD(pThis, uSD);
2498
2499 PHDASTREAM pStream = pTag->pStream;
2500 AssertPtr(pStream);
2501
2502 if (fInReset)
2503 {
2504 Assert(!fReset);
2505 Assert(!fInRun && !fRun);
2506
2507 /* Exit reset state. */
2508 ASMAtomicXchgBool(&pStream->State.fInReset, false);
2509
2510 /* Report that we're done resetting this stream by clearing SRST. */
2511 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_SRST;
2512
2513 LogFunc(("[SD%RU8]: Reset exit\n", uSD));
2514 }
2515 else if (fReset)
2516 {
2517 /* ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset. */
2518 Assert(!fInRun && !fRun);
2519
2520 LogFunc(("[SD%RU8]: Reset enter\n", pStream->u8SD));
2521
2522 hdaStreamLock(pStream);
2523
2524#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
2525 hdaStreamAsyncIOLock(pStream);
2526 hdaStreamAsyncIOEnable(pStream, false /* fEnable */);
2527#endif
2528 hdaStreamReset(pThis, pStream, pStream->u8SD);
2529
2530#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
2531 hdaStreamAsyncIOUnlock(pStream);
2532#endif
2533 hdaStreamUnlock(pStream);
2534 }
2535 else
2536 {
2537 /*
2538 * We enter here to change DMA states only.
2539 */
2540 if (fInRun != fRun)
2541 {
2542 Assert(!fReset && !fInReset);
2543 LogFunc(("[SD%RU8]: State changed (fRun=%RTbool)\n", pStream->u8SD, fRun));
2544
2545 hdaStreamLock(pStream);
2546
2547#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
2548 hdaStreamAsyncIOLock(pStream);
2549 hdaStreamAsyncIOEnable(pStream, fRun /* fEnable */);
2550#endif
2551 /* (Re-)initialize the stream with current values. */
2552 int rc2 = hdaStreamInit(pThis, pStream, pStream->u8SD);
2553 AssertRC(rc2);
2554
2555 /* Enable/disable the stream. */
2556 hdaStreamEnable(pThis, pStream, fRun /* fEnable */);
2557
2558 if (fRun)
2559 {
2560 /* (Re-)init the stream's period. */
2561 hdaStreamPeriodInit(&pStream->State.Period,
2562 pStream->u8SD, pStream->u16LVI, pStream->u32CBL, &pStream->State.strmCfg);
2563
2564 /* Begin a new period for this stream. */
2565 rc2 = hdaStreamPeriodBegin(&pStream->State.Period, hdaWalClkGetCurrent(pThis)/* Use current wall clock time */);
2566 AssertRC(rc2);
2567 }
2568 else
2569 {
2570 /* Make sure to (re-)schedule outstanding (delayed) interrupts. */
2571 hdaReschedulePendingInterrupts(pThis);
2572
2573 /* Reset the period. */
2574 hdaStreamPeriodReset(&pStream->State.Period);
2575 }
2576
2577#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
2578 hdaStreamAsyncIOUnlock(pStream);
2579#endif
2580 /* Make sure to leave the lock before (eventually) starting the timer. */
2581 hdaStreamUnlock(pStream);
2582
2583#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
2584 /* See if we need to start or stop the timer. */
2585 if (!fRun)
2586 hdaTimerMaybeStop(pThis);
2587 else
2588 hdaTimerMaybeStart(pThis);
2589#endif
2590 }
2591 }
2592
2593 int rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
2594 AssertRC(rc2);
2595
2596 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2597#else /* !IN_RING3 */
2598 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2599 return VINF_IOM_R3_MMIO_WRITE;
2600#endif /* IN_RING3 */
2601}
2602
2603static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2604{
2605#ifdef IN_RING3
2606 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, STS, iReg));
2607 if (!pStream)
2608 {
2609 AssertMsgFailed(("[SD%RU8]: Warning: Writing SDSTS on non-attached stream (0x%x)\n",
2610 HDA_SD_NUM_FROM_REG(pThis, STS, iReg), u32Value));
2611 return hdaRegWriteU16(pThis, iReg, u32Value);
2612 }
2613
2614 uint32_t v = HDA_REG_IND(pThis, iReg);
2615
2616 /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */
2617 HDA_REG_IND(pThis, iReg) &= ~(u32Value & v);
2618
2619 /* Some guests tend to write SDnSTS even if the stream is not running.
2620 * So make sure to check if the RUN bit is set first. */
2621 const bool fInRun = RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN);
2622
2623 Log3Func(("[SD%RU8] fRun=%RTbool %R[sdsts]\n", pStream->u8SD, fInRun, v));
2624
2625 PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
2626
2627 if (hdaStreamPeriodLock(pPeriod))
2628 {
2629 const bool fNeedsInterrupt = hdaStreamPeriodNeedsInterrupt(pPeriod);
2630 if (fNeedsInterrupt)
2631 hdaStreamPeriodReleaseInterrupt(pPeriod);
2632
2633 if (hdaStreamPeriodIsComplete(pPeriod))
2634 {
2635 hdaStreamPeriodEnd(pPeriod);
2636
2637 if (fInRun)
2638 hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis) /* Use current wall clock time */);
2639 }
2640
2641 hdaStreamPeriodUnlock(pPeriod); /* Unlock before processing interrupt. */
2642
2643 if (fNeedsInterrupt)
2644 {
2645#ifndef DEBUG
2646 hdaProcessInterrupt(pThis);
2647#else
2648 hdaProcessInterrupt(pThis, __FUNCTION__);
2649#endif
2650 }
2651 }
2652
2653 return VINF_SUCCESS;
2654#else /* IN_RING3 */
2655 RT_NOREF(pThis, iReg, u32Value);
2656 return VINF_IOM_R3_MMIO_WRITE;
2657#endif /* !IN_RING3 */
2658}
2659
2660static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2661{
2662#ifdef IN_RING3
2663 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
2664 return VINF_SUCCESS;
2665
2666 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
2667
2668 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
2669 if (!pStream)
2670 {
2671 AssertMsgFailed(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", uSD, u32Value));
2672 return hdaRegWriteU16(pThis, iReg, u32Value);
2673 }
2674
2675 /** @todo Validate LVI. */
2676 pStream->u16LVI = u32Value;
2677 LogFunc(("[SD%RU8]: Updating LVI to %RU16\n", uSD, pStream->u16LVI));
2678
2679# ifdef HDA_USE_DMA_ACCESS_HANDLER
2680 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
2681 {
2682 /* Try registering the DMA handlers.
2683 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
2684 if (hdaStreamRegisterDMAHandlers(pThis, pStream))
2685 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
2686 }
2687# endif
2688
2689 int rc2 = hdaRegWriteU16(pThis, iReg, u32Value);
2690 AssertRC(rc2);
2691
2692 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2693#else /* !IN_RING3 */
2694 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2695 return VINF_IOM_R3_MMIO_WRITE;
2696#endif /* IN_RING3 */
2697}
2698
2699static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2700{
2701#ifdef IN_RING3
2702 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
2703
2704 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_IN) /* FIFOW for input streams only. */
2705 {
2706 LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", uSD));
2707 return VINF_SUCCESS;
2708 }
2709
2710 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg));
2711 if (!pStream)
2712 {
2713 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOW on non-attached stream (0x%x)\n", uSD, u32Value));
2714 return hdaRegWriteU16(pThis, iReg, u32Value);
2715 }
2716
2717 uint32_t u32FIFOW = 0;
2718
2719 switch (u32Value)
2720 {
2721 case HDA_SDFIFOW_8B:
2722 case HDA_SDFIFOW_16B:
2723 case HDA_SDFIFOW_32B:
2724 u32FIFOW = u32Value;
2725 break;
2726 default:
2727 LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
2728 u32Value, uSD));
2729 AssertFailed();
2730 u32FIFOW = HDA_SDFIFOW_32B;
2731 break;
2732 }
2733
2734 if (u32FIFOW)
2735 {
2736 pStream->u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW);
2737 LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, pStream->u16FIFOW));
2738
2739 int rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOW);
2740 AssertRC(rc2);
2741 }
2742
2743 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2744#else /* !IN_RING3 */
2745 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2746 return VINF_IOM_R3_MMIO_WRITE;
2747#endif /* IN_RING3 */
2748}
2749
2750/**
2751 * @note This method could be called for changing value on Output Streams only (ICH6 datasheet 18.2.39).
2752 */
2753static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2754{
2755#ifdef IN_RING3
2756 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
2757
2758 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_OUT) /* FIFOS for output streams only. */
2759 {
2760 LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to input stream #%RU8, ignoring\n", uSD));
2761 return VINF_SUCCESS;
2762 }
2763
2764 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
2765 if (!pStream)
2766 {
2767 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOS on non-attached stream (0x%x)\n", uSD, u32Value));
2768 return hdaRegWriteU16(pThis, iReg, u32Value);
2769 }
2770
2771 uint32_t u32FIFOS = 0;
2772
2773 switch(u32Value)
2774 {
2775 case HDA_SDOFIFO_16B:
2776 case HDA_SDOFIFO_32B:
2777 case HDA_SDOFIFO_64B:
2778 case HDA_SDOFIFO_128B:
2779 case HDA_SDOFIFO_192B:
2780 case HDA_SDOFIFO_256B:
2781 u32FIFOS = u32Value;
2782 break;
2783
2784 default:
2785 LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
2786 u32Value, uSD));
2787 AssertFailed();
2788 u32FIFOS = HDA_SDOFIFO_192B;
2789 break;
2790 }
2791
2792 if (u32FIFOS)
2793 {
2794 pStream->u16FIFOS = u32FIFOS + 1;
2795 LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", uSD, pStream->u16FIFOS));
2796
2797 int rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOS);
2798 AssertRC(rc2);
2799 }
2800
2801 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2802#else /* !IN_RING3 */
2803 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2804 return VINF_IOM_R3_MMIO_WRITE;
2805#endif /* IN_RING3 */
2806}
2807
2808#ifdef IN_RING3
2809/**
2810 * Converts an HDA stream's SDFMT register into a given PCM properties structure.
2811 *
2812 * @return IPRT status code.
2813 * @param u32SDFMT The HDA stream's SDFMT value to convert.
2814 * @param pProps PCM properties structure to hold converted result on success.
2815 */
2816static int hdaSDFMTToPCMProps(uint32_t u32SDFMT, PPDMAUDIOPCMPROPS pProps)
2817{
2818 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
2819
2820# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
2821
2822 int rc = VINF_SUCCESS;
2823
2824 uint32_t u32Hz = EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
2825 ? 44100 : 48000;
2826 uint32_t u32HzMult = 1;
2827 uint32_t u32HzDiv = 1;
2828
2829 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
2830 {
2831 case 0: u32HzMult = 1; break;
2832 case 1: u32HzMult = 2; break;
2833 case 2: u32HzMult = 3; break;
2834 case 3: u32HzMult = 4; break;
2835 default:
2836 LogFunc(("Unsupported multiplier %x\n",
2837 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
2838 rc = VERR_NOT_SUPPORTED;
2839 break;
2840 }
2841 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
2842 {
2843 case 0: u32HzDiv = 1; break;
2844 case 1: u32HzDiv = 2; break;
2845 case 2: u32HzDiv = 3; break;
2846 case 3: u32HzDiv = 4; break;
2847 case 4: u32HzDiv = 5; break;
2848 case 5: u32HzDiv = 6; break;
2849 case 6: u32HzDiv = 7; break;
2850 case 7: u32HzDiv = 8; break;
2851 default:
2852 LogFunc(("Unsupported divisor %x\n",
2853 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
2854 rc = VERR_NOT_SUPPORTED;
2855 break;
2856 }
2857
2858 uint8_t cBits = 0;
2859 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
2860 {
2861 case 0:
2862 cBits = 8;
2863 break;
2864 case 1:
2865 cBits = 16;
2866 break;
2867 case 4:
2868 cBits = 32;
2869 break;
2870 default:
2871 AssertMsgFailed(("Unsupported bits per sample %x\n",
2872 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
2873 rc = VERR_NOT_SUPPORTED;
2874 break;
2875 }
2876
2877 if (RT_SUCCESS(rc))
2878 {
2879 RT_BZERO(pProps, sizeof(PDMAUDIOPCMPROPS));
2880
2881 pProps->cBits = cBits;
2882 pProps->fSigned = true;
2883 pProps->cChannels = (u32SDFMT & 0xf) + 1;
2884 pProps->uHz = u32Hz * u32HzMult / u32HzDiv;
2885 pProps->cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cBits, pProps->cChannels);
2886 }
2887
2888# undef EXTRACT_VALUE
2889 return rc;
2890}
2891
2892/**
2893 * Adds an audio output stream to the device setup using the given configuration.
2894 *
2895 * @returns IPRT status code.
2896 * @param pThis Device state.
2897 * @param pCfg Stream configuration to use for adding a stream.
2898 */
2899static int hdaAddStreamOut(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
2900{
2901 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2902 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2903
2904 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
2905
2906 LogFlowFunc(("Stream=%s\n", pCfg->szName));
2907
2908 int rc = VINF_SUCCESS;
2909
2910 bool fUseFront = true; /* Always use front out by default. */
2911#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2912 bool fUseRear;
2913 bool fUseCenter;
2914 bool fUseLFE;
2915
2916 fUseRear = fUseCenter = fUseLFE = false;
2917
2918 /*
2919 * Use commonly used setups for speaker configurations.
2920 */
2921
2922 /** @todo Make the following configurable through mixer API and/or CFGM? */
2923 switch (pCfg->Props.cChannels)
2924 {
2925 case 3: /* 2.1: Front (Stereo) + LFE. */
2926 {
2927 fUseLFE = true;
2928 break;
2929 }
2930
2931 case 4: /* Quadrophonic: Front (Stereo) + Rear (Stereo). */
2932 {
2933 fUseRear = true;
2934 break;
2935 }
2936
2937 case 5: /* 4.1: Front (Stereo) + Rear (Stereo) + LFE. */
2938 {
2939 fUseRear = true;
2940 fUseLFE = true;
2941 break;
2942 }
2943
2944 case 6: /* 5.1: Front (Stereo) + Rear (Stereo) + Center/LFE. */
2945 {
2946 fUseRear = true;
2947 fUseCenter = true;
2948 fUseLFE = true;
2949 break;
2950 }
2951
2952 default: /* Unknown; fall back to 2 front channels (stereo). */
2953 {
2954 rc = VERR_NOT_SUPPORTED;
2955 break;
2956 }
2957 }
2958#else /* !VBOX_WITH_AUDIO_HDA_51_SURROUND */
2959 /* Only support mono or stereo channels. */
2960 if ( pCfg->Props.cChannels != 1 /* Mono */
2961 && pCfg->Props.cChannels != 2 /* Stereo */)
2962 {
2963 rc = VERR_NOT_SUPPORTED;
2964 }
2965#endif
2966
2967 if (rc == VERR_NOT_SUPPORTED)
2968 {
2969 LogRel2(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->Props.cChannels));
2970
2971 /* Fall back to 2 channels (see below in fUseFront block). */
2972 rc = VINF_SUCCESS;
2973 }
2974
2975 do
2976 {
2977 if (RT_FAILURE(rc))
2978 break;
2979
2980 if (fUseFront)
2981 {
2982 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Front");
2983
2984 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
2985 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
2986
2987 pCfg->Props.cChannels = 2;
2988 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBits, pCfg->Props.cChannels);
2989
2990 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT);
2991 if (RT_SUCCESS(rc))
2992 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
2993 }
2994
2995#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2996 if ( RT_SUCCESS(rc)
2997 && (fUseCenter || fUseLFE))
2998 {
2999 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Center/LFE");
3000
3001 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE;
3002 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
3003
3004 pCfg->Props.cChannels = (fUseCenter && fUseLFE) ? 2 : 1;
3005 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBits, pCfg->Props.cChannels);
3006
3007 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE);
3008 if (RT_SUCCESS(rc))
3009 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
3010 }
3011
3012 if ( RT_SUCCESS(rc)
3013 && fUseRear)
3014 {
3015 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Rear");
3016
3017 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR;
3018 pCfg->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
3019
3020 pCfg->Props.cChannels = 2;
3021 pCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfg->Props.cBits, pCfg->Props.cChannels);
3022
3023 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR);
3024 if (RT_SUCCESS(rc))
3025 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
3026 }
3027#endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
3028
3029 } while (0);
3030
3031 LogFlowFuncLeaveRC(rc);
3032 return rc;
3033}
3034
3035/**
3036 * Adds an audio input stream to the device setup using the given configuration.
3037 *
3038 * @returns IPRT status code.
3039 * @param pThis Device state.
3040 * @param pCfg Stream configuration to use for adding a stream.
3041 */
3042static int hdaAddStreamIn(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
3043{
3044 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3045 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3046
3047 AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER);
3048
3049 LogFlowFunc(("Stream=%s, Source=%ld\n", pCfg->szName, pCfg->DestSource.Source));
3050
3051 int rc;
3052
3053 switch (pCfg->DestSource.Source)
3054 {
3055 case PDMAUDIORECSOURCE_LINE:
3056 {
3057 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN);
3058 if (RT_SUCCESS(rc))
3059 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
3060 break;
3061 }
3062#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3063 case PDMAUDIORECSOURCE_MIC:
3064 {
3065 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN);
3066 if (RT_SUCCESS(rc))
3067 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
3068 break;
3069 }
3070#endif
3071 default:
3072 rc = VERR_NOT_SUPPORTED;
3073 break;
3074 }
3075
3076 LogFlowFuncLeaveRC(rc);
3077 return rc;
3078}
3079
3080/**
3081 * Adds an audio stream to the device setup using the given configuration.
3082 *
3083 * @returns IPRT status code.
3084 * @param pThis Device state.
3085 * @param pCfg Stream configuration to use for adding a stream.
3086 */
3087static int hdaAddStream(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
3088{
3089 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3090 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3091
3092 int rc = VINF_SUCCESS;
3093
3094 PHDADRIVER pDrv;
3095 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3096 {
3097 int rc2;
3098
3099 switch (pCfg->enmDir)
3100 {
3101 case PDMAUDIODIR_OUT:
3102 rc2 = hdaAddStreamOut(pThis, pCfg);
3103 break;
3104
3105 case PDMAUDIODIR_IN:
3106 rc2 = hdaAddStreamIn(pThis, pCfg);
3107 break;
3108
3109 default:
3110 rc2 = VERR_NOT_SUPPORTED;
3111 AssertFailed();
3112 break;
3113 }
3114
3115 if ( RT_FAILURE(rc2)
3116 && (pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY)) /* We only care about primary drivers here, the rest may fail. */
3117 {
3118 if (RT_SUCCESS(rc))
3119 rc = rc2;
3120 /* Keep going. */
3121 }
3122 }
3123
3124 return rc;
3125}
3126#endif /* IN_RING3 */
3127
3128static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3129{
3130#ifdef IN_RING3
3131 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FMT, iReg));
3132 if (!pStream)
3133 {
3134 LogFunc(("[SD%RU8]: Warning: Changing SDFMT on non-attached stream (0x%x)\n",
3135 HDA_SD_NUM_FROM_REG(pThis, FMT, iReg), u32Value));
3136 return hdaRegWriteU16(pThis, iReg, u32Value);
3137 }
3138
3139 /* Write the wanted stream format into the register in any case.
3140 *
3141 * This is important for e.g. MacOS guests, as those try to initialize streams which are not reported
3142 * by the device emulation (wants 4 channels, only have 2 channels at the moment).
3143 *
3144 * When ignoring those (invalid) formats, this leads to MacOS thinking that the device is malfunctioning
3145 * and therefore disabling the device completely. */
3146 int rc = hdaRegWriteU16(pThis, iReg, u32Value);
3147 AssertRC(rc);
3148
3149 rc = hdaStreamInit(pThis, pStream, pStream->u8SD);
3150 if (RT_SUCCESS(rc))
3151 {
3152 /* Add the stream to the device setup. */
3153 rc = hdaAddStream(pThis, &pStream->State.strmCfg);
3154# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
3155 if (RT_SUCCESS(rc))
3156 rc = hdaStreamAsyncIOCreate(pThis, pStream);
3157# endif
3158 }
3159 return VINF_SUCCESS; /* Never return failure. */
3160#else /* !IN_RING3 */
3161 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
3162 return VINF_IOM_R3_MMIO_WRITE;
3163#endif
3164}
3165
3166/* Note: Will be called for both, BDPL and BDPU, registers. */
3167DECLINLINE(int) hdaRegWriteSDBDPX(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value, uint8_t uSD)
3168{
3169#ifdef IN_RING3
3170 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
3171 AssertRC(rc2);
3172
3173 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
3174 if (!pStream)
3175 return VINF_SUCCESS;
3176
3177 /* Update BDL base. */
3178 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
3179 HDA_STREAM_REG(pThis, BDPU, uSD));
3180
3181# ifdef HDA_USE_DMA_ACCESS_HANDLER
3182 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
3183 {
3184 /* Try registering the DMA handlers.
3185 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
3186 if (hdaStreamRegisterDMAHandlers(pThis, pStream))
3187 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
3188 }
3189# endif
3190
3191 LogFlowFunc(("[SD%RU8]: BDLBase=0x%x\n", pStream->u8SD, pStream->u64BDLBase));
3192
3193 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
3194#else /* !IN_RING3 */
3195 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value); RT_NOREF_PV(uSD);
3196 return VINF_IOM_R3_MMIO_WRITE;
3197#endif /* IN_RING3 */
3198}
3199
3200static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3201{
3202 return hdaRegWriteSDBDPX(pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPL, iReg));
3203}
3204
3205static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3206{
3207 return hdaRegWriteSDBDPX(pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPU, iReg));
3208}
3209
3210static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
3211{
3212 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
3213 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
3214 || (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
3215 {
3216 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
3217 }
3218
3219 return hdaRegReadU32(pThis, iReg, pu32Value);
3220}
3221
3222static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3223{
3224 RT_NOREF_PV(iReg);
3225
3226 /*
3227 * If the guest set the ICB bit of IRS register, HDA should process the verb in IC register,
3228 * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
3229 */
3230 if ( (u32Value & HDA_IRS_ICB)
3231 && !(HDA_REG(pThis, IRS) & HDA_IRS_ICB))
3232 {
3233#ifdef IN_RING3
3234 uint32_t uCmd = HDA_REG(pThis, IC);
3235
3236 if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP))
3237 {
3238 /*
3239 * 3.4.3: Defines behavior of immediate Command status register.
3240 */
3241 LogRel(("HDA: Guest attempted process immediate verb (%x) with active CORB\n", uCmd));
3242 return VINF_SUCCESS;
3243 }
3244
3245 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
3246
3247 uint64_t uResp;
3248 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec,
3249 HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
3250 if (RT_FAILURE(rc2))
3251 LogFunc(("Codec lookup failed with rc2=%Rrc\n", rc2));
3252
3253 HDA_REG(pThis, IR) = (uint32_t)uResp; /** @todo r=andy Do we need a 64-bit response? */
3254 HDA_REG(pThis, IRS) = HDA_IRS_IRV; /* result is ready */
3255 /** @todo r=michaln We just set the IRS value, why are we clearing unset bits? */
3256 HDA_REG(pThis, IRS) &= ~HDA_IRS_ICB; /* busy is clear */
3257 return VINF_SUCCESS;
3258#else /* !IN_RING3 */
3259 return VINF_IOM_R3_MMIO_WRITE;
3260#endif /* !IN_RING3 */
3261 }
3262
3263 /*
3264 * Once the guest read the response, it should clear the IRV bit of the IRS register.
3265 */
3266 HDA_REG(pThis, IRS) &= ~(u32Value & HDA_IRS_IRV);
3267 return VINF_SUCCESS;
3268}
3269
3270static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3271{
3272 RT_NOREF_PV(iReg);
3273
3274 if (u32Value & HDA_RIRBWP_RST)
3275 HDA_REG(pThis, RIRBWP) = 0;
3276
3277 /* The remaining bits are O, see 6.2.22. */
3278 return VINF_SUCCESS;
3279}
3280
3281static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3282{
3283 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
3284 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
3285 if (RT_FAILURE(rc))
3286 AssertRCReturn(rc, rc);
3287
3288 switch(iReg)
3289 {
3290 case HDA_REG_CORBLBASE:
3291 pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
3292 pThis->u64CORBBase |= pThis->au32Regs[iRegMem];
3293 break;
3294 case HDA_REG_CORBUBASE:
3295 pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
3296 pThis->u64CORBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
3297 break;
3298 case HDA_REG_RIRBLBASE:
3299 pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
3300 pThis->u64RIRBBase |= pThis->au32Regs[iRegMem];
3301 break;
3302 case HDA_REG_RIRBUBASE:
3303 pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
3304 pThis->u64RIRBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
3305 break;
3306 case HDA_REG_DPLBASE:
3307 {
3308 pThis->u64DPBase = pThis->au32Regs[iRegMem] & DPBASE_ADDR_MASK;
3309 Assert(pThis->u64DPBase % 128 == 0); /* Must be 128-byte aligned. */
3310
3311 /* Also make sure to handle the DMA position enable bit. */
3312 pThis->fDMAPosition = pThis->au32Regs[iRegMem] & RT_BIT_32(0);
3313 LogRel(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));
3314 break;
3315 }
3316 case HDA_REG_DPUBASE:
3317 pThis->u64DPBase = RT_MAKE_U64(RT_LO_U32(pThis->u64DPBase) & DPBASE_ADDR_MASK, pThis->au32Regs[iRegMem]);
3318 break;
3319 default:
3320 AssertMsgFailed(("Invalid index\n"));
3321 break;
3322 }
3323
3324 LogFunc(("CORB base:%llx RIRB base: %llx DP base: %llx\n",
3325 pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
3326 return rc;
3327}
3328
3329static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3330{
3331 RT_NOREF_PV(iReg);
3332
3333 uint8_t v = HDA_REG(pThis, RIRBSTS);
3334 HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
3335
3336#ifndef DEBUG
3337 return hdaProcessInterrupt(pThis);
3338#else
3339 return hdaProcessInterrupt(pThis, __FUNCTION__);
3340#endif
3341}
3342
3343#ifdef IN_RING3
3344
3345# ifdef HDA_USE_DMA_ACCESS_HANDLER
3346/**
3347 * Registers access handlers for a stream's BDLE DMA accesses.
3348 *
3349 * @returns true if registration was successful, false if not.
3350 * @param pThis HDA state.
3351 * @param pStream HDA stream to register BDLE access handlers for.
3352 */
3353static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
3354{
3355 /* At least LVI and the BDL base must be set. */
3356 if ( !pStream->u16LVI
3357 || !pStream->u64BDLBase)
3358 {
3359 return false;
3360 }
3361
3362 hdaStreamUnregisterDMAHandlers(pThis, pStream);
3363
3364 LogFunc(("Registering ...\n"));
3365
3366 int rc = VINF_SUCCESS;
3367
3368 /*
3369 * Create BDLE ranges.
3370 */
3371
3372 struct BDLERANGE
3373 {
3374 RTGCPHYS uAddr;
3375 uint32_t uSize;
3376 } arrRanges[16]; /** @todo Use a define. */
3377
3378 size_t cRanges = 0;
3379
3380 for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)
3381 {
3382 HDABDLE BDLE;
3383 rc = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);
3384 if (RT_FAILURE(rc))
3385 break;
3386
3387 bool fAddRange = true;
3388 BDLERANGE *pRange;
3389
3390 if (cRanges)
3391 {
3392 pRange = &arrRanges[cRanges - 1];
3393
3394 /* Is the current range a direct neighbor of the current BLDE? */
3395 if ((pRange->uAddr + pRange->uSize) == BDLE.Desc.u64BufAdr)
3396 {
3397 /* Expand the current range by the current BDLE's size. */
3398 pRange->uSize += BDLE.Desc.u32BufSize;
3399
3400 /* Adding a new range in this case is not needed anymore. */
3401 fAddRange = false;
3402
3403 LogFunc(("Expanding range %zu by %RU32 (%RU32 total now)\n", cRanges - 1, BDLE.Desc.u32BufSize, pRange->uSize));
3404 }
3405 }
3406
3407 /* Do we need to add a new range? */
3408 if ( fAddRange
3409 && cRanges < RT_ELEMENTS(arrRanges))
3410 {
3411 pRange = &arrRanges[cRanges];
3412
3413 pRange->uAddr = BDLE.Desc.u64BufAdr;
3414 pRange->uSize = BDLE.Desc.u32BufSize;
3415
3416 LogFunc(("Adding range %zu - 0x%x (%RU32)\n", cRanges, pRange->uAddr, pRange->uSize));
3417
3418 cRanges++;
3419 }
3420 }
3421
3422 LogFunc(("%zu ranges total\n", cRanges));
3423
3424 /*
3425 * Register all ranges as DMA access handlers.
3426 */
3427
3428 for (size_t i = 0; i < cRanges; i++)
3429 {
3430 BDLERANGE *pRange = &arrRanges[i];
3431
3432 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)RTMemAllocZ(sizeof(HDADMAACCESSHANDLER));
3433 if (!pHandler)
3434 {
3435 rc = VERR_NO_MEMORY;
3436 break;
3437 }
3438
3439 RTListAppend(&pStream->State.lstDMAHandlers, &pHandler->Node);
3440
3441 pHandler->pStream = pStream; /* Save a back reference to the owner. */
3442
3443 char szDesc[32];
3444 RTStrPrintf(szDesc, sizeof(szDesc), "HDA[SD%RU8 - RANGE%02zu]", pStream->u8SD, i);
3445
3446 int rc2 = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
3447 hdaDMAAccessHandler,
3448 NULL, NULL, NULL,
3449 NULL, NULL, NULL,
3450 szDesc, &pHandler->hAccessHandlerType);
3451 AssertRCBreak(rc2);
3452
3453 pHandler->BDLEAddr = pRange->uAddr;
3454 pHandler->BDLESize = pRange->uSize;
3455
3456 /* Get first and last pages of the BDLE range. */
3457 RTGCPHYS pgFirst = pRange->uAddr & ~PAGE_OFFSET_MASK;
3458 RTGCPHYS pgLast = RT_ALIGN(pgFirst + pRange->uSize, PAGE_SIZE);
3459
3460 /* Calculate the region size (in pages). */
3461 RTGCPHYS regionSize = RT_ALIGN(pgLast - pgFirst, PAGE_SIZE);
3462
3463 pHandler->GCPhysFirst = pgFirst;
3464 pHandler->GCPhysLast = pHandler->GCPhysFirst + (regionSize - 1);
3465
3466 LogFunc(("\tRegistering region '%s': 0x%x - 0x%x (region size: %zu)\n",
3467 szDesc, pHandler->GCPhysFirst, pHandler->GCPhysLast, regionSize));
3468 LogFunc(("\tBDLE @ 0x%x - 0x%x (%RU32)\n",
3469 pHandler->BDLEAddr, pHandler->BDLEAddr + pHandler->BDLESize, pHandler->BDLESize));
3470
3471 rc2 = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
3472 pHandler->GCPhysFirst, pHandler->GCPhysLast,
3473 pHandler->hAccessHandlerType, pHandler, NIL_RTR0PTR, NIL_RTRCPTR,
3474 szDesc);
3475 AssertRCBreak(rc2);
3476
3477 pHandler->fRegistered = true;
3478 }
3479
3480 LogFunc(("Registration ended with rc=%Rrc\n", rc));
3481
3482 return RT_SUCCESS(rc);
3483}
3484
3485/**
3486 * Unregisters access handlers of a stream's BDLEs.
3487 *
3488 * @param pThis HDA state.
3489 * @param pStream HDA stream to unregister BDLE access handlers for.
3490 */
3491static void hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
3492{
3493 LogFunc(("\n"));
3494
3495 PHDADMAACCESSHANDLER pHandler, pHandlerNext;
3496 RTListForEachSafe(&pStream->State.lstDMAHandlers, pHandler, pHandlerNext, HDADMAACCESSHANDLER, Node)
3497 {
3498 if (!pHandler->fRegistered) /* Handler not registered? Skip. */
3499 continue;
3500
3501 LogFunc(("Unregistering 0x%x - 0x%x (%zu)\n",
3502 pHandler->GCPhysFirst, pHandler->GCPhysLast, pHandler->GCPhysLast - pHandler->GCPhysFirst));
3503
3504 int rc2 = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3),
3505 pHandler->GCPhysFirst);
3506 AssertRC(rc2);
3507
3508 RTListNodeRemove(&pHandler->Node);
3509
3510 RTMemFree(pHandler);
3511 pHandler = NULL;
3512 }
3513
3514 Assert(RTListIsEmpty(&pStream->State.lstDMAHandlers));
3515}
3516# endif /* HDA_USE_DMA_ACCESS_HANDLER */
3517
3518#ifdef LOG_ENABLED
3519static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
3520{
3521 LogFlowFunc(("BDLEs @ 0x%x (%RU16):\n", u64BDLBase, cBDLE));
3522 if (!u64BDLBase)
3523 return;
3524
3525 uint32_t cbBDLE = 0;
3526 for (uint16_t i = 0; i < cBDLE; i++)
3527 {
3528 HDABDLEDESC bd;
3529 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
3530
3531 LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
3532 i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC));
3533
3534 cbBDLE += bd.u32BufSize;
3535 }
3536
3537 LogFlowFunc(("Total: %RU32 bytes\n", cbBDLE));
3538
3539 if (!pThis->u64DPBase) /* No DMA base given? Bail out. */
3540 return;
3541
3542 LogFlowFunc(("DMA counters:\n"));
3543
3544 for (int i = 0; i < cBDLE; i++)
3545 {
3546 uint32_t uDMACnt;
3547 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
3548 &uDMACnt, sizeof(uDMACnt));
3549
3550 LogFlowFunc(("\t#%03d DMA @ 0x%x\n", i , uDMACnt));
3551 }
3552}
3553#endif /* LOG_ENABLED */
3554
3555/**
3556 * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.
3557 *
3558 * @param pThis Pointer to HDA state.
3559 * @param pBDLE Where to store the fetched result.
3560 * @param u64BaseDMA Address base of DMA engine to use.
3561 * @param u16Entry BDLE entry to fetch.
3562 */
3563static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)
3564{
3565 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3566 AssertPtrReturn(pBDLE, VERR_INVALID_POINTER);
3567 AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
3568
3569 if (!u64BaseDMA)
3570 {
3571 LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));
3572 return VERR_NOT_FOUND;
3573 }
3574 /** @todo Compare u16Entry with LVI. */
3575
3576 int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)),
3577 &pBDLE->Desc, sizeof(pBDLE->Desc));
3578
3579 if (RT_SUCCESS(rc))
3580 {
3581 /* Reset internal state. */
3582 RT_ZERO(pBDLE->State);
3583 pBDLE->State.u32BDLIndex = u16Entry;
3584 }
3585
3586 Log3Func(("Entry #%d @ 0x%x: %R[bdle], rc=%Rrc\n", u16Entry, u64BaseDMA + (u16Entry * sizeof(HDABDLEDESC)), pBDLE, rc));
3587
3588
3589 return VINF_SUCCESS;
3590}
3591
3592/**
3593 * Returns the number of outstanding stream data bytes which need to be processed
3594 * by the DMA engine assigned to this stream.
3595 *
3596 * @return Number of bytes for the DMA engine to process.
3597 */
3598DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream)
3599{
3600 AssertPtrReturn(pThis, 0);
3601 AssertPtrReturn(pStream, 0);
3602
3603 if (!RT_BOOL(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
3604 {
3605 AssertFailed(); /* Should never happen. */
3606 return 0;
3607 }
3608
3609 /* Determine how much for the current BDL entry we have left to transfer. */
3610 PHDABDLE pBDLE = &pStream->State.BDLE;
3611 const uint32_t cbBDLE = RT_MIN(pBDLE->Desc.u32BufSize, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
3612
3613 /* Determine how much we (still) can stuff in the stream's internal FIFO. */
3614 const uint32_t cbCircBuf = (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
3615
3616 uint32_t cbToTransfer = cbBDLE;
3617
3618 /* Make sure that we don't transfer more than our FIFO can hold at the moment.
3619 * As the host sets the overall pace it needs to process some of the FIFO data first before
3620 * we can issue a new DMA data transfer. */
3621 if (cbToTransfer > cbCircBuf)
3622 cbToTransfer = cbCircBuf;
3623
3624 Log3Func(("[SD%RU8] LPIB=%RU32 CBL=%RU32 cbCircBuf=%RU32, -> cbToTransfer=%RU32 %R[bdle]\n", pStream->u8SD,
3625 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u32CBL, cbCircBuf, cbToTransfer, pBDLE));
3626 return cbToTransfer;
3627}
3628
3629
3630DECLINLINE(void) hdaStreamTransferInc(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)
3631{
3632 AssertPtrReturnVoid(pThis);
3633 AssertPtrReturnVoid(pStream);
3634
3635 if (!cbInc)
3636 return;
3637
3638 const uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
3639
3640 Log3Func(("[SD%RU8] %RU32 + %RU32 -> %RU32, CBL=%RU32\n",
3641 pStream->u8SD, u32LPIB, cbInc, u32LPIB + cbInc, pStream->u32CBL));
3642
3643 hdaStreamUpdateLPIB(pThis, pStream, u32LPIB + cbInc);
3644}
3645
3646
3647/**
3648 * Retrieves a corresponding sink for a given mixer control.
3649 * Returns NULL if no sink is found.
3650 *
3651 * @return PHDAMIXERSINK
3652 * @param pThis HDA state.
3653 * @param enmMixerCtl Mixer control to get the corresponding sink for.
3654 */
3655static PHDAMIXERSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
3656{
3657 PHDAMIXERSINK pSink;
3658
3659 switch (enmMixerCtl)
3660 {
3661 case PDMAUDIOMIXERCTL_VOLUME_MASTER:
3662 /* Fall through is intentional. */
3663 case PDMAUDIOMIXERCTL_FRONT:
3664 pSink = &pThis->SinkFront;
3665 break;
3666#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3667 case PDMAUDIOMIXERCTL_CENTER_LFE:
3668 pSink = &pThis->SinkCenterLFE;
3669 break;
3670 case PDMAUDIOMIXERCTL_REAR:
3671 pSink = &pThis->SinkRear;
3672 break;
3673#endif
3674 case PDMAUDIOMIXERCTL_LINE_IN:
3675 pSink = &pThis->SinkLineIn;
3676 break;
3677#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3678 case PDMAUDIOMIXERCTL_MIC_IN:
3679 pSink = &pThis->SinkMicIn;
3680 break;
3681#endif
3682 default:
3683 pSink = NULL;
3684 AssertMsgFailed(("Unhandled mixer control\n"));
3685 break;
3686 }
3687
3688 return pSink;
3689}
3690
3691static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PHDAMIXERSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
3692{
3693 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3694 AssertPtrReturn(pSink, VERR_INVALID_POINTER);
3695 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3696
3697 LogFunc(("Sink=%s, Stream=%s\n", pSink->pMixSink->pszName, pCfg->szName));
3698
3699 if (!DrvAudioHlpStreamCfgIsValid(pCfg))
3700 {
3701 LogRel(("HDA: Invalid stream configuration used for sink #%RU8: %RU8 bit, %RU8 channel(s) @ %RU32Hz\n",
3702 pSink->uSD, pCfg->Props.cBits, pCfg->Props.cChannels, pCfg->Props.uHz));
3703
3704 AssertFailed(); /* Should not happen. */
3705 return VERR_INVALID_PARAMETER;
3706 }
3707
3708 int rc = AudioMixerSinkSetFormat(pSink->pMixSink, &pCfg->Props);
3709 if (RT_FAILURE(rc))
3710 return rc;
3711
3712 PHDADRIVER pDrv;
3713 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3714 {
3715 int rc2 = VINF_SUCCESS;
3716 PHDADRIVERSTREAM pDrvStream = NULL;
3717
3718 PPDMAUDIOSTREAMCFG pStreamCfg = DrvAudioHlpStreamCfgDup(pCfg);
3719 if (!pStreamCfg)
3720 {
3721 rc = VERR_NO_MEMORY;
3722 break;
3723 }
3724
3725 /* Include the driver's LUN in the stream name for easier identification. */
3726 RTStrPrintf(pStreamCfg->szName, RT_ELEMENTS(pStreamCfg->szName), "[LUN#%RU8] %s", pDrv->uLUN, pCfg->szName);
3727
3728 if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
3729 {
3730 LogFunc(("enmRecSource=%d\n", pStreamCfg->DestSource.Source));
3731
3732 switch (pStreamCfg->DestSource.Source)
3733 {
3734 case PDMAUDIORECSOURCE_LINE:
3735 pDrvStream = &pDrv->LineIn;
3736 break;
3737#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3738 case PDMAUDIORECSOURCE_MIC:
3739 pDrvStream = &pDrv->MicIn;
3740 break;
3741#endif
3742 default:
3743 rc2 = VERR_NOT_SUPPORTED;
3744 break;
3745 }
3746 }
3747 else if (pStreamCfg->enmDir == PDMAUDIODIR_OUT)
3748 {
3749 LogFunc(("enmPlaybackDest=%d\n", pStreamCfg->DestSource.Dest));
3750
3751 switch (pStreamCfg->DestSource.Dest)
3752 {
3753 case PDMAUDIOPLAYBACKDEST_FRONT:
3754 pDrvStream = &pDrv->Front;
3755 break;
3756#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3757 case PDMAUDIOPLAYBACKDEST_CENTER_LFE:
3758 pDrvStream = &pDrv->CenterLFE;
3759 break;
3760 case PDMAUDIOPLAYBACKDEST_REAR:
3761 pDrvStream = &pDrv->Rear;
3762 break;
3763#endif
3764 default:
3765 rc2 = VERR_NOT_SUPPORTED;
3766 break;
3767 }
3768 }
3769 else
3770 rc2 = VERR_NOT_SUPPORTED;
3771
3772 if (RT_SUCCESS(rc2))
3773 {
3774 AssertPtr(pDrvStream);
3775
3776 AudioMixerSinkRemoveStream(pSink->pMixSink, pDrvStream->pMixStrm);
3777
3778 AudioMixerStreamDestroy(pDrvStream->pMixStrm);
3779 pDrvStream->pMixStrm = NULL;
3780
3781 PAUDMIXSTREAM pMixStrm;
3782 rc2 = AudioMixerSinkCreateStream(pSink->pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, &pMixStrm);
3783 if (RT_SUCCESS(rc2))
3784 {
3785 rc2 = AudioMixerSinkAddStream(pSink->pMixSink, pMixStrm);
3786 LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName , rc2));
3787 }
3788
3789 if (RT_SUCCESS(rc2))
3790 pDrvStream->pMixStrm = pMixStrm;
3791
3792 /* If creating a stream fails, be forgiving and continue -- don't pass rc2 to rc here. */
3793 }
3794
3795 if (pStreamCfg)
3796 {
3797 RTMemFree(pStreamCfg);
3798 pStreamCfg = NULL;
3799 }
3800 }
3801
3802 LogFlowFuncLeaveRC(rc);
3803 return rc;
3804}
3805
3806/**
3807 * Adds a new audio stream to a specific mixer control.
3808 * Depending on the mixer control the stream then gets assigned to one of the internal
3809 * mixer sinks, which in turn then handle the mixing of all connected streams to that sink.
3810 *
3811 * @return IPRT status code.
3812 * @param pThis HDA state.
3813 * @param enmMixerCtl Mixer control to assign new stream to.
3814 * @param pCfg Stream configuration for the new stream.
3815 */
3816static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
3817{
3818 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3819 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3820
3821 int rc;
3822
3823 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3824 if (pSink)
3825 {
3826 rc = hdaMixerAddStream(pThis, pSink, pCfg);
3827
3828 AssertPtr(pSink->pMixSink);
3829 LogFlowFunc(("Sink=%s, enmMixerCtl=%d\n", pSink->pMixSink->pszName, enmMixerCtl));
3830 }
3831 else
3832 rc = VERR_NOT_FOUND;
3833
3834 LogFlowFuncLeaveRC(rc);
3835 return rc;
3836}
3837
3838/**
3839 * Removes a specified mixer control from the HDA's mixer.
3840 *
3841 * @return IPRT status code.
3842 * @param pThis HDA state.
3843 * @param enmMixerCtl Mixer control to remove.
3844 *
3845 * @remarks Can be called as a callback by the HDA codec.
3846 */
3847static DECLCALLBACK(int) hdaMixerRemoveStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
3848{
3849 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3850
3851 int rc;
3852
3853 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3854 if (pSink)
3855 {
3856 PHDADRIVER pDrv;
3857 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3858 {
3859 PAUDMIXSTREAM pMixStream = NULL;
3860 switch (enmMixerCtl)
3861 {
3862 /*
3863 * Input.
3864 */
3865 case PDMAUDIOMIXERCTL_LINE_IN:
3866 pMixStream = pDrv->LineIn.pMixStrm;
3867 pDrv->LineIn.pMixStrm = NULL;
3868 break;
3869#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3870 case PDMAUDIOMIXERCTL_MIC_IN:
3871 pMixStream = pDrv->MicIn.pMixStrm;
3872 pDrv->MicIn.pMixStrm = NULL;
3873 break;
3874#endif
3875 /*
3876 * Output.
3877 */
3878 case PDMAUDIOMIXERCTL_FRONT:
3879 pMixStream = pDrv->Front.pMixStrm;
3880 pDrv->Front.pMixStrm = NULL;
3881 break;
3882#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3883 case PDMAUDIOMIXERCTL_CENTER_LFE:
3884 pMixStream = pDrv->CenterLFE.pMixStrm;
3885 pDrv->CenterLFE.pMixStrm = NULL;
3886 break;
3887 case PDMAUDIOMIXERCTL_REAR:
3888 pMixStream = pDrv->Rear.pMixStrm;
3889 pDrv->Rear.pMixStrm = NULL;
3890 break;
3891#endif
3892 default:
3893 AssertMsgFailed(("Mixer control %d not implemented\n", enmMixerCtl));
3894 break;
3895 }
3896
3897 if (pMixStream)
3898 {
3899 AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
3900 AudioMixerStreamDestroy(pMixStream);
3901
3902 pMixStream = NULL;
3903 }
3904 }
3905
3906 AudioMixerSinkRemoveAllStreams(pSink->pMixSink);
3907 rc = VINF_SUCCESS;
3908 }
3909 else
3910 rc = VERR_NOT_FOUND;
3911
3912 LogFlowFunc(("enmMixerCtl=%d, rc=%Rrc\n", enmMixerCtl, rc));
3913 return rc;
3914}
3915
3916/**
3917 * Sets a SDn stream number and channel to a particular mixer control.
3918 *
3919 * @returns IPRT status code.
3920 * @param pThis HDA State.
3921 * @param enmMixerCtl Mixer control to set SD stream number and channel for.
3922 * @param uSD SD stream number (number + 1) to set. Set to 0 for unassign.
3923 * @param uChannel Channel to set. Only valid if a valid SD stream number is specified.
3924 *
3925 * @remarks Can be called as a callback by the HDA codec.
3926 */
3927static DECLCALLBACK(int) hdaMixerSetStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
3928{
3929 LogFlowFunc(("enmMixerCtl=%RU32, uSD=%RU8, uChannel=%RU8\n", enmMixerCtl, uSD, uChannel));
3930
3931 if (uSD == 0) /* Stream number 0 is reserved. */
3932 {
3933 LogFlowFunc(("Invalid SDn (%RU8) number for mixer control %d, ignoring\n", uSD, enmMixerCtl));
3934 return VINF_SUCCESS;
3935 }
3936 /* uChannel is optional. */
3937
3938 /* SDn0 starts as 1. */
3939 Assert(uSD);
3940 uSD--;
3941
3942 int rc;
3943
3944 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3945 if (pSink)
3946 {
3947 if ( (uSD < HDA_MAX_SDI)
3948 && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT)
3949 {
3950 uSD += HDA_MAX_SDI;
3951 }
3952
3953 LogFlowFunc(("%s: Setting to stream ID=%RU8, channel=%RU8, enmMixerCtl=%RU32\n",
3954 pSink->pMixSink->pszName, uSD, uChannel, enmMixerCtl));
3955
3956 Assert(uSD < HDA_MAX_STREAMS);
3957
3958 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
3959 if (pStream)
3960 {
3961 hdaStreamLock(pStream);
3962
3963 pSink->uSD = uSD;
3964 pSink->uChannel = uChannel;
3965 pStream->pMixSink = pSink;
3966
3967 hdaStreamUnlock(pStream);
3968
3969 rc = VINF_SUCCESS;
3970 }
3971 else
3972 {
3973 LogRel(("HDA: Guest wanted to assign invalid stream ID=%RU8 (channel %RU8) to mixer control %RU32, skipping\n",
3974 uSD, uChannel, enmMixerCtl));
3975 rc = VERR_INVALID_PARAMETER;
3976 }
3977 }
3978 else
3979 rc = VERR_NOT_FOUND;
3980
3981 LogFlowFuncLeaveRC(rc);
3982 return rc;
3983}
3984
3985/**
3986 * Sets the volume of a specified mixer control.
3987 *
3988 * @return IPRT status code.
3989 * @param pThis HDA State.
3990 * @param enmMixerCtl Mixer control to set volume for.
3991 * @param pVol Pointer to volume data to set.
3992 *
3993 * @remarks Can be called as a callback by the HDA codec.
3994 */
3995static DECLCALLBACK(int) hdaMixerSetVolume(PHDASTATE pThis,
3996 PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)
3997{
3998 int rc;
3999
4000 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
4001 if ( pSink
4002 && pSink->pMixSink)
4003 {
4004 LogRel2(("HDA: Setting volume for mixer sink '%s' to %RU8/%RU8 (%s)\n",
4005 pSink->pMixSink->pszName, pVol->uLeft, pVol->uRight, pVol->fMuted ? "Muted" : "Unmuted"));
4006
4007 /* Set the volume.
4008 * We assume that the codec already converted it to the correct range. */
4009 rc = AudioMixerSinkSetVolume(pSink->pMixSink, pVol);
4010 }
4011 else
4012 rc = VERR_NOT_FOUND;
4013
4014 LogFlowFuncLeaveRC(rc);
4015 return rc;
4016}
4017
4018#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
4019/**
4020 * Starts the internal audio device timer (if not started yet).
4021 *
4022 * @param pThis HDA state.
4023 */
4024static void hdaTimerMaybeStart(PHDASTATE pThis)
4025{
4026 LogFlowFuncEnter();
4027
4028 if (!pThis->pTimer)
4029 return;
4030
4031 pThis->cStreamsActive++;
4032
4033 /* Only start the timer at the first active stream. */
4034 if (pThis->cStreamsActive == 1)
4035 {
4036 LogRel2(("HDA: Starting transfers\n"));
4037
4038 /* Set timer flag. */
4039 ASMAtomicXchgBool(&pThis->fTimerActive, true);
4040
4041 /* Update current time timestamp. */
4042 pThis->tsTimerExpire = TMTimerGet(pThis->pTimer) + pThis->cTimerTicks;
4043
4044 /* Start transfers. */
4045 hdaTimerMain(pThis);
4046 }
4047}
4048
4049/**
4050 * Stops the internal audio device timer.
4051 *
4052 * @param pThis HDA state.
4053 */
4054static void hdaTimerStop(PHDASTATE pThis)
4055{
4056 LogFlowFuncEnter();
4057
4058 /* Set timer flag. */
4059 ASMAtomicXchgBool(&pThis->fTimerActive, false);
4060
4061 /*
4062 * Stop the timer, if any.
4063 */
4064 if ( pThis->pTimer
4065 && TMTimerIsActive(pThis->pTimer))
4066 {
4067 int rc2 = TMTimerStop(pThis->pTimer);
4068 AssertRC(rc2);
4069 }
4070}
4071
4072/**
4073 * Decreases the active HDA streams count by one and
4074 * then checks if the internal audio device timer can be
4075 * stopped.
4076 *
4077 * @param pThis HDA state.
4078 */
4079static void hdaTimerMaybeStop(PHDASTATE pThis)
4080{
4081 LogFlowFuncEnter();
4082
4083 if (!pThis->pTimer)
4084 return;
4085
4086 if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
4087 {
4088 pThis->cStreamsActive--;
4089
4090 if (pThis->cStreamsActive == 0)
4091 hdaTimerStop(pThis);
4092 }
4093}
4094
4095/**
4096 * Main routine for the device timer.
4097 *
4098 * @returns IPRT status code.
4099 * @param pThis HDA state.
4100 */
4101static void hdaTimerMain(PHDASTATE pThis)
4102{
4103 AssertPtrReturnVoid(pThis);
4104
4105 STAM_PROFILE_START(&pThis->StatTimer, a);
4106
4107 /* Flag indicating whether to kick the timer again for a
4108 * new data processing round. */
4109 bool fKickTimer = false;
4110
4111 hdaDoTransfers(pThis);
4112
4113 /* Do we need to kick the timer again? */
4114 if ( AudioMixerSinkIsActive(pThis->SinkFront.pMixSink)
4115#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4116 || AudioMixerSinkIsActive(pThis->SinkCenterLFE.pMixSink)
4117 || AudioMixerSinkIsActive(pThis->SinkRear.pMixSink)
4118#endif
4119 || AudioMixerSinkIsActive(pThis->SinkLineIn.pMixSink)
4120#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4121 || AudioMixerSinkIsActive(pThis->SinkMicIn.pMixSink)
4122#endif
4123 )
4124 {
4125 fKickTimer = true;
4126 }
4127
4128 if ( ASMAtomicReadBool(&pThis->fTimerActive)
4129 || fKickTimer)
4130 {
4131 /* Kick the timer again. */
4132 pThis->tsTimerExpire += pThis->cTimerTicks;
4133 TMTimerSet(pThis->pTimer, pThis->tsTimerExpire);
4134 }
4135 else
4136 LogRel2(("HDA: Stopping transfers\n"));
4137
4138 STAM_PROFILE_STOP(&pThis->StatTimer, a);
4139}
4140
4141#ifdef HDA_USE_DMA_ACCESS_HANDLER
4142/**
4143 * HC access handler for the FIFO.
4144 *
4145 * @returns VINF_SUCCESS if the handler have carried out the operation.
4146 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
4147 * @param pVM VM Handle.
4148 * @param pVCpu The cross context CPU structure for the calling EMT.
4149 * @param GCPhys The physical address the guest is writing to.
4150 * @param pvPhys The HC mapping of that address.
4151 * @param pvBuf What the guest is reading/writing.
4152 * @param cbBuf How much it's reading/writing.
4153 * @param enmAccessType The access type.
4154 * @param enmOrigin Who is making the access.
4155 * @param pvUser User argument.
4156 */
4157static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
4158 void *pvBuf, size_t cbBuf,
4159 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
4160{
4161 RT_NOREF(pVM, pVCpu, pvPhys, pvBuf, enmOrigin);
4162
4163 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)pvUser;
4164 AssertPtr(pHandler);
4165
4166 PHDASTREAM pStream = pHandler->pStream;
4167 AssertPtr(pStream);
4168
4169 Assert(GCPhys >= pHandler->GCPhysFirst);
4170 Assert(GCPhys <= pHandler->GCPhysLast);
4171 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
4172
4173 /* Not within BDLE range? Bail out. */
4174 if ( (GCPhys < pHandler->BDLEAddr)
4175 || (GCPhys + cbBuf > pHandler->BDLEAddr + pHandler->BDLESize))
4176 {
4177 return VINF_PGM_HANDLER_DO_DEFAULT;
4178 }
4179
4180 switch(enmAccessType)
4181 {
4182 case PGMACCESSTYPE_WRITE:
4183 {
4184# ifdef DEBUG
4185 PHDASTREAMDBGINFO pStreamDbg = &pStream->Dbg;
4186
4187 const uint64_t tsNowNs = RTTimeNanoTS();
4188 const uint32_t tsElapsedMs = (tsNowNs - pStreamDbg->tsWriteSlotBegin) / 1000 / 1000;
4189
4190 uint64_t cWritesHz = ASMAtomicReadU64(&pStreamDbg->cWritesHz);
4191 uint64_t cbWrittenHz = ASMAtomicReadU64(&pStreamDbg->cbWrittenHz);
4192
4193 if (tsElapsedMs >= (1000 / HDA_TIMER_HZ))
4194 {
4195 LogFunc(("[SD%RU8] %RU32ms elapsed, cbWritten=%RU64, cWritten=%RU64 -- %RU32 bytes on average per time slot (%zums)\n",
4196 pStream->u8SD, tsElapsedMs, cbWrittenHz, cWritesHz,
4197 ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ));
4198
4199 pStreamDbg->tsWriteSlotBegin = tsNowNs;
4200
4201 cWritesHz = 0;
4202 cbWrittenHz = 0;
4203 }
4204
4205 cWritesHz += 1;
4206 cbWrittenHz += cbBuf;
4207
4208 ASMAtomicIncU64(&pStreamDbg->cWritesTotal);
4209 ASMAtomicAddU64(&pStreamDbg->cbWrittenTotal, cbBuf);
4210
4211 ASMAtomicWriteU64(&pStreamDbg->cWritesHz, cWritesHz);
4212 ASMAtomicWriteU64(&pStreamDbg->cbWrittenHz, cbWrittenHz);
4213
4214 LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n",
4215 pStream->u8SD, cbBuf, GCPhys, GCPhys - pHandler->BDLEAddr));
4216
4217 LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n",
4218 pStream->u8SD, pStreamDbg->cWritesTotal, pStreamDbg->cbWrittenTotal,
4219 ASMDivU64ByU32RetU32(pStreamDbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));
4220# endif
4221
4222# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4223 RTFILE fh;
4224 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessWrite.pcm",
4225 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4226 RTFileWrite(fh, pvBuf, cbBuf, NULL);
4227 RTFileClose(fh);
4228# endif
4229
4230# ifdef HDA_USE_DMA_ACCESS_HANDLER_WRITING
4231 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4232 AssertPtr(pCircBuf);
4233
4234 uint8_t *pbBuf = (uint8_t *)pvBuf;
4235 while (cbBuf)
4236 {
4237 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
4238 void *pvChunk;
4239 size_t cbChunk;
4240 RTCircBufAcquireWriteBlock(pCircBuf, cbBuf, &pvChunk, &cbChunk);
4241
4242 if (cbChunk)
4243 {
4244 memcpy(pvChunk, pbBuf, cbChunk);
4245
4246 pbBuf += cbChunk;
4247 Assert(cbBuf >= cbChunk);
4248 cbBuf -= cbChunk;
4249 }
4250 else
4251 {
4252 //AssertMsg(RTCircBufFree(pCircBuf), ("No more space but still %zu bytes to write\n", cbBuf));
4253 break;
4254 }
4255
4256 LogFunc(("[SD%RU8] cbChunk=%zu\n", pStream->u8SD, cbChunk));
4257
4258 RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
4259 }
4260# endif /* HDA_USE_DMA_ACCESS_HANDLER_WRITING */
4261 break;
4262 }
4263
4264 default:
4265 AssertMsgFailed(("Access type not implemented\n"));
4266 break;
4267 }
4268
4269 return VINF_PGM_HANDLER_DO_DEFAULT;
4270}
4271#endif /* HDA_USE_DMA_ACCESS_HANDLER */
4272
4273/**
4274 * Reads DMA data from a given HDA output stream into its associated FIFO buffer.
4275 *
4276 * @return IPRT status code.
4277 * @param pThis HDA state.
4278 * @param pStream HDA output stream to read DMA data from.
4279 * @param cbToRead How much (in bytes) to read from DMA.
4280 * @param pcbRead Returns read bytes from DMA. Optional.
4281 */
4282static int hdaDMARead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
4283{
4284 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
4285 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4286 /* pcbRead is optional. */
4287
4288 int rc = VINF_SUCCESS;
4289
4290 uint32_t cbReadTotal = 0;
4291
4292 PHDABDLE pBDLE = &pStream->State.BDLE;
4293 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4294 AssertPtr(pCircBuf);
4295
4296#ifdef HDA_DEBUG_SILENCE
4297 uint64_t csSilence = 0;
4298
4299 pStream->Dbg.cSilenceThreshold = 100;
4300 pStream->Dbg.cbSilenceReadMin = _1M;
4301#endif
4302
4303 while (cbToRead)
4304 {
4305 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
4306 void *pvBuf;
4307 size_t cbBuf;
4308 RTCircBufAcquireWriteBlock(pCircBuf, RT_MIN(cbToRead, pStream->u16FIFOS), &pvBuf, &cbBuf);
4309
4310 if (cbBuf)
4311 {
4312 /*
4313 * Read from the current BDLE's DMA buffer.
4314 */
4315 int rc2 = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
4316 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbReadTotal, pvBuf, cbBuf);
4317 AssertRC(rc2);
4318
4319#ifdef HDA_DEBUG_SILENCE
4320 uint16_t *pu16Buf = (uint16_t *)pvBuf;
4321 for (size_t i = 0; i < cbBuf / sizeof(uint16_t); i++)
4322 {
4323 if (*pu16Buf == 0)
4324 {
4325 csSilence++;
4326 }
4327 else
4328 break;
4329 pu16Buf++;
4330 }
4331#endif
4332
4333#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4334 if (cbBuf)
4335 {
4336 RTFILE fh;
4337 rc2 = RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm",
4338 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4339 if (RT_SUCCESS(rc2))
4340 {
4341 RTFileWrite(fh, pvBuf, cbBuf, NULL);
4342 RTFileClose(fh);
4343 }
4344 else
4345 AssertRC(rc2);
4346 }
4347#endif
4348
4349#if 0
4350 pStream->Dbg.cbReadTotal += cbBuf;
4351 const uint64_t cbWritten = ASMAtomicReadU64(&pStream->Dbg.cbWrittenTotal);
4352 Log3Func(("cbRead=%RU64, cbWritten=%RU64 -> %RU64 bytes %s\n",
4353 pStream->Dbg.cbReadTotal, cbWritten,
4354 pStream->Dbg.cbReadTotal >= cbWritten ? pStream->Dbg.cbReadTotal - cbWritten : cbWritten - pStream->Dbg.cbReadTotal,
4355 pStream->Dbg.cbReadTotal > cbWritten ? "too much" : "too little"));
4356#endif
4357
4358#ifdef VBOX_WITH_STATISTICS
4359 STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBuf);
4360#endif
4361 }
4362
4363 RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
4364
4365 if (!cbBuf)
4366 {
4367 rc = VERR_BUFFER_OVERFLOW;
4368 break;
4369 }
4370
4371 cbReadTotal += (uint32_t)cbBuf;
4372 Assert(pBDLE->State.u32BufOff + cbReadTotal <= pBDLE->Desc.u32BufSize);
4373
4374 Assert(cbToRead >= cbBuf);
4375 cbToRead -= (uint32_t)cbBuf;
4376 }
4377
4378#ifdef HDA_DEBUG_SILENCE
4379
4380 if (csSilence)
4381 pStream->Dbg.csSilence += csSilence;
4382
4383 if ( csSilence == 0
4384 && pStream->Dbg.csSilence > pStream->Dbg.cSilenceThreshold
4385 && pStream->Dbg.cbReadTotal >= pStream->Dbg.cbSilenceReadMin)
4386 {
4387 LogFunc(("Silent block detected: %RU64 audio samples\n", pStream->Dbg.csSilence));
4388 pStream->Dbg.csSilence = 0;
4389 }
4390#endif
4391
4392 if (RT_SUCCESS(rc))
4393 {
4394 if (pcbRead)
4395 *pcbRead = cbReadTotal;
4396 }
4397
4398 return rc;
4399}
4400
4401/**
4402 * Tells whether a given BDLE is complete or not.
4403 *
4404 * @return true if BDLE is complete, false if not.
4405 * @param pBDLE BDLE to retrieve status for.
4406 */
4407static bool hdaBDLEIsComplete(PHDABDLE pBDLE)
4408{
4409 bool fIsComplete = false;
4410
4411 if ( !pBDLE->Desc.u32BufSize /* There can be BDLEs with 0 size. */
4412 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize))
4413 {
4414 Assert(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize);
4415 fIsComplete = true;
4416 }
4417
4418 Log3Func(("%R[bdle] => %s\n", pBDLE, fIsComplete ? "COMPLETE" : "INCOMPLETE"));
4419
4420 return fIsComplete;
4421}
4422
4423
4424/**
4425 * Tells whether a given BDLE needs an interrupt or not.
4426 *
4427 * @return true if BDLE needs an interrupt, false if not.
4428 * @param pBDLE BDLE to retrieve status for.
4429 */
4430static bool hdaBDLENeedsInterrupt(PHDABDLE pBDLE)
4431{
4432 return (pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC);
4433}
4434
4435/**
4436 * Writes audio data from an HDA input stream's FIFO to its associated DMA area.
4437 *
4438 * @return IPRT status code.
4439 * @param pThis HDA state.
4440 * @param pStream HDA input stream to write audio data to.
4441 * @param cbToWrite How much (in bytes) to write.
4442 * @param pcbWritten Returns written bytes on success. Optional.
4443 */
4444static int hdaDMAWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
4445{
4446 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
4447 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4448 /* pcbWritten is optional. */
4449
4450 PHDABDLE pBDLE = &pStream->State.BDLE;
4451 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4452 AssertPtr(pCircBuf);
4453
4454 int rc = VINF_SUCCESS;
4455
4456 uint32_t cbWrittenTotal = 0;
4457
4458 void *pvBuf = NULL;
4459 size_t cbBuf = 0;
4460
4461 uint8_t abSilence[HDA_FIFO_MAX + 1] = { 0 };
4462
4463 while (cbToWrite)
4464 {
4465 size_t cbChunk = RT_MIN(cbToWrite, pStream->u16FIFOS);
4466
4467 size_t cbBlock = 0;
4468 RTCircBufAcquireReadBlock(pCircBuf, cbChunk, &pvBuf, &cbBlock);
4469
4470 if (cbBlock)
4471 {
4472 cbBuf = cbBlock;
4473 }
4474 else /* No audio data available? Send silence. */
4475 {
4476 pvBuf = &abSilence;
4477 cbBuf = cbChunk;
4478 }
4479
4480 /* Sanity checks. */
4481 Assert(cbBuf <= pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
4482 Assert(cbBuf % HDA_FRAME_SIZE == 0);
4483 Assert((cbBuf >> 1) >= 1);
4484
4485#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4486 RTFILE fh;
4487 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",
4488 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4489 RTFileWrite(fh, pvBuf, cbBuf, NULL);
4490 RTFileClose(fh);
4491#endif
4492 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
4493 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff + cbWrittenTotal,
4494 pvBuf, cbBuf);
4495 AssertRC(rc2);
4496
4497#ifdef VBOX_WITH_STATISTICS
4498 STAM_COUNTER_ADD(&pThis->StatBytesWritten, cbBuf);
4499#endif
4500 if (cbBlock)
4501 RTCircBufReleaseReadBlock(pCircBuf, cbBlock);
4502
4503 Assert(cbToWrite >= cbBuf);
4504 cbToWrite -= (uint32_t)cbBuf;
4505
4506 cbWrittenTotal += (uint32_t)cbBuf;
4507 }
4508
4509 if (RT_SUCCESS(rc))
4510 {
4511 if (pcbWritten)
4512 *pcbWritten = cbWrittenTotal;
4513 }
4514 else
4515 LogFunc(("Failed with %Rrc\n", rc));
4516
4517 return rc;
4518}
4519
4520/**
4521 * Soft reset of the device triggered via GCTL.
4522 *
4523 * @param pThis HDA state.
4524 *
4525 */
4526static void hdaGctlReset(PHDASTATE pThis)
4527{
4528 LogFlowFuncEnter();
4529
4530# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
4531 /*
4532 * Stop the timer, if any.
4533 */
4534 hdaTimerStop(pThis);
4535
4536 pThis->cStreamsActive = 0;
4537# endif
4538
4539 memset(pThis->au32Regs, 0, sizeof(pThis->au32Regs));
4540 /* See 6.2.1. */
4541 HDA_REG(pThis, GCAP) = HDA_MAKE_GCAP(HDA_MAX_SDO /* Ouput streams */,
4542 HDA_MAX_SDI /* Input streams */,
4543 0 /* Bidirectional output streams */,
4544 0 /* Serial data out signals */,
4545 1 /* 64-bit */);
4546 HDA_REG(pThis, VMIN) = 0x00; /* see 6.2.2 */
4547 HDA_REG(pThis, VMAJ) = 0x01; /* see 6.2.3 */
4548 /* Announce the full 60 words output payload. */
4549 HDA_REG(pThis, OUTPAY) = 0x003C; /* see 6.2.4 */
4550 /* Announce the full 29 words input payload. */
4551 HDA_REG(pThis, INPAY) = 0x001D; /* see 6.2.5 */
4552 HDA_REG(pThis, CORBSIZE) = 0x42; /* see 6.2.1 */
4553 HDA_REG(pThis, RIRBSIZE) = 0x42; /* see 6.2.1 */
4554
4555 /*
4556 * Stop any audio currently playing and/or recording.
4557 */
4558 if (pThis->SinkFront.pMixSink)
4559 AudioMixerSinkReset(pThis->SinkFront.pMixSink);
4560# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4561 if (pThis->SinkMicIn.pMixSink)
4562 AudioMixerSinkReset(pThis->SinkMicIn.pMixSink);
4563# endif
4564 if (pThis->SinkLineIn.pMixSink)
4565 AudioMixerSinkReset(pThis->SinkLineIn.pMixSink);
4566# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4567 if (pThis->SinkCenterLFE.pMixSink)
4568 AudioMixerSinkReset(pThis->SinkCenterLFE.pMixSink);
4569 if (pThis->SinkRear.pMixSink)
4570 AudioMixerSinkReset(pThis->SinkRear.pMixSink);
4571# endif
4572
4573 /*
4574 * Reset the codec.
4575 */
4576 if ( pThis->pCodec
4577 && pThis->pCodec->pfnReset)
4578 {
4579 pThis->pCodec->pfnReset(pThis->pCodec);
4580 }
4581
4582 /*
4583 * Set some sensible defaults for which HDA sinks
4584 * are connected to which stream number.
4585 *
4586 * We use SD0 for input and SD4 for output by default.
4587 * These stream numbers can be changed by the guest dynamically lateron.
4588 */
4589#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4590 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_MIC_IN , 1 /* SD0 */, 0 /* Channel */);
4591#endif
4592 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_LINE_IN , 1 /* SD0 */, 0 /* Channel */);
4593
4594 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_FRONT , 5 /* SD4 */, 0 /* Channel */);
4595#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4596 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
4597 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_REAR , 5 /* SD4 */, 0 /* Channel */);
4598#endif
4599
4600 pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */
4601
4602 if (pThis->pu32CorbBuf)
4603 RT_BZERO(pThis->pu32CorbBuf, pThis->cbCorbBuf);
4604 else
4605 pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
4606
4607 pThis->cbRirbBuf = 256 * sizeof(uint64_t); /** @todo Use a define here. */
4608 if (pThis->pu64RirbBuf)
4609 RT_BZERO(pThis->pu64RirbBuf, pThis->cbRirbBuf);
4610 else
4611 pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
4612
4613 for (uint8_t uSD = 0; uSD < HDA_MAX_STREAMS; ++uSD)
4614 {
4615 /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
4616 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_RUN;
4617 hdaStreamReset(pThis, &pThis->aStreams[uSD], uSD);
4618 }
4619
4620 /* Clear stream tags <-> objects mapping table. */
4621 RT_ZERO(pThis->aTags);
4622
4623 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
4624 HDA_REG(pThis, STATESTS) = 0x1;
4625
4626 LogFlowFuncLeave();
4627 LogRel(("HDA: Reset\n"));
4628}
4629
4630
4631/**
4632 * Timer callback which handles the audio data transfers on a periodic basis.
4633 *
4634 * @param pDevIns Device instance.
4635 * @param pTimer Timer which was used when calling this.
4636 * @param pvUser User argument as PHDASTATE.
4637 */
4638static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
4639{
4640 RT_NOREF(pDevIns, pTimer);
4641
4642 PHDASTATE pThis = (PHDASTATE)pvUser;
4643 Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE));
4644 AssertPtr(pThis);
4645
4646 hdaTimerMain(pThis);
4647}
4648
4649#else /* VBOX_WITH_AUDIO_HDA_CALLBACKS */
4650
4651static DECLCALLBACK(int) hdaCallbackInput(PDMAUDIOCBTYPE enmType, void *pvCtx, size_t cbCtx, void *pvUser, size_t cbUser)
4652{
4653 Assert(enmType == PDMAUDIOCALLBACKTYPE_INPUT);
4654 AssertPtrReturn(pvCtx, VERR_INVALID_POINTER);
4655 AssertReturn(cbCtx, VERR_INVALID_PARAMETER);
4656 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
4657 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
4658
4659 PHDACALLBACKCTX pCtx = (PHDACALLBACKCTX)pvCtx;
4660 AssertReturn(cbCtx == sizeof(HDACALLBACKCTX), VERR_INVALID_PARAMETER);
4661
4662 PPDMAUDIOCBDATA_DATA_INPUT pData = (PPDMAUDIOCBDATA_DATA_INPUT)pvUser;
4663 AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_INPUT), VERR_INVALID_PARAMETER);
4664
4665 return hdaStreamDoDMA(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
4666}
4667
4668static DECLCALLBACK(int) hdaCallbackOutput(PDMAUDIOCBTYPE enmType, void *pvCtx, size_t cbCtx, void *pvUser, size_t cbUser)
4669{
4670 Assert(enmType == PDMAUDIOCALLBACKTYPE_OUTPUT);
4671 AssertPtrReturn(pvCtx, VERR_INVALID_POINTER);
4672 AssertReturn(cbCtx, VERR_INVALID_PARAMETER);
4673 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
4674 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
4675
4676 PHDACALLBACKCTX pCtx = (PHDACALLBACKCTX)pvCtx;
4677 AssertReturn(cbCtx == sizeof(HDACALLBACKCTX), VERR_INVALID_PARAMETER);
4678
4679 PPDMAUDIOCBDATA_DATA_OUTPUT pData = (PPDMAUDIOCBDATA_DATA_OUTPUT)pvUser;
4680 AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_OUTPUT), VERR_INVALID_PARAMETER);
4681
4682 PHDASTATE pThis = pCtx->pThis;
4683
4684 int rc = hdaStreamDoDMA(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
4685 if ( RT_SUCCESS(rc)
4686 && pData->cbOutWritten)
4687 {
4688 PHDADRIVER pDrv;
4689 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
4690 {
4691 uint32_t cSamplesPlayed;
4692 int rc2 = pDrv->pConnector->pfnPlay(pDrv->pConnector, &cSamplesPlayed);
4693 LogFlowFunc(("LUN#%RU8: cSamplesPlayed=%RU32, rc=%Rrc\n", pDrv->uLUN, cSamplesPlayed, rc2));
4694 }
4695 }
4696}
4697#endif /* VBOX_WITH_AUDIO_HDA_CALLBACKS */
4698
4699/**
4700 * Main routine to perform the actual audio data transfers from the HDA streams
4701 * to the backend(s) and vice versa.
4702 *
4703 * @param pThis HDA state.
4704 */
4705static void hdaDoTransfers(PHDASTATE pThis)
4706{
4707 PHDASTREAM pStreamLineIn = hdaSinkGetStream(pThis, &pThis->SinkLineIn);
4708#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4709 PHDASTREAM pStreamMicIn = hdaSinkGetStream(pThis, &pThis->SinkMicIn);
4710#endif
4711 PHDASTREAM pStreamFront = hdaSinkGetStream(pThis, &pThis->SinkFront);
4712#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4713 /** @todo See note below. */
4714#endif
4715
4716 hdaStreamUpdate(pThis, pStreamFront, true /* fInTimer */);
4717#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4718 hdaStreamUpdate(pThis, pStreamMicIn, true /* fInTimer */);
4719#endif
4720 hdaStreamUpdate(pThis, pStreamLineIn, true /* fInTimer */);
4721}
4722
4723#ifdef DEBUG_andy
4724# define HDA_DEBUG_DMA
4725#endif
4726
4727/**
4728 * Retrieves the available size of (buffered) audio data (in bytes) of a given HDA stream.
4729 *
4730 * @returns Available data (in bytes).
4731 * @param pStream HDA stream to retrieve size for.
4732 */
4733static uint32_t hdaStreamGetUsed(PHDASTREAM pStream)
4734{
4735 AssertPtrReturn(pStream, 0);
4736
4737 if (!pStream->State.pCircBuf)
4738 return 0;
4739
4740 return (uint32_t)RTCircBufUsed(pStream->State.pCircBuf);
4741}
4742
4743/**
4744 * Retrieves the free size of audio data (in bytes) of a given HDA stream.
4745 *
4746 * @returns Free data (in bytes).
4747 * @param pStream HDA stream to retrieve size for.
4748 */
4749static uint32_t hdaStreamGetFree(PHDASTREAM pStream)
4750{
4751 AssertPtrReturn(pStream, 0);
4752
4753 if (!pStream->State.pCircBuf)
4754 return 0;
4755
4756 return (uint32_t)RTCircBufFree(pStream->State.pCircBuf);
4757}
4758
4759
4760/**
4761 * Writes audio data from a mixer sink into an HDA stream's DMA buffer.
4762 *
4763 * @returns IPRT status code.
4764 * @param pThis HDA state.
4765 * @param pStream HDA stream to write to.
4766 * @param cbToWrite Number of bytes to write.
4767 * @param pcbWritten Number of bytes written. Optional.
4768 */
4769static int hdaStreamWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
4770{
4771 RT_NOREF(pThis);
4772 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4773 AssertReturn(cbToWrite, VERR_INVALID_PARAMETER);
4774 /* pcbWritten is optional. */
4775
4776 PHDAMIXERSINK pSink = pStream->pMixSink;
4777 if (!pSink)
4778 {
4779 AssertMsgFailed(("[SD%RU8]: Can't write to a stream with no sink attached\n", pStream->u8SD));
4780
4781 if (pcbWritten)
4782 *pcbWritten = 0;
4783 return VINF_SUCCESS;
4784 }
4785
4786 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4787 AssertPtr(pCircBuf);
4788
4789 int rc = VINF_SUCCESS;
4790
4791 uint32_t cbWrittenTotal = 0;
4792 uint32_t cbLeft = RT_MIN(cbToWrite, (uint32_t)RTCircBufFree(pCircBuf));
4793
4794 while (cbLeft)
4795 {
4796 void *pvDst;
4797 size_t cbDst;
4798
4799 uint32_t cbRead = 0;
4800
4801 RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite, &pvDst, &cbDst);
4802
4803 if (cbDst)
4804 {
4805 rc = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, (uint32_t)cbDst, &cbRead);
4806 AssertRC(rc);
4807
4808 Assert(cbDst >= cbRead);
4809 Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbRead, cbDst));
4810
4811#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4812 RTFILE fh;
4813 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm",
4814 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4815 RTFileWrite(fh, pvDst, cbRead, NULL);
4816 RTFileClose(fh);
4817#endif
4818 }
4819
4820 RTCircBufReleaseWriteBlock(pCircBuf, cbRead);
4821
4822 if (RT_FAILURE(rc))
4823 break;
4824
4825 Assert(cbLeft >= cbRead);
4826 cbLeft -= cbRead;
4827
4828 cbWrittenTotal += cbRead;
4829 }
4830
4831 if (pcbWritten)
4832 *pcbWritten = cbWrittenTotal;
4833
4834 return rc;
4835}
4836
4837
4838/**
4839 * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink.
4840 *
4841 * @returns IPRT status code.
4842 * @param pThis HDA state.
4843 * @param pStream HDA stream to read audio data from.
4844 * @param cbToRead Number of bytes to read.
4845 * @param pcbRead Number of bytes read. Optional.
4846 */
4847static int hdaStreamRead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
4848{
4849 RT_NOREF(pThis);
4850 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4851 AssertReturn(cbToRead, VERR_INVALID_PARAMETER);
4852 /* pcbWritten is optional. */
4853
4854 PHDAMIXERSINK pSink = pStream->pMixSink;
4855 if (!pSink)
4856 {
4857 AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));
4858
4859 if (pcbRead)
4860 *pcbRead = 0;
4861 return VINF_SUCCESS;
4862 }
4863
4864 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4865 AssertPtr(pCircBuf);
4866
4867 int rc = VINF_SUCCESS;
4868
4869 uint32_t cbReadTotal = 0;
4870 uint32_t cbLeft = RT_MIN(cbToRead, (uint32_t)RTCircBufUsed(pCircBuf));
4871
4872 while (cbLeft)
4873 {
4874 void *pvSrc;
4875 size_t cbSrc;
4876
4877 uint32_t cbWritten = 0;
4878
4879 RTCircBufAcquireReadBlock(pCircBuf, cbLeft, &pvSrc, &cbSrc);
4880
4881 if (cbSrc)
4882 {
4883#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4884 RTFILE fh;
4885 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm",
4886 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4887 RTFileWrite(fh, pvSrc, cbSrc, NULL);
4888 RTFileClose(fh);
4889#endif
4890 rc = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbWritten);
4891 AssertRC(rc);
4892
4893 Assert(cbSrc >= cbWritten);
4894 Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
4895 }
4896
4897 RTCircBufReleaseReadBlock(pCircBuf, cbWritten);
4898
4899 if (RT_FAILURE(rc))
4900 break;
4901
4902 Assert(cbLeft >= cbWritten);
4903 cbLeft -= cbWritten;
4904
4905 cbReadTotal += cbWritten;
4906 }
4907
4908 if (pcbRead)
4909 *pcbRead = cbReadTotal;
4910
4911 return rc;
4912}
4913
4914#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
4915/**
4916 * Asynchronous I/O thread for a HDA stream.
4917 * This will do the heavy lifting work for us as soon as it's getting notified by another thread.
4918 *
4919 * @returns IPRT status code.
4920 * @param hThreadSelf Thread handle.
4921 * @param pvUser User argument. Must be of type PHDASTREAMTHREADCTX.
4922 */
4923static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
4924{
4925 PHDASTREAMTHREADCTX pCtx = (PHDASTREAMTHREADCTX)pvUser;
4926 AssertPtr(pCtx);
4927
4928 PHDASTATE pThis = pCtx->pThis;
4929 AssertPtr(pThis);
4930
4931 PHDASTREAM pStream = pCtx->pStream;
4932 AssertPtr(pStream);
4933
4934 PHDASTREAMSTATEAIO pAIO = &pCtx->pStream->State.AIO;
4935
4936 ASMAtomicXchgBool(&pAIO->fStarted, true);
4937
4938 RTThreadUserSignal(hThreadSelf);
4939
4940 LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));
4941
4942 for (;;)
4943 {
4944 int rc2 = RTSemEventWait(pAIO->Event, RT_INDEFINITE_WAIT);
4945 if (RT_FAILURE(rc2))
4946 break;
4947
4948 if (ASMAtomicReadBool(&pAIO->fShutdown))
4949 break;
4950
4951 rc2 = RTCritSectEnter(&pAIO->CritSect);
4952 if (RT_SUCCESS(rc2))
4953 {
4954 if (!pAIO->fEnabled)
4955 {
4956 RTCritSectLeave(&pAIO->CritSect);
4957 continue;
4958 }
4959
4960 hdaStreamUpdate(pThis, pStream, false /* fInTimer */);
4961
4962 int rc3 = RTCritSectLeave(&pAIO->CritSect);
4963 AssertRC(rc3);
4964 }
4965
4966 AssertRC(rc2);
4967 }
4968
4969 LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));
4970
4971 ASMAtomicXchgBool(&pAIO->fStarted, false);
4972
4973 return VINF_SUCCESS;
4974}
4975
4976/**
4977 * Creates the async I/O thread for a specific HDA audio stream.
4978 *
4979 * @returns IPRT status code.
4980 * @param pThis HDA state.
4981 * @param pStream HDA audio stream to create the async I/O thread for.
4982 */
4983static int hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream)
4984{
4985 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4986
4987 int rc;
4988
4989 if (!ASMAtomicReadBool(&pAIO->fStarted))
4990 {
4991 pAIO->fShutdown = false;
4992
4993 rc = RTSemEventCreate(&pAIO->Event);
4994 if (RT_SUCCESS(rc))
4995 {
4996 rc = RTCritSectInit(&pAIO->CritSect);
4997 if (RT_SUCCESS(rc))
4998 {
4999 HDASTREAMTHREADCTX Ctx = { pThis, pStream };
5000
5001 char szThreadName[64];
5002 RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
5003
5004 rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,
5005 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
5006 if (RT_SUCCESS(rc))
5007 rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
5008 }
5009 }
5010 }
5011 else
5012 rc = VINF_SUCCESS;
5013
5014 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
5015 return rc;
5016}
5017
5018/**
5019 * Destroys the async I/O thread of a specific HDA audio stream.
5020 *
5021 * @returns IPRT status code.
5022 * @param pThis HDA state.
5023 * @param pStream HDA audio stream to destroy the async I/O thread for.
5024 */
5025static int hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream)
5026{
5027 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
5028
5029 if (!ASMAtomicReadBool(&pAIO->fStarted))
5030 return VINF_SUCCESS;
5031
5032 ASMAtomicWriteBool(&pAIO->fShutdown, true);
5033
5034 int rc = hdaStreamAsyncIONotify(pThis, pStream);
5035 AssertRC(rc);
5036
5037 int rcThread;
5038 rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
5039 LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
5040
5041 if (RT_SUCCESS(rc))
5042 {
5043 rc = RTCritSectDelete(&pAIO->CritSect);
5044 AssertRC(rc);
5045
5046 rc = RTSemEventDestroy(pAIO->Event);
5047 AssertRC(rc);
5048
5049 pAIO->fStarted = false;
5050 pAIO->fShutdown = false;
5051 pAIO->fEnabled = false;
5052 }
5053
5054 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
5055 return rc;
5056}
5057
5058/**
5059 * Lets the stream's async I/O thread know that there is some data to process.
5060 *
5061 * @returns IPRT status code.
5062 * @param pThis HDA state.
5063 * @param pStream HDA stream to notify async I/O thread for.
5064 */
5065static int hdaStreamAsyncIONotify(PHDASTATE pThis, PHDASTREAM pStream)
5066{
5067 RT_NOREF(pThis);
5068 return RTSemEventSignal(pStream->State.AIO.Event);
5069}
5070
5071/**
5072 * Locks the async I/O thread of a specific HDA audio stream.
5073 *
5074 * @param pStream HDA stream to lock async I/O thread for.
5075 */
5076static void hdaStreamAsyncIOLock(PHDASTREAM pStream)
5077{
5078 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
5079
5080 if (!ASMAtomicReadBool(&pAIO->fStarted))
5081 return;
5082
5083 int rc2 = RTCritSectEnter(&pAIO->CritSect);
5084 AssertRC(rc2);
5085}
5086
5087/**
5088 * Unlocks the async I/O thread of a specific HDA audio stream.
5089 *
5090 * @param pStream HDA stream to unlock async I/O thread for.
5091 */
5092static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream)
5093{
5094 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
5095
5096 if (!ASMAtomicReadBool(&pAIO->fStarted))
5097 return;
5098
5099 int rc2 = RTCritSectLeave(&pAIO->CritSect);
5100 AssertRC(rc2);
5101}
5102
5103/**
5104 * Enables (resumes) or disables (pauses) the async I/O thread.
5105 *
5106 * @param pStream HDA stream to enable/disable async I/O thread for.
5107 * @param fEnable Whether to enable or disable the I/O thread.
5108 *
5109 * @remarks Does not do locking.
5110 */
5111static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable)
5112{
5113 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
5114 ASMAtomicXchgBool(&pAIO->fEnabled, fEnable);
5115}
5116#endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */
5117
5118static uint32_t hdaStreamTransferGetElapsed(PHDASTATE pThis, PHDASTREAM pStream)
5119{
5120 const uint64_t cTicksNow = TMTimerGet(pThis->pTimer);
5121 const uint64_t cTicksPerSec = TMTimerGetFreq(pThis->pTimer);
5122
5123 const uint64_t cTicksElapsed = cTicksNow - pStream->State.uTimerTS;
5124#ifdef DEBUG
5125 const uint64_t cMsElapsed = cTicksElapsed / (cTicksPerSec / 1000);
5126#endif
5127
5128 AssertPtr(pThis->pCodec);
5129
5130 PPDMAUDIOSTREAMCFG pCfg = &pStream->State.strmCfg;
5131
5132 /* A stream *always* runs with 48 kHz device-wise, regardless of the actual stream input/output format (Hz) being set. */
5133 uint32_t csPerPeriod = (int)((pCfg->Props.cChannels * cTicksElapsed * 48000 /* Hz */ + cTicksPerSec) / cTicksPerSec / 2);
5134 uint32_t cbPerPeriod = csPerPeriod << pCfg->Props.cShift;
5135
5136 Log3Func(("[SD%RU8] %RU64ms (%zu samples, %zu bytes) elapsed\n", pStream->u8SD, cMsElapsed, csPerPeriod, cbPerPeriod));
5137
5138 return cbPerPeriod;
5139}
5140
5141/**
5142 * Transfers data of an HDA stream according to its usage (input / output).
5143 *
5144 * For an SDO (output) stream this means reading DMA data from the device to
5145 * the HDA stream's internal FIFO buffer.
5146 *
5147 * For an SDI (input) stream this is reading audio data from the HDA stream's
5148 * internal FIFO buffer and writing it as DMA data to the device.
5149 *
5150 * @returns IPRT status code.
5151 * @param pThis HDA state.
5152 * @param pStream HDA stream to update.
5153 * @param cbToProcessMax Maximum of data (in bytes) to process.
5154 */
5155static int hdaStreamTransfer(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToProcessMax)
5156{
5157 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
5158 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
5159 AssertReturn(cbToProcessMax, VERR_INVALID_PARAMETER);
5160
5161 hdaStreamLock(pStream);
5162
5163 PHDASTREAMPERIOD pPeriod = &pStream->State.Period;
5164 int rc = hdaStreamPeriodLock(pPeriod);
5165 AssertRC(rc);
5166
5167 bool fProceed = true;
5168
5169 /* Stream not running? */
5170 if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
5171 {
5172 Log3Func(("[SD%RU8] RUN bit not set\n", pStream->u8SD));
5173 fProceed = false;
5174 }
5175 /* Period complete? */
5176 else if (hdaStreamPeriodIsComplete(pPeriod))
5177 {
5178 Log3Func(("[SD%RU8] Period is complete, nothing to do\n", pStream->u8SD));
5179 fProceed = false;
5180 }
5181
5182 if (!fProceed)
5183 {
5184 hdaStreamPeriodUnlock(pPeriod);
5185 hdaStreamUnlock(pStream);
5186 return VINF_SUCCESS;
5187 }
5188
5189 /* Sanity checks. */
5190 Assert(pStream->u8SD < HDA_MAX_STREAMS);
5191 Assert(pStream->u64BDLBase);
5192 Assert(pStream->u32CBL);
5193
5194 /* State sanity checks. */
5195 Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false);
5196
5197 /* Fetch first / next BDL entry. */
5198 PHDABDLE pBDLE = &pStream->State.BDLE;
5199 if (hdaBDLEIsComplete(pBDLE))
5200 {
5201 rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
5202 AssertRC(rc);
5203 }
5204
5205 const uint32_t cbPeriodRemaining = hdaStreamPeriodGetRemainingFrames(pPeriod) * HDA_FRAME_SIZE;
5206 Assert(cbPeriodRemaining); /* Paranoia. */
5207
5208 const uint32_t cbElapsed = hdaStreamTransferGetElapsed(pThis, pStream);
5209 Assert(cbElapsed); /* Paranoia. */
5210
5211 /* Limit the data to read, as this routine could be delayed and therefore
5212 * report wrong (e.g. too much) cbElapsed bytes. */
5213 uint32_t cbLeft = RT_MIN(RT_MIN(cbPeriodRemaining, cbElapsed), cbToProcessMax);
5214
5215 Log3Func(("[SD%RU8] cbPeriodRemaining=%RU32, cbElapsed=%RU32, cbToProcessMax=%RU32 -> cbLeft=%RU32\n",
5216 pStream->u8SD, cbPeriodRemaining, cbElapsed, cbToProcessMax, cbLeft));
5217
5218 Assert(cbLeft % HDA_FRAME_SIZE == 0); /* Paranoia. */
5219
5220 while (cbLeft)
5221 {
5222 uint32_t cbChunk = RT_MIN(hdaStreamGetTransferSize(pThis, pStream), cbLeft);
5223 if (!cbChunk)
5224 break;
5225
5226 uint32_t cbDMA = 0;
5227
5228 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
5229 {
5230 STAM_PROFILE_START(&pThis->StatOut, a);
5231
5232 rc = hdaDMARead(pThis, pStream, cbChunk, &cbDMA /* pcbRead */);
5233 if (RT_FAILURE(rc))
5234 LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
5235
5236 STAM_PROFILE_STOP(&pThis->StatOut, a);
5237 }
5238 else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */
5239 {
5240 STAM_PROFILE_START(&pThis->StatIn, a);
5241
5242 rc = hdaDMAWrite(pThis, pStream, cbChunk, &cbDMA /* pcbWritten */);
5243 if (RT_FAILURE(rc))
5244 LogRel(("HDA: Writing to stream #%RU8 DMA failed with %Rrc\n", pStream->u8SD, rc));
5245
5246 STAM_PROFILE_STOP(&pThis->StatIn, a);
5247 }
5248 else /** @todo Handle duplex streams? */
5249 AssertFailed();
5250
5251 if (cbDMA)
5252 {
5253 Assert(cbDMA % HDA_FRAME_SIZE == 0);
5254
5255 /* We always increment the position of DMA buffer counter because we're always reading
5256 * into an intermediate buffer. */
5257 pBDLE->State.u32BufOff += (uint32_t)cbDMA;
5258 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
5259
5260 hdaStreamTransferInc(pThis, pStream, cbDMA);
5261
5262 uint32_t framesDMA = cbDMA / HDA_FRAME_SIZE;
5263
5264 /* Add the transferred frames to the period. */
5265 hdaStreamPeriodInc(pPeriod, framesDMA);
5266
5267 /* Save the timestamp of when the last successful DMA transfer has been for this stream. */
5268 pStream->State.uTimerTS = TMTimerGet(pThis->pTimer);
5269
5270 Assert(cbLeft >= cbDMA);
5271 cbLeft -= cbDMA;
5272 }
5273
5274 if (hdaBDLEIsComplete(pBDLE))
5275 {
5276 Log3Func(("[SD%RU8] Complete: %R[bdle]\n", pStream->u8SD, pBDLE));
5277
5278 if (hdaBDLENeedsInterrupt(pBDLE))
5279 {
5280 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set
5281 * we need to generate an interrupt.
5282 */
5283 if (HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_IOCE)
5284 hdaStreamPeriodAcquireInterrupt(pPeriod);
5285 }
5286
5287 if (pStream->State.uCurBDLE == pStream->u16LVI)
5288 {
5289 Assert(pStream->u32CBL == HDA_STREAM_REG(pThis, LPIB, pStream->u8SD));
5290
5291 pStream->State.uCurBDLE = 0;
5292 hdaStreamUpdateLPIB(pThis, pStream, 0 /* LPIB */);
5293 }
5294 else
5295 pStream->State.uCurBDLE++;
5296
5297 hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
5298
5299 Log3Func(("[SD%RU8] Fetching: %R[bdle]\n", pStream->u8SD, pBDLE));
5300 }
5301
5302 if (RT_FAILURE(rc))
5303 break;
5304 }
5305
5306 if (hdaStreamPeriodIsComplete(pPeriod))
5307 {
5308 Log3Func(("[SD%RU8] Period complete -- Current: %R[bdle]\n", pStream->u8SD, &pStream->State.BDLE));
5309
5310 /* Set the stream's BCIS bit.
5311 *
5312 * Note: This only must be done if the whole period is complete, and not if only
5313 * one specific BDL entry is complete (if it has the IOC bit set).
5314 *
5315 * This will otherwise confuses the guest when it 1) deasserts the interrupt,
5316 * 2) reads SDSTS (with BCIS set) and then 3) too early reads a (wrong) WALCLK value.
5317 *
5318 * snd_hda_intel on Linux will tell. */
5319 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;
5320
5321 /* Try updating the wall clock. */
5322 const uint64_t u64WalClk = hdaStreamPeriodGetAbsElapsedWalClk(pPeriod);
5323 const bool fWalClkSet = hdaWalClkSet(pThis, u64WalClk, false /* fForce */);
5324
5325 /* Does the period have any interrupts outstanding? */
5326 if (hdaStreamPeriodNeedsInterrupt(pPeriod))
5327 {
5328 if (fWalClkSet)
5329 {
5330 Log3Func(("[SD%RU8] Set WALCLK to %RU64, triggering interrupt\n", pStream->u8SD, u64WalClk));
5331
5332 /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
5333 * ending / beginning a period. */
5334#ifndef DEBUG
5335 hdaProcessInterrupt(pThis);
5336#else
5337 hdaProcessInterrupt(pThis, __FUNCTION__);
5338#endif
5339 }
5340 }
5341 else
5342 {
5343 /* End the period first ... */
5344 hdaStreamPeriodEnd(pPeriod);
5345
5346 /* ... and immediately begin the next one. */
5347 hdaStreamPeriodBegin(pPeriod, hdaWalClkGetCurrent(pThis));
5348 }
5349 }
5350
5351 hdaStreamPeriodUnlock(pPeriod);
5352
5353 Log3Func(("[SD%RU8] Returning %Rrc ==========================================\n", pStream->u8SD, rc));
5354
5355 if (RT_FAILURE(rc))
5356 LogFunc(("[SD%RU8] Failed with rc=%Rrcc\n", pStream->u8SD, rc));
5357
5358 hdaStreamUnlock(pStream);
5359
5360 return VINF_SUCCESS;
5361}
5362
5363/**
5364 * Updates a HDA stream by doing its required data transfers.
5365 * The host sink(s) set the overall pace.
5366 *
5367 * This routine is called by both, the synchronous and the asynchronous, implementations.
5368 *
5369 * @param pThis HDA state.
5370 * @param pStream HDA stream to update.
5371 * @param fInTimer Whether to this function was called from the timer
5372 * context or an asynchronous I/O stream thread (if supported).
5373 */
5374static void hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream, bool fInTimer)
5375{
5376 PAUDMIXSINK pSink = NULL;
5377 if ( pStream->pMixSink
5378 && pStream->pMixSink->pMixSink)
5379 {
5380 pSink = pStream->pMixSink->pMixSink;
5381 }
5382
5383 if (!AudioMixerSinkIsActive(pSink)) /* No sink available? Bail out. */
5384 return;
5385
5386 int rc2;
5387
5388 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
5389 {
5390 /* Is the HDA stream ready to be written (guest output data) to? If so, by how much? */
5391 const uint32_t cbFree = hdaStreamGetFree(pStream);
5392
5393 if ( fInTimer
5394 && cbFree)
5395 {
5396 Log3Func(("[SD%RU8] cbFree=%RU32\n", pStream->u8SD, cbFree));
5397
5398 /* Do the DMA transfer. */
5399 rc2 = hdaStreamTransfer(pThis, pStream, cbFree);
5400 AssertRC(rc2);
5401 }
5402
5403 /* How much (guest output) data is available at the moment for the HDA stream? */
5404 uint32_t cbUsed = hdaStreamGetUsed(pStream);
5405
5406#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5407 if ( fInTimer
5408 && cbUsed)
5409 {
5410 rc2 = hdaStreamAsyncIONotify(pThis, pStream);
5411 AssertRC(rc2);
5412 }
5413 else
5414 {
5415#endif
5416 const uint32_t cbSinkWritable = AudioMixerSinkGetWritable(pSink);
5417
5418 /* Do not write more than the sink can hold at the moment.
5419 * The host sets the overall pace. */
5420 if (cbUsed > cbSinkWritable)
5421 cbUsed = cbSinkWritable;
5422
5423 if (cbUsed)
5424 {
5425 /* Read (guest output) data and write it to the stream's sink. */
5426 rc2 = hdaStreamRead(pThis, pStream, cbUsed, NULL /* pcbRead */);
5427 AssertRC(rc2);
5428 }
5429
5430 /* When running synchronously, update the associated sink here.
5431 * Otherwise this will be done in the device timer. */
5432 rc2 = AudioMixerSinkUpdate(pSink);
5433 AssertRC(rc2);
5434
5435#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5436 }
5437#endif
5438 }
5439 else /* Input (SDI). */
5440 {
5441#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5442 if (fInTimer)
5443 {
5444 rc2 = hdaStreamAsyncIONotify(pThis, pStream);
5445 AssertRC(rc2);
5446 }
5447 else
5448 {
5449#endif
5450 rc2 = AudioMixerSinkUpdate(pSink);
5451 AssertRC(rc2);
5452
5453 /* Is the sink ready to be read (host input data) from? If so, by how much? */
5454 const uint32_t cbReadable = AudioMixerSinkGetReadable(pSink);
5455
5456 /* How much (guest input) data is free at the moment? */
5457 uint32_t cbFree = hdaStreamGetFree(pStream);
5458
5459 Log3Func(("[SD%RU8] cbReadable=%RU32, cbFree=%RU32\n", pStream->u8SD, cbReadable, cbFree));
5460
5461 /* Do not read more than the sink can provide at the moment.
5462 * The host sets the overall pace. */
5463 if (cbFree > cbReadable)
5464 cbFree = cbReadable;
5465
5466 if (cbFree)
5467 {
5468 /* Write (guest input) data to the stream which was read from stream's sink before. */
5469 rc2 = hdaStreamWrite(pThis, pStream, cbFree, NULL /* pcbWritten */);
5470 AssertRC(rc2);
5471 }
5472#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5473 }
5474#endif
5475
5476#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5477 if (fInTimer)
5478 {
5479#endif
5480 const uint32_t cbToTransfer = hdaStreamGetUsed(pStream);
5481 if (cbToTransfer)
5482 {
5483 /* When running synchronously, do the DMA data transfers here.
5484 * Otherwise this will be done in the stream's async I/O thread. */
5485 rc2 = hdaStreamTransfer(pThis, pStream, cbToTransfer);
5486 AssertRC(rc2);
5487 }
5488#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5489 }
5490#endif
5491 }
5492}
5493#endif /* IN_RING3 */
5494
5495/* MMIO callbacks */
5496
5497/**
5498 * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
5499 *
5500 * @note During implementation, we discovered so-called "forgotten" or "hole"
5501 * registers whose description is not listed in the RPM, datasheet, or
5502 * spec.
5503 */
5504PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
5505{
5506 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5507 int rc;
5508 RT_NOREF_PV(pvUser);
5509
5510 /*
5511 * Look up and log.
5512 */
5513 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
5514 int idxRegDsc = hdaRegLookup(offReg); /* Register descriptor index. */
5515#ifdef LOG_ENABLED
5516 unsigned const cbLog = cb;
5517 uint32_t offRegLog = offReg;
5518#endif
5519
5520 Log3Func(("offReg=%#x cb=%#x\n", offReg, cb));
5521 Assert(cb == 4); Assert((offReg & 3) == 0);
5522
5523 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
5524 LogFunc(("Access to registers except GCTL is blocked while reset\n"));
5525
5526 if (idxRegDsc == -1)
5527 LogRel(("HDA: Invalid read access @0x%x (bytes=%u)\n", offReg, cb));
5528
5529 if (idxRegDsc != -1)
5530 {
5531 /* ASSUMES gapless DWORD at end of map. */
5532 if (g_aHdaRegMap[idxRegDsc].size == 4)
5533 {
5534 /*
5535 * Straight forward DWORD access.
5536 */
5537 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, (uint32_t *)pv);
5538 Log3Func(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
5539 }
5540 else
5541 {
5542 /*
5543 * Multi register read (unless there are trailing gaps).
5544 * ASSUMES that only DWORD reads have sideeffects.
5545 */
5546 uint32_t u32Value = 0;
5547 unsigned cbLeft = 4;
5548 do
5549 {
5550 uint32_t const cbReg = g_aHdaRegMap[idxRegDsc].size;
5551 uint32_t u32Tmp = 0;
5552
5553 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Tmp);
5554 Log3Func(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
5555 if (rc != VINF_SUCCESS)
5556 break;
5557 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
5558
5559 cbLeft -= cbReg;
5560 offReg += cbReg;
5561 idxRegDsc++;
5562 } while (cbLeft > 0 && g_aHdaRegMap[idxRegDsc].offset == offReg);
5563
5564 if (rc == VINF_SUCCESS)
5565 *(uint32_t *)pv = u32Value;
5566 else
5567 Assert(!IOM_SUCCESS(rc));
5568 }
5569 }
5570 else
5571 {
5572 rc = VINF_IOM_MMIO_UNUSED_FF;
5573 Log3Func(("\tHole at %x is accessed for read\n", offReg));
5574 }
5575
5576 /*
5577 * Log the outcome.
5578 */
5579#ifdef LOG_ENABLED
5580 if (cbLog == 4)
5581 Log3Func(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
5582 else if (cbLog == 2)
5583 Log3Func(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
5584 else if (cbLog == 1)
5585 Log3Func(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
5586#endif
5587 return rc;
5588}
5589
5590
5591DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxRegDsc, uint32_t u32Value, char const *pszLog)
5592{
5593 if (!(HDA_REG(pThis, GCTL) & HDA_GCTL_CRST) && idxRegDsc != HDA_REG_GCTL)
5594 {
5595 Log(("hdaWriteReg: Warning: Access to %s is blocked while controller is in reset mode\n", g_aHdaRegMap[idxRegDsc].abbrev));
5596 LogRel2(("HDA: Warning: Access to register %s is blocked while controller is in reset mode\n",
5597 g_aHdaRegMap[idxRegDsc].abbrev));
5598 return VINF_SUCCESS;
5599 }
5600
5601 /*
5602 * Handle RD (register description) flags.
5603 */
5604
5605 /* For SDI / SDO: Check if writes to those registers are allowed while SDCTL's RUN bit is set. */
5606 if (idxRegDsc >= HDA_NUM_GENERAL_REGS)
5607 {
5608 const uint32_t uSDCTL = HDA_STREAM_REG(pThis, CTL, HDA_SD_NUM_FROM_REG(pThis, CTL, idxRegDsc));
5609
5610 /*
5611 * Some OSes (like Win 10 AU) violate the spec by writing stuff to registers which are not supposed to be be touched
5612 * while SDCTL's RUN bit is set. So just ignore those values.
5613 */
5614
5615 /* Is the RUN bit currently set? */
5616 if ( RT_BOOL(uSDCTL & HDA_SDCTL_RUN)
5617 /* Are writes to the register denied if RUN bit is set? */
5618 && !(g_aHdaRegMap[idxRegDsc].fFlags & HDA_RD_FLAG_SD_WRITE_RUN))
5619 {
5620 Log(("hdaWriteReg: Warning: Access to %s is blocked! %R[sdctl]\n", g_aHdaRegMap[idxRegDsc].abbrev, uSDCTL));
5621 LogRel2(("HDA: Warning: Access to register %s is blocked while the stream's RUN bit is set\n",
5622 g_aHdaRegMap[idxRegDsc].abbrev));
5623 return VINF_SUCCESS;
5624 }
5625 }
5626
5627#ifdef LOG_ENABLED
5628 uint32_t const idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5629 uint32_t const u32OldValue = pThis->au32Regs[idxRegMem];
5630#endif
5631 int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value);
5632 Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
5633 g_aHdaRegMap[idxRegDsc].size, u32OldValue, pThis->au32Regs[idxRegMem], pszLog));
5634 RT_NOREF(pszLog);
5635 return rc;
5636}
5637
5638
5639/**
5640 * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
5641 */
5642PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
5643{
5644 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5645 int rc;
5646 RT_NOREF_PV(pvUser);
5647
5648 /*
5649 * The behavior of accesses that aren't aligned on natural boundraries is
5650 * undefined. Just reject them outright.
5651 */
5652 /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
5653 Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
5654 if (GCPhysAddr & (cb - 1))
5655 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
5656
5657 /*
5658 * Look up and log the access.
5659 */
5660 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
5661 int idxRegDsc = hdaRegLookup(offReg);
5662 uint32_t idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
5663 uint64_t u64Value;
5664 if (cb == 4) u64Value = *(uint32_t const *)pv;
5665 else if (cb == 2) u64Value = *(uint16_t const *)pv;
5666 else if (cb == 1) u64Value = *(uint8_t const *)pv;
5667 else if (cb == 8) u64Value = *(uint64_t const *)pv;
5668 else
5669 {
5670 u64Value = 0; /* shut up gcc. */
5671 AssertReleaseMsgFailed(("%u\n", cb));
5672 }
5673
5674#ifdef LOG_ENABLED
5675 uint32_t const u32LogOldValue = idxRegDsc >= 0 ? pThis->au32Regs[idxRegMem] : UINT32_MAX;
5676 if (idxRegDsc == -1)
5677 Log3Func(("@%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
5678 else if (cb == 4)
5679 Log3Func(("@%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5680 else if (cb == 2)
5681 Log3Func(("@%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5682 else if (cb == 1)
5683 Log3Func(("@%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5684
5685 if (idxRegDsc >= 0 && g_aHdaRegMap[idxRegDsc].size != cb)
5686 Log3Func(("\tsize=%RU32 != cb=%u!!\n", g_aHdaRegMap[idxRegDsc].size, cb));
5687#endif
5688
5689 /*
5690 * Try for a direct hit first.
5691 */
5692 if (idxRegDsc != -1 && g_aHdaRegMap[idxRegDsc].size == cb)
5693 {
5694 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "");
5695 Log3Func(("\t%#x -> %#x\n", u32LogOldValue, idxRegMem != UINT32_MAX ? pThis->au32Regs[idxRegMem] : UINT32_MAX));
5696 }
5697 /*
5698 * Partial or multiple register access, loop thru the requested memory.
5699 */
5700 else
5701 {
5702 /*
5703 * If it's an access beyond the start of the register, shift the input
5704 * value and fill in missing bits. Natural alignment rules means we
5705 * will only see 1 or 2 byte accesses of this kind, so no risk of
5706 * shifting out input values.
5707 */
5708 if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(offReg)) != -1)
5709 {
5710 uint32_t const cbBefore = offReg - g_aHdaRegMap[idxRegDsc].offset; Assert(cbBefore > 0 && cbBefore < 4);
5711 offReg -= cbBefore;
5712 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5713 u64Value <<= cbBefore * 8;
5714 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbBefore];
5715 Log3Func(("\tWithin register, supplied %u leading bits: %#llx -> %#llx ...\n",
5716 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
5717 }
5718
5719 /* Loop thru the write area, it may cover multiple registers. */
5720 rc = VINF_SUCCESS;
5721 for (;;)
5722 {
5723 uint32_t cbReg;
5724 if (idxRegDsc != -1)
5725 {
5726 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5727 cbReg = g_aHdaRegMap[idxRegDsc].size;
5728 if (cb < cbReg)
5729 {
5730 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbReg] & ~g_afMasks[cb];
5731 Log3Func(("\tSupplying missing bits (%#x): %#llx -> %#llx ...\n",
5732 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
5733 }
5734#ifdef LOG_ENABLED
5735 uint32_t uLogOldVal = pThis->au32Regs[idxRegMem];
5736#endif
5737 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "*");
5738 Log3Func(("\t%#x -> %#x\n", uLogOldVal, pThis->au32Regs[idxRegMem]));
5739 }
5740 else
5741 {
5742 LogRel(("HDA: Invalid write access @0x%x\n", offReg));
5743 cbReg = 1;
5744 }
5745 if (rc != VINF_SUCCESS)
5746 break;
5747 if (cbReg >= cb)
5748 break;
5749
5750 /* Advance. */
5751 offReg += cbReg;
5752 cb -= cbReg;
5753 u64Value >>= cbReg * 8;
5754 if (idxRegDsc == -1)
5755 idxRegDsc = hdaRegLookup(offReg);
5756 else
5757 {
5758 idxRegDsc++;
5759 if ( (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
5760 || g_aHdaRegMap[idxRegDsc].offset != offReg)
5761 {
5762 idxRegDsc = -1;
5763 }
5764 }
5765 }
5766 }
5767
5768 return rc;
5769}
5770
5771
5772/* PCI callback. */
5773
5774#ifdef IN_RING3
5775/**
5776 * @callback_method_impl{FNPCIIOREGIONMAP}
5777 */
5778static DECLCALLBACK(int) hdaPciIoRegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
5779 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
5780{
5781 RT_NOREF(iRegion, enmType);
5782 PHDASTATE pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
5783
5784 /*
5785 * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
5786 *
5787 * Let IOM talk DWORDs when reading, saves a lot of complications. On
5788 * writing though, we have to do it all ourselves because of sideeffects.
5789 */
5790 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
5791 int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
5792 IOMMMIO_FLAGS_READ_DWORD
5793 | IOMMMIO_FLAGS_WRITE_PASSTHRU,
5794 hdaMMIOWrite, hdaMMIORead, "HDA");
5795
5796 if (RT_FAILURE(rc))
5797 return rc;
5798
5799 if (pThis->fR0Enabled)
5800 {
5801 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
5802 "hdaMMIOWrite", "hdaMMIORead");
5803 if (RT_FAILURE(rc))
5804 return rc;
5805 }
5806
5807 if (pThis->fRCEnabled)
5808 {
5809 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
5810 "hdaMMIOWrite", "hdaMMIORead");
5811 if (RT_FAILURE(rc))
5812 return rc;
5813 }
5814
5815 pThis->MMIOBaseAddr = GCPhysAddress;
5816 return VINF_SUCCESS;
5817}
5818
5819
5820/* Saved state callbacks. */
5821
5822static int hdaSaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStrm)
5823{
5824 RT_NOREF(pDevIns);
5825#ifdef VBOX_STRICT
5826 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5827#endif
5828
5829 Log2Func(("[SD%RU8]\n", pStrm->u8SD));
5830
5831 /* Save stream ID. */
5832 int rc = SSMR3PutU8(pSSM, pStrm->u8SD);
5833 AssertRCReturn(rc, rc);
5834 Assert(pStrm->u8SD < HDA_MAX_STREAMS);
5835
5836 rc = SSMR3PutStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields7, NULL);
5837 AssertRCReturn(rc, rc);
5838
5839#ifdef VBOX_STRICT /* Sanity checks. */
5840 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8SD),
5841 HDA_STREAM_REG(pThis, BDPU, pStrm->u8SD));
5842 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStrm->u8SD);
5843 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStrm->u8SD);
5844
5845 Assert(u64BaseDMA == pStrm->u64BDLBase);
5846 Assert(u16LVI == pStrm->u16LVI);
5847 Assert(u32CBL == pStrm->u32CBL);
5848#endif
5849
5850 rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
5851 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
5852 AssertRCReturn(rc, rc);
5853
5854 rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
5855 0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
5856 AssertRCReturn(rc, rc);
5857
5858 rc = SSMR3PutStructEx(pSSM, &pStrm->State.Period, sizeof(HDASTREAMPERIOD),
5859 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
5860 AssertRCReturn(rc, rc);
5861
5862#ifdef VBOX_STRICT /* Sanity checks. */
5863 PHDABDLE pBDLE = &pStrm->State.BDLE;
5864 if (u64BaseDMA)
5865 {
5866 Assert(pStrm->State.uCurBDLE <= u16LVI + 1);
5867
5868 HDABDLE curBDLE;
5869 rc = hdaBDLEFetch(pThis, &curBDLE, u64BaseDMA, pStrm->State.uCurBDLE);
5870 AssertRC(rc);
5871
5872 Assert(curBDLE.Desc.u32BufSize == pBDLE->Desc.u32BufSize);
5873 Assert(curBDLE.Desc.u64BufAdr == pBDLE->Desc.u64BufAdr);
5874 Assert(curBDLE.Desc.fFlags == pBDLE->Desc.fFlags);
5875 }
5876 else
5877 {
5878 Assert(pBDLE->Desc.u64BufAdr == 0);
5879 Assert(pBDLE->Desc.u32BufSize == 0);
5880 }
5881#endif
5882
5883 uint32_t cbCircBufSize = 0;
5884 uint32_t cbCircBufUsed = 0;
5885
5886 if (pStrm->State.pCircBuf)
5887 {
5888 cbCircBufSize = (uint32_t)RTCircBufSize(pStrm->State.pCircBuf);
5889 cbCircBufUsed = (uint32_t)RTCircBufUsed(pStrm->State.pCircBuf);
5890 }
5891
5892 rc = SSMR3PutU32(pSSM, cbCircBufSize);
5893 AssertRCReturn(rc, rc);
5894
5895 rc = SSMR3PutU32(pSSM, cbCircBufUsed);
5896 AssertRCReturn(rc, rc);
5897
5898 if (cbCircBufUsed)
5899 {
5900 /*
5901 * We now need to get the circular buffer's data without actually modifying
5902 * the internal read / used offsets -- otherwise we would end up with broken audio
5903 * data after saving the state.
5904 *
5905 * So get the current read offset and serialize the buffer data manually based on that.
5906 */
5907 size_t cbCircBufOffRead = RTCircBufOffsetRead(pStrm->State.pCircBuf);
5908
5909 void *pvBuf;
5910 size_t cbBuf;
5911 RTCircBufAcquireReadBlock(pStrm->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
5912
5913 if (cbBuf)
5914 {
5915 size_t cbToRead = cbCircBufUsed;
5916 size_t cbEnd = 0;
5917
5918 if (cbCircBufUsed > cbCircBufOffRead)
5919 cbEnd = cbCircBufUsed - cbCircBufOffRead;
5920
5921 if (cbEnd) /* Save end of buffer first. */
5922 {
5923 rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf + cbCircBufSize - cbEnd /* End of buffer */, cbEnd);
5924 AssertRCReturn(rc, rc);
5925
5926 Assert(cbToRead >= cbEnd);
5927 cbToRead -= cbEnd;
5928 }
5929
5930 if (cbToRead) /* Save remaining stuff at start of buffer (if any). */
5931 {
5932 rc = SSMR3PutMem(pSSM, (uint8_t *)pvBuf - cbCircBufUsed /* Start of buffer */, cbToRead);
5933 AssertRCReturn(rc, rc);
5934 }
5935 }
5936
5937 RTCircBufReleaseReadBlock(pStrm->State.pCircBuf, 0 /* Don't advance read pointer -- see comment above */);
5938 }
5939
5940 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
5941 pStrm->u8SD,
5942 HDA_STREAM_REG(pThis, LPIB, pStrm->u8SD), HDA_STREAM_REG(pThis, CBL, pStrm->u8SD), HDA_STREAM_REG(pThis, LVI, pStrm->u8SD)));
5943
5944#ifdef LOG_ENABLED
5945 hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
5946#endif
5947
5948 return rc;
5949}
5950
5951/**
5952 * @callback_method_impl{FNSSMDEVSAVEEXEC}
5953 */
5954static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
5955{
5956 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5957
5958 /* Save Codec nodes states. */
5959 hdaCodecSaveState(pThis->pCodec, pSSM);
5960
5961 /* Save MMIO registers. */
5962 SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
5963 SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
5964
5965 /* Save controller-specifc internals. */
5966 SSMR3PutU64(pSSM, pThis->u64WalClk);
5967 SSMR3PutU8(pSSM, pThis->u8IRQL);
5968
5969 /* Save number of streams. */
5970 SSMR3PutU32(pSSM, HDA_MAX_STREAMS);
5971
5972 /* Save stream states. */
5973 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
5974 {
5975 int rc = hdaSaveStream(pDevIns, pSSM, &pThis->aStreams[i]);
5976 AssertRCReturn(rc, rc);
5977 }
5978
5979 return VINF_SUCCESS;
5980}
5981
5982/**
5983 * Does required post processing when loading a saved state.
5984 *
5985 * @param pThis Pointer to HDA state.
5986 */
5987static int hdaLoadExecPost(PHDASTATE pThis)
5988{
5989 int rc = VINF_SUCCESS;
5990
5991 bool fStartTimer = false; /* Whether to resume the device timer. */
5992
5993 /*
5994 * Enable all previously active streams.
5995 */
5996 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
5997 {
5998 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
5999 if (pStream)
6000 {
6001 int rc2;
6002
6003 bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
6004 if (fActive)
6005 {
6006#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
6007 /* Make sure to also create the async I/O thread before actually enabling the stream. */
6008 rc2 = hdaStreamAsyncIOCreate(pThis, pStream);
6009 AssertRC(rc2);
6010
6011 /* ... and enabling it. */
6012 hdaStreamAsyncIOEnable(pStream, true /* fEnable */);
6013#endif
6014 /* (Re-)initialize the stream with current values. */
6015 rc2 = hdaStreamInit(pThis, pStream, pStream->u8SD);
6016 AssertRC(rc2);
6017
6018 /* Resume the stream's period. */
6019 hdaStreamPeriodResume(&pStream->State.Period);
6020
6021 /* (Re-)enable the stream. */
6022 rc2 = hdaStreamEnable(pThis, pStream, true /* fEnable */);
6023 AssertRC(rc2);
6024
6025 /* Add the stream to the device setup. */
6026 rc2 = hdaAddStream(pThis, &pStream->State.strmCfg);
6027 AssertRC(rc2);
6028
6029#ifdef HDA_USE_DMA_ACCESS_HANDLER
6030 /* (Re-)install the DMA handler. */
6031 hdaStreamRegisterDMAHandlers(pThis, pStream);
6032#endif
6033 fStartTimer = true;
6034 }
6035 }
6036 }
6037
6038#ifndef VBOX_WITH_AUDIO_CALLBACKS
6039 /* Start the timer if one of the above streams were active during taking the saved state. */
6040 if (fStartTimer)
6041 hdaTimerMaybeStart(pThis);
6042#endif
6043
6044 LogFlowFuncLeaveRC(rc);
6045 return rc;
6046}
6047
6048
6049/**
6050 * Handles loading of all saved state versions older than the current one.
6051 *
6052 * @param pThis Pointer to HDA state.
6053 * @param pSSM Pointer to SSM handle.
6054 * @param uVersion Saved state version to load.
6055 * @param uPass Loading stage to handle.
6056 */
6057static int hdaLoadExecLegacy(PHDASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
6058{
6059 RT_NOREF(uPass);
6060
6061 int rc = VINF_SUCCESS;
6062
6063 /*
6064 * Load MMIO registers.
6065 */
6066 uint32_t cRegs;
6067 switch (uVersion)
6068 {
6069 case HDA_SSM_VERSION_1:
6070 /* Starting with r71199, we would save 112 instead of 113
6071 registers due to some code cleanups. This only affected trunk
6072 builds in the 4.1 development period. */
6073 cRegs = 113;
6074 if (SSMR3HandleRevision(pSSM) >= 71199)
6075 {
6076 uint32_t uVer = SSMR3HandleVersion(pSSM);
6077 if ( VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
6078 && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
6079 && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
6080 cRegs = 112;
6081 }
6082 break;
6083
6084 case HDA_SSM_VERSION_2:
6085 case HDA_SSM_VERSION_3:
6086 cRegs = 112;
6087 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= 112);
6088 break;
6089
6090 /* Since version 4 we store the register count to stay flexible. */
6091 case HDA_SSM_VERSION_4:
6092 case HDA_SSM_VERSION_5:
6093 case HDA_SSM_VERSION_6:
6094 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
6095 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
6096 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
6097 break;
6098
6099 default:
6100 LogRel(("HDA: Unsupported / too new saved state version (%RU32)\n", uVersion));
6101 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
6102 }
6103
6104 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
6105 {
6106 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
6107 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
6108 }
6109 else
6110 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
6111
6112 /* Make sure to update the base addresses first before initializing any streams down below. */
6113 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
6114 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
6115 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
6116
6117 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
6118 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
6119
6120 /*
6121 * Note: Saved states < v5 store LVI (u32BdleMaxCvi) for
6122 * *every* BDLE state, whereas it only needs to be stored
6123 * *once* for every stream. Most of the BDLE state we can
6124 * get out of the registers anyway, so just ignore those values.
6125 *
6126 * Also, only the current BDLE was saved, regardless whether
6127 * there were more than one (and there are at least two entries,
6128 * according to the spec).
6129 */
6130#define HDA_SSM_LOAD_BDLE_STATE_PRE_V5(v, x) \
6131 { \
6132 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */ \
6133 AssertRCReturn(rc, rc); \
6134 rc = SSMR3GetU64(pSSM, &x.Desc.u64BufAdr); /* u64BdleCviAddr */ \
6135 AssertRCReturn(rc, rc); \
6136 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* u32BdleMaxCvi */ \
6137 AssertRCReturn(rc, rc); \
6138 rc = SSMR3GetU32(pSSM, &x.State.u32BDLIndex); /* u32BdleCvi */ \
6139 AssertRCReturn(rc, rc); \
6140 rc = SSMR3GetU32(pSSM, &x.Desc.u32BufSize); /* u32BdleCviLen */ \
6141 AssertRCReturn(rc, rc); \
6142 rc = SSMR3GetU32(pSSM, &x.State.u32BufOff); /* u32BdleCviPos */ \
6143 AssertRCReturn(rc, rc); \
6144 bool fIOC; \
6145 rc = SSMR3GetBool(pSSM, &fIOC); /* fBdleCviIoc */ \
6146 AssertRCReturn(rc, rc); \
6147 x.Desc.fFlags = fIOC ? HDA_BDLE_FLAG_IOC : 0; \
6148 rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */ \
6149 AssertRCReturn(rc, rc); \
6150 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO */ \
6151 AssertRCReturn(rc, rc); \
6152 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */ \
6153 AssertRCReturn(rc, rc); \
6154 }
6155
6156 /*
6157 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
6158 */
6159 switch (uVersion)
6160 {
6161 case HDA_SSM_VERSION_1:
6162 case HDA_SSM_VERSION_2:
6163 case HDA_SSM_VERSION_3:
6164 case HDA_SSM_VERSION_4:
6165 {
6166 /* Only load the internal states.
6167 * The rest will be initialized from the saved registers later. */
6168
6169 /* Note 1: Only the *current* BDLE for a stream was saved! */
6170 /* Note 2: The stream's saving order is/was fixed, so don't touch! */
6171
6172 /* Output */
6173 PHDASTREAM pStream = &pThis->aStreams[4];
6174 rc = hdaStreamInit(pThis, pStream, 4 /* Stream descriptor, hardcoded */);
6175 if (RT_FAILURE(rc))
6176 break;
6177 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
6178 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
6179
6180 /* Microphone-In */
6181 pStream = &pThis->aStreams[2];
6182 rc = hdaStreamInit(pThis, pStream, 2 /* Stream descriptor, hardcoded */);
6183 if (RT_FAILURE(rc))
6184 break;
6185 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
6186 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
6187
6188 /* Line-In */
6189 pStream = &pThis->aStreams[0];
6190 rc = hdaStreamInit(pThis, pStream, 0 /* Stream descriptor, hardcoded */);
6191 if (RT_FAILURE(rc))
6192 break;
6193 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
6194 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
6195 break;
6196 }
6197
6198#undef HDA_SSM_LOAD_BDLE_STATE_PRE_V5
6199
6200 default: /* Since v5 we support flexible stream and BDLE counts. */
6201 {
6202 uint32_t cStreams;
6203 rc = SSMR3GetU32(pSSM, &cStreams);
6204 if (RT_FAILURE(rc))
6205 break;
6206
6207 if (cStreams > HDA_MAX_STREAMS)
6208 cStreams = HDA_MAX_STREAMS; /* Sanity. */
6209
6210 /* Load stream states. */
6211 for (uint32_t i = 0; i < cStreams; i++)
6212 {
6213 uint8_t uStreamID;
6214 rc = SSMR3GetU8(pSSM, &uStreamID);
6215 if (RT_FAILURE(rc))
6216 break;
6217
6218 PHDASTREAM pStrm = hdaStreamGetFromSD(pThis, uStreamID);
6219 HDASTREAM StreamDummy;
6220
6221 if (!pStrm)
6222 {
6223 pStrm = &StreamDummy;
6224 LogRel2(("HDA: Warning: Stream ID=%RU32 not supported, skipping to load ...\n", uStreamID));
6225 }
6226
6227 rc = hdaStreamInit(pThis, pStrm, uStreamID);
6228 if (RT_FAILURE(rc))
6229 {
6230 LogRel(("HDA: Stream #%RU32: Initialization of stream %RU8 failed, rc=%Rrc\n", i, uStreamID, rc));
6231 break;
6232 }
6233
6234 /*
6235 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
6236 */
6237
6238 if (uVersion == HDA_SSM_VERSION_5)
6239 {
6240 /* Get the current BDLE entry and skip the rest. */
6241 uint16_t cBDLE;
6242
6243 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
6244 AssertRC(rc);
6245 rc = SSMR3GetU16(pSSM, &cBDLE); /* cBDLE */
6246 AssertRC(rc);
6247 rc = SSMR3GetU16(pSSM, &pStrm->State.uCurBDLE); /* uCurBDLE */
6248 AssertRC(rc);
6249 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
6250 AssertRC(rc);
6251
6252 uint32_t u32BDLEIndex;
6253 for (uint16_t a = 0; a < cBDLE; a++)
6254 {
6255 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
6256 AssertRC(rc);
6257 rc = SSMR3GetU32(pSSM, &u32BDLEIndex); /* u32BDLIndex */
6258 AssertRC(rc);
6259
6260 /* Does the current BDLE index match the current BDLE to process? */
6261 if (u32BDLEIndex == pStrm->State.uCurBDLE)
6262 {
6263 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */
6264 AssertRC(rc);
6265 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO, deprecated */
6266 AssertRC(rc);
6267 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.u32BufOff); /* u32BufOff */
6268 AssertRC(rc);
6269 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
6270 AssertRC(rc);
6271 }
6272 else /* Skip not current BDLEs. */
6273 {
6274 rc = SSMR3Skip(pSSM, sizeof(uint32_t) /* cbBelowFIFOW */
6275 + sizeof(uint8_t) * 256 /* au8FIFO */
6276 + sizeof(uint32_t) /* u32BufOff */
6277 + sizeof(uint32_t)); /* End marker */
6278 AssertRC(rc);
6279 }
6280 }
6281 }
6282 else
6283 {
6284 rc = SSMR3GetStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE),
6285 0 /* fFlags */, g_aSSMStreamStateFields6, NULL);
6286 if (RT_FAILURE(rc))
6287 break;
6288
6289 /* Get HDABDLEDESC. */
6290 uint32_t uMarker;
6291 rc = SSMR3GetU32(pSSM, &uMarker); /* Begin marker. */
6292 AssertRC(rc);
6293 Assert(uMarker == UINT32_C(0x19200102) /* SSMR3STRUCT_BEGIN */);
6294 rc = SSMR3GetU64(pSSM, &pStrm->State.BDLE.Desc.u64BufAdr);
6295 AssertRC(rc);
6296 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.Desc.u32BufSize);
6297 AssertRC(rc);
6298 bool fFlags = false;
6299 rc = SSMR3GetBool(pSSM, &fFlags); /* Saved states < v7 only stored the IOC as boolean flag. */
6300 AssertRC(rc);
6301 pStrm->State.BDLE.Desc.fFlags = fFlags ? HDA_BDLE_FLAG_IOC : 0;
6302 rc = SSMR3GetU32(pSSM, &uMarker); /* End marker. */
6303 AssertRC(rc);
6304 Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */);
6305
6306 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
6307 0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
6308 if (RT_FAILURE(rc))
6309 break;
6310
6311 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
6312 uStreamID,
6313 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
6314#ifdef LOG_ENABLED
6315 hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
6316#endif
6317 }
6318
6319 } /* for cStreams */
6320 break;
6321 } /* default */
6322 }
6323
6324 return rc;
6325}
6326
6327/**
6328 * @callback_method_impl{FNSSMDEVLOADEXEC}
6329 */
6330static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
6331{
6332 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6333
6334 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
6335
6336 LogRel2(("hdaLoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
6337
6338 /*
6339 * Load Codec nodes states.
6340 */
6341 int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
6342 if (RT_FAILURE(rc))
6343 {
6344 LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
6345 return rc;
6346 }
6347
6348 if (uVersion < HDA_SSM_VERSION) /* Handle older saved states? */
6349 {
6350 rc = hdaLoadExecLegacy(pThis, pSSM, uVersion, uPass);
6351 if (RT_SUCCESS(rc))
6352 rc = hdaLoadExecPost(pThis);
6353
6354 return rc;
6355 }
6356
6357 /*
6358 * Load MMIO registers.
6359 */
6360 uint32_t cRegs;
6361 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
6362 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
6363 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
6364
6365 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
6366 {
6367 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
6368 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
6369 }
6370 else
6371 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
6372
6373 /* Make sure to update the base addresses first before initializing any streams down below. */
6374 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
6375 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
6376 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
6377
6378 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
6379 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
6380
6381 /*
6382 * Load controller-specifc internals.
6383 */
6384 if (SSMR3HandleRevision(pSSM) >= 116273) /* Don't annoy other team mates (forgot this for state v7). */
6385 {
6386 rc = SSMR3GetU64(pSSM, &pThis->u64WalClk);
6387 AssertRC(rc);
6388
6389 rc = SSMR3GetU8(pSSM, &pThis->u8IRQL);
6390 AssertRC(rc);
6391 }
6392
6393 /*
6394 * Load streams.
6395 */
6396 uint32_t cStreams;
6397 rc = SSMR3GetU32(pSSM, &cStreams);
6398 AssertRC(rc);
6399
6400 if (cStreams > HDA_MAX_STREAMS)
6401 cStreams = HDA_MAX_STREAMS; /* Sanity. */
6402
6403 Log2Func(("cStreams=%RU32\n", cStreams));
6404
6405 /* Load stream states. */
6406 for (uint32_t i = 0; i < cStreams; i++)
6407 {
6408 uint8_t uStreamID;
6409 rc = SSMR3GetU8(pSSM, &uStreamID);
6410 AssertRC(rc);
6411
6412 PHDASTREAM pStrm = hdaStreamGetFromSD(pThis, uStreamID);
6413 HDASTREAM StreamDummy;
6414
6415 if (!pStrm)
6416 {
6417 pStrm = &StreamDummy;
6418 LogRel2(("HDA: Warning: Loading of stream #%RU8 not supported, skipping to load ...\n", uStreamID));
6419 }
6420
6421 rc = hdaStreamInit(pThis, pStrm, uStreamID);
6422 if (RT_FAILURE(rc))
6423 {
6424 LogRel(("HDA: Stream #%RU8: Loading initialization failed, rc=%Rrc\n", uStreamID, rc));
6425 /* Continue. */
6426 }
6427
6428 /*
6429 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
6430 */
6431 rc = SSMR3GetStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE),
6432 0 /* fFlags */, g_aSSMStreamStateFields7,
6433 NULL);
6434 AssertRC(rc);
6435
6436 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
6437 0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
6438 AssertRC(rc);
6439
6440 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
6441 0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
6442 AssertRC(rc);
6443
6444 Log2Func(("[SD%RU8] %R[bdle]\n", pStrm->u8SD, &pStrm->State.BDLE));
6445
6446 /*
6447 * Load period state.
6448 */
6449 hdaStreamPeriodInit(&pStrm->State.Period,
6450 pStrm->u8SD, pStrm->u16LVI, pStrm->u32CBL, &pStrm->State.strmCfg);
6451
6452 if (SSMR3HandleRevision(pSSM) >= 116273) /* Don't annoy other team mates (forgot this for state v7). */
6453 {
6454 rc = SSMR3GetStructEx(pSSM, &pStrm->State.Period, sizeof(HDASTREAMPERIOD),
6455 0 /* fFlags */, g_aSSMStreamPeriodFields7, NULL);
6456 AssertRC(rc);
6457 }
6458
6459 /*
6460 * Load internal (FIFO) buffer.
6461 */
6462
6463 uint32_t cbCircBufSize = 0;
6464 rc = SSMR3GetU32(pSSM, &cbCircBufSize); /* cbCircBuf */
6465 AssertRC(rc);
6466
6467 uint32_t cbCircBufUsed = 0;
6468 rc = SSMR3GetU32(pSSM, &cbCircBufUsed); /* cbCircBuf */
6469 AssertRC(rc);
6470
6471 if (cbCircBufSize) /* If 0, skip the buffer. */
6472 {
6473 /* Paranoia. */
6474 AssertReleaseMsg(cbCircBufSize <= _1M,
6475 ("HDA: Saved state contains bogus DMA buffer size (%RU32) for stream #%RU8",
6476 cbCircBufSize, uStreamID));
6477 AssertReleaseMsg(cbCircBufUsed <= cbCircBufSize,
6478 ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
6479 cbCircBufUsed, cbCircBufSize, uStreamID));
6480 AssertPtr(pStrm->State.pCircBuf);
6481
6482 /* Do we need to cre-create the circular buffer do fit the data size? */
6483 if (cbCircBufSize != (uint32_t)RTCircBufSize(pStrm->State.pCircBuf))
6484 {
6485 RTCircBufDestroy(pStrm->State.pCircBuf);
6486 pStrm->State.pCircBuf = NULL;
6487
6488 rc = RTCircBufCreate(&pStrm->State.pCircBuf, cbCircBufSize);
6489 AssertRC(rc);
6490 }
6491
6492 if ( RT_SUCCESS(rc)
6493 && cbCircBufUsed)
6494 {
6495 void *pvBuf;
6496 size_t cbBuf;
6497
6498 RTCircBufAcquireWriteBlock(pStrm->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
6499
6500 if (cbBuf)
6501 {
6502 rc = SSMR3GetMem(pSSM, pvBuf, cbBuf);
6503 AssertRC(rc);
6504 }
6505
6506 RTCircBufReleaseWriteBlock(pStrm->State.pCircBuf, cbBuf);
6507
6508 Assert(cbBuf == cbCircBufUsed);
6509 }
6510 }
6511
6512 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
6513 uStreamID,
6514 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
6515#ifdef LOG_ENABLED
6516 hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
6517#endif
6518 /** @todo (Re-)initialize active periods? */
6519
6520 } /* for cStreams */
6521
6522 rc = hdaLoadExecPost(pThis);
6523 AssertRC(rc);
6524
6525 LogFlowFuncLeaveRC(rc);
6526 return rc;
6527}
6528
6529/* Debug and log type formatters. */
6530
6531/**
6532 * @callback_method_impl{FNRTSTRFORMATTYPE}
6533 */
6534static DECLCALLBACK(size_t) hdaDbgFmtBDLE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6535 const char *pszType, void const *pvValue,
6536 int cchWidth, int cchPrecision, unsigned fFlags,
6537 void *pvUser)
6538{
6539 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6540 PHDABDLE pBDLE = (PHDABDLE)pvValue;
6541 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6542 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])",
6543 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,
6544 pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC, pBDLE->Desc.u32BufSize, pBDLE->Desc.u64BufAdr);
6545}
6546
6547/**
6548 * @callback_method_impl{FNRTSTRFORMATTYPE}
6549 */
6550static DECLCALLBACK(size_t) hdaDbgFmtSDCTL(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6551 const char *pszType, void const *pvValue,
6552 int cchWidth, int cchPrecision, unsigned fFlags,
6553 void *pvUser)
6554{
6555 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6556 uint32_t uSDCTL = (uint32_t)(uintptr_t)pvValue;
6557 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6558 "SDCTL(raw:%#x, DIR:%s, TP:%RTbool, STRIPE:%x, DEIE:%RTbool, FEIE:%RTbool, IOCE:%RTbool, RUN:%RTbool, RESET:%RTbool)",
6559 uSDCTL,
6560 uSDCTL & HDA_SDCTL_DIR ? "OUT" : "IN",
6561 RT_BOOL(uSDCTL & HDA_SDCTL_TP),
6562 (uSDCTL & HDA_SDCTL_STRIPE_MASK) >> HDA_SDCTL_STRIPE_SHIFT,
6563 RT_BOOL(uSDCTL & HDA_SDCTL_DEIE),
6564 RT_BOOL(uSDCTL & HDA_SDCTL_FEIE),
6565 RT_BOOL(uSDCTL & HDA_SDCTL_IOCE),
6566 RT_BOOL(uSDCTL & HDA_SDCTL_RUN),
6567 RT_BOOL(uSDCTL & HDA_SDCTL_SRST));
6568}
6569
6570/**
6571 * @callback_method_impl{FNRTSTRFORMATTYPE}
6572 */
6573static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6574 const char *pszType, void const *pvValue,
6575 int cchWidth, int cchPrecision, unsigned fFlags,
6576 void *pvUser)
6577{
6578 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6579 uint32_t uSDFIFOS = (uint32_t)(uintptr_t)pvValue;
6580 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw:%#x, sdfifos:%RU8 B)", uSDFIFOS, uSDFIFOS ? uSDFIFOS + 1 : 0);
6581}
6582
6583/**
6584 * @callback_method_impl{FNRTSTRFORMATTYPE}
6585 */
6586static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOW(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6587 const char *pszType, void const *pvValue,
6588 int cchWidth, int cchPrecision, unsigned fFlags,
6589 void *pvUser)
6590{
6591 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6592 uint32_t uSDFIFOW = (uint32_t)(uintptr_t)pvValue;
6593 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSDFIFOW, hdaSDFIFOWToBytes(uSDFIFOW));
6594}
6595
6596/**
6597 * @callback_method_impl{FNRTSTRFORMATTYPE}
6598 */
6599static DECLCALLBACK(size_t) hdaDbgFmtSDSTS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6600 const char *pszType, void const *pvValue,
6601 int cchWidth, int cchPrecision, unsigned fFlags,
6602 void *pvUser)
6603{
6604 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6605 uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
6606 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6607 "SDSTS(raw:%#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
6608 uSdSts,
6609 RT_BOOL(uSdSts & HDA_SDSTS_FIFORDY),
6610 RT_BOOL(uSdSts & HDA_SDSTS_DESE),
6611 RT_BOOL(uSdSts & HDA_SDSTS_FIFOE),
6612 RT_BOOL(uSdSts & HDA_SDSTS_BCIS));
6613}
6614
6615static int hdaDbgLookupRegByName(const char *pszArgs)
6616{
6617 int iReg = 0;
6618 for (; iReg < HDA_NUM_REGS; ++iReg)
6619 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
6620 return iReg;
6621 return -1;
6622}
6623
6624
6625static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
6626{
6627 Assert( pThis
6628 && iHdaIndex >= 0
6629 && iHdaIndex < HDA_NUM_REGS);
6630 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
6631}
6632
6633/**
6634 * @callback_method_impl{FNDBGFHANDLERDEV}
6635 */
6636static DECLCALLBACK(void) hdaDbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6637{
6638 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6639 int iHdaRegisterIndex = hdaDbgLookupRegByName(pszArgs);
6640 if (iHdaRegisterIndex != -1)
6641 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
6642 else
6643 {
6644 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NUM_REGS; ++iHdaRegisterIndex)
6645 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
6646 }
6647}
6648
6649static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
6650{
6651 Assert( pThis
6652 && iIdx >= 0
6653 && iIdx < HDA_MAX_STREAMS);
6654
6655 const PHDASTREAM pStrm = &pThis->aStreams[iIdx];
6656
6657 pHlp->pfnPrintf(pHlp, "Stream #%d:\n", iIdx);
6658 pHlp->pfnPrintf(pHlp, "\tSD%dCTL : %R[sdctl]\n", iIdx, HDA_STREAM_REG(pThis, CTL, iIdx));
6659 pHlp->pfnPrintf(pHlp, "\tSD%dCTS : %R[sdsts]\n", iIdx, HDA_STREAM_REG(pThis, STS, iIdx));
6660 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOS: %R[sdfifos]\n", iIdx, HDA_STREAM_REG(pThis, FIFOS, iIdx));
6661 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOW: %R[sdfifow]\n", iIdx, HDA_STREAM_REG(pThis, FIFOW, iIdx));
6662 pHlp->pfnPrintf(pHlp, "\tBDLE : %R[bdle]\n", &pStrm->State.BDLE);
6663}
6664
6665static void hdaDbgPrintBDLE(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
6666{
6667 Assert( pThis
6668 && iIdx >= 0
6669 && iIdx < HDA_MAX_STREAMS);
6670
6671 const PHDASTREAM pStrm = &pThis->aStreams[iIdx];
6672 const PHDABDLE pBDLE = &pStrm->State.BDLE;
6673
6674 pHlp->pfnPrintf(pHlp, "Stream #%d BDLE:\n", iIdx);
6675
6676 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, iIdx),
6677 HDA_STREAM_REG(pThis, BDPU, iIdx));
6678 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, iIdx);
6679 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, iIdx);
6680
6681 if (!u64BaseDMA)
6682 return;
6683
6684 pHlp->pfnPrintf(pHlp, "\tCurrent: %R[bdle]\n\n", pBDLE);
6685
6686 pHlp->pfnPrintf(pHlp, "\tMemory:\n");
6687
6688 uint32_t cbBDLE = 0;
6689 for (uint16_t i = 0; i < u16LVI + 1; i++)
6690 {
6691 HDABDLEDESC bd;
6692 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
6693
6694 pHlp->pfnPrintf(pHlp, "\t\t%s #%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
6695 pBDLE->State.u32BDLIndex == i ? "*" : " ", i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC);
6696
6697 cbBDLE += bd.u32BufSize;
6698 }
6699
6700 pHlp->pfnPrintf(pHlp, "Total: %RU32 bytes\n", cbBDLE);
6701
6702 if (cbBDLE != u32CBL)
6703 pHlp->pfnPrintf(pHlp, "Warning: %RU32 bytes does not match CBL (%RU32)!\n", cbBDLE, u32CBL);
6704
6705 pHlp->pfnPrintf(pHlp, "DMA counters (base @ 0x%llx):\n", u64BaseDMA);
6706 if (!u64BaseDMA) /* No DMA base given? Bail out. */
6707 {
6708 pHlp->pfnPrintf(pHlp, "\tNo counters found\n");
6709 return;
6710 }
6711
6712 for (int i = 0; i < u16LVI + 1; i++)
6713 {
6714 uint32_t uDMACnt;
6715 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
6716 &uDMACnt, sizeof(uDMACnt));
6717
6718 pHlp->pfnPrintf(pHlp, "\t#%03d DMA @ 0x%x\n", i , uDMACnt);
6719 }
6720}
6721
6722static int hdaDbgLookupStrmIdx(PHDASTATE pThis, const char *pszArgs)
6723{
6724 RT_NOREF(pThis, pszArgs);
6725 /** @todo Add args parsing. */
6726 return -1;
6727}
6728
6729/**
6730 * @callback_method_impl{FNDBGFHANDLERDEV}
6731 */
6732static DECLCALLBACK(void) hdaDbgInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6733{
6734 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6735 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
6736 if (iHdaStreamdex != -1)
6737 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
6738 else
6739 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
6740 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
6741}
6742
6743/**
6744 * @callback_method_impl{FNDBGFHANDLERDEV}
6745 */
6746static DECLCALLBACK(void) hdaDbgInfoBDLE(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6747{
6748 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6749 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
6750 if (iHdaStreamdex != -1)
6751 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
6752 else
6753 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
6754 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
6755}
6756
6757/**
6758 * @callback_method_impl{FNDBGFHANDLERDEV}
6759 */
6760static DECLCALLBACK(void) hdaDbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6761{
6762 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6763
6764 if (pThis->pCodec->pfnDbgListNodes)
6765 pThis->pCodec->pfnDbgListNodes(pThis->pCodec, pHlp, pszArgs);
6766 else
6767 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
6768}
6769
6770/**
6771 * @callback_method_impl{FNDBGFHANDLERDEV}
6772 */
6773static DECLCALLBACK(void) hdaDbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6774{
6775 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6776
6777 if (pThis->pCodec->pfnDbgSelector)
6778 pThis->pCodec->pfnDbgSelector(pThis->pCodec, pHlp, pszArgs);
6779 else
6780 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
6781}
6782
6783/**
6784 * @callback_method_impl{FNDBGFHANDLERDEV}
6785 */
6786static DECLCALLBACK(void) hdaDbgInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6787{
6788 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6789
6790 if (pThis->pMixer)
6791 AudioMixerDebug(pThis->pMixer, pHlp, pszArgs);
6792 else
6793 pHlp->pfnPrintf(pHlp, "Mixer not available\n");
6794}
6795
6796
6797/* PDMIBASE */
6798
6799/**
6800 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6801 */
6802static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
6803{
6804 PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
6805 Assert(&pThis->IBase == pInterface);
6806
6807 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
6808 return NULL;
6809}
6810
6811
6812/* PDMDEVREG */
6813
6814
6815/**
6816 * @interface_method_impl{PDMDEVREG,pfnReset}
6817 */
6818static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
6819{
6820 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6821
6822 LogFlowFuncEnter();
6823 /*
6824 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
6825 * hdaReset shouldn't affects these registers.
6826 */
6827 HDA_REG(pThis, WAKEEN) = 0x0;
6828
6829 hdaGctlReset(pThis);
6830
6831 /* Indicate that HDA is not in reset. The firmware is supposed to (un)reset HDA,
6832 * but we can take a shortcut.
6833 */
6834 HDA_REG(pThis, GCTL) = HDA_GCTL_CRST;
6835}
6836
6837/**
6838 * @interface_method_impl{PDMDEVREG,pfnDestruct}
6839 */
6840static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
6841{
6842 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6843
6844 PHDADRIVER pDrv;
6845 while (!RTListIsEmpty(&pThis->lstDrv))
6846 {
6847 pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node);
6848
6849 RTListNodeRemove(&pDrv->Node);
6850 RTMemFree(pDrv);
6851 }
6852
6853 if (pThis->pCodec)
6854 {
6855 hdaCodecDestruct(pThis->pCodec);
6856
6857 RTMemFree(pThis->pCodec);
6858 pThis->pCodec = NULL;
6859 }
6860
6861 RTMemFree(pThis->pu32CorbBuf);
6862 pThis->pu32CorbBuf = NULL;
6863
6864 RTMemFree(pThis->pu64RirbBuf);
6865 pThis->pu64RirbBuf = NULL;
6866
6867 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
6868 hdaStreamDestroy(pThis, &pThis->aStreams[i]);
6869
6870 return VINF_SUCCESS;
6871}
6872
6873
6874/**
6875 * Attach command, internal version.
6876 *
6877 * This is called to let the device attach to a driver for a specified LUN
6878 * during runtime. This is not called during VM construction, the device
6879 * constructor has to attach to all the available drivers.
6880 *
6881 * @returns VBox status code.
6882 * @param pDevIns The device instance.
6883 * @param pDrv Driver to (re-)use for (re-)attaching to.
6884 * If NULL is specified, a new driver will be created and appended
6885 * to the driver list.
6886 * @param uLUN The logical unit which is being detached.
6887 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6888 */
6889static int hdaAttachInternal(PPDMDEVINS pDevIns, PHDADRIVER pDrv, unsigned uLUN, uint32_t fFlags)
6890{
6891 RT_NOREF(fFlags);
6892 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6893
6894 /*
6895 * Attach driver.
6896 */
6897 char *pszDesc = NULL;
6898 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
6899 AssertReleaseMsgReturn(pszDesc,
6900 ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
6901 VERR_NO_MEMORY);
6902
6903 PPDMIBASE pDrvBase;
6904 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
6905 &pThis->IBase, &pDrvBase, pszDesc);
6906 if (RT_SUCCESS(rc))
6907 {
6908 if (pDrv == NULL)
6909 pDrv = (PHDADRIVER)RTMemAllocZ(sizeof(HDADRIVER));
6910 if (pDrv)
6911 {
6912 pDrv->pDrvBase = pDrvBase;
6913 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
6914 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
6915 pDrv->pHDAState = pThis;
6916 pDrv->uLUN = uLUN;
6917
6918 /*
6919 * For now we always set the driver at LUN 0 as our primary
6920 * host backend. This might change in the future.
6921 */
6922 if (pDrv->uLUN == 0)
6923 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
6924
6925 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
6926
6927 /* Attach to driver list if not attached yet. */
6928 if (!pDrv->fAttached)
6929 {
6930 RTListAppend(&pThis->lstDrv, &pDrv->Node);
6931 pDrv->fAttached = true;
6932 }
6933 }
6934 else
6935 rc = VERR_NO_MEMORY;
6936 }
6937 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
6938 LogFunc(("No attached driver for LUN #%u\n", uLUN));
6939
6940 if (RT_FAILURE(rc))
6941 {
6942 /* Only free this string on failure;
6943 * must remain valid for the live of the driver instance. */
6944 RTStrFree(pszDesc);
6945 }
6946
6947 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
6948 return rc;
6949}
6950
6951/**
6952 * Attach command.
6953 *
6954 * This is called to let the device attach to a driver for a specified LUN
6955 * during runtime. This is not called during VM construction, the device
6956 * constructor has to attach to all the available drivers.
6957 *
6958 * @returns VBox status code.
6959 * @param pDevIns The device instance.
6960 * @param uLUN The logical unit which is being detached.
6961 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6962 */
6963static DECLCALLBACK(int) hdaAttach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
6964{
6965 return hdaAttachInternal(pDevIns, NULL /* pDrv */, uLUN, fFlags);
6966}
6967
6968static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
6969{
6970 RT_NOREF(pDevIns, uLUN, fFlags);
6971 LogFunc(("iLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
6972}
6973
6974/**
6975 * Powers off the device.
6976 *
6977 * @param pDevIns Device instance to power off.
6978 */
6979static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns)
6980{
6981 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6982
6983 LogRel2(("HDA: Powering off ...\n"));
6984
6985 /* Ditto goes for the codec, which in turn uses the mixer. */
6986 hdaCodecPowerOff(pThis->pCodec);
6987
6988 /**
6989 * Note: Destroy the mixer while powering off and *not* in hdaDestruct,
6990 * giving the mixer the chance to release any references held to
6991 * PDM audio streams it maintains.
6992 */
6993 if (pThis->pMixer)
6994 {
6995 AudioMixerDestroy(pThis->pMixer);
6996 pThis->pMixer = NULL;
6997 }
6998}
6999
7000/**
7001 * Re-attaches a new driver to the device's driver chain.
7002 *
7003 * @returns VBox status code.
7004 * @param pThis Device instance to re-attach driver to.
7005 * @param pDrv Driver instance used for attaching to.
7006 * If NULL is specified, a new driver will be created and appended
7007 * to the driver list.
7008 * @param uLUN The logical unit which is being re-detached.
7009 * @param pszDriver Driver name.
7010 */
7011static int hdaReattach(PHDASTATE pThis, PHDADRIVER pDrv, uint8_t uLUN, const char *pszDriver)
7012{
7013 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
7014 AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
7015
7016 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
7017 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
7018 PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/hda/0/");
7019
7020 /* Remove LUN branch. */
7021 CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
7022
7023 if (pDrv)
7024 {
7025 /* Re-use a driver instance => detach the driver before. */
7026 int rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
7027 if (RT_FAILURE(rc))
7028 return rc;
7029 }
7030
7031#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
7032
7033 int rc = VINF_SUCCESS;
7034 do
7035 {
7036 PCFGMNODE pLunL0;
7037 rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN); RC_CHECK();
7038 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
7039 rc = CFGMR3InsertNode(pLunL0, "Config/", NULL); RC_CHECK();
7040
7041 PCFGMNODE pLunL1, pLunL2;
7042 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver/", &pLunL1); RC_CHECK();
7043 rc = CFGMR3InsertNode (pLunL1, "Config/", &pLunL2); RC_CHECK();
7044 rc = CFGMR3InsertString(pLunL1, "Driver", pszDriver); RC_CHECK();
7045
7046 rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver); RC_CHECK();
7047
7048 } while (0);
7049
7050 if (RT_SUCCESS(rc))
7051 rc = hdaAttachInternal(pThis->pDevInsR3, pDrv, uLUN, 0 /* fFlags */);
7052
7053 LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
7054
7055#undef RC_CHECK
7056
7057 return rc;
7058}
7059
7060/**
7061 * @interface_method_impl{PDMDEVREG,pfnConstruct}
7062 */
7063static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
7064{
7065 RT_NOREF(iInstance);
7066 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
7067 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
7068 Assert(iInstance == 0);
7069
7070 /*
7071 * Validations.
7072 */
7073 if (!CFGMR3AreValuesValid(pCfg, "R0Enabled\0"
7074 "RCEnabled\0"
7075 "TimerHz\0"))
7076 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
7077 N_ ("Invalid configuration for the Intel HDA device"));
7078
7079 int rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &pThis->fRCEnabled, false);
7080 if (RT_FAILURE(rc))
7081 return PDMDEV_SET_ERROR(pDevIns, rc,
7082 N_("HDA configuration error: failed to read RCEnabled as boolean"));
7083 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, false);
7084 if (RT_FAILURE(rc))
7085 return PDMDEV_SET_ERROR(pDevIns, rc,
7086 N_("HDA configuration error: failed to read R0Enabled as boolean"));
7087#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
7088 uint16_t uTimerHz;
7089 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, HDA_TIMER_HZ /* Default value, if not set. */);
7090 if (RT_FAILURE(rc))
7091 return PDMDEV_SET_ERROR(pDevIns, rc,
7092 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
7093#endif
7094
7095 /*
7096 * Initialize data (most of it anyway).
7097 */
7098 pThis->pDevInsR3 = pDevIns;
7099 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
7100 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
7101 /* IBase */
7102 pThis->IBase.pfnQueryInterface = hdaQueryInterface;
7103
7104 /* PCI Device */
7105 PCIDevSetVendorId (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
7106 PCIDevSetDeviceId (&pThis->PciDev, HDA_PCI_DEVICE_ID); /* HDA */
7107
7108 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
7109 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
7110 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */
7111 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */
7112 PCIDevSetClassSub (&pThis->PciDev, 0x03); /* 0a ro - scc; 03 == HDA. */
7113 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
7114 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */
7115 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - MMIO */
7116 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
7117 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */
7118 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */
7119
7120#if defined(HDA_AS_PCI_EXPRESS)
7121 PCIDevSetCapabilityList (&pThis->PciDev, 0x80);
7122#elif defined(VBOX_WITH_MSI_DEVICES)
7123 PCIDevSetCapabilityList (&pThis->PciDev, 0x60);
7124#else
7125 PCIDevSetCapabilityList (&pThis->PciDev, 0x50); /* ICH6 datasheet 18.1.16 */
7126#endif
7127
7128 /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
7129 /// of these values needs to be properly documented!
7130 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
7131 PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
7132
7133 /* Power Management */
7134 PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
7135 PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
7136 PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
7137
7138#ifdef HDA_AS_PCI_EXPRESS
7139 /* PCI Express */
7140 PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
7141 PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
7142 /* Device flags */
7143 PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
7144 /* version */ 0x1 |
7145 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
7146 /* MSI */ (100) << 9 );
7147 /* Device capabilities */
7148 PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
7149 /* Device control */
7150 PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
7151 /* Device status */
7152 PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
7153 /* Link caps */
7154 PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
7155 /* Link control */
7156 PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
7157 /* Link status */
7158 PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
7159 /* Slot capabilities */
7160 PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
7161 /* Slot control */
7162 PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
7163 /* Slot status */
7164 PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
7165 /* Root control */
7166 PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
7167 /* Root capabilities */
7168 PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
7169 /* Root status */
7170 PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
7171 /* Device capabilities 2 */
7172 PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
7173 /* Device control 2 */
7174 PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
7175 /* Link control 2 */
7176 PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
7177 /* Slot control 2 */
7178 PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
7179#endif
7180
7181 /*
7182 * Register the PCI device.
7183 */
7184 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
7185 if (RT_FAILURE(rc))
7186 return rc;
7187
7188 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
7189 if (RT_FAILURE(rc))
7190 return rc;
7191
7192#ifdef VBOX_WITH_MSI_DEVICES
7193 PDMMSIREG MsiReg;
7194 RT_ZERO(MsiReg);
7195 MsiReg.cMsiVectors = 1;
7196 MsiReg.iMsiCapOffset = 0x60;
7197 MsiReg.iMsiNextOffset = 0x50;
7198 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
7199 if (RT_FAILURE(rc))
7200 {
7201 /* That's OK, we can work without MSI */
7202 PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
7203 }
7204#endif
7205
7206 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
7207 if (RT_FAILURE(rc))
7208 return rc;
7209
7210 RTListInit(&pThis->lstDrv);
7211
7212#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
7213 LogRel(("HDA: Asynchronous I/O enabled\n"));
7214#endif
7215
7216 uint8_t uLUN;
7217 for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
7218 {
7219 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
7220 rc = hdaAttachInternal(pDevIns, NULL /* pDrv */, uLUN, 0 /* fFlags */);
7221 if (RT_FAILURE(rc))
7222 {
7223 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
7224 rc = VINF_SUCCESS;
7225 else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
7226 {
7227 hdaReattach(pThis, NULL /* pDrv */, uLUN, "NullAudio");
7228 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
7229 N_("Host audio backend initialization has failed. Selecting the NULL audio backend "
7230 "with the consequence that no sound is audible"));
7231 /* Attaching to the NULL audio backend will never fail. */
7232 rc = VINF_SUCCESS;
7233 }
7234 break;
7235 }
7236 }
7237
7238 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
7239
7240 if (RT_SUCCESS(rc))
7241 {
7242 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer);
7243 if (RT_SUCCESS(rc))
7244 {
7245 /*
7246 * Add mixer output sinks.
7247 */
7248#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
7249 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front",
7250 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
7251 AssertRC(rc);
7252 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer",
7253 AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink);
7254 AssertRC(rc);
7255 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear",
7256 AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink);
7257 AssertRC(rc);
7258#else
7259 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output",
7260 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
7261 AssertRC(rc);
7262#endif
7263 /*
7264 * Add mixer input sinks.
7265 */
7266 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",
7267 AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink);
7268 AssertRC(rc);
7269#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7270 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In",
7271 AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink);
7272 AssertRC(rc);
7273#endif
7274 /* There is no master volume control. Set the master to max. */
7275 PDMAUDIOVOLUME vol = { false, 255, 255 };
7276 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
7277 AssertRC(rc);
7278 }
7279 }
7280
7281 if (RT_SUCCESS(rc))
7282 {
7283 /* Construct codec. */
7284 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
7285 if (!pThis->pCodec)
7286 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state"));
7287
7288 /* Set codec callbacks to this controller. */
7289 pThis->pCodec->pfnCbMixerAddStream = hdaMixerAddStream;
7290 pThis->pCodec->pfnCbMixerRemoveStream = hdaMixerRemoveStream;
7291 pThis->pCodec->pfnCbMixerSetStream = hdaMixerSetStream;
7292 pThis->pCodec->pfnCbMixerSetVolume = hdaMixerSetVolume;
7293
7294 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */
7295
7296 /* Construct the codec. */
7297 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg);
7298 if (RT_FAILURE(rc))
7299 AssertRCReturn(rc, rc);
7300
7301 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
7302 verb F20 should provide device/codec recognition. */
7303 Assert(pThis->pCodec->u16VendorId);
7304 Assert(pThis->pCodec->u16DeviceId);
7305 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
7306 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
7307 }
7308
7309 if (RT_SUCCESS(rc))
7310 {
7311 /*
7312 * Create all hardware streams.
7313 */
7314 for (uint8_t i = 0; i < HDA_MAX_STREAMS; ++i)
7315 {
7316 rc = hdaStreamCreate(pThis, &pThis->aStreams[i]);
7317 AssertRC(rc);
7318 }
7319
7320#ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
7321 /*
7322 * Initialize the driver chain.
7323 */
7324 PHDADRIVER pDrv;
7325 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
7326 {
7327 /*
7328 * Only primary drivers are critical for the VM to run. Everything else
7329 * might not worth showing an own error message box in the GUI.
7330 */
7331 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
7332 continue;
7333
7334 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
7335 AssertPtr(pCon);
7336
7337 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
7338# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7339 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
7340# endif
7341 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
7342# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
7343 /** @todo Anything to do here? */
7344# endif
7345
7346 if ( !fValidLineIn
7347# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7348 && !fValidMicIn
7349# endif
7350 && !fValidOut)
7351 {
7352 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
7353
7354 hdaReset(pDevIns);
7355 hdaReattach(pThis, pDrv, pDrv->uLUN, "NullAudio");
7356
7357 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
7358 N_("No audio devices could be opened. Selecting the NULL audio backend "
7359 "with the consequence that no sound is audible"));
7360 }
7361 else
7362 {
7363 bool fWarn = false;
7364
7365 PDMAUDIOBACKENDCFG backendCfg;
7366 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
7367 if (RT_SUCCESS(rc2))
7368 {
7369 if (backendCfg.cMaxStreamsIn)
7370 {
7371# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7372 /* If the audio backend supports two or more input streams at once,
7373 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
7374 if (backendCfg.cMaxStreamsIn >= 2)
7375 fWarn = !fValidLineIn || !fValidMicIn;
7376 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
7377 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
7378 * One of the two simply is not in use then. */
7379 else if (backendCfg.cMaxStreamsIn == 1)
7380 fWarn = !fValidLineIn && !fValidMicIn;
7381 /* Don't warn if our backend is not able of supporting any input streams at all. */
7382# else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
7383 /* We only have line-in as input source. */
7384 fWarn = !fValidLineIn;
7385# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
7386 }
7387
7388 if ( !fWarn
7389 && backendCfg.cMaxStreamsOut)
7390 {
7391 fWarn = !fValidOut;
7392 }
7393 }
7394 else
7395 {
7396 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
7397 fWarn = true;
7398 }
7399
7400 if (fWarn)
7401 {
7402 char szMissingStreams[255];
7403 size_t len = 0;
7404 if (!fValidLineIn)
7405 {
7406 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
7407 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
7408 }
7409# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7410 if (!fValidMicIn)
7411 {
7412 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
7413 len += RTStrPrintf(szMissingStreams + len,
7414 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
7415 }
7416# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
7417 if (!fValidOut)
7418 {
7419 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
7420 len += RTStrPrintf(szMissingStreams + len,
7421 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
7422 }
7423
7424 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
7425 N_("Some HDA audio streams (%s) could not be opened. Guest applications generating audio "
7426 "output or depending on audio input may hang. Make sure your host audio device "
7427 "is working properly. Check the logfile for error messages of the audio "
7428 "subsystem"), szMissingStreams);
7429 }
7430 }
7431 }
7432#endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
7433 }
7434
7435 if (RT_SUCCESS(rc))
7436 {
7437 hdaReset(pDevIns);
7438
7439 /*
7440 * Debug and string formatter types.
7441 */
7442 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaDbgInfo);
7443 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaDbgInfoBDLE);
7444 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastream", "HDA stream info. (hdastream [stream number])", hdaDbgInfoStream);
7445 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaDbgInfoCodecNodes);
7446 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaDbgInfoCodecSelector);
7447 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaDbgInfoMixer);
7448
7449 rc = RTStrFormatTypeRegister("bdle", hdaDbgFmtBDLE, NULL);
7450 AssertRC(rc);
7451 rc = RTStrFormatTypeRegister("sdctl", hdaDbgFmtSDCTL, NULL);
7452 AssertRC(rc);
7453 rc = RTStrFormatTypeRegister("sdsts", hdaDbgFmtSDSTS, NULL);
7454 AssertRC(rc);
7455 rc = RTStrFormatTypeRegister("sdfifos", hdaDbgFmtSDFIFOS, NULL);
7456 AssertRC(rc);
7457 rc = RTStrFormatTypeRegister("sdfifow", hdaDbgFmtSDFIFOW, NULL);
7458 AssertRC(rc);
7459
7460 /*
7461 * Some debug assertions.
7462 */
7463 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
7464 {
7465 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
7466 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
7467
7468 /* binary search order. */
7469 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
7470 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7471 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
7472
7473 /* alignment. */
7474 AssertReleaseMsg( pReg->size == 1
7475 || (pReg->size == 2 && (pReg->offset & 1) == 0)
7476 || (pReg->size == 3 && (pReg->offset & 3) == 0)
7477 || (pReg->size == 4 && (pReg->offset & 3) == 0),
7478 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7479
7480 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
7481 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
7482 if (pReg->offset & 3)
7483 {
7484 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL;
7485 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7486 if (pPrevReg)
7487 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
7488 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7489 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
7490 }
7491#if 0
7492 if ((pReg->offset + pReg->size) & 3)
7493 {
7494 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7495 if (pNextReg)
7496 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
7497 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7498 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
7499 }
7500#endif
7501 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */
7502 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
7503 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7504 }
7505 }
7506
7507# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
7508 if (RT_SUCCESS(rc))
7509 {
7510 /* Create the emulation timer.
7511 *
7512 * Note: Use TMCLOCK_VIRTUAL_SYNC here, as the guest's HDA driver
7513 * relies on exact (virtual) DMA timing and uses DMA Position Buffers
7514 * instead of the LPIB registers.
7515 */
7516 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hdaTimer, pThis,
7517 TMTIMER_FLAGS_NO_CRIT_SECT, "DevHDA", &pThis->pTimer);
7518 AssertRCReturn(rc, rc);
7519
7520 if (RT_SUCCESS(rc))
7521 {
7522 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
7523 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
7524 }
7525 }
7526# else
7527 if (RT_SUCCESS(rc))
7528 {
7529 PHDADRIVER pDrv;
7530 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
7531 {
7532 /* Only register primary driver.
7533 * The device emulation does the output multiplexing then. */
7534 if (pDrv->fFlags != PDMAUDIODRVFLAGS_PRIMARY)
7535 continue;
7536
7537 PDMAUDIOCALLBACK AudioCallbacks[2];
7538
7539 HDACALLBACKCTX Ctx = { pThis, pDrv };
7540
7541 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT;
7542 AudioCallbacks[0].pfnCallback = hdaCallbackInput;
7543 AudioCallbacks[0].pvCtx = &Ctx;
7544 AudioCallbacks[0].cbCtx = sizeof(HDACALLBACKCTX);
7545
7546 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT;
7547 AudioCallbacks[1].pfnCallback = hdaCallbackOutput;
7548 AudioCallbacks[1].pvCtx = &Ctx;
7549 AudioCallbacks[1].cbCtx = sizeof(HDACALLBACKCTX);
7550
7551 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
7552 if (RT_FAILURE(rc))
7553 break;
7554 }
7555 }
7556# endif
7557
7558# ifdef VBOX_WITH_STATISTICS
7559 if (RT_SUCCESS(rc))
7560 {
7561 /*
7562 * Register statistics.
7563 */
7564# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
7565 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer.");
7566# endif
7567 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "/Devices/HDA/Input", STAMUNIT_TICKS_PER_CALL, "Profiling input.");
7568 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "/Devices/HDA/Output", STAMUNIT_TICKS_PER_CALL, "Profiling output.");
7569 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation.");
7570 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation.");
7571 }
7572# endif
7573
7574#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
7575 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm");
7576 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm");
7577 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm");
7578 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm");
7579#endif
7580
7581 LogFlowFuncLeaveRC(rc);
7582 return rc;
7583}
7584
7585/**
7586 * The device registration structure.
7587 */
7588const PDMDEVREG g_DeviceHDA =
7589{
7590 /* u32Version */
7591 PDM_DEVREG_VERSION,
7592 /* szName */
7593 "hda",
7594 /* szRCMod */
7595 "VBoxDDRC.rc",
7596 /* szR0Mod */
7597 "VBoxDDR0.r0",
7598 /* pszDescription */
7599 "Intel HD Audio Controller",
7600 /* fFlags */
7601 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
7602 /* fClass */
7603 PDM_DEVREG_CLASS_AUDIO,
7604 /* cMaxInstances */
7605 1,
7606 /* cbInstance */
7607 sizeof(HDASTATE),
7608 /* pfnConstruct */
7609 hdaConstruct,
7610 /* pfnDestruct */
7611 hdaDestruct,
7612 /* pfnRelocate */
7613 NULL,
7614 /* pfnMemSetup */
7615 NULL,
7616 /* pfnPowerOn */
7617 NULL,
7618 /* pfnReset */
7619 hdaReset,
7620 /* pfnSuspend */
7621 NULL,
7622 /* pfnResume */
7623 NULL,
7624 /* pfnAttach */
7625 hdaAttach,
7626 /* pfnDetach */
7627 hdaDetach,
7628 /* pfnQueryInterface. */
7629 NULL,
7630 /* pfnInitComplete */
7631 NULL,
7632 /* pfnPowerOff */
7633 hdaPowerOff,
7634 /* pfnSoftReset */
7635 NULL,
7636 /* u32VersionEnd */
7637 PDM_DEVREG_VERSION
7638};
7639
7640#endif /* IN_RING3 */
7641#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