VirtualBox

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

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

Audio/DevIchHda.cpp: Lowered timer Hertz rate from 500Hz to 200Hz by default.

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