VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio_old/DevIchHda.cpp@ 61413

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

Audio: Use the old audio code for now when doing a release. Set VBOX_WITH_AUDIO_STABLE to an empty value to enable the new audio code (default for non-release builds for now).

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