VirtualBox

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

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

Audio: Implemented support for audio device enumeration handling, audio device information and audio backend notifications. This will enable to let the backends tell the audio subsystem that the host audio configuration has changed and react accordingly to it. For now only the Core Audio backend supports device enumeration. Further this also will get rid of the static initialization on the device emulation side, which, if at VM startup no audio input(s) / output(s) were available, was triggering a warning. The NULL backend therefore does not need to act as a (static) fallback anymore.

Work in progress.

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

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