VirtualBox

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

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

Audio: Implemented dynamic fallback support to NULL audio backends for HDA, AC'97 and SB16 emulation; also did some preparations for audio hotplugging support.

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