VirtualBox

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

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

Audio/HDA: windows build fixes

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

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