VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevIchHda.cpp@ 60941

Last change on this file since 60941 was 60941, checked in by vboxsync, 9 years ago

Audio/HDA:

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