VirtualBox

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

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

Audio: Start async I/O threads on demand.

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

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