VirtualBox

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

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

HDA: Warning.

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