VirtualBox

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

Last change on this file since 53853 was 53853, checked in by vboxsync, 10 years ago

PDM/Audio: Initialize rc.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 161.1 KB
Line 
1/* $Id: DevIchHda.cpp 53853 2015-01-16 11:36: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-2014 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* Header Files *
24*******************************************************************************/
25#include <VBox/vmm/pdmdev.h>
26#include <VBox/vmm/pdmaudioifs.h>
27#include <VBox/version.h>
28
29#include <iprt/assert.h>
30#include <iprt/asm.h>
31#include <iprt/asm-math.h>
32#ifdef IN_RING3
33# include <iprt/uuid.h>
34# include <iprt/string.h>
35# include <iprt/mem.h>
36#endif
37#include <iprt/list.h>
38
39#if 0
40/* Warning: Enabling this causes a *lot* of output! */
41#ifdef LOG_GROUP
42# undef LOG_GROUP
43#endif
44#define LOG_GROUP LOG_GROUP_DEV_AUDIO
45#include <VBox/log.h>
46#endif
47
48#include "VBoxDD.h"
49
50#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
51# include "AudioMixer.h"
52#else
53 extern "C" {
54 #include "audio.h"
55 }
56#endif
57#include "DevIchHdaCodec.h"
58
59#ifdef DEBUG
60//#define DEBUG_LUN
61# ifdef DEBUG_LUN
62# define DEBUG_LUN_NUM 0
63# endif
64#endif /* DEBUG */
65
66/*******************************************************************************
67* Defined Constants And Macros *
68*******************************************************************************/
69//#define HDA_AS_PCI_EXPRESS
70#define VBOX_WITH_INTEL_HDA
71
72#if (defined(DEBUG) && defined(DEBUG_andy))
73/* Enables experimental support for separate mic-in handling.
74 Do not enable this yet for regular builds, as this needs more testing first! */
75# define VBOX_WITH_HDA_MIC_IN
76#endif
77
78#if defined(VBOX_WITH_HP_HDA)
79/* HP Pavilion dv4t-1300 */
80# define HDA_PCI_VENDOR_ID 0x103c
81# define HDA_PCI_DEVICE_ID 0x30f7
82#elif defined(VBOX_WITH_INTEL_HDA)
83/* Intel HDA controller */
84# define HDA_PCI_VENDOR_ID 0x8086
85# define HDA_PCI_DEVICE_ID 0x2668
86#elif defined(VBOX_WITH_NVIDIA_HDA)
87/* nVidia HDA controller */
88# define HDA_PCI_VENDOR_ID 0x10de
89# define HDA_PCI_DEVICE_ID 0x0ac0
90#else
91# error "Please specify your HDA device vendor/device IDs"
92#endif
93
94/** @todo r=bird: Looking at what the linux driver (accidentally?) does when
95 * updating CORBWP, I belive that the ICH6 datahsheet is wrong and that CORBRP
96 * is read only except for bit 15 like the HDA spec states.
97 *
98 * Btw. the CORBRPRST implementation is incomplete according to both docs (sw
99 * writes 1, hw sets it to 1 (after completion), sw reads 1, sw writes 0). */
100#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
101
102#define HDA_NREGS 114
103#define HDA_NREGS_SAVED 112
104
105/**
106 * NB: Register values stored in memory (au32Regs[]) are indexed through
107 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
108 * register descriptors in g_aHdaRegMap[] are indexed through the
109 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
110 *
111 * The au32Regs[] layout is kept unchanged for saved state
112 * compatibility. */
113
114/* Registers */
115#define HDA_REG_IND_NAME(x) HDA_REG_##x
116#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
117#define HDA_REG_FIELD_MASK(reg, x) HDA_##reg##_##x##_MASK
118#define HDA_REG_FIELD_FLAG_MASK(reg, x) RT_BIT(HDA_##reg##_##x##_SHIFT)
119#define HDA_REG_FIELD_SHIFT(reg, x) HDA_##reg##_##x##_SHIFT
120#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
121#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
122#define HDA_REG_FLAG_VALUE(pThis, reg, val) (HDA_REG((pThis),reg) & (((HDA_REG_FIELD_FLAG_MASK(reg, val)))))
123
124
125#define HDA_REG_GCAP 0 /* range 0x00-0x01*/
126#define HDA_RMX_GCAP 0
127/* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
128 * oss (15:12) - number of output streams supported
129 * iss (11:8) - number of input streams supported
130 * bss (7:3) - number of bidirectional streams supported
131 * bds (2:1) - number of serial data out signals supported
132 * b64sup (0) - 64 bit addressing supported.
133 */
134#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
135 ( (((oss) & 0xF) << 12) \
136 | (((iss) & 0xF) << 8) \
137 | (((bss) & 0x1F) << 3) \
138 | (((bds) & 0x3) << 2) \
139 | ((b64sup) & 1))
140
141#define HDA_REG_VMIN 1 /* 0x02 */
142#define HDA_RMX_VMIN 1
143
144#define HDA_REG_VMAJ 2 /* 0x03 */
145#define HDA_RMX_VMAJ 2
146
147#define HDA_REG_OUTPAY 3 /* 0x04-0x05 */
148#define HDA_RMX_OUTPAY 3
149
150#define HDA_REG_INPAY 4 /* 0x06-0x07 */
151#define HDA_RMX_INPAY 4
152
153#define HDA_REG_GCTL 5 /* 0x08-0x0B */
154#define HDA_RMX_GCTL 5
155#define HDA_GCTL_RST_SHIFT 0
156#define HDA_GCTL_FSH_SHIFT 1
157#define HDA_GCTL_UR_SHIFT 8
158
159#define HDA_REG_WAKEEN 6 /* 0x0C */
160#define HDA_RMX_WAKEEN 6
161
162#define HDA_REG_STATESTS 7 /* 0x0E */
163#define HDA_RMX_STATESTS 7
164#define HDA_STATES_SCSF 0x7
165
166#define HDA_REG_GSTS 8 /* 0x10-0x11*/
167#define HDA_RMX_GSTS 8
168#define HDA_GSTS_FSH_SHIFT 1
169
170#define HDA_REG_OUTSTRMPAY 9 /* 0x18 */
171#define HDA_RMX_OUTSTRMPAY 112
172
173#define HDA_REG_INSTRMPAY 10 /* 0x1a */
174#define HDA_RMX_INSTRMPAY 113
175
176#define HDA_REG_INTCTL 11 /* 0x20 */
177#define HDA_RMX_INTCTL 9
178#define HDA_INTCTL_GIE_SHIFT 31
179#define HDA_INTCTL_CIE_SHIFT 30
180#define HDA_INTCTL_S0_SHIFT 0
181#define HDA_INTCTL_S1_SHIFT 1
182#define HDA_INTCTL_S2_SHIFT 2
183#define HDA_INTCTL_S3_SHIFT 3
184#define HDA_INTCTL_S4_SHIFT 4
185#define HDA_INTCTL_S5_SHIFT 5
186#define HDA_INTCTL_S6_SHIFT 6
187#define HDA_INTCTL_S7_SHIFT 7
188#define INTCTL_SX(pThis, X) (HDA_REG_FLAG_VALUE((pThis), INTCTL, S##X))
189
190#define HDA_REG_INTSTS 12 /* 0x24 */
191#define HDA_RMX_INTSTS 10
192#define HDA_INTSTS_GIS_SHIFT 31
193#define HDA_INTSTS_CIS_SHIFT 30
194#define HDA_INTSTS_S0_SHIFT 0
195#define HDA_INTSTS_S1_SHIFT 1
196#define HDA_INTSTS_S2_SHIFT 2
197#define HDA_INTSTS_S3_SHIFT 3
198#define HDA_INTSTS_S4_SHIFT 4
199#define HDA_INTSTS_S5_SHIFT 5
200#define HDA_INTSTS_S6_SHIFT 6
201#define HDA_INTSTS_S7_SHIFT 7
202#define HDA_INTSTS_S_MASK(num) RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
203
204#define HDA_REG_WALCLK 13 /* 0x24 */
205#define HDA_RMX_WALCLK /* Not defined! */
206
207/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
208 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
209 * the datasheet.
210 */
211#define HDA_REG_SSYNC 14 /* 0x34 */
212#define HDA_RMX_SSYNC 12
213
214#define HDA_REG_CORBLBASE 15 /* 0x40 */
215#define HDA_RMX_CORBLBASE 13
216
217#define HDA_REG_CORBUBASE 16 /* 0x44 */
218#define HDA_RMX_CORBUBASE 14
219
220#define HDA_REG_CORBWP 17 /* 0x48 */
221#define HDA_RMX_CORBWP 15
222
223#define HDA_REG_CORBRP 18 /* 0x4A */
224#define HDA_RMX_CORBRP 16
225#define HDA_CORBRP_RST_SHIFT 15
226#define HDA_CORBRP_WP_SHIFT 0
227#define HDA_CORBRP_WP_MASK 0xFF
228
229#define HDA_REG_CORBCTL 19 /* 0x4C */
230#define HDA_RMX_CORBCTL 17
231#define HDA_CORBCTL_DMA_SHIFT 1
232#define HDA_CORBCTL_CMEIE_SHIFT 0
233
234#define HDA_REG_CORBSTS 20 /* 0x4D */
235#define HDA_RMX_CORBSTS 18
236#define HDA_CORBSTS_CMEI_SHIFT 0
237
238#define HDA_REG_CORBSIZE 21 /* 0x4E */
239#define HDA_RMX_CORBSIZE 19
240#define HDA_CORBSIZE_SZ_CAP 0xF0
241#define HDA_CORBSIZE_SZ 0x3
242/* till ich 10 sizes of CORB and RIRB are hardcoded to 256 in real hw */
243
244#define HDA_REG_RIRBLBASE 22 /* 0x50 */
245#define HDA_RMX_RIRBLBASE 20
246
247#define HDA_REG_RIRBUBASE 23 /* 0x54 */
248#define HDA_RMX_RIRBUBASE 21
249
250#define HDA_REG_RIRBWP 24 /* 0x58 */
251#define HDA_RMX_RIRBWP 22
252#define HDA_RIRBWP_RST_SHIFT 15
253#define HDA_RIRBWP_WP_MASK 0xFF
254
255#define HDA_REG_RINTCNT 25 /* 0x5A */
256#define HDA_RMX_RINTCNT 23
257#define RINTCNT_N(pThis) (HDA_REG(pThis, RINTCNT) & 0xff)
258
259#define HDA_REG_RIRBCTL 26 /* 0x5C */
260#define HDA_RMX_RIRBCTL 24
261#define HDA_RIRBCTL_RIC_SHIFT 0
262#define HDA_RIRBCTL_DMA_SHIFT 1
263#define HDA_ROI_DMA_SHIFT 2
264
265#define HDA_REG_RIRBSTS 27 /* 0x5D */
266#define HDA_RMX_RIRBSTS 25
267#define HDA_RIRBSTS_RINTFL_SHIFT 0
268#define HDA_RIRBSTS_RIRBOIS_SHIFT 2
269
270#define HDA_REG_RIRBSIZE 28 /* 0x5E */
271#define HDA_RMX_RIRBSIZE 26
272#define HDA_RIRBSIZE_SZ_CAP 0xF0
273#define HDA_RIRBSIZE_SZ 0x3
274
275#define RIRBSIZE_SZ(pThis) (HDA_REG(pThis, HDA_REG_RIRBSIZE) & HDA_RIRBSIZE_SZ)
276#define RIRBSIZE_SZ_CAP(pThis) (HDA_REG(pThis, HDA_REG_RIRBSIZE) & HDA_RIRBSIZE_SZ_CAP)
277
278
279#define HDA_REG_IC 29 /* 0x60 */
280#define HDA_RMX_IC 27
281
282#define HDA_REG_IR 30 /* 0x64 */
283#define HDA_RMX_IR 28
284
285#define HDA_REG_IRS 31 /* 0x68 */
286#define HDA_RMX_IRS 29
287#define HDA_IRS_ICB_SHIFT 0
288#define HDA_IRS_IRV_SHIFT 1
289
290#define HDA_REG_DPLBASE 32 /* 0x70 */
291#define HDA_RMX_DPLBASE 30
292#define DPLBASE(pThis) (HDA_REG((pThis), DPLBASE))
293
294#define HDA_REG_DPUBASE 33 /* 0x74 */
295#define HDA_RMX_DPUBASE 31
296#define DPUBASE(pThis) (HDA_REG((pThis), DPUBASE))
297#define DPBASE_ENABLED 1
298#define DPBASE_ADDR_MASK (~(uint64_t)0x7f)
299
300#define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)
301#define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)
302/* Note: sdnum here _MUST_ be stream reg number [0,7]. */
303#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
304
305#define HDA_REG_SD0CTL 34 /* 0x80 */
306#define HDA_REG_SD1CTL (HDA_STREAM_REG_DEF(CTL, 0) + 10) /* 0xA0 */
307#define HDA_REG_SD2CTL (HDA_STREAM_REG_DEF(CTL, 0) + 20) /* 0xC0 */
308#define HDA_REG_SD3CTL (HDA_STREAM_REG_DEF(CTL, 0) + 30) /* 0xE0 */
309#define HDA_REG_SD4CTL (HDA_STREAM_REG_DEF(CTL, 0) + 40) /* 0x100 */
310#define HDA_REG_SD5CTL (HDA_STREAM_REG_DEF(CTL, 0) + 50) /* 0x120 */
311#define HDA_REG_SD6CTL (HDA_STREAM_REG_DEF(CTL, 0) + 60) /* 0x140 */
312#define HDA_REG_SD7CTL (HDA_STREAM_REG_DEF(CTL, 0) + 70) /* 0x160 */
313#define HDA_RMX_SD0CTL 32
314#define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
315#define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
316#define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
317#define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
318#define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
319#define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
320#define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
321
322#define SD(func, num) SD##num##func
323#define SDCTL(pThis, num) HDA_REG((pThis), SD(CTL, num))
324#define SDCTL_NUM(pThis, num) ((SDCTL((pThis), num) & HDA_REG_FIELD_MASK(SDCTL,NUM)) >> HDA_REG_FIELD_SHIFT(SDCTL, NUM))
325#define HDA_SDCTL_NUM_MASK 0xF
326#define HDA_SDCTL_NUM_SHIFT 20
327#define HDA_SDCTL_DIR_SHIFT 19
328#define HDA_SDCTL_TP_SHIFT 18
329#define HDA_SDCTL_STRIPE_MASK 0x3
330#define HDA_SDCTL_STRIPE_SHIFT 16
331#define HDA_SDCTL_DEIE_SHIFT 4
332#define HDA_SDCTL_FEIE_SHIFT 3
333#define HDA_SDCTL_ICE_SHIFT 2
334#define HDA_SDCTL_RUN_SHIFT 1
335#define HDA_SDCTL_SRST_SHIFT 0
336
337#define HDA_REG_SD0STS 35 /* 0x83 */
338#define HDA_REG_SD1STS (HDA_STREAM_REG_DEF(STS, 0) + 10) /* 0xA3 */
339#define HDA_REG_SD2STS (HDA_STREAM_REG_DEF(STS, 0) + 20) /* 0xC3 */
340#define HDA_REG_SD3STS (HDA_STREAM_REG_DEF(STS, 0) + 30) /* 0xE3 */
341#define HDA_REG_SD4STS (HDA_STREAM_REG_DEF(STS, 0) + 40) /* 0x103 */
342#define HDA_REG_SD5STS (HDA_STREAM_REG_DEF(STS, 0) + 50) /* 0x123 */
343#define HDA_REG_SD6STS (HDA_STREAM_REG_DEF(STS, 0) + 60) /* 0x143 */
344#define HDA_REG_SD7STS (HDA_STREAM_REG_DEF(STS, 0) + 70) /* 0x163 */
345#define HDA_RMX_SD0STS 33
346#define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)
347#define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)
348#define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)
349#define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)
350#define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)
351#define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)
352#define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)
353
354#define SDSTS(pThis, num) HDA_REG((pThis), SD(STS, num))
355#define HDA_SDSTS_FIFORDY_SHIFT 5
356#define HDA_SDSTS_DE_SHIFT 4
357#define HDA_SDSTS_FE_SHIFT 3
358#define HDA_SDSTS_BCIS_SHIFT 2
359
360#define HDA_REG_SD0LPIB 36 /* 0x84 */
361#define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
362#define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
363#define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
364#define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
365#define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
366#define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
367#define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
368#define HDA_RMX_SD0LPIB 34
369#define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
370#define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
371#define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
372#define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
373#define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
374#define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
375#define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
376
377#define HDA_REG_SD0CBL 37 /* 0x88 */
378#define HDA_REG_SD1CBL (HDA_STREAM_REG_DEF(CBL, 0) + 10) /* 0xA8 */
379#define HDA_REG_SD2CBL (HDA_STREAM_REG_DEF(CBL, 0) + 20) /* 0xC8 */
380#define HDA_REG_SD3CBL (HDA_STREAM_REG_DEF(CBL, 0) + 30) /* 0xE8 */
381#define HDA_REG_SD4CBL (HDA_STREAM_REG_DEF(CBL, 0) + 40) /* 0x108 */
382#define HDA_REG_SD5CBL (HDA_STREAM_REG_DEF(CBL, 0) + 50) /* 0x128 */
383#define HDA_REG_SD6CBL (HDA_STREAM_REG_DEF(CBL, 0) + 60) /* 0x148 */
384#define HDA_REG_SD7CBL (HDA_STREAM_REG_DEF(CBL, 0) + 70) /* 0x168 */
385#define HDA_RMX_SD0CBL 35
386#define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
387#define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
388#define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
389#define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
390#define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
391#define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
392#define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
393
394
395#define HDA_REG_SD0LVI 38 /* 0x8C */
396#define HDA_REG_SD1LVI (HDA_STREAM_REG_DEF(LVI, 0) + 10) /* 0xAC */
397#define HDA_REG_SD2LVI (HDA_STREAM_REG_DEF(LVI, 0) + 20) /* 0xCC */
398#define HDA_REG_SD3LVI (HDA_STREAM_REG_DEF(LVI, 0) + 30) /* 0xEC */
399#define HDA_REG_SD4LVI (HDA_STREAM_REG_DEF(LVI, 0) + 40) /* 0x10C */
400#define HDA_REG_SD5LVI (HDA_STREAM_REG_DEF(LVI, 0) + 50) /* 0x12C */
401#define HDA_REG_SD6LVI (HDA_STREAM_REG_DEF(LVI, 0) + 60) /* 0x14C */
402#define HDA_REG_SD7LVI (HDA_STREAM_REG_DEF(LVI, 0) + 70) /* 0x16C */
403#define HDA_RMX_SD0LVI 36
404#define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
405#define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
406#define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
407#define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
408#define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
409#define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
410#define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
411
412#define HDA_REG_SD0FIFOW 39 /* 0x8E */
413#define HDA_REG_SD1FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 10) /* 0xAE */
414#define HDA_REG_SD2FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 20) /* 0xCE */
415#define HDA_REG_SD3FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 30) /* 0xEE */
416#define HDA_REG_SD4FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 40) /* 0x10E */
417#define HDA_REG_SD5FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 50) /* 0x12E */
418#define HDA_REG_SD6FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 60) /* 0x14E */
419#define HDA_REG_SD7FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 70) /* 0x16E */
420#define HDA_RMX_SD0FIFOW 37
421#define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
422#define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
423#define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
424#define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
425#define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
426#define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
427#define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
428
429/*
430 * ICH6 datasheet defined limits for FIFOW values (18.2.38)
431 */
432#define HDA_SDFIFOW_8B 0x2
433#define HDA_SDFIFOW_16B 0x3
434#define HDA_SDFIFOW_32B 0x4
435
436#define HDA_REG_SD0FIFOS 40 /* 0x90 */
437#define HDA_REG_SD1FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 10) /* 0xB0 */
438#define HDA_REG_SD2FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 20) /* 0xD0 */
439#define HDA_REG_SD3FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 30) /* 0xF0 */
440#define HDA_REG_SD4FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 40) /* 0x110 */
441#define HDA_REG_SD5FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 50) /* 0x130 */
442#define HDA_REG_SD6FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 60) /* 0x150 */
443#define HDA_REG_SD7FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 70) /* 0x170 */
444#define HDA_RMX_SD0FIFOS 38
445#define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
446#define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
447#define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
448#define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
449#define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
450#define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
451#define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
452
453/*
454 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
455 * formula: size - 1
456 * Other values not listed are not supported.
457 */
458#define HDA_SDONFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
459#define HDA_SDONFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
460#define HDA_SDONFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
461#define HDA_SDONFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
462#define HDA_SDONFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
463#define HDA_SDONFIFO_256B 0xFF /* 20-, 24-bit Output Streams */
464#define HDA_SDINFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
465#define HDA_SDINFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */
466#define SDFIFOS(pThis, num) HDA_REG((pThis), SD(FIFOS, num))
467
468#define HDA_REG_SD0FMT 41 /* 0x92 */
469#define HDA_REG_SD1FMT (HDA_STREAM_REG_DEF(FMT, 0) + 10) /* 0xB2 */
470#define HDA_REG_SD2FMT (HDA_STREAM_REG_DEF(FMT, 0) + 20) /* 0xD2 */
471#define HDA_REG_SD3FMT (HDA_STREAM_REG_DEF(FMT, 0) + 30) /* 0xF2 */
472#define HDA_REG_SD4FMT (HDA_STREAM_REG_DEF(FMT, 0) + 40) /* 0x112 */
473#define HDA_REG_SD5FMT (HDA_STREAM_REG_DEF(FMT, 0) + 50) /* 0x132 */
474#define HDA_REG_SD6FMT (HDA_STREAM_REG_DEF(FMT, 0) + 60) /* 0x152 */
475#define HDA_REG_SD7FMT (HDA_STREAM_REG_DEF(FMT, 0) + 70) /* 0x172 */
476#define HDA_RMX_SD0FMT 39
477#define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
478#define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
479#define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
480#define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
481#define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
482#define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
483#define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
484
485#define SDFMT(pThis, num) (HDA_REG((pThis), SD(FMT, num)))
486#define HDA_SDFMT_BASE_RATE_SHIFT 14
487#define HDA_SDFMT_MULT_SHIFT 11
488#define HDA_SDFMT_MULT_MASK 0x7
489#define HDA_SDFMT_DIV_SHIFT 8
490#define HDA_SDFMT_DIV_MASK 0x7
491#define HDA_SDFMT_BITS_SHIFT 4
492#define HDA_SDFMT_BITS_MASK 0x7
493#define SDFMT_BASE_RATE(pThis, num) ((SDFMT(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDFMT, BASE_RATE)) >> HDA_REG_FIELD_SHIFT(SDFMT, BASE_RATE))
494#define SDFMT_MULT(pThis, num) ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,MULT)) >> HDA_REG_FIELD_SHIFT(SDFMT, MULT))
495#define SDFMT_DIV(pThis, num) ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,DIV)) >> HDA_REG_FIELD_SHIFT(SDFMT, DIV))
496
497#define HDA_REG_SD0BDPL 42 /* 0x98 */
498#define HDA_REG_SD1BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 10) /* 0xB8 */
499#define HDA_REG_SD2BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 20) /* 0xD8 */
500#define HDA_REG_SD3BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 30) /* 0xF8 */
501#define HDA_REG_SD4BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 40) /* 0x118 */
502#define HDA_REG_SD5BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 50) /* 0x138 */
503#define HDA_REG_SD6BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 60) /* 0x158 */
504#define HDA_REG_SD7BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 70) /* 0x178 */
505#define HDA_RMX_SD0BDPL 40
506#define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
507#define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
508#define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
509#define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
510#define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
511#define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
512#define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
513
514#define HDA_REG_SD0BDPU 43 /* 0x9C */
515#define HDA_REG_SD1BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 10) /* 0xBC */
516#define HDA_REG_SD2BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 20) /* 0xDC */
517#define HDA_REG_SD3BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 30) /* 0xFC */
518#define HDA_REG_SD4BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 40) /* 0x11C */
519#define HDA_REG_SD5BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 50) /* 0x13C */
520#define HDA_REG_SD6BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 60) /* 0x15C */
521#define HDA_REG_SD7BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 70) /* 0x17C */
522#define HDA_RMX_SD0BDPU 41
523#define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
524#define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
525#define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
526#define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
527#define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
528#define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
529#define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
530
531#define HDA_CODEC_CAD_SHIFT 28
532/* Encodes the (required) LUN into a codec command. */
533#define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
534
535
536
537/*******************************************************************************
538* Structures and Typedefs *
539*******************************************************************************/
540typedef struct HDABDLEDESC
541{
542 uint64_t u64BdleCviAddr;
543 uint32_t u32BdleMaxCvi;
544 uint32_t u32BdleCvi;
545 uint32_t u32BdleCviLen;
546 uint32_t u32BdleCviPos;
547 bool fBdleCviIoc;
548 uint32_t cbUnderFifoW;
549 uint8_t au8HdaBuffer[HDA_SDONFIFO_256B + 1];
550} HDABDLEDESC, *PHDABDLEDESC;
551
552typedef struct HDASTREAMTRANSFERDESC
553{
554 uint64_t u64BaseDMA;
555 uint32_t u32Ctl;
556 uint32_t *pu32Sts;
557 uint8_t u8Strm;
558 uint32_t *pu32Lpib;
559 uint32_t u32Cbl;
560 uint32_t u32Fifos;
561} HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC;
562
563#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
564typedef struct HDAINPUTSTREAM
565{
566 /** PCM line input stream. */
567 R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn;
568 /** Mixer handle for line input stream. */
569 R3PTRTYPE(PAUDMIXSTREAM) phStrmIn;
570} HDAINPUTSTREAM, *PHDAINPUTSTREAM;
571
572typedef struct HDAOUTPUTSTREAM
573{
574 /** PCM output stream. */
575 R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut;
576} HDAOUTPUTSTREAM, *PHDAOUTPUTSTREAM;
577
578/**
579 * Struct for maintaining a host backend driver.
580 * This driver must be associated to one, and only one,
581 * HDA codec. The HDA controller does the actual multiplexing
582 * of HDA codec data to various host backend drivers then.
583 *
584 * This HDA device uses a timer in order to synchronize all
585 * read/write accesses across all attached LUNs / backends.
586 */
587typedef struct HDADRIVER
588{
589 union
590 {
591 /** Node for storing this driver in our device driver
592 * list of HDASTATE. */
593 RTLISTNODE Node;
594 struct
595 {
596 R3PTRTYPE(void *) dummy1;
597 R3PTRTYPE(void *) dummy2;
598 } dummy;
599 };
600
601 /** Pointer to HDA controller (state). */
602 R3PTRTYPE(PHDASTATE) pHDAState;
603 /** Driver flags. */
604 PDMAUDIODRVFLAGS Flags;
605 uint8_t u32Padding0[3];
606 /** LUN to which this driver has been assigned. */
607 uint8_t uLUN;
608 /** Audio connector interface to the underlying
609 * host backend. */
610 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
611 /** Stream for line input. */
612 HDAINPUTSTREAM LineIn;
613 /** Stream for mic input. */
614 HDAINPUTSTREAM MicIn;
615 /** Stream for output. */
616 HDAOUTPUTSTREAM Out;
617 /** Number of samples to play (output), needed
618 * for the timer routine. */
619 uint32_t cSamplesLive;
620} HDADRIVER, *PHDADRIVER;
621#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
622
623/**
624 * ICH Intel HD Audio Controller state.
625 */
626typedef struct HDASTATE
627{
628 /** The PCI device structure. */
629 PCIDevice PciDev;
630 /** R3 Pointer to the device instance. */
631 PPDMDEVINSR3 pDevInsR3;
632 /** R0 Pointer to the device instance. */
633 PPDMDEVINSR0 pDevInsR0;
634 /** R0 Pointer to the device instance. */
635 PPDMDEVINSRC pDevInsRC;
636
637 uint32_t u32Padding;
638
639 /** Pointer to the attached audio driver. */
640 R3PTRTYPE(PPDMIBASE) pDrvBase;
641 /** The base interface for LUN\#0. */
642 PDMIBASE IBase;
643 RTGCPHYS MMIOBaseAddr;
644 uint32_t au32Regs[HDA_NREGS];
645 HDABDLEDESC StInBdle;
646 HDABDLEDESC StOutBdle;
647 HDABDLEDESC StMicBdle;
648 uint64_t u64CORBBase;
649 uint64_t u64RIRBBase;
650 uint64_t u64DPBase;
651 /** Pointer to CORB buffer. */
652 R3PTRTYPE(uint32_t *) pu32CorbBuf;
653 /** Size in bytes of CORB buffer. */
654 uint32_t cbCorbBuf;
655 uint32_t u32Padding2;
656 /** Pointer to RIRB buffer. */
657 R3PTRTYPE(uint64_t *) pu64RirbBuf;
658 /** Size in bytes of RIRB buffer. */
659 uint32_t cbRirbBuf;
660 /** Indicates if HDA is in reset. */
661 bool fInReset;
662 /** Interrupt on completion */
663 bool fCviIoc;
664 /** Flag whether the R0 part is enabled. */
665 bool fR0Enabled;
666 /** Flag whether the RC part is enabled. */
667 bool fRCEnabled;
668#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
669 /** The emulation timer for handling the attached
670 * LUN drivers. */
671 PTMTIMERR3 pTimer;
672 /** Timer ticks for handling the LUN drivers. */
673 uint64_t uTicks;
674# ifdef VBOX_WITH_STATISTICS
675 STAMPROFILE StatTimer;
676 STAMCOUNTER StatBytesRead;
677 STAMCOUNTER StatBytesWritten;
678# endif
679 /** Pointer to HDA codec to use. */
680 R3PTRTYPE(PHDACODEC) pCodec;
681 union
682 {
683 /** List of associated LUN drivers. */
684 RTLISTANCHOR lstDrv;
685 struct
686 {
687 R3PTRTYPE(void *) dummy1;
688 R3PTRTYPE(void *) dummy2;
689 } dummy;
690 };
691 /** The device' software mixer. */
692 R3PTRTYPE(PAUDIOMIXER) pMixer;
693 /** Audio mixer sink for line input. */
694 R3PTRTYPE(PAUDMIXSINK) pSinkLineIn;
695 /** Audio mixer sink for microphone input. */
696 R3PTRTYPE(PAUDMIXSINK) pSinkMicIn;
697#else /* !VBOX_WITH_PDM_AUDIO_DRIVER */
698 /** The HDA codec to use. */
699 R3PTRTYPE(PHDACODEC) pCodec;
700#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
701 uint64_t u64BaseTS;
702 /** 1.2.3.4.5.6.7. - someone please tell me what I'm counting! - .8.9.10... */
703 uint8_t u8Counter;
704#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
705 uint8_t au8Padding[7];
706#else
707 uint8_t au8Padding[7];
708#endif
709} HDASTATE;
710/** Pointer to the ICH Intel HD Audio Controller state. */
711typedef HDASTATE *PHDASTATE;
712
713#define ISD0FMT_TO_AUDIO_SELECTOR(pThis) \
714 ( AUDIO_FORMAT_SELECTOR((pThis)->pCodec, In, SDFMT_BASE_RATE(pThis, 0), SDFMT_MULT(pThis, 0), SDFMT_DIV(pThis, 0)) )
715#define OSD0FMT_TO_AUDIO_SELECTOR(pThis) \
716 ( AUDIO_FORMAT_SELECTOR((pThis)->pCodec, Out, SDFMT_BASE_RATE(pThis, 4), SDFMT_MULT(pThis, 4), SDFMT_DIV(pThis, 4)) )
717
718
719/*******************************************************************************
720* Internal Functions *
721*******************************************************************************/
722#ifndef VBOX_DEVICE_STRUCT_TESTCASE
723static FNPDMDEVRESET hdaReset;
724
725static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
726static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
727static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
728static int hdaRegReadSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
729static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
730static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
731static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
732static int hdaRegWriteINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
733static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
734static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
735static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
736static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
737static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
738static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
739static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
740static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
741static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
742
743static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
744static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
745static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
746static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
747static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
748static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
749static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
750static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
751static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
752static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
753static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
754static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
755static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
756static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
757static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
758static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
759
760#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
761static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
762static int hdaTransfer(PHDASTATE pThis, ENMSOUNDSOURCE enmSrc, uint32_t cbAvail);
763#else
764static int hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSource, int cbAvail);
765#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
766
767#ifdef IN_RING3
768DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
769 PHDASTREAMTRANSFERDESC pStreamDesc);
770static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc);
771#ifdef LOG_ENABLED
772static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
773#endif
774#endif
775
776
777/*******************************************************************************
778* Global Variables *
779*******************************************************************************/
780
781/* see 302349 p 6.2*/
782static const struct HDAREGDESC
783{
784 /** Register offset in the register space. */
785 uint32_t offset;
786 /** Size in bytes. Registers of size > 4 are in fact tables. */
787 uint32_t size;
788 /** Readable bits. */
789 uint32_t readable;
790 /** Writable bits. */
791 uint32_t writable;
792 /** Read callback. */
793 int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
794 /** Write callback. */
795 int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
796 /** Index into the register storage array. */
797 uint32_t mem_idx;
798 /** Abbreviated name. */
799 const char *abbrev;
800} g_aHdaRegMap[HDA_NREGS] =
801
802/* Turn a short register name into an memory index and a stringized name. */
803#define RA(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
804/* Same as above for an input stream ('I' prefixed). */
805#define IA(abbrev) HDA_MEM_IND_NAME(abbrev), "I"#abbrev
806/* Same as above for an output stream ('O' prefixed). */
807#define OA(abbrev) HDA_MEM_IND_NAME(abbrev), "O"#abbrev
808/* Same as above for a register *not* stored in memory. */
809#define UA(abbrev) 0, #abbrev
810
811{
812 /* offset size read mask write mask read callback write callback abbrev */
813 /*------- ------- ---------- ---------- ----------------------- ------------------------ ---------- */
814 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , RA(GCAP) }, /* Global Capabilities */
815 { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , RA(VMIN) }, /* Minor Version */
816 { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , RA(VMAJ) }, /* Major Version */
817 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , RA(OUTPAY) }, /* Output Payload Capabilities */
818 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , RA(INPAY) }, /* Input Payload Capabilities */
819 { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadU32 , hdaRegWriteGCTL , RA(GCTL) }, /* Global Control */
820 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, hdaRegReadU16 , hdaRegWriteU16 , RA(WAKEEN) }, /* Wake Enable */
821 { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteSTATESTS , RA(STATESTS) }, /* State Change Status */
822 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimpl , hdaRegWriteUnimpl , RA(GSTS) }, /* Global Status */
823 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , RA(OUTSTRMPAY)}, /* Output Stream Payload Capability */
824 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimpl , RA(INSTRMPAY) }, /* Input Stream Payload Capability */
825 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWriteU32 , RA(INTCTL) }, /* Interrupt Control */
826 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS , hdaRegWriteUnimpl , RA(INTSTS) }, /* Interrupt Status */
827 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK , hdaRegWriteUnimpl , UA(WALCLK) }, /* Wall Clock Counter */
828 /// @todo r=michaln: Doesn't the SSYNC register need to actually stop the stream(s)?
829 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32 , hdaRegWriteU32 , RA(SSYNC) }, /* Stream Synchronization */
830 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , RA(CORBLBASE) }, /* CORB Lower Base Address */
831 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , RA(CORBUBASE) }, /* CORB Upper Base Address */
832 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteCORBWP , RA(CORBWP) }, /* CORB Write Pointer */
833 { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, hdaRegReadU16 , hdaRegWriteCORBRP , RA(CORBRP) }, /* CORB Read Pointer */
834 { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8 , hdaRegWriteCORBCTL , RA(CORBCTL) }, /* CORB Control */
835 { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8 , hdaRegWriteCORBSTS , RA(CORBSTS) }, /* CORB Status */
836 { 0x0004E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , RA(CORBSIZE) }, /* CORB Size */
837 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , RA(RIRBLBASE) }, /* RIRB Lower Base Address */
838 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , RA(RIRBUBASE) }, /* RIRB Upper Base Address */
839 { 0x00058, 0x00002, 0x000000FF, 0x00008000, hdaRegReadU8 , hdaRegWriteRIRBWP , RA(RIRBWP) }, /* RIRB Write Pointer */
840 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteU16 , RA(RINTCNT) }, /* Response Interrupt Count */
841 { 0x0005C, 0x00001, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteU8 , RA(RIRBCTL) }, /* RIRB Control */
842 { 0x0005D, 0x00001, 0x00000005, 0x00000005, hdaRegReadU8 , hdaRegWriteRIRBSTS , RA(RIRBSTS) }, /* RIRB Status */
843 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimpl , RA(RIRBSIZE) }, /* RIRB Size */
844 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , RA(IC) }, /* Immediate Command */
845 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteUnimpl , RA(IR) }, /* Immediate Response */
846 { 0x00068, 0x00002, 0x00000002, 0x00000002, hdaRegReadIRS , hdaRegWriteIRS , RA(IRS) }, /* Immediate Command Status */
847 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32 , hdaRegWriteBase , RA(DPLBASE) }, /* MA Position Lower Base */
848 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , RA(DPUBASE) }, /* DMA Position Upper Base */
849
850 { 0x00080, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , IA(SD0CTL) }, /* Input Stream Descriptor 0 (ICD0) Control */
851 { 0x00083, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , IA(SD0STS) }, /* ISD0 Status */
852 { 0x00084, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , IA(SD0LPIB) }, /* ISD0 Link Position In Buffer */
853 { 0x00088, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , IA(SD0CBL) }, /* ISD0 Cyclic Buffer Length */
854 { 0x0008C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , IA(SD0LVI) }, /* ISD0 Last Valid Index */
855 { 0x0008E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , IA(SD0FIFOW) }, /* ISD0 FIFO Watermark */
856 { 0x00090, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , IA(SD0FIFOS) }, /* ISD0 FIFO Size */
857 { 0x00092, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , IA(SD0FMT) }, /* ISD0 Format */
858 { 0x00098, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , IA(SD0BDPL) }, /* ISD0 Buffer Descriptor List Pointer-Lower Base Address */
859 { 0x0009C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , IA(SD0BDPU) }, /* ISD0 Buffer Descriptor List Pointer-Upper Base Address */
860
861 { 0x000A0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , IA(SD1CTL) }, /* Input Stream Descriptor 1 (ISD1) Control */
862 { 0x000A3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , IA(SD1STS) }, /* ISD1 Status */
863 { 0x000A4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , IA(SD1LPIB) }, /* ISD1 Link Position In Buffer */
864 { 0x000A8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , IA(SD1CBL) }, /* ISD1 Cyclic Buffer Length */
865 { 0x000AC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , IA(SD1LVI) }, /* ISD1 Last Valid Index */
866 { 0x000AE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , IA(SD1FIFOW) }, /* ISD1 FIFO Watermark */
867 { 0x000B0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , IA(SD1FIFOS) }, /* ISD1 FIFO Size */
868 { 0x000B2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , IA(SD1FMT) }, /* ISD1 Format */
869 { 0x000B8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , IA(SD1BDPL) }, /* ISD1 Buffer Descriptor List Pointer-Lower Base Address */
870 { 0x000BC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , IA(SD1BDPU) }, /* ISD1 Buffer Descriptor List Pointer-Upper Base Address */
871
872 { 0x000C0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , IA(SD2CTL) }, /* Input Stream Descriptor 2 (ISD2) Control */
873 { 0x000C3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , IA(SD2STS) }, /* ISD2 Status */
874 { 0x000C4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , IA(SD2LPIB) }, /* ISD2 Link Position In Buffer */
875 { 0x000C8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , IA(SD2CBL) }, /* ISD2 Cyclic Buffer Length */
876 { 0x000CC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , IA(SD2LVI) }, /* ISD2 Last Valid Index */
877 { 0x000CE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , IA(SD2FIFOW) }, /* ISD2 FIFO Watermark */
878 { 0x000D0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , IA(SD2FIFOS) }, /* ISD2 FIFO Size */
879 { 0x000D2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , IA(SD2FMT) }, /* ISD2 Format */
880 { 0x000D8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , IA(SD2BDPL) }, /* ISD2 Buffer Descriptor List Pointer-Lower Base Address */
881 { 0x000DC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , IA(SD2BDPU) }, /* ISD2 Buffer Descriptor List Pointer-Upper Base Address */
882
883 { 0x000E0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , IA(SD3CTL) }, /* Input Stream Descriptor 3 (ISD3) Control */
884 { 0x000E3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , IA(SD3STS) }, /* ISD3 Status */
885 { 0x000E4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , IA(SD3LPIB) }, /* ISD3 Link Position In Buffer */
886 { 0x000E8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , IA(SD3CBL) }, /* ISD3 Cyclic Buffer Length */
887 { 0x000EC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , IA(SD3LVI) }, /* ISD3 Last Valid Index */
888 { 0x000EE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , IA(SD3FIFOW) }, /* ISD3 FIFO Watermark */
889 { 0x000F0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , IA(SD3FIFOS) }, /* ISD3 FIFO Size */
890 { 0x000F2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , IA(SD3FMT) }, /* ISD3 Format */
891 { 0x000F8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , IA(SD3BDPL) }, /* ISD3 Buffer Descriptor List Pointer-Lower Base Address */
892 { 0x000FC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , IA(SD3BDPU) }, /* ISD3 Buffer Descriptor List Pointer-Upper Base Address */
893
894 { 0x00100, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , OA(SD4CTL) }, /* Output Stream Descriptor 4 (OSD4) Control */
895 { 0x00103, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , OA(SD4STS) }, /* OSD4 Status */
896 { 0x00104, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , OA(SD4LPIB) }, /* OSD4 Link Position In Buffer */
897 { 0x00108, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , OA(SD4CBL) }, /* OSD4 Cyclic Buffer Length */
898 { 0x0010C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , OA(SD4LVI) }, /* OSD4 Last Valid Index */
899 { 0x0010E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , OA(SD4FIFOW) }, /* OSD4 FIFO Watermark */
900 { 0x00110, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , OA(SD4FIFOS) }, /* OSD4 FIFO Size */
901 { 0x00112, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , OA(SD4FMT) }, /* OSD4 Format */
902 { 0x00118, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , OA(SD4BDPL) }, /* OSD4 Buffer Descriptor List Pointer-Lower Base Address */
903 { 0x0011C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , OA(SD4BDPU) }, /* OSD4 Buffer Descriptor List Pointer-Upper Base Address */
904
905 { 0x00120, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , OA(SD5CTL) }, /* Output Stream Descriptor 5 (OSD5) Control */
906 { 0x00123, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , OA(SD5STS) }, /* OSD5 Status */
907 { 0x00124, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , OA(SD5LPIB) }, /* OSD5 Link Position In Buffer */
908 { 0x00128, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , OA(SD5CBL) }, /* OSD5 Cyclic Buffer Length */
909 { 0x0012C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , OA(SD5LVI) }, /* OSD5 Last Valid Index */
910 { 0x0012E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , OA(SD5FIFOW) }, /* OSD5 FIFO Watermark */
911 { 0x00130, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , OA(SD5FIFOS) }, /* OSD5 FIFO Size */
912 { 0x00132, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , OA(SD5FMT) }, /* OSD5 Format */
913 { 0x00138, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , OA(SD5BDPL) }, /* OSD5 Buffer Descriptor List Pointer-Lower Base Address */
914 { 0x0013C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , OA(SD5BDPU) }, /* OSD5 Buffer Descriptor List Pointer-Upper Base Address */
915
916 { 0x00140, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , OA(SD6CTL) }, /* Output Stream Descriptor 6 (OSD6) Control */
917 { 0x00143, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , OA(SD6STS) }, /* OSD6 Status */
918 { 0x00144, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , OA(SD6LPIB) }, /* OSD6 Link Position In Buffer */
919 { 0x00148, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , OA(SD6CBL) }, /* OSD6 Cyclic Buffer Length */
920 { 0x0014C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , OA(SD6LVI) }, /* OSD6 Last Valid Index */
921 { 0x0014E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , OA(SD6FIFOW) }, /* OSD6 FIFO Watermark */
922 { 0x00150, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , OA(SD6FIFOS) }, /* OSD6 FIFO Size */
923 { 0x00152, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , OA(SD6FMT) }, /* OSD6 Format */
924 { 0x00158, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , OA(SD6BDPL) }, /* OSD6 Buffer Descriptor List Pointer-Lower Base Address */
925 { 0x0015C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , OA(SD6BDPU) }, /* OSD6 Buffer Descriptor List Pointer-Upper Base Address */
926
927 { 0x00160, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , OA(SD7CTL) }, /* Output Stream Descriptor 7 (OSD7) Control */
928 { 0x00163, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , OA(SD7STS) }, /* OSD7 Status */
929 { 0x00164, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , OA(SD7LPIB) }, /* OSD7 Link Position In Buffer */
930 { 0x00168, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , OA(SD7CBL) }, /* OSD7 Cyclic Buffer Length */
931 { 0x0016C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , OA(SD7LVI) }, /* OSD7 Last Valid Index */
932 { 0x0016E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , OA(SD7FIFOW) }, /* OSD7 FIFO Watermark */
933 { 0x00170, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , OA(SD7FIFOS) }, /* OSD7 FIFO Size */
934 { 0x00172, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , OA(SD7FMT) }, /* OSD7 Format */
935 { 0x00178, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , OA(SD7BDPL) }, /* OSD7 Buffer Descriptor List Pointer-Lower Base Address */
936 { 0x0017C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , OA(SD7BDPU) }, /* OSD7 Buffer Descriptor List Pointer-Upper Base Address */
937};
938
939/**
940 * HDA register aliases (HDA spec 3.3.45).
941 * @remarks Sorted by offReg.
942 */
943static const struct
944{
945 /** The alias register offset. */
946 uint32_t offReg;
947 /** The register index. */
948 int idxAlias;
949} g_aHdaRegAliases[] =
950{
951 { 0x2084, HDA_REG_SD0LPIB },
952 { 0x20a4, HDA_REG_SD1LPIB },
953 { 0x20c4, HDA_REG_SD2LPIB },
954 { 0x20e4, HDA_REG_SD3LPIB },
955 { 0x2104, HDA_REG_SD4LPIB },
956 { 0x2124, HDA_REG_SD5LPIB },
957 { 0x2144, HDA_REG_SD6LPIB },
958 { 0x2164, HDA_REG_SD7LPIB },
959};
960
961#ifdef IN_RING3
962/** HDABDLEDESC field descriptors the v3+ saved state. */
963static SSMFIELD const g_aHdaBDLEDescFields[] =
964{
965 SSMFIELD_ENTRY( HDABDLEDESC, u64BdleCviAddr),
966 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleMaxCvi),
967 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCvi),
968 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviLen),
969 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviPos),
970 SSMFIELD_ENTRY( HDABDLEDESC, fBdleCviIoc),
971 SSMFIELD_ENTRY( HDABDLEDESC, cbUnderFifoW),
972 SSMFIELD_ENTRY( HDABDLEDESC, au8HdaBuffer),
973 SSMFIELD_ENTRY_TERM()
974};
975
976/** HDABDLEDESC field descriptors the v1 and v2 saved state. */
977static SSMFIELD const g_aHdaBDLEDescFieldsOld[] =
978{
979 SSMFIELD_ENTRY( HDABDLEDESC, u64BdleCviAddr),
980 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleMaxCvi),
981 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCvi),
982 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviLen),
983 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviPos),
984 SSMFIELD_ENTRY( HDABDLEDESC, fBdleCviIoc),
985 SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
986 SSMFIELD_ENTRY( HDABDLEDESC, cbUnderFifoW),
987 SSMFIELD_ENTRY( HDABDLEDESC, au8HdaBuffer),
988 SSMFIELD_ENTRY_TERM()
989};
990#endif
991
992/**
993 * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
994 */
995static uint32_t const g_afMasks[5] =
996{
997 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff)
998};
999
1000#ifdef IN_RING3
1001DECLINLINE(void) hdaUpdatePosBuf(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
1002{
1003 if (pThis->u64DPBase & DPBASE_ENABLED)
1004 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
1005 (pThis->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm * 8,
1006 pStreamDesc->pu32Lpib, sizeof(uint32_t));
1007}
1008#endif
1009
1010DECLINLINE(uint32_t) hdaFifoWToSz(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
1011{
1012#if 0
1013 switch(HDA_STREAM_REG(pThis, FIFOW, pStreamDesc->u8Strm))
1014 {
1015 case HDA_SDFIFOW_8B: return 8;
1016 case HDA_SDFIFOW_16B: return 16;
1017 case HDA_SDFIFOW_32B: return 32;
1018 default:
1019 AssertMsgFailed(("unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pThis, pStreamDesc->u8Strm), pStreamDesc->u8Strm));
1020 }
1021#endif
1022 return 0;
1023}
1024
1025static int hdaProcessInterrupt(PHDASTATE pThis)
1026{
1027#define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \
1028 ( INTCTL_SX((pThis), num) \
1029 && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
1030 bool fIrq = false;
1031 if ( HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE)
1032 && ( HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
1033 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
1034 || (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))))
1035 fIrq = true;
1036
1037 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
1038 || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4))
1039 fIrq = true;
1040
1041 if (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
1042 {
1043 LogFunc(("irq %s\n", fIrq ? "asserted" : "deasserted"));
1044 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0 , fIrq);
1045 }
1046 return VINF_SUCCESS;
1047}
1048
1049/**
1050 * Looks up a register at the exact offset given by @a offReg.
1051 *
1052 * @returns Register index on success, -1 if not found.
1053 * @param pThis The HDA device state.
1054 * @param offReg The register offset.
1055 */
1056static int hdaRegLookup(PHDASTATE pThis, uint32_t offReg)
1057{
1058 /*
1059 * Aliases.
1060 */
1061 if (offReg >= g_aHdaRegAliases[0].offReg)
1062 {
1063 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1064 if (offReg == g_aHdaRegAliases[i].offReg)
1065 return g_aHdaRegAliases[i].idxAlias;
1066 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1067 return -1;
1068 }
1069
1070 /*
1071 * Binary search the
1072 */
1073 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1074 int idxLow = 0;
1075 for (;;)
1076 {
1077 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1078 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1079 {
1080 if (idxLow == idxMiddle)
1081 break;
1082 idxEnd = idxMiddle;
1083 }
1084 else if (offReg > g_aHdaRegMap[idxMiddle].offset)
1085 {
1086 idxLow = idxMiddle + 1;
1087 if (idxLow >= idxEnd)
1088 break;
1089 }
1090 else
1091 return idxMiddle;
1092 }
1093
1094#ifdef RT_STRICT
1095 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1096 Assert(g_aHdaRegMap[i].offset != offReg);
1097#endif
1098 return -1;
1099}
1100
1101/**
1102 * Looks up a register covering the offset given by @a offReg.
1103 *
1104 * @returns Register index on success, -1 if not found.
1105 * @param pThis The HDA device state.
1106 * @param offReg The register offset.
1107 */
1108static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg)
1109{
1110 /*
1111 * Aliases.
1112 */
1113 if (offReg >= g_aHdaRegAliases[0].offReg)
1114 {
1115 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1116 {
1117 uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
1118 if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
1119 return g_aHdaRegAliases[i].idxAlias;
1120 }
1121 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1122 return -1;
1123 }
1124
1125 /*
1126 * Binary search the
1127 */
1128 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1129 int idxLow = 0;
1130 for (;;)
1131 {
1132 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1133 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1134 {
1135 if (idxLow == idxMiddle)
1136 break;
1137 idxEnd = idxMiddle;
1138 }
1139 else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
1140 {
1141 idxLow = idxMiddle + 1;
1142 if (idxLow >= idxEnd)
1143 break;
1144 }
1145 else
1146 return idxMiddle;
1147 }
1148
1149#ifdef RT_STRICT
1150 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1151 Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
1152#endif
1153 return -1;
1154}
1155
1156#ifdef IN_RING3
1157static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
1158{
1159 int rc = VINF_SUCCESS;
1160 if (fLocal)
1161 {
1162 Assert((HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)));
1163 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
1164 if (RT_FAILURE(rc))
1165 AssertRCReturn(rc, rc);
1166#ifdef DEBUG_CMD_BUFFER
1167 uint8_t i = 0;
1168 do
1169 {
1170 LogFunc(("corb%02x: ", i));
1171 uint8_t j = 0;
1172 do
1173 {
1174 const char *prefix;
1175 if ((i + j) == HDA_REG(pThis, CORBRP);
1176 prefix = "[R]";
1177 else if ((i + j) == HDA_REG(pThis, CORBWP);
1178 prefix = "[W]";
1179 else
1180 prefix = " "; /* three spaces */
1181 LogFunc(("%s%08x", prefix, pThis->pu32CorbBuf[i + j]));
1182 j++;
1183 } while (j < 8);
1184 LogFunc(("\n"));
1185 i += 8;
1186 } while(i != 0);
1187#endif
1188 }
1189 else
1190 {
1191 Assert((HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA)));
1192 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
1193 if (RT_FAILURE(rc))
1194 AssertRCReturn(rc, rc);
1195#ifdef DEBUG_CMD_BUFFER
1196 uint8_t i = 0;
1197 do {
1198 LogFunc(("rirb%02x: ", i));
1199 uint8_t j = 0;
1200 do {
1201 const char *prefix;
1202 if ((i + j) == HDA_REG(pThis, RIRBWP))
1203 prefix = "[W]";
1204 else
1205 prefix = " ";
1206 LogFunc((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
1207 } while (++j < 8);
1208 LogFunc(("\n"));
1209 i += 8;
1210 } while (i != 0);
1211#endif
1212 }
1213 return rc;
1214}
1215
1216static int hdaCORBCmdProcess(PHDASTATE pThis)
1217{
1218 int rc;
1219 uint8_t corbRp;
1220 uint8_t corbWp;
1221 uint8_t rirbWp;
1222
1223 PFNHDACODECVERBPROCESSOR pfn = (PFNHDACODECVERBPROCESSOR)NULL;
1224
1225 rc = hdaCmdSync(pThis, true);
1226 if (RT_FAILURE(rc))
1227 AssertRCReturn(rc, rc);
1228 corbRp = HDA_REG(pThis, CORBRP);
1229 corbWp = HDA_REG(pThis, CORBWP);
1230 rirbWp = HDA_REG(pThis, RIRBWP);
1231 Assert((corbWp != corbRp));
1232 LogFlowFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP),
1233 HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1234 while (corbRp != corbWp)
1235 {
1236 uint32_t cmd;
1237 uint64_t resp;
1238 pfn = NULL;
1239 corbRp++;
1240 cmd = pThis->pu32CorbBuf[corbRp];
1241
1242 rc = pThis->pCodec->pfnLookup(pThis->pCodec,
1243 HDA_CODEC_CMD(cmd, 0 /* Codec index */),
1244 &pfn);
1245 if (RT_SUCCESS(rc))
1246 {
1247 rc = pfn(pThis->pCodec,
1248 HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp);
1249 }
1250
1251 if (RT_FAILURE(rc))
1252 AssertRCReturn(rc, rc);
1253 Assert(pfn);
1254 (rirbWp)++;
1255
1256 LogFunc(("verb:%08x->%016lx\n", cmd, resp));
1257 if ( (resp & CODEC_RESPONSE_UNSOLICITED)
1258 && !HDA_REG_FLAG_VALUE(pThis, GCTL, UR))
1259 {
1260 LogFunc(("unexpected unsolicited response.\n"));
1261 HDA_REG(pThis, CORBRP) = corbRp;
1262 return rc;
1263 }
1264 pThis->pu64RirbBuf[rirbWp] = resp;
1265 pThis->u8Counter++;
1266 if (pThis->u8Counter == RINTCNT_N(pThis))
1267 break;
1268 }
1269 HDA_REG(pThis, CORBRP) = corbRp;
1270 HDA_REG(pThis, RIRBWP) = rirbWp;
1271 rc = hdaCmdSync(pThis, false);
1272 LogFunc(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP),
1273 HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1274 if (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC))
1275 {
1276 HDA_REG(pThis, RIRBSTS) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
1277 pThis->u8Counter = 0;
1278 rc = hdaProcessInterrupt(pThis);
1279 }
1280 if (RT_FAILURE(rc))
1281 AssertRCReturn(rc, rc);
1282 return rc;
1283}
1284#endif
1285
1286static void hdaStreamReset(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm)
1287{
1288 LogFunc(("reset of stream (%d) started\n", u8Strm));
1289 Assert(( pThis
1290 && pBdle
1291 && pStreamDesc
1292 && u8Strm <= 7));
1293 RT_BZERO(pBdle, sizeof(HDABDLEDESC));
1294 *pStreamDesc->pu32Lpib = 0;
1295 *pStreamDesc->pu32Sts = 0;
1296 /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
1297 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */
1298 HDA_STREAM_REG(pThis, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
1299
1300 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
1301 HDA_STREAM_REG(pThis, FIFOS, u8Strm) = u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
1302 HDA_STREAM_REG(pThis, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B;
1303 HDA_STREAM_REG(pThis, CBL, u8Strm) = 0;
1304 HDA_STREAM_REG(pThis, LVI, u8Strm) = 0;
1305 HDA_STREAM_REG(pThis, FMT, u8Strm) = 0;
1306 HDA_STREAM_REG(pThis, BDPU, u8Strm) = 0;
1307 HDA_STREAM_REG(pThis, BDPL, u8Strm) = 0;
1308 LogFunc(("reset of stream (%d) finished\n", u8Strm));
1309}
1310
1311/* Register access handlers. */
1312
1313static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1314{
1315 *pu32Value = 0;
1316 return VINF_SUCCESS;
1317}
1318
1319static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1320{
1321 return VINF_SUCCESS;
1322}
1323
1324/* U8 */
1325static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1326{
1327 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
1328 return hdaRegReadU32(pThis, iReg, pu32Value);
1329}
1330
1331static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1332{
1333 Assert((u32Value & 0xffffff00) == 0);
1334 return hdaRegWriteU32(pThis, iReg, u32Value);
1335}
1336
1337/* U16 */
1338static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1339{
1340 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
1341 return hdaRegReadU32(pThis, iReg, pu32Value);
1342}
1343
1344static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1345{
1346 Assert((u32Value & 0xffff0000) == 0);
1347 return hdaRegWriteU32(pThis, iReg, u32Value);
1348}
1349
1350/* U24 */
1351static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1352{
1353 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
1354 return hdaRegReadU32(pThis, iReg, pu32Value);
1355}
1356
1357static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1358{
1359 Assert((u32Value & 0xff000000) == 0);
1360 return hdaRegWriteU32(pThis, iReg, u32Value);
1361}
1362
1363/* U32 */
1364static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1365{
1366 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
1367
1368 *pu32Value = pThis->au32Regs[iRegMem] & g_aHdaRegMap[iReg].readable;
1369 return VINF_SUCCESS;
1370}
1371
1372static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1373{
1374 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
1375
1376 pThis->au32Regs[iRegMem] = (u32Value & g_aHdaRegMap[iReg].writable)
1377 | (pThis->au32Regs[iRegMem] & ~g_aHdaRegMap[iReg].writable);
1378 return VINF_SUCCESS;
1379}
1380
1381static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1382{
1383 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
1384 {
1385 /* exit reset state */
1386 HDA_REG(pThis, GCTL) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
1387 pThis->fInReset = false;
1388 }
1389 else
1390 {
1391#ifdef IN_RING3
1392 /* enter reset state*/
1393 if ( HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)
1394 || HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA))
1395 {
1396 LogFunc(("HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
1397 HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) ? "on" : "off",
1398 HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA) ? "on" : "off"));
1399 }
1400 hdaReset(pThis->CTX_SUFF(pDevIns));
1401 HDA_REG(pThis, GCTL) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
1402 pThis->fInReset = true;
1403#else
1404 return VINF_IOM_R3_MMIO_WRITE;
1405#endif
1406 }
1407 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
1408 {
1409 /* Flush: GSTS:1 set, see 6.2.6*/
1410 HDA_REG(pThis, GSTS) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
1411 /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6)*/
1412 }
1413 return VINF_SUCCESS;
1414}
1415
1416static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1417{
1418 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
1419
1420 uint32_t v = pThis->au32Regs[iRegMem];
1421 uint32_t nv = u32Value & HDA_STATES_SCSF;
1422 pThis->au32Regs[iRegMem] &= ~(v & nv); /* write of 1 clears corresponding bit */
1423 return VINF_SUCCESS;
1424}
1425
1426static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1427{
1428 uint32_t v = 0;
1429 if ( HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS)
1430 || HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL)
1431 || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI)
1432 || HDA_REG(pThis, STATESTS))
1433 v |= RT_BIT(30);
1434#define HDA_IS_STREAM_EVENT(pThis, stream) \
1435 ( (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \
1436 || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \
1437 || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
1438#define MARK_STREAM(pThis, stream, v) do { (v) |= HDA_IS_STREAM_EVENT((pThis),stream) ? RT_BIT((stream)) : 0; } while(0)
1439 MARK_STREAM(pThis, 0, v);
1440 MARK_STREAM(pThis, 1, v);
1441 MARK_STREAM(pThis, 2, v);
1442 MARK_STREAM(pThis, 3, v);
1443 MARK_STREAM(pThis, 4, v);
1444 MARK_STREAM(pThis, 5, v);
1445 MARK_STREAM(pThis, 6, v);
1446 MARK_STREAM(pThis, 7, v);
1447 v |= v ? RT_BIT(31) : 0;
1448 *pu32Value = v;
1449 return VINF_SUCCESS;
1450}
1451
1452static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1453{
1454 /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
1455 *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns))
1456 - pThis->u64BaseTS, 24, 1000);
1457 return VINF_SUCCESS;
1458}
1459
1460static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1461{
1462 if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
1463 HDA_REG(pThis, CORBRP) = 0;
1464#ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO
1465 else
1466 return hdaRegWriteU8(pThis, iReg, u32Value);
1467#endif
1468 return VINF_SUCCESS;
1469}
1470
1471static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1472{
1473#ifdef IN_RING3
1474 int rc = hdaRegWriteU8(pThis, iReg, u32Value);
1475 AssertRC(rc);
1476 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
1477 && HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) != 0)
1478 return hdaCORBCmdProcess(pThis);
1479 return rc;
1480#else
1481 return VINF_IOM_R3_MMIO_WRITE;
1482#endif
1483}
1484
1485static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1486{
1487 uint32_t v = HDA_REG(pThis, CORBSTS);
1488 HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
1489 return VINF_SUCCESS;
1490}
1491
1492static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1493{
1494#ifdef IN_RING3
1495 int rc;
1496 rc = hdaRegWriteU16(pThis, iReg, u32Value);
1497 if (RT_FAILURE(rc))
1498 AssertRCReturn(rc, rc);
1499 if (HDA_REG(pThis, CORBWP) == HDA_REG(pThis, CORBRP))
1500 return VINF_SUCCESS;
1501 if (!HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
1502 return VINF_SUCCESS;
1503 rc = hdaCORBCmdProcess(pThis);
1504 return rc;
1505#else
1506 return VINF_IOM_R3_MMIO_WRITE;
1507#endif
1508}
1509
1510static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1511{
1512 bool fRun = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1513 bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1514 bool fReset = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
1515 bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
1516
1517 if (fInReset)
1518 {
1519 /*
1520 * Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit
1521 * from reset
1522 */
1523 Assert((!fReset));
1524 LogFunc(("guest initiated exit of stream reset.\n"));
1525 }
1526 else if (fReset)
1527 {
1528#ifdef IN_RING3
1529 /*
1530 * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset.
1531 */
1532 uint8_t u8Strm = 0;
1533 PHDABDLEDESC pBdle = NULL;
1534 HDASTREAMTRANSFERDESC StreamDesc;
1535 Assert((!fInRun && !fRun));
1536 switch (iReg)
1537 {
1538 case HDA_REG_SD0CTL:
1539 u8Strm = 0;
1540 pBdle = &pThis->StInBdle;
1541 break;
1542#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1543# ifdef VBOX_WITH_HDA_MIC_IN
1544 case HDA_REG_SD2CTL:
1545 u8Strm = 2;
1546 pBdle = &pThis->StMicBdle;
1547 break;
1548# endif
1549#endif
1550 case HDA_REG_SD4CTL:
1551 u8Strm = 4;
1552 pBdle = &pThis->StOutBdle;
1553 break;
1554 default:
1555 LogFunc(("changing SRST bit on non-attached stream\n"));
1556 return hdaRegWriteU24(pThis, iReg, u32Value);
1557 }
1558 LogFunc(("guest initiated enter to stream reset.\n"));
1559 hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
1560 hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
1561#else
1562 return VINF_IOM_R3_MMIO_WRITE;
1563#endif
1564 }
1565 else
1566 {
1567#ifdef IN_RING3
1568 /* we enter here to change DMA states only */
1569 if ( (fInRun && !fRun)
1570 || (fRun && !fInRun))
1571 {
1572 Assert((!fReset && !fInReset));
1573
1574# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1575 PHDADRIVER pDrv;
1576# endif
1577 switch (iReg)
1578 {
1579 case HDA_REG_SD0CTL:
1580# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1581 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
1582 pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
1583 pDrv->LineIn.pStrmIn, fRun);
1584# else
1585 AUD_set_active_in(pThis->pCodec->SwVoiceIn, fRun);
1586# endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1587 break;
1588# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1589# ifdef VBOX_WITH_HDA_MIC_IN
1590 case HDA_REG_SD2CTL:
1591 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
1592 pDrv->pConnector->pfnEnableIn(pDrv->pConnector,
1593 pDrv->MicIn.pStrmIn, fRun);
1594# endif
1595# endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1596 break;
1597 case HDA_REG_SD4CTL:
1598# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1599 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
1600 pDrv->pConnector->pfnEnableOut(pDrv->pConnector,
1601 pDrv->Out.pStrmOut, fRun);
1602# else
1603 AUD_set_active_out(pThis->pCodec->SwVoiceOut, fRun);
1604# endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1605 break;
1606 default:
1607 AssertMsgFailed(("Changing RUN bit on non-attached stream, register %RU32\n", iReg));
1608 break;
1609 }
1610 }
1611#else /* !IN_RING3 */
1612 return VINF_IOM_R3_MMIO_WRITE;
1613#endif /* IN_RING3 */
1614 }
1615
1616 return hdaRegWriteU24(pThis, iReg, u32Value);
1617}
1618
1619static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1620{
1621 uint32_t v = HDA_REG_IND(pThis, iReg);
1622 v &= ~(u32Value & v);
1623 HDA_REG_IND(pThis, iReg) = v;
1624 hdaProcessInterrupt(pThis);
1625 return VINF_SUCCESS;
1626}
1627
1628static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1629{
1630 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
1631 if (RT_FAILURE(rc))
1632 AssertRCReturn(rc, VINF_SUCCESS);
1633 return rc;
1634}
1635
1636static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1637{
1638 switch (u32Value)
1639 {
1640 case HDA_SDFIFOW_8B:
1641 case HDA_SDFIFOW_16B:
1642 case HDA_SDFIFOW_32B:
1643 return hdaRegWriteU16(pThis, iReg, u32Value);
1644 default:
1645 LogFunc(("Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
1646 return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
1647 }
1648 return VINF_SUCCESS;
1649}
1650
1651/**
1652 * @note This method could be called for changing value on Output Streams
1653 * only (ICH6 datasheet 18.2.39)
1654 */
1655static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1656{
1657 switch (iReg)
1658 {
1659 /* SDInFIFOS is RO, n=0-3 */
1660 case HDA_REG_SD0FIFOS:
1661 case HDA_REG_SD1FIFOS:
1662 case HDA_REG_SD2FIFOS:
1663 case HDA_REG_SD3FIFOS:
1664 LogFunc(("Guest tries change value of FIFO size of input stream\n"));
1665 break;
1666 case HDA_REG_SD4FIFOS:
1667 case HDA_REG_SD5FIFOS:
1668 case HDA_REG_SD6FIFOS:
1669 case HDA_REG_SD7FIFOS:
1670 switch(u32Value)
1671 {
1672 case HDA_SDONFIFO_16B:
1673 case HDA_SDONFIFO_32B:
1674 case HDA_SDONFIFO_64B:
1675 case HDA_SDONFIFO_128B:
1676 case HDA_SDONFIFO_192B:
1677 return hdaRegWriteU16(pThis, iReg, u32Value);
1678
1679 case HDA_SDONFIFO_256B:
1680 LogFunc(("256-bit is unsupported, HDA is switched into 192-bit mode\n"));
1681 default:
1682 return hdaRegWriteU16(pThis, iReg, HDA_SDONFIFO_192B);
1683 }
1684 break;
1685 default:
1686 AssertMsgFailed(("Something weird happened with register lookup routine\n"));
1687 }
1688
1689 return VINF_SUCCESS;
1690}
1691
1692#ifdef IN_RING3
1693#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1694static int hdaSdFmtToAudSettings(uint32_t u32SdFmt, PPDMAUDIOSTREAMCFG pCfg)
1695#else
1696static int hdaSdFmtToAudSettings(uint32_t u32SdFmt, audsettings_t *pCfg)
1697#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1698{
1699 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
1700
1701# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
1702
1703 int rc = VINF_SUCCESS;
1704
1705 uint32_t u32Hz = (u32SdFmt & HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
1706 uint32_t u32HzMult = 1;
1707 uint32_t u32HzDiv = 1;
1708
1709 switch (EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
1710 {
1711 case 0: u32HzMult = 1; break;
1712 case 1: u32HzMult = 2; break;
1713 case 2: u32HzMult = 3; break;
1714 case 3: u32HzMult = 4; break;
1715 default:
1716 LogFunc(("Unsupported multiplier %x\n",
1717 EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
1718 rc = VERR_NOT_SUPPORTED;
1719 break;
1720 }
1721 switch (EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
1722 {
1723 case 0: u32HzDiv = 1; break;
1724 case 1: u32HzDiv = 2; break;
1725 case 2: u32HzDiv = 3; break;
1726 case 3: u32HzDiv = 4; break;
1727 case 4: u32HzDiv = 5; break;
1728 case 5: u32HzDiv = 6; break;
1729 case 6: u32HzDiv = 7; break;
1730 case 7: u32HzDiv = 8; break;
1731 default:
1732 LogFunc(("Unsupported divisor %x\n",
1733 EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
1734 rc = VERR_NOT_SUPPORTED;
1735 break;
1736 }
1737
1738#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1739 PDMAUDIOFMT enmFmt = AUD_FMT_S16; /* Default to 16-bit signed. */
1740#else
1741 audfmt_e enmFmt = AUD_FMT_S16; /* Default to 16-bit signed. */
1742#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1743
1744 switch (EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
1745 {
1746 case 0:
1747 LogFunc(("%s requested 8-bit\n", __FUNCTION__));
1748#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1749 enmFmt = AUD_FMT_S8;
1750#else
1751 enmFmt = AUD_FMT_S8;
1752#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1753 break;
1754 case 1:
1755 LogFunc(("%s requested 16-bit\n", __FUNCTION__));
1756#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1757 enmFmt = AUD_FMT_S16;
1758#else
1759 enmFmt = AUD_FMT_S16;
1760#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1761 break;
1762 case 2:
1763 LogFunc(("%s requested 20-bit\n", __FUNCTION__));
1764 break;
1765 case 3:
1766 LogFunc(("%s requested 24-bit\n", __FUNCTION__));
1767 break;
1768 case 4:
1769 LogFunc(("%s requested 32-bit\n", __FUNCTION__));
1770#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1771 enmFmt = AUD_FMT_S32;
1772#else
1773 enmFmt = AUD_FMT_S32;
1774#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1775 break;
1776 default:
1777 AssertMsgFailed(("Unsupported bits shift %x\n",
1778 EXTRACT_VALUE(u32SdFmt, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
1779 rc = VERR_NOT_SUPPORTED;
1780 break;
1781 }
1782
1783 if (RT_SUCCESS(rc))
1784 {
1785#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1786 pCfg->uHz = u32Hz * u32HzMult / u32HzDiv;
1787 pCfg->cChannels = (u32SdFmt & 0xf) + 1;
1788 pCfg->enmFormat = enmFmt;
1789 pCfg->enmEndianness = PDMAUDIOHOSTENDIANESS;
1790#else
1791 pCfg->nchannels = (u32SdFmt & 0xf) + 1;
1792 pCfg->fmt = enmFmt;
1793 pCfg->endianness = 0;
1794#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
1795 }
1796
1797# undef EXTRACT_VALUE
1798
1799 return rc;
1800}
1801#endif
1802
1803static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1804{
1805#ifdef IN_RING3
1806# ifdef VBOX_WITH_HDA_CODEC_EMU
1807 /* No reason to reopen voice with same settings. */
1808 if (u32Value == HDA_REG_IND(pThis, iReg))
1809 return VINF_SUCCESS;
1810
1811 PDMAUDIOSTREAMCFG as;
1812 int rc = hdaSdFmtToAudSettings(u32Value, &as);
1813 if (RT_FAILURE(rc))
1814 return rc;
1815
1816 PHDADRIVER pDrv;
1817 switch (iReg)
1818 {
1819 case HDA_REG_SD0FMT:
1820 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
1821 rc = hdaCodecOpenStream(pThis->pCodec, PI_INDEX, &as);
1822 break;
1823#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
1824# ifdef VBOX_WITH_HDA_MIC_IN
1825 case HDA_REG_SD2FMT:
1826 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
1827 rc = hdaCodecOpenStream(pThis->pCodec, MC_INDEX, &as);
1828 break;
1829# endif
1830#endif
1831 default:
1832 LogFunc(("Warning: Attempt to change format on register %d\n", iReg));
1833 break;
1834 }
1835
1836 /** @todo r=andy rc gets lost; needs fixing. */
1837 return hdaRegWriteU16(pThis, iReg, u32Value);
1838# else
1839 return hdaRegWriteU16(pThis, iReg, u32Value);
1840# endif
1841#else
1842 return VINF_IOM_R3_MMIO_WRITE;
1843#endif
1844}
1845
1846static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1847{
1848 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
1849 if (RT_FAILURE(rc))
1850 AssertRCReturn(rc, VINF_SUCCESS);
1851 return rc;
1852}
1853
1854static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1855{
1856 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
1857 if (RT_FAILURE(rc))
1858 AssertRCReturn(rc, VINF_SUCCESS);
1859 return rc;
1860}
1861
1862static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
1863{
1864 int rc = VINF_SUCCESS;
1865 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
1866 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
1867 || HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
1868 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1869
1870 rc = hdaRegReadU32(pThis, iReg, pu32Value);
1871 return rc;
1872}
1873
1874static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1875{
1876 int rc = VINF_SUCCESS;
1877
1878 /*
1879 * If the guest set the ICB bit of IRS register, HDA should process the verb in IC register,
1880 * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
1881 */
1882 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
1883 && !HDA_REG_FLAG_VALUE(pThis, IRS, ICB))
1884 {
1885#ifdef IN_RING3
1886 PFNHDACODECVERBPROCESSOR pfn = NULL;
1887 uint64_t resp;
1888 uint32_t cmd = HDA_REG(pThis, IC);
1889 if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP))
1890 {
1891 /*
1892 * 3.4.3 defines behavior of immediate Command status register.
1893 */
1894 LogRel(("guest attempted process immediate verb (%x) with active CORB\n", cmd));
1895 return rc;
1896 }
1897 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1898 LogFunc(("IC:%x\n", cmd));
1899
1900 rc = pThis->pCodec->pfnLookup(pThis->pCodec,
1901 HDA_CODEC_CMD(cmd, 0 /* LUN */),
1902 &pfn);
1903 if (RT_FAILURE(rc))
1904 AssertRCReturn(rc, rc);
1905 rc = pfn(pThis->pCodec,
1906 HDA_CODEC_CMD(cmd, 0 /* LUN */), &resp);
1907 if (RT_FAILURE(rc))
1908 AssertRCReturn(rc, rc);
1909
1910 HDA_REG(pThis, IR) = (uint32_t)resp;
1911 LogFunc(("IR:%x\n", HDA_REG(pThis, IR)));
1912 HDA_REG(pThis, IRS) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */
1913 HDA_REG(pThis, IRS) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
1914#else /* !IN_RING3 */
1915 rc = VINF_IOM_R3_MMIO_WRITE;
1916#endif
1917 return rc;
1918 }
1919 /*
1920 * Once the guest read the response, it should clean the IRV bit of the IRS register.
1921 */
1922 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
1923 && HDA_REG_FLAG_VALUE(pThis, IRS, IRV))
1924 HDA_REG(pThis, IRS) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
1925 return rc;
1926}
1927
1928static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1929{
1930 if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
1931 {
1932 HDA_REG(pThis, RIRBWP) = 0;
1933 }
1934 /* The remaining bits are O, see 6.2.22 */
1935 return VINF_SUCCESS;
1936}
1937
1938static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1939{
1940 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
1941 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
1942 if (RT_FAILURE(rc))
1943 AssertRCReturn(rc, rc);
1944
1945 switch(iReg)
1946 {
1947 case HDA_REG_CORBLBASE:
1948 pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
1949 pThis->u64CORBBase |= pThis->au32Regs[iRegMem];
1950 break;
1951 case HDA_REG_CORBUBASE:
1952 pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
1953 pThis->u64CORBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
1954 break;
1955 case HDA_REG_RIRBLBASE:
1956 pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
1957 pThis->u64RIRBBase |= pThis->au32Regs[iRegMem];
1958 break;
1959 case HDA_REG_RIRBUBASE:
1960 pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
1961 pThis->u64RIRBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
1962 break;
1963 case HDA_REG_DPLBASE:
1964 /** @todo: first bit has special meaning */
1965 pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
1966 pThis->u64DPBase |= pThis->au32Regs[iRegMem];
1967 break;
1968 case HDA_REG_DPUBASE:
1969 pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
1970 pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
1971 break;
1972 default:
1973 AssertMsgFailed(("Invalid index"));
1974 break;
1975 }
1976
1977 LogFunc(("CORB base:%llx RIRB base: %llx DP base: %llx\n",
1978 pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
1979 return rc;
1980}
1981
1982static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
1983{
1984 uint8_t v = HDA_REG(pThis, RIRBSTS);
1985 HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
1986
1987 return hdaProcessInterrupt(pThis);
1988}
1989
1990#ifdef IN_RING3
1991#ifdef LOG_ENABLED
1992static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1993{
1994#if 0
1995 uint64_t addr;
1996 uint32_t len;
1997 uint32_t ioc;
1998 uint8_t bdle[16];
1999 uint32_t counter;
2000 uint32_t i;
2001 uint32_t sum = 0;
2002 Assert(pBdle && pBdle->u32BdleMaxCvi);
2003 for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
2004 {
2005 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + i*16, bdle, 16);
2006 addr = *(uint64_t *)bdle;
2007 len = *(uint32_t *)&bdle[8];
2008 ioc = *(uint32_t *)&bdle[12];
2009 LogFunc(("%s bdle[%d] a:%llx, len:%d, ioc:%d\n", (i == pBdle->u32BdleCvi? "[C]": " "), i, addr, len, ioc & 0x1));
2010 sum += len;
2011 }
2012 LogFunc(("sum: %d\n", sum));
2013 for (i = 0; i < 8; ++i)
2014 {
2015 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
2016 LogFunc(("%s stream[%d] counter=%x\n", i == SDCTL_NUM(pThis, 4) || i == SDCTL_NUM(pThis, 0)? "[C]": " ",
2017 i , counter));
2018 }
2019#endif
2020}
2021#endif
2022
2023static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
2024{
2025 uint8_t bdle[16];
2026 Assert(( pStreamDesc->u64BaseDMA
2027 && pBdle
2028 && pBdle->u32BdleMaxCvi));
2029 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
2030 pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
2031 pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
2032 pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
2033#ifdef LOG_ENABLED
2034 dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
2035#endif
2036}
2037
2038DECLINLINE(uint32_t) hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
2039 uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit)
2040{
2041 /*
2042 * Number of bytes depends on the current position in buffer (u32BdleCviLen-u32BdleCviPos)
2043 */
2044 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
2045 uint32_t cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
2046 /*
2047 * we may increase the counter in range of [0, FIFOS + 1]
2048 */
2049 cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1);
2050 Assert((u32SoundBackendBufferBytesAvail > 0));
2051
2052 /* sanity check to avoid overriding the backend audio buffer */
2053 cb2Copy = RT_MIN(cb2Copy, u32SoundBackendBufferBytesAvail);
2054 cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
2055
2056 if (cb2Copy <= pBdle->cbUnderFifoW)
2057 return 0;
2058 cb2Copy -= pBdle->cbUnderFifoW; /* forcibly reserve the amount of unreported bytes to copy */
2059 return cb2Copy;
2060}
2061
2062DECLINLINE(void) hdaBackendWriteTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
2063 uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
2064{
2065 LogFunc(("cbArranged2Copy: %d, cbCopied: %d, pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
2066 cbArranged2Copy, cbCopied, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
2067 Assert((cbCopied));
2068 AssertPtr(pu32DMACursor);
2069 Assert((pu32BackendBufferCapacity && *pu32BackendBufferCapacity));
2070 /* Assertion!!! Fewer than cbUnderFifoW bytes were copied.
2071 * Probably we need to move the buffer, but it is rather hard to imagine a situation
2072 * where it might happen.
2073 */
2074 AssertMsg((cbCopied == pBdle->cbUnderFifoW + cbArranged2Copy), /* we assume that we write the entire buffer including unreported bytes */
2075 ("cbCopied=%RU32 != pBdle->cbUnderFifoW=%RU32 + cbArranged2Copy=%RU32\n",
2076 cbCopied, pBdle->cbUnderFifoW, cbArranged2Copy));
2077 if ( pBdle->cbUnderFifoW
2078 && pBdle->cbUnderFifoW <= cbCopied)
2079 {
2080 LogFunc(("CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n",
2081 pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2082 }
2083
2084 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbCopied);
2085 Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Incorrect assumption */
2086
2087 /* We always increment the position of DMA buffer counter because we're always reading into an intermediate buffer */
2088 pBdle->u32BdleCviPos += cbArranged2Copy;
2089
2090 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32BackendBufferCapacity >= cbCopied)); /* sanity */
2091 /* We report all bytes (including previously unreported bytes) */
2092 *pu32DMACursor += cbCopied;
2093 /* Decrease the backend counter by the number of bytes we copied to the backend */
2094 *pu32BackendBufferCapacity -= cbCopied;
2095 LogFunc(("CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
2096 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, *pu32DMACursor, *pu32BackendBufferCapacity));
2097}
2098
2099DECLINLINE(void) hdaBackendReadTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
2100 uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
2101{
2102 Assert((cbCopied, cbArranged2Copy));
2103 *pu32BackendBufferCapacity -= cbCopied;
2104 pBdle->u32BdleCviPos += cbCopied;
2105 LogFunc(("CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2106 *pu32DMACursor += cbCopied + pBdle->cbUnderFifoW;
2107 pBdle->cbUnderFifoW = 0;
2108 LogFunc(("CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
2109 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
2110}
2111
2112DECLINLINE(void) hdaBackendTransferUnreported(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
2113 uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
2114{
2115 LogFunc(("CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2116 pBdle->u32BdleCviPos += cbCopied;
2117 pBdle->cbUnderFifoW += cbCopied;
2118 /* In case of a read transaction we're always copying from the backend buffer */
2119 if (pu32BackendBufferCapacity)
2120 *pu32BackendBufferCapacity -= cbCopied;
2121 LogFunc(("CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2122 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pThis, pStreamDesc)));
2123}
2124
2125DECLINLINE(bool) hdaIsTransferCountersOverlapped(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
2126{
2127 bool fOnBufferEdge = ( *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl
2128 || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen);
2129
2130 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
2131
2132 if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
2133 *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl;
2134 hdaUpdatePosBuf(pThis, pStreamDesc);
2135
2136 /* don't touch BdleCvi counter on uninitialized descriptor */
2137 if ( pBdle->u32BdleCviPos
2138 && pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
2139 {
2140 pBdle->u32BdleCviPos = 0;
2141 pBdle->u32BdleCvi++;
2142 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
2143 pBdle->u32BdleCvi = 0;
2144 }
2145 return fOnBufferEdge;
2146}
2147
2148DECLINLINE(void) hdaStreamCounterUpdate(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
2149 uint32_t cbInc)
2150{
2151 /*
2152 * if we're below the FIFO Watermark, it's expected that HDA doesn't fetch anything.
2153 * (ICH6 datasheet 18.2.38)
2154 */
2155 if (!pBdle->cbUnderFifoW)
2156 {
2157 *pStreamDesc->pu32Lpib += cbInc;
2158
2159 /*
2160 * Assert. The buffer counters should never overlap.
2161 */
2162 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
2163
2164 hdaUpdatePosBuf(pThis, pStreamDesc);
2165 }
2166}
2167
2168static bool hdaDoNextTransferCycle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
2169{
2170 bool fDoNextTransferLoop = true;
2171 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
2172 || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
2173 {
2174 if ( !pBdle->cbUnderFifoW
2175 && pBdle->fBdleCviIoc)
2176 {
2177 /**
2178 * @todo - more carefully investigate BCIS flag.
2179 * Speech synthesis works fine on Mac Guest if this bit isn't set
2180 * but in general sound quality gets worse.
2181 */
2182 *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
2183
2184 /*
2185 * we should generate the interrupt if ICE bit of SDCTL register is set.
2186 */
2187 if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
2188 hdaProcessInterrupt(pThis);
2189 }
2190 fDoNextTransferLoop = false;
2191 }
2192 return fDoNextTransferLoop;
2193}
2194
2195#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2196/**
2197 * hdaReadAudio - copies samples from audio backend to DMA.
2198 * Note: This function writes to the DMA buffer immediately,
2199 * but "reports bytes" when all conditions are met (FIFOW).
2200 */
2201static int hdaReadAudio(PHDASTATE pThis, PAUDMIXSINK pSink,
2202 PHDASTREAMTRANSFERDESC pStreamDesc,
2203 uint32_t u32CblLimit, uint32_t *pcbAvail, uint32_t *pcbRead)
2204{
2205 PHDABDLEDESC pBdle = &pThis->StInBdle; /** @todo Add support for mic in. */
2206
2207 int rc;
2208 uint32_t cbTransferred = 0;
2209
2210 LogFlowFunc(("CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2211
2212 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pcbAvail, u32CblLimit);
2213 if (!cb2Copy)
2214 {
2215 /* If we enter here we can't report "unreported bits". */
2216 rc = VERR_NO_DATA;
2217 }
2218 else
2219 {
2220 uint32_t cbRead = 0;
2221 rc = audioMixerProcessSinkIn(pSink, pBdle->au8HdaBuffer, cb2Copy, &cbRead);
2222 if (RT_SUCCESS(rc))
2223 {
2224 Assert(cbRead);
2225
2226 /*
2227 * Write the HDA DMA buffer.
2228 */
2229 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
2230 pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos,
2231 pBdle->au8HdaBuffer, cbRead);
2232
2233 /* Don't see any reason why cb2Copy would differ from cbRead. */
2234 Assert((cbRead == cb2Copy && (*pcbAvail) >= cb2Copy)); /* sanity */
2235
2236 if (pBdle->cbUnderFifoW + cbRead > hdaFifoWToSz(pThis, 0))
2237 hdaBackendReadTransferReported(pBdle, cb2Copy, cbRead, &cbTransferred, pcbAvail);
2238 else
2239 {
2240 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbRead, pcbAvail);
2241 rc = VERR_NO_DATA;
2242 }
2243 }
2244 }
2245
2246 Assert((cbTransferred <= (SDFIFOS(pThis, 0) + 1)));
2247 LogFunc(("CVI(pos:%RU32, len:%RU32), cbTransferred=%RU32, rc=%Rrc\n",
2248 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred, rc));
2249
2250 if (RT_SUCCESS(rc))
2251 *pcbRead = cbTransferred;
2252
2253 return rc;
2254}
2255#else
2256static int hdaReadAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc,
2257 uint32_t u32CblLimit, uint32_t *pu32Avail, uint32_t *pcbRead)
2258{
2259 PHDABDLEDESC pBdle = &pThis->StInBdle;
2260
2261 uint32_t cbTransferred = 0;
2262 uint32_t cb2Copy = 0;
2263 uint32_t cbBackendCopy = 0;
2264
2265 int rc;
2266
2267 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2268
2269 cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
2270 if (!cb2Copy)
2271 {
2272 /* if we enter here we can't report "unreported bits" */
2273 rc = VERR_NO_DATA;
2274 }
2275 else
2276 {
2277 /*
2278 * read from backend input line to the last unreported position or at the begining.
2279 */
2280 cbBackendCopy = AUD_read(pThis->pCodec->SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);
2281
2282 /*
2283 * write the HDA DMA buffer
2284 */
2285 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer,
2286 cbBackendCopy);
2287
2288 /* Don't see any reason why cb2Copy would differ from cbBackendCopy */
2289 Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
2290
2291 if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pThis, 0))
2292 {
2293 hdaBackendReadTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransferred, pu32Avail);
2294 rc = VINF_SUCCESS;
2295 }
2296 else
2297 {
2298 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbBackendCopy, pu32Avail);
2299 rc = VERR_NO_DATA;
2300 }
2301 }
2302
2303 Assert((cbTransferred <= (SDFIFOS(pThis, 0) + 1)));
2304 Log(("hda:ra: CVI(pos:%d, len:%d) cbTransferred: %d\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred));
2305
2306 if (pcbRead)
2307 *pcbRead = cbTransferred;
2308
2309 return rc;
2310}
2311#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2312
2313static int hdaWriteAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t u32CblLimit,
2314 uint32_t *pcbAvail, uint32_t *pcbWritten)
2315{
2316 PHDABDLEDESC pBdle = &pThis->StOutBdle;
2317
2318 int rc = VINF_SUCCESS;
2319
2320 uint32_t cbTransferred = 0;
2321 uint32_t cbWrittenMin = 0; /* local byte counter, how many bytes copied to backend */
2322
2323 LogFunc(("CVI(cvi:%RU32, pos:%RU32, len:%RU32)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
2324
2325 /* Local byte counter (on local buffer). */
2326 uint32_t cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pcbAvail, u32CblLimit);
2327
2328 /*
2329 * Copy from DMA to the corresponding hdaBuffer (if there are any bytes from the
2330 * previous unreported transfer we write at offset 'pBdle->cbUnderFifoW').
2331 */
2332 if (!cb2Copy)
2333 {
2334 rc = VERR_NO_DATA;
2335 }
2336 else
2337 {
2338 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
2339 pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos,
2340 pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
2341#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2342 STAM_COUNTER_ADD(&pThis->StatBytesRead, cb2Copy);
2343#endif
2344
2345 /*
2346 * Write to audio backend. We should ensure that we have enough bytes to copy to the backend.
2347 */
2348 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pThis, pStreamDesc))
2349 {
2350#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2351 uint32_t cbWritten;
2352 cbWrittenMin = UINT32_MAX;
2353
2354 PHDADRIVER pDrv;
2355 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2356 {
2357 if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
2358 {
2359 rc = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
2360 pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW,
2361 &cbWritten);
2362 if (RT_FAILURE(rc))
2363 continue;
2364 }
2365 else /* Stream disabled, just assume all was copied. */
2366 cbWritten = cb2Copy;
2367
2368 cbWrittenMin = RT_MIN(cbWrittenMin, cbWritten);
2369 LogFlowFunc(("\tLUN#%RU8: cbWritten=%RU32, cWrittenMin=%RU32\n", pDrv->uLUN, cbWritten, cbWrittenMin));
2370 }
2371
2372 if (cbWrittenMin == UINT32_MAX)
2373 cbWrittenMin = 0;
2374#else
2375 cbWrittenMin = AUD_write (pThis->pCodec->SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
2376#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2377
2378 hdaBackendWriteTransferReported(pBdle, cb2Copy, cbWrittenMin, &cbTransferred, pcbAvail);
2379 }
2380 else
2381 {
2382 /* Not enough bytes to be processed and reported, we'll try our luck next time around. */
2383 hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cb2Copy, NULL);
2384 rc = VERR_NO_DATA;
2385 }
2386 }
2387
2388 Assert(cbTransferred <= SDFIFOS(pThis, 4) + 1);
2389 LogFunc(("CVI(pos:%RU32, len:%RU32, cbTransferred:%RU32), rc=%Rrc\n",
2390 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred, rc));
2391
2392 if (RT_SUCCESS(rc))
2393 *pcbWritten = cbTransferred;
2394
2395 return rc;
2396}
2397
2398/**
2399 * @interface_method_impl{HDACODEC,pfnReset}
2400 */
2401DECLCALLBACK(int) hdaCodecReset(PHDACODEC pCodec)
2402{
2403 PHDASTATE pThis = pCodec->pHDAState;
2404 NOREF(pThis);
2405 return VINF_SUCCESS;
2406}
2407
2408DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
2409 PHDASTREAMTRANSFERDESC pStreamDesc)
2410{
2411 Assert(pThis); Assert(pBdle); Assert(pStreamDesc); Assert(u8Strm <= 7);
2412
2413 RT_BZERO(pStreamDesc, sizeof(HDASTREAMTRANSFERDESC));
2414 pStreamDesc->u8Strm = u8Strm;
2415 pStreamDesc->u32Ctl = HDA_STREAM_REG(pThis, CTL, u8Strm);
2416 pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, u8Strm),
2417 HDA_STREAM_REG(pThis, BDPU, u8Strm));
2418 pStreamDesc->pu32Lpib = &HDA_STREAM_REG(pThis, LPIB, u8Strm);
2419 pStreamDesc->pu32Sts = &HDA_STREAM_REG(pThis, STS, u8Strm);
2420 pStreamDesc->u32Cbl = HDA_STREAM_REG(pThis, CBL, u8Strm);
2421 pStreamDesc->u32Fifos = HDA_STREAM_REG(pThis, FIFOS, u8Strm);
2422
2423 pBdle->u32BdleMaxCvi = HDA_STREAM_REG(pThis, LVI, u8Strm);
2424
2425#ifdef LOG_ENABLED
2426 if ( pBdle
2427 && pBdle->u32BdleMaxCvi)
2428 {
2429 LogFunc(("Initialization of transfer descriptor:\n"));
2430 dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
2431 }
2432#endif
2433}
2434
2435static DECLCALLBACK(void) hdaCloseIn(PHDASTATE pThis, PDMAUDIORECSOURCE enmRecSource)
2436{
2437 NOREF(pThis);
2438 NOREF(enmRecSource);
2439 LogFlowFuncEnter();
2440}
2441
2442static DECLCALLBACK(void) hdaCloseOut(PHDASTATE pThis)
2443{
2444 NOREF(pThis);
2445 LogFlowFuncEnter();
2446}
2447
2448#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2449static DECLCALLBACK(int) hdaOpenIn(PHDASTATE pThis,
2450 const char *pszName, PDMAUDIORECSOURCE enmRecSource,
2451 PPDMAUDIOSTREAMCFG pCfg)
2452{
2453 PAUDMIXSINK pSink;
2454
2455 switch (enmRecSource)
2456 {
2457# ifdef VBOX_WITH_HDA_MIC_IN
2458 case PDMAUDIORECSOURCE_MIC:
2459 pSink = pThis->pSinkMicIn;
2460 break;
2461# endif
2462 case PDMAUDIORECSOURCE_LINE_IN:
2463 pSink = pThis->pSinkLineIn;
2464 break;
2465 default:
2466 AssertMsgFailed(("Audio source %ld not supported\n", enmRecSource));
2467 return VERR_NOT_SUPPORTED;
2468 }
2469
2470 int rc;
2471 char *pszDesc;
2472
2473 PHDADRIVER pDrv;
2474 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2475 {
2476 if (RTStrAPrintf(&pszDesc, "[LUN#%RU8] %s", pDrv->uLUN, pszName) <= 0)
2477 {
2478 rc = VERR_NO_MEMORY;
2479 break;
2480 }
2481
2482 rc = pDrv->pConnector->pfnOpenIn(pDrv->pConnector,
2483 pszDesc, enmRecSource,
2484 NULL /* fnCallback */, NULL /* pvCallback */,
2485 pCfg,
2486 &pDrv->LineIn.pStrmIn);
2487 LogFlowFunc(("LUN#%RU8: Opened input \"%s\", with rc=%Rrc\n", pDrv->uLUN, pszDesc, rc));
2488 if (rc == VINF_SUCCESS) /* Note: Could return VWRN_ALREADY_EXISTS. */
2489 {
2490 audioMixerRemoveStream(pSink, pDrv->LineIn.phStrmIn);
2491 rc = audioMixerAddStreamIn(pSink,
2492 pDrv->pConnector, pDrv->LineIn.pStrmIn,
2493 0 /* uFlags */, &pDrv->LineIn.phStrmIn);
2494 }
2495
2496 RTStrFree(pszDesc);
2497 }
2498
2499 LogFlowFuncLeaveRC(rc);
2500 return rc;
2501}
2502
2503static DECLCALLBACK(int) hdaOpenOut(PHDASTATE pThis,
2504 const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
2505{
2506 int rc = VINF_SUCCESS;
2507
2508 PHDADRIVER pDrv;
2509 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2510 {
2511 int rc2 = pDrv->pConnector->pfnOpenOut(pDrv->pConnector, pszName,
2512 NULL /* fnCallback */, pDrv /* pvCallback */,
2513 pCfg,
2514 &pDrv->Out.pStrmOut);
2515 if (RT_FAILURE(rc2))
2516 {
2517 LogFunc(("LUN#%RU8: Opening stream \"%s\" failed, rc=%Rrc\n", pDrv->uLUN, pszName, rc2));
2518 if (RT_SUCCESS(rc))
2519 rc = rc2;
2520 /* Keep going. */
2521 }
2522 }
2523
2524 LogFlowFuncLeaveRC(rc);
2525 return rc;
2526}
2527
2528static DECLCALLBACK(int) hdaSetVolume(PHDASTATE pThis,
2529 bool fMute, uint8_t uVolLeft, uint8_t uVolRight)
2530{
2531 int rc = VINF_SUCCESS;
2532
2533 PHDADRIVER pDrv;
2534 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2535 {
2536 int rc2 = pDrv->pConnector->pfnSetVolume(pDrv->pConnector,
2537 fMute, uVolLeft, uVolRight);
2538 if (RT_FAILURE(rc2))
2539 {
2540 LogFunc(("Failed for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
2541 if (RT_SUCCESS(rc))
2542 rc = rc2;
2543 /* Keep going. */
2544 }
2545 }
2546
2547 LogFlowFuncLeaveRC(rc);
2548 return rc;
2549}
2550#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2551
2552#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2553static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
2554{
2555 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
2556 AssertPtr(pThis);
2557
2558 STAM_PROFILE_START(&pThis->StatTimer, a);
2559
2560 int rc = VINF_SUCCESS;
2561
2562 uint32_t cbInMax = 0;
2563 uint32_t cbOutMin = UINT32_MAX;
2564
2565 PHDADRIVER pDrv;
2566 uint32_t cbIn, cbOut;
2567#ifdef DEBUG_LUN
2568 uint8_t uLUN = 0;
2569#endif
2570 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2571 {
2572 if (!pDrv->pConnector->pfnIsOutputOK(pDrv->pConnector, pDrv->Out.pStrmOut))
2573 continue;
2574
2575 rc = pDrv->pConnector->pfnQueryData(pDrv->pConnector, /** @todo Rename QueryStatus */
2576 &cbIn, &cbOut, &pDrv->cSamplesLive);
2577 if (RT_SUCCESS(rc))
2578 {
2579#ifdef DEBUG_LUN
2580 LogFlowFunc(("\tLUN#%RU8: cbIn=%RU32, cbOut=%RU32\n", uLUN, cbIn, cbOut));
2581#endif
2582 cbInMax = RT_MAX(cbInMax, cbIn);
2583 cbOutMin = RT_MIN(cbOutMin, cbOut);
2584 }
2585 else
2586 pDrv->cSamplesLive = 0;
2587
2588#ifdef DEBUG_LUN
2589 uLUN++;
2590#endif
2591 }
2592
2593 /*
2594 * Playback.
2595 */
2596 if (cbOutMin)
2597 {
2598 Assert(cbOutMin != UINT32_MAX);
2599 hdaTransfer(pThis, PO_INDEX, cbOutMin); /** @todo Add rc! */
2600 }
2601 else
2602 {
2603 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2604 {
2605 if (pDrv->cSamplesLive)
2606 pDrv->pConnector->pfnPlayOut(pDrv->pConnector);
2607 }
2608 }
2609
2610 /*
2611 * Recording.
2612 */
2613 if (cbInMax)
2614 hdaTransfer(pThis, PI_INDEX, cbInMax); /** @todo Add rc! */
2615
2616 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
2617
2618 STAM_PROFILE_STOP(&pThis->StatTimer, a);
2619}
2620
2621static DECLCALLBACK(int) hdaTransfer(PHDASTATE pThis,
2622 ENMSOUNDSOURCE enmSrc, uint32_t cbAvail)
2623{
2624 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2625
2626 LogFlowFunc(("pThis=%p, cbAvail=%RU32\n", pThis, cbAvail));
2627#else
2628static DECLCALLBACK(int) hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE enmSrc, uint32_t cbAvail)
2629{
2630 AssertPtrReturn(pCodec, VERR_INVALID_POINTER);
2631 PHDASTATE pThis = pCodec->pHDAState;
2632 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2633#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2634 int rc;
2635
2636 uint8_t u8Strm;
2637 PHDABDLEDESC pBdle;
2638
2639 switch (enmSrc)
2640 {
2641 case PI_INDEX:
2642 {
2643 u8Strm = 0;
2644 pBdle = &pThis->StInBdle;
2645 break;
2646 }
2647
2648#ifdef VBOX_WITH_HDA_MIC_IN
2649 case MC_INDEX:
2650 {
2651 u8Strm = 2;
2652 pBdle = &pThis->StMicBdle;
2653 break;
2654 }
2655#endif
2656 case PO_INDEX:
2657 {
2658 u8Strm = 4;
2659 pBdle = &pThis->StOutBdle;
2660 break;
2661 }
2662
2663 default:
2664 AssertMsgFailed(("Unknown source index %ld\n", enmSrc));
2665 return VERR_NOT_SUPPORTED;
2666 }
2667
2668 HDASTREAMTRANSFERDESC StreamDesc;
2669 hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
2670
2671 while (cbAvail)
2672 {
2673 Assert( (StreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
2674 && cbAvail
2675 && StreamDesc.u64BaseDMA);
2676
2677 /* Fetch the Buffer Descriptor Entry (BDE). */
2678 if (hdaIsTransferCountersOverlapped(pThis, pBdle, &StreamDesc))
2679 hdaFetchBdle(pThis, pBdle, &StreamDesc);
2680
2681 *StreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
2682 Assert((StreamDesc.u32Cbl >= (*StreamDesc.pu32Lpib))); /* sanity */
2683 uint32_t u32CblLimit = StreamDesc.u32Cbl - (*StreamDesc.pu32Lpib);
2684 Assert((u32CblLimit > hdaFifoWToSz(pThis, &StreamDesc)));
2685
2686 LogFunc(("CBL=%RU32, LPIB=%RU32\n", StreamDesc.u32Cbl, *StreamDesc.pu32Lpib));
2687
2688#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2689 PAUDMIXSINK pSink;
2690#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2691 uint32_t cbWritten;
2692 switch (enmSrc)
2693 {
2694 case PI_INDEX:
2695#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2696 pSink = pThis->pSinkLineIn;
2697 rc = hdaReadAudio(pThis, pSink, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten);
2698#else
2699 rc = hdaReadAudio(pThis, &StreamDesc, u32CblLimit, (uint32_t *)&cbAvail, &cbWritten);
2700#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2701 break;
2702 case PO_INDEX:
2703 rc = hdaWriteAudio(pThis, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten);
2704 break;
2705#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
2706# ifdef VBOX_WITH_HDA_MIC_IN
2707 case MC_INDEX:
2708 pSink = pThis->pSinkMicIn;
2709 rc = hdaReadAudio(pThis, pSink, &StreamDesc, u32CblLimit, &cbAvail, &cbWritten);
2710 break;
2711# endif
2712#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
2713 default:
2714 AssertMsgFailed(("Unsupported source index %ld\n", enmSrc));
2715 rc = VERR_NOT_SUPPORTED;
2716 break;
2717 }
2718 Assert(cbWritten <= StreamDesc.u32Fifos + 1);
2719 *StreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
2720
2721 /* Process end of buffer condition. */
2722 hdaStreamCounterUpdate(pThis, pBdle, &StreamDesc, cbWritten);
2723
2724 if ( !hdaDoNextTransferCycle(pThis, pBdle, &StreamDesc)
2725 || RT_FAILURE(rc))
2726 {
2727 if (rc == VERR_NO_DATA) /* No more data to process. */
2728 rc = VINF_SUCCESS;
2729
2730 break;
2731 }
2732 }
2733
2734 return rc;
2735}
2736#endif /* IN_RING3 */
2737
2738/* MMIO callbacks */
2739
2740/**
2741 * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
2742 *
2743 * @note During implementation, we discovered so-called "forgotten" or "hole"
2744 * registers whose description is not listed in the RPM, datasheet, or
2745 * spec.
2746 */
2747PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
2748{
2749 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
2750 int rc;
2751
2752 /*
2753 * Look up and log.
2754 */
2755 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
2756 int idxRegDsc = hdaRegLookup(pThis, offReg); /* Register descriptor index. */
2757#ifdef LOG_ENABLED
2758 unsigned const cbLog = cb;
2759 uint32_t offRegLog = offReg;
2760#endif
2761
2762 LogFunc(("offReg=%#x cb=%#x\n", offReg, cb));
2763#define NEW_READ_CODE
2764#ifdef NEW_READ_CODE
2765 Assert(cb == 4); Assert((offReg & 3) == 0);
2766
2767 if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
2768 LogFunc(("access to registers except GCTL is blocked while reset\n"));
2769
2770 if (idxRegDsc == -1)
2771 LogRel(("Invalid read access @0x%x(of bytes:%d)\n", offReg, cb));
2772
2773 if (idxRegDsc != -1)
2774 {
2775 /* ASSUMES gapless DWORD at end of map. */
2776 if (g_aHdaRegMap[idxRegDsc].size == 4)
2777 {
2778 /*
2779 * Straight forward DWORD access.
2780 */
2781 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, (uint32_t *)pv);
2782 LogFunc(("read %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
2783 }
2784 else
2785 {
2786 /*
2787 * Multi register read (unless there are trailing gaps).
2788 * ASSUMES that only DWORD reads have sideeffects.
2789 */
2790 uint32_t u32Value = 0;
2791 unsigned cbLeft = 4;
2792 do
2793 {
2794 uint32_t const cbReg = g_aHdaRegMap[idxRegDsc].size;
2795 uint32_t u32Tmp = 0;
2796
2797 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Tmp);
2798 LogFunc(("read %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
2799 if (rc != VINF_SUCCESS)
2800 break;
2801 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
2802
2803 cbLeft -= cbReg;
2804 offReg += cbReg;
2805 idxRegDsc++;
2806 } while (cbLeft > 0 && g_aHdaRegMap[idxRegDsc].offset == offReg);
2807
2808 if (rc == VINF_SUCCESS)
2809 *(uint32_t *)pv = u32Value;
2810 else
2811 Assert(!IOM_SUCCESS(rc));
2812 }
2813 }
2814 else
2815 {
2816 rc = VINF_IOM_MMIO_UNUSED_FF;
2817 LogFunc(("hole at %x is accessed for read\n", offReg));
2818 }
2819#else
2820 if (idxRegDsc != -1)
2821 {
2822 /** @todo r=bird: Accesses crossing register boundraries aren't handled
2823 * right from what I can tell? If they are, please explain
2824 * what the rules are. */
2825 uint32_t mask = 0;
2826 uint32_t shift = (g_aHdaRegMap[idxRegDsc].offset - offReg) % sizeof(uint32_t) * 8;
2827 uint32_t u32Value = 0;
2828 switch(cb)
2829 {
2830 case 1: mask = 0x000000ff; break;
2831 case 2: mask = 0x0000ffff; break;
2832 case 4:
2833 /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
2834 case 8:
2835 mask = 0xffffffff;
2836 cb = 4;
2837 break;
2838 }
2839#if 0
2840 /* Cross-register access. Mac guest hits this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL
2841 */
2842 //Assert((cb <= g_aHdaRegMap[idxRegDsc].size - (offReg - g_aHdaRegMap[idxRegDsc].offset)));
2843 if (cb > g_aHdaRegMap[idxRegDsc].size - (offReg - g_aHdaRegMap[idxRegDsc].offset))
2844 {
2845 int off = cb - (g_aHdaRegMap[idxRegDsc].size - (offReg - g_aHdaRegMap[idxRegDsc].offset));
2846 rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off);
2847 if (RT_FAILURE(rc))
2848 AssertRCReturn (rc, rc);
2849 }
2850 //Assert(((offReg - g_aHdaRegMap[idxRegDsc].offset) == 0));
2851#endif
2852 mask <<= shift;
2853 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Value);
2854 *(uint32_t *)pv |= (u32Value & mask);
2855 LogFunc(("read %s[%x/%x]\n", g_aHdaRegMap[idxRegDsc].abbrev, u32Value, *(uint32_t *)pv));
2856 }
2857 else
2858 {
2859 *(uint32_t *)pv = 0xFF;
2860 LogFunc(("hole at %x is accessed for read\n", offReg));
2861 rc = VINF_SUCCESS;
2862 }
2863#endif
2864
2865 /*
2866 * Log the outcome.
2867 */
2868#ifdef LOG_ENABLED
2869 if (cbLog == 4)
2870 LogFunc(("@%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
2871 else if (cbLog == 2)
2872 LogFunc(("@%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
2873 else if (cbLog == 1)
2874 LogFunc(("@%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
2875#endif
2876 return rc;
2877}
2878
2879
2880DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxRegDsc, uint32_t u32Value, char const *pszLog)
2881{
2882 if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
2883 LogFunc(("access to registers except GCTL is blocked while reset\n")); /** @todo where is this enforced? */
2884
2885 uint32_t idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
2886#ifdef LOG_ENABLED
2887 uint32_t const u32CurValue = pThis->au32Regs[idxRegMem];
2888#endif
2889 int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value);
2890 LogFunc(("write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
2891 g_aHdaRegMap[idxRegDsc].size, u32CurValue, pThis->au32Regs[idxRegMem], pszLog));
2892 return rc;
2893}
2894
2895
2896/**
2897 * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
2898 */
2899PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
2900{
2901 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
2902 int rc;
2903
2904 /*
2905 * The behavior of accesses that aren't aligned on natural boundraries is
2906 * undefined. Just reject them outright.
2907 */
2908 /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
2909 Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
2910 if (GCPhysAddr & (cb - 1))
2911 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
2912
2913 /*
2914 * Look up and log the access.
2915 */
2916 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
2917 int idxRegDsc = hdaRegLookup(pThis, offReg);
2918 uint32_t idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
2919 uint64_t u64Value;
2920 if (cb == 4) u64Value = *(uint32_t const *)pv;
2921 else if (cb == 2) u64Value = *(uint16_t const *)pv;
2922 else if (cb == 1) u64Value = *(uint8_t const *)pv;
2923 else if (cb == 8) u64Value = *(uint64_t const *)pv;
2924 else
2925 {
2926 u64Value = 0; /* shut up gcc. */
2927 AssertReleaseMsgFailed(("%d\n", cb));
2928 }
2929
2930#ifdef LOG_ENABLED
2931 uint32_t const u32LogOldValue = idxRegDsc >= 0 ? pThis->au32Regs[idxRegMem] : UINT32_MAX;
2932 uint32_t const offRegLog = offReg;
2933 int const idxRegLog = idxRegMem;
2934 if (idxRegDsc == -1)
2935 LogFunc(("@%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
2936 else if (cb == 4)
2937 LogFunc(("@%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
2938 else if (cb == 2)
2939 LogFunc(("@%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
2940 else if (cb == 1)
2941 LogFunc(("@%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
2942 if (idxRegDsc >= 0 && g_aHdaRegMap[idxRegDsc].size != cb)
2943 LogFunc(("size=%d != cb=%d!!\n", g_aHdaRegMap[idxRegDsc].size, cb));
2944#endif
2945
2946#define NEW_WRITE_CODE
2947#ifdef NEW_WRITE_CODE
2948 /*
2949 * Try for a direct hit first.
2950 */
2951 if (idxRegDsc != -1 && g_aHdaRegMap[idxRegDsc].size == cb)
2952 {
2953 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "");
2954 LogFunc(("@%#05x %#x -> %#x\n", offRegLog, u32LogOldValue,
2955 idxRegLog != -1 ? pThis->au32Regs[idxRegLog] : UINT32_MAX));
2956 }
2957 /*
2958 * Partial or multiple register access, loop thru the requested memory.
2959 */
2960 else
2961 {
2962 /* If it's an access beyond the start of the register, shift the input
2963 value and fill in missing bits. Natural alignment rules means we
2964 will only see 1 or 2 byte accesses of this kind, so no risk of
2965 shifting out input values. */
2966 if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(pThis, offReg)) != -1)
2967 {
2968 uint32_t const cbBefore = offReg - g_aHdaRegMap[idxRegDsc].offset; Assert(cbBefore > 0 && cbBefore < 4);
2969 offReg -= cbBefore;
2970 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
2971 u64Value <<= cbBefore * 8;
2972 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbBefore];
2973 LogFunc(("Within register, supplied %u leading bits: %#llx -> %#llx ...\n",
2974 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
2975 }
2976
2977 /* Loop thru the write area, it may cover multiple registers. */
2978 rc = VINF_SUCCESS;
2979 for (;;)
2980 {
2981 uint32_t cbReg;
2982 if (idxRegDsc != -1)
2983 {
2984 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
2985 cbReg = g_aHdaRegMap[idxRegDsc].size;
2986 if (cb < cbReg)
2987 {
2988 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbReg] & ~g_afMasks[cb];
2989 LogFunc(("Supplying missing bits (%#x): %#llx -> %#llx ...\n",
2990 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
2991 }
2992 uint32_t u32LogOldVal = pThis->au32Regs[idxRegMem];
2993 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "*");
2994 LogFunc(("@%#05x %#x -> %#x\n", offRegLog, u32LogOldVal,
2995 pThis->au32Regs[idxRegMem]));
2996 }
2997 else
2998 {
2999 LogRel(("HDA: Invalid write access @0x%x!\n", offReg));
3000 cbReg = 1;
3001 }
3002 if (rc != VINF_SUCCESS)
3003 break;
3004 if (cbReg >= cb)
3005 break;
3006
3007 /* advance */
3008 offReg += cbReg;
3009 cb -= cbReg;
3010 u64Value >>= cbReg * 8;
3011 if (idxRegDsc == -1)
3012 idxRegDsc = hdaRegLookup(pThis, offReg);
3013 else
3014 {
3015 idxRegDsc++;
3016 if ( (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
3017 || g_aHdaRegMap[idxRegDsc].offset != offReg)
3018 idxRegDsc = -1;
3019 }
3020 }
3021 }
3022#else
3023 if (idxRegDsc != -1)
3024 {
3025 /** @todo r=bird: This looks like code for handling unaligned register
3026 * accesses. If it isn't, then add a comment explaining what you're
3027 * trying to do here. OTOH, if it is then it has the following
3028 * issues:
3029 * -# You're calculating the wrong new value for the register.
3030 * -# You're not handling cross register accesses. Imagine a
3031 * 4-byte write starting at CORBCTL, or a 8-byte write.
3032 *
3033 * PS! consider dropping the 'offset' argument to pfnWrite/pfnRead as
3034 * nobody seems to be using it and it just adds complexity when reading
3035 * the code.
3036 *
3037 */
3038 uint32_t u32CurValue = pThis->au32Regs[idxRegMem];
3039 uint32_t u32NewValue;
3040 uint32_t mask;
3041 switch (cb)
3042 {
3043 case 1:
3044 u32NewValue = *(uint8_t const *)pv;
3045 mask = 0xff;
3046 break;
3047 case 2:
3048 u32NewValue = *(uint16_t const *)pv;
3049 mask = 0xffff;
3050 break;
3051 case 4:
3052 case 8:
3053 /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
3054 u32NewValue = *(uint32_t const *)pv;
3055 mask = 0xffffffff;
3056 cb = 4;
3057 break;
3058 default:
3059 AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */
3060 }
3061 /* cross-register access, see corresponding comment in hdaMMIORead */
3062 uint32_t shift = (g_aHdaRegMap[idxRegDsc].offset - offReg) % sizeof(uint32_t) * 8;
3063 mask <<= shift;
3064 u32NewValue <<= shift;
3065 u32NewValue &= mask;
3066 u32NewValue |= (u32CurValue & ~mask);
3067
3068 rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32NewValue);
3069 LogFunc(("write %s:(%x) %x => %x\n", g_aHdaRegMap[idxRegDsc].abbrev, u32NewValue,
3070 u32CurValue, pThis->au32Regs[idxRegMem]));
3071 }
3072 else
3073 rc = VINF_SUCCESS;
3074
3075 LogFunc(("@%#05x %#x -> %#x\n", offRegLog, u32LogOldValue,
3076 idxRegLog != -1 ? pThis->au32Regs[idxRegLog] : UINT32_MAX));
3077#endif
3078 return rc;
3079}
3080
3081
3082/* PCI callback. */
3083
3084#ifdef IN_RING3
3085/**
3086 * @callback_method_impl{FNPCIIOREGIONMAP}
3087 */
3088static DECLCALLBACK(int) hdaPciIoRegionMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
3089 PCIADDRESSSPACE enmType)
3090{
3091 PPDMDEVINS pDevIns = pPciDev->pDevIns;
3092 PHDASTATE pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
3093 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
3094 int rc;
3095
3096 /*
3097 * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
3098 *
3099 * Let IOM talk DWORDs when reading, saves a lot of complications. On
3100 * writing though, we have to do it all ourselves because of sideeffects.
3101 */
3102 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
3103 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
3104#ifdef NEW_READ_CODE
3105 IOMMMIO_FLAGS_READ_DWORD |
3106#else
3107 IOMMMIO_FLAGS_READ_PASSTHRU |
3108#endif
3109 IOMMMIO_FLAGS_WRITE_PASSTHRU,
3110 hdaMMIOWrite, hdaMMIORead, "HDA");
3111
3112 if (RT_FAILURE(rc))
3113 return rc;
3114
3115 if (pThis->fR0Enabled)
3116 {
3117 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
3118 "hdaMMIOWrite", "hdaMMIORead");
3119 if (RT_FAILURE(rc))
3120 return rc;
3121 }
3122
3123 if (pThis->fRCEnabled)
3124 {
3125 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
3126 "hdaMMIOWrite", "hdaMMIORead");
3127 if (RT_FAILURE(rc))
3128 return rc;
3129 }
3130
3131 pThis->MMIOBaseAddr = GCPhysAddress;
3132 return VINF_SUCCESS;
3133}
3134
3135
3136/* Saved state callbacks. */
3137
3138/**
3139 * @callback_method_impl{FNSSMDEVSAVEEXEC}
3140 */
3141static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
3142{
3143 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3144
3145 /* Save Codec nodes states */
3146 hdaCodecSaveState(pThis->pCodec, pSSM);
3147
3148 /* Save MMIO registers */
3149 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= HDA_NREGS_SAVED);
3150 SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
3151 SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3152
3153 /* Save HDA dma counters */
3154 SSMR3PutStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
3155 SSMR3PutStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
3156 SSMR3PutStructEx(pSSM, &pThis->StInBdle, sizeof(pThis->StInBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
3157 return VINF_SUCCESS;
3158}
3159
3160
3161/**
3162 * @callback_method_impl{FNSSMDEVLOADEXEC}
3163 */
3164static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3165{
3166 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3167
3168 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3169
3170 /*
3171 * Load Codec nodes states.
3172 */
3173 int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
3174 if (RT_FAILURE(rc))
3175 return rc;
3176
3177 /*
3178 * Load MMIO registers.
3179 */
3180 uint32_t cRegs;
3181 switch (uVersion)
3182 {
3183 case HDA_SSM_VERSION_1:
3184 /* Starting with r71199, we would save 112 instead of 113
3185 registers due to some code cleanups. This only affected trunk
3186 builds in the 4.1 development period. */
3187 cRegs = 113;
3188 if (SSMR3HandleRevision(pSSM) >= 71199)
3189 {
3190 uint32_t uVer = SSMR3HandleVersion(pSSM);
3191 if ( VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
3192 && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
3193 && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
3194 cRegs = 112;
3195 }
3196 break;
3197
3198 case HDA_SSM_VERSION_2:
3199 case HDA_SSM_VERSION_3:
3200 cRegs = 112;
3201 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= HDA_NREGS_SAVED);
3202 break;
3203
3204 case HDA_SSM_VERSION:
3205 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
3206 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
3207 LogRel(("cRegs is %d, expected %d\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
3208 break;
3209
3210 default:
3211 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3212 }
3213
3214 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
3215 {
3216 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
3217 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
3218 }
3219 else
3220 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
3221
3222 /*
3223 * Load HDA DMA counters.
3224 */
3225 uint32_t fFlags = uVersion <= HDA_SSM_VERSION_2 ? SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED : 0;
3226 PCSSMFIELD paFields = uVersion <= HDA_SSM_VERSION_2 ? g_aHdaBDLEDescFieldsOld : g_aHdaBDLEDescFields;
3227 rc = SSMR3GetStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), fFlags, paFields, NULL);
3228 AssertRCReturn(rc, rc);
3229 rc = SSMR3GetStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), fFlags, paFields, NULL);
3230 AssertRCReturn(rc, rc);
3231 rc = SSMR3GetStructEx(pSSM, &pThis->StInBdle, sizeof(pThis->StInBdle), fFlags, paFields, NULL);
3232 AssertRCReturn(rc, rc);
3233
3234 /*
3235 * Update stuff after the state changes.
3236 */
3237 bool fEnableIn = RT_BOOL(SDCTL(pThis, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
3238#ifdef VBOX_WITH_HDA_MIC_IN
3239 bool fEnableMicIn = RT_BOOL(SDCTL(pThis, 2) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
3240#endif
3241 bool fEnableOut = RT_BOOL(SDCTL(pThis, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
3242
3243#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3244 PHDADRIVER pDrv;
3245 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3246 {
3247 rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn,
3248 fEnableIn);
3249 if (RT_FAILURE(rc))
3250 break;
3251# ifdef VBOX_WITH_HDA_MIC_IN
3252 rc = pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn,
3253 fEnableMicIn);
3254 if (RT_FAILURE(rc))
3255 break;
3256# endif
3257 rc = pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut,
3258 fEnableOut);
3259 if (RT_FAILURE(rc))
3260 break;
3261 }
3262#else
3263 AUD_set_active_in(pThis->pCodec->SwVoiceIn, SDCTL(pThis, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
3264 AUD_set_active_out(pThis->pCodec->SwVoiceOut, SDCTL(pThis, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
3265#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3266
3267 if (RT_SUCCESS(rc))
3268 {
3269 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
3270 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
3271 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE), HDA_REG(pThis, DPUBASE));
3272 }
3273
3274 LogFlowFuncLeaveRC(rc);
3275 return rc;
3276}
3277
3278
3279/* Debug and log type formatters. */
3280
3281/**
3282 * @callback_method_impl{FNRTSTRFORMATTYPE}
3283 */
3284static DECLCALLBACK(size_t)
3285hdaFormatStrmCtl(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
3286 const char *pszType, void const *pvValue,
3287 int cchWidth, int cchPrecision, unsigned fFlags,
3288 void *pvUser)
3289{
3290 uint32_t sdCtl = (uint32_t)(uintptr_t)pvValue;
3291 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
3292 "SDCTL(raw: %#x, strm:%#x, dir:%RTbool, tp:%RTbool strip:%x, deie:%RTbool, ioce:%RTbool, run:%RTbool, srst:%RTbool)",
3293 sdCtl,
3294 (sdCtl & HDA_REG_FIELD_MASK(SDCTL, NUM)) >> HDA_SDCTL_NUM_SHIFT,
3295 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DIR)),
3296 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, TP)),
3297 (sdCtl & HDA_REG_FIELD_MASK(SDCTL, STRIPE)) >> HDA_SDCTL_STRIPE_SHIFT,
3298 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DEIE)),
3299 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)),
3300 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
3301 RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
3302}
3303
3304/**
3305 * @callback_method_impl{FNRTSTRFORMATTYPE}
3306 */
3307static DECLCALLBACK(size_t)
3308hdaFormatStrmFifos(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
3309 const char *pszType, void const *pvValue,
3310 int cchWidth, int cchPrecision, unsigned fFlags,
3311 void *pvUser)
3312{
3313 uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
3314 uint32_t cb;
3315 switch (uSdFifos)
3316 {
3317 case HDA_SDONFIFO_16B: cb = 16; break;
3318 case HDA_SDONFIFO_32B: cb = 32; break;
3319 case HDA_SDONFIFO_64B: cb = 64; break;
3320 case HDA_SDONFIFO_128B: cb = 128; break;
3321 case HDA_SDONFIFO_192B: cb = 192; break;
3322 case HDA_SDONFIFO_256B: cb = 256; break;
3323 case HDA_SDINFIFO_120B: cb = 120; break;
3324 case HDA_SDINFIFO_160B: cb = 160; break;
3325 default: cb = 0; break;
3326 }
3327 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw: %#x, sdfifos:%u B)", uSdFifos, cb);
3328}
3329
3330/**
3331 * @callback_method_impl{FNRTSTRFORMATTYPE}
3332 */
3333static DECLCALLBACK(size_t)
3334hdaFormatStrmFifow(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
3335 const char *pszType, void const *pvValue,
3336 int cchWidth, int cchPrecision, unsigned fFlags,
3337 void *pvUser)
3338{
3339 uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
3340 uint32_t cb;
3341 switch (uSdFifos)
3342 {
3343 case HDA_SDFIFOW_8B: cb = 8; break;
3344 case HDA_SDFIFOW_16B: cb = 16; break;
3345 case HDA_SDFIFOW_32B: cb = 32; break;
3346 default: cb = 0; break;
3347 }
3348 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSdFifos, cb);
3349}
3350
3351/**
3352 * @callback_method_impl{FNRTSTRFORMATTYPE}
3353 */
3354static DECLCALLBACK(size_t)
3355hdaFormatStrmSts(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
3356 const char *pszType, void const *pvValue,
3357 int cchWidth, int cchPrecision, unsigned fFlags,
3358 void *pvUser)
3359{
3360 uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
3361 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
3362 "SDSTS(raw: %#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
3363 uSdSts,
3364 RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY)),
3365 RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)),
3366 RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)),
3367 RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)));
3368}
3369
3370
3371static int hdaLookUpRegisterByName(PHDASTATE pThis, const char *pszArgs)
3372{
3373 int iReg = 0;
3374 for (; iReg < HDA_NREGS; ++iReg)
3375 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
3376 return iReg;
3377 return -1;
3378}
3379
3380
3381static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
3382{
3383 Assert( pThis
3384 && iHdaIndex >= 0
3385 && iHdaIndex < HDA_NREGS);
3386 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
3387}
3388
3389
3390/**
3391 * @callback_method_impl{FNDBGFHANDLERDEV}
3392 */
3393static DECLCALLBACK(void) hdaInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
3394{
3395 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3396 int iHdaRegisterIndex = hdaLookUpRegisterByName(pThis, pszArgs);
3397 if (iHdaRegisterIndex != -1)
3398 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
3399 else
3400 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NREGS; ++iHdaRegisterIndex)
3401 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
3402}
3403
3404
3405static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaStrmIndex)
3406{
3407 Assert( pThis
3408 && iHdaStrmIndex >= 0
3409 && iHdaStrmIndex < 7);
3410 pHlp->pfnPrintf(pHlp, "Dump of %d HDA Stream:\n", iHdaStrmIndex);
3411 pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, CTL, iHdaStrmIndex));
3412 pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, STS, iHdaStrmIndex));
3413 pHlp->pfnPrintf(pHlp, "SD%dFIFOS: %R[sdfifos]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, FIFOS, iHdaStrmIndex));
3414 pHlp->pfnPrintf(pHlp, "SD%dFIFOW: %R[sdfifow]\n", iHdaStrmIndex, HDA_STREAM_REG(pThis, FIFOW, iHdaStrmIndex));
3415}
3416
3417
3418static int hdaLookUpStreamIndex(PHDASTATE pThis, const char *pszArgs)
3419{
3420 /* todo: add args parsing */
3421 return -1;
3422}
3423
3424
3425/**
3426 * @callback_method_impl{FNDBGFHANDLERDEV}
3427 */
3428static DECLCALLBACK(void) hdaInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
3429{
3430 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3431 int iHdaStrmIndex = hdaLookUpStreamIndex(pThis, pszArgs);
3432 if (iHdaStrmIndex != -1)
3433 hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
3434 else
3435 for(iHdaStrmIndex = 0; iHdaStrmIndex < 7; ++iHdaStrmIndex)
3436 hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
3437}
3438
3439
3440/**
3441 * @callback_method_impl{FNDBGFHANDLERDEV}
3442 */
3443static DECLCALLBACK(void) hdaInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
3444{
3445 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3446
3447 if (pThis->pCodec->pfnCodecDbgListNodes)
3448 pThis->pCodec->pfnCodecDbgListNodes(pThis->pCodec, pHlp, pszArgs);
3449 else
3450 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
3451}
3452
3453
3454/**
3455 * @callback_method_impl{FNDBGFHANDLERDEV}
3456 */
3457static DECLCALLBACK(void) hdaInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
3458{
3459 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3460
3461 if (pThis->pCodec->pfnCodecDbgSelector)
3462 pThis->pCodec->pfnCodecDbgSelector(pThis->pCodec, pHlp, pszArgs);
3463 else
3464 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
3465}
3466
3467
3468/* PDMIBASE */
3469
3470/**
3471 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
3472 */
3473static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
3474{
3475 PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
3476 Assert(&pThis->IBase == pInterface);
3477
3478 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
3479 return NULL;
3480}
3481
3482
3483/* PDMDEVREG */
3484
3485/**
3486 * Reset notification.
3487 *
3488 * @returns VBox status.
3489 * @param pDevIns The device instance data.
3490 *
3491 * @remark The original sources didn't install a reset handler, but it seems to
3492 * make sense to me so we'll do it.
3493 */
3494static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
3495{
3496 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3497 HDA_REG(pThis, GCAP) = HDA_MAKE_GCAP(4,4,0,0,1); /* see 6.2.1 */
3498 HDA_REG(pThis, VMIN) = 0x00; /* see 6.2.2 */
3499 HDA_REG(pThis, VMAJ) = 0x01; /* see 6.2.3 */
3500 HDA_REG(pThis, OUTPAY) = 0x003C; /* see 6.2.4 */
3501 HDA_REG(pThis, INPAY) = 0x001D; /* see 6.2.5 */
3502 HDA_REG(pThis, CORBSIZE) = 0x42; /* see 6.2.1 */
3503 HDA_REG(pThis, RIRBSIZE) = 0x42; /* see 6.2.1 */
3504 HDA_REG(pThis, CORBRP) = 0x0;
3505 HDA_REG(pThis, RIRBWP) = 0x0;
3506
3507 LogFunc(("Resetting ...\n"));
3508
3509#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3510 /* Stop any audio currently playing. */
3511 PHDADRIVER pDrv;
3512 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3513 {
3514 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->LineIn.pStrmIn, false /* Disable */);
3515 /* Ignore rc. */
3516 pDrv->pConnector->pfnEnableIn(pDrv->pConnector, pDrv->MicIn.pStrmIn, false /* Disable */);
3517 /* Ditto. */
3518 pDrv->pConnector->pfnEnableOut(pDrv->pConnector, pDrv->Out.pStrmOut, false /* Disable */);
3519 /* Ditto. */
3520 }
3521#else
3522 AUD_set_active_in(pThis->pCodec->SwVoiceIn, false);
3523 AUD_set_active_out(pThis->pCodec->SwVoiceOut, false);
3524#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3525
3526 pThis->cbCorbBuf = 256 * sizeof(uint32_t);
3527
3528 if (pThis->pu32CorbBuf)
3529 RT_BZERO(pThis->pu32CorbBuf, pThis->cbCorbBuf);
3530 else
3531 pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
3532
3533 pThis->cbRirbBuf = 256 * sizeof(uint64_t);
3534 if (pThis->pu64RirbBuf)
3535 RT_BZERO(pThis->pu64RirbBuf, pThis->cbRirbBuf);
3536 else
3537 pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
3538
3539 pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
3540
3541 HDABDLEDESC StEmptyBdle;
3542 for (uint8_t u8Strm = 0; u8Strm < 8; ++u8Strm)
3543 {
3544 HDASTREAMTRANSFERDESC StreamDesc;
3545 PHDABDLEDESC pBdle = NULL;
3546 if (u8Strm == 0)
3547 pBdle = &pThis->StInBdle;
3548# ifdef VBOX_WITH_HDA_MIC_IN
3549 else if (u8Strm == 2)
3550 pBdle = &pThis->StMicBdle;
3551# endif
3552 else if(u8Strm == 4)
3553 pBdle = &pThis->StOutBdle;
3554 else
3555 {
3556 RT_ZERO(StEmptyBdle);
3557 pBdle = &StEmptyBdle;
3558 }
3559 hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
3560 /* hdaStreamReset prevents changing the SRST bit, so we force it to zero here. */
3561 HDA_STREAM_REG(pThis, CTL, u8Strm) = 0;
3562 hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
3563 }
3564
3565 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
3566 HDA_REG(pThis, STATESTS) = 0x1;
3567
3568 LogRel(("HDA: Reset\n"));
3569}
3570
3571/**
3572 * @interface_method_impl{PDMDEVREG,pfnDestruct}
3573 */
3574static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
3575{
3576 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3577
3578#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3579 PHDADRIVER pDrv;
3580 while (!RTListIsEmpty(&pThis->lstDrv))
3581 {
3582 pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node);
3583
3584 RTListNodeRemove(&pDrv->Node);
3585 RTMemFree(pDrv);
3586 }
3587
3588 if (pThis->pMixer)
3589 {
3590 audioMixerDestroy(pThis->pMixer);
3591 pThis->pMixer = NULL;
3592 }
3593#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3594
3595 if (pThis->pCodec)
3596 {
3597 int rc = hdaCodecDestruct(pThis->pCodec);
3598 AssertRC(rc);
3599
3600 RTMemFree(pThis->pCodec);
3601 pThis->pCodec = NULL;
3602 }
3603
3604 RTMemFree(pThis->pu32CorbBuf);
3605 pThis->pu32CorbBuf = NULL;
3606
3607 RTMemFree(pThis->pu64RirbBuf);
3608 pThis->pu64RirbBuf = NULL;
3609
3610 return VINF_SUCCESS;
3611}
3612
3613#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3614/**
3615 * Attach command.
3616 *
3617 * This is called to let the device attach to a driver for a specified LUN
3618 * during runtime. This is not called during VM construction, the device
3619 * constructor have to attach to all the available drivers.
3620 *
3621 * @returns VBox status code.
3622 * @param pDevIns The device instance.
3623 * @param uLUN The logical unit which is being detached.
3624 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
3625 */
3626static DECLCALLBACK(int) hdaAttach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
3627{
3628 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3629
3630 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
3631 ("HDA device does not support hotplugging\n"),
3632 VERR_INVALID_PARAMETER);
3633
3634 /*
3635 * Attach driver.
3636 */
3637 char *pszDesc = NULL;
3638 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
3639 AssertMsgReturn(pszDesc,
3640 ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
3641 VERR_NO_MEMORY);
3642
3643 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
3644 &pThis->IBase, &pThis->pDrvBase, pszDesc);
3645 if (RT_SUCCESS(rc))
3646 {
3647 PHDADRIVER pDrv = (PHDADRIVER)RTMemAllocZ(sizeof(HDADRIVER));
3648 if (pDrv)
3649 {
3650 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR);
3651 AssertMsg(pDrv->pConnector != NULL,
3652 ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n",
3653 uLUN, rc));
3654 pDrv->pHDAState = pThis;
3655 pDrv->uLUN = uLUN;
3656
3657 /*
3658 * For now we always set the driver at LUN 0 as our primary
3659 * host backend. This might change in the future.
3660 */
3661 if (pDrv->uLUN == 0)
3662 pDrv->Flags |= PDMAUDIODRVFLAG_PRIMARY;
3663
3664 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->Flags));
3665
3666 /* Attach to driver list. */
3667 RTListAppend(&pThis->lstDrv, &pDrv->Node);
3668 }
3669 else
3670 rc = VERR_NO_MEMORY;
3671 }
3672 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
3673 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
3674 {
3675 LogFunc(("No attached driver for LUN #%u\n", uLUN));
3676 }
3677 else if (RT_FAILURE(rc))
3678 AssertMsgFailed(("Failed to attach HDA LUN #%u (\"%s\"), rc=%Rrc\n",
3679 uLUN, pszDesc, rc));
3680
3681 RTStrFree(pszDesc);
3682
3683 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
3684 return rc;
3685}
3686
3687static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
3688{
3689 NOREF(pDevIns); NOREF(iLUN); NOREF(fFlags);
3690
3691 LogFlowFuncEnter();
3692}
3693#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3694
3695/**
3696 * @interface_method_impl{PDMDEVREG,pfnConstruct}
3697 */
3698static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
3699{
3700 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
3701 Assert(iInstance == 0);
3702 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
3703
3704 /*
3705 * Validations.
3706 */
3707 if (!CFGMR3AreValuesValid(pCfgHandle, "R0Enabled\0"
3708 "RCEnabled\0"))
3709 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
3710 N_ ("Invalid configuration for the Intel HDA device"));
3711
3712 int rc = CFGMR3QueryBoolDef(pCfgHandle, "RCEnabled", &pThis->fRCEnabled, false);
3713 if (RT_FAILURE(rc))
3714 return PDMDEV_SET_ERROR(pDevIns, rc,
3715 N_("HDA configuration error: failed to read RCEnabled as boolean"));
3716 rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &pThis->fR0Enabled, false);
3717 if (RT_FAILURE(rc))
3718 return PDMDEV_SET_ERROR(pDevIns, rc,
3719 N_("HDA configuration error: failed to read R0Enabled as boolean"));
3720
3721 /*
3722 * Initialize data (most of it anyway).
3723 */
3724 pThis->pDevInsR3 = pDevIns;
3725 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
3726 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
3727 /* IBase */
3728 pThis->IBase.pfnQueryInterface = hdaQueryInterface;
3729
3730 /* PCI Device */
3731 PCIDevSetVendorId (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
3732 PCIDevSetDeviceId (&pThis->PciDev, HDA_PCI_DEVICE_ID); /* HDA */
3733
3734 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
3735 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
3736 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */
3737 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */
3738 PCIDevSetClassSub (&pThis->PciDev, 0x03); /* 0a ro - scc; 03 == HDA. */
3739 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
3740 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */
3741 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - MMIO */
3742 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
3743 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */
3744 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */
3745
3746#if defined(HDA_AS_PCI_EXPRESS)
3747 PCIDevSetCapabilityList (&pThis->PciDev, 0x80);
3748#elif defined(VBOX_WITH_MSI_DEVICES)
3749 PCIDevSetCapabilityList (&pThis->PciDev, 0x60);
3750#else
3751 PCIDevSetCapabilityList (&pThis->PciDev, 0x50); /* ICH6 datasheet 18.1.16 */
3752#endif
3753
3754 /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
3755 /// of these values needs to be properly documented!
3756 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
3757 PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
3758
3759 /* Power Management */
3760 PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
3761 PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
3762 PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
3763
3764#ifdef HDA_AS_PCI_EXPRESS
3765 /* PCI Express */
3766 PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
3767 PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
3768 /* Device flags */
3769 PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
3770 /* version */ 0x1 |
3771 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
3772 /* MSI */ (100) << 9 );
3773 /* Device capabilities */
3774 PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
3775 /* Device control */
3776 PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
3777 /* Device status */
3778 PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
3779 /* Link caps */
3780 PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
3781 /* Link control */
3782 PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
3783 /* Link status */
3784 PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
3785 /* Slot capabilities */
3786 PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
3787 /* Slot control */
3788 PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
3789 /* Slot status */
3790 PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
3791 /* Root control */
3792 PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
3793 /* Root capabilities */
3794 PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
3795 /* Root status */
3796 PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
3797 /* Device capabilities 2 */
3798 PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
3799 /* Device control 2 */
3800 PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
3801 /* Link control 2 */
3802 PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
3803 /* Slot control 2 */
3804 PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
3805#endif
3806
3807 /*
3808 * Register the PCI device.
3809 */
3810 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
3811 if (RT_FAILURE(rc))
3812 return rc;
3813
3814 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
3815 if (RT_FAILURE(rc))
3816 return rc;
3817
3818#ifdef VBOX_WITH_MSI_DEVICES
3819 PDMMSIREG MsiReg;
3820 RT_ZERO(MsiReg);
3821 MsiReg.cMsiVectors = 1;
3822 MsiReg.iMsiCapOffset = 0x60;
3823 MsiReg.iMsiNextOffset = 0x50;
3824 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
3825 if (RT_FAILURE(rc))
3826 {
3827 /* That's OK, we can work without MSI */
3828 PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
3829 }
3830#endif
3831
3832 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
3833 if (RT_FAILURE(rc))
3834 return rc;
3835
3836#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3837 RTListInit(&pThis->lstDrv);
3838
3839 unsigned uLUN = 0;
3840 do
3841 {
3842 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
3843 rc = hdaAttach(pDevIns, uLUN++, PDM_TACH_FLAGS_NOT_HOT_PLUG);
3844 if (RT_FAILURE(rc))
3845 {
3846 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
3847 rc = VINF_SUCCESS;
3848
3849 break;
3850 }
3851
3852 } while (RT_SUCCESS(rc));
3853
3854 if (RT_SUCCESS(rc))
3855 {
3856 rc = audioMixerCreate("HDA Mixer", 0 /* uFlags */,
3857 &pThis->pMixer);
3858 if (RT_SUCCESS(rc))
3859 {
3860 PDMAUDIOSTREAMCFG streamCfg;
3861 streamCfg.uHz = 48000;
3862 streamCfg.cChannels = 2;
3863 streamCfg.enmFormat = AUD_FMT_S16;
3864 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANESS;
3865
3866 rc = audioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
3867 AssertRC(rc);
3868
3869 /* Add all required audio sinks. */
3870 rc = audioMixerAddSink(pThis->pMixer, "[Recording] Line In",
3871 &pThis->pSinkLineIn);
3872 AssertRC(rc);
3873
3874 rc = audioMixerAddSink(pThis->pMixer, "[Recording] Microphone In",
3875 &pThis->pSinkMicIn);
3876 AssertRC(rc);
3877 }
3878 }
3879
3880 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
3881#else
3882 /*
3883 * Attach driver.
3884 */
3885 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port");
3886 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
3887 Log(("hda: No attached driver!\n"));
3888 else if (RT_FAILURE(rc))
3889 {
3890 AssertMsgFailed(("Failed to attach Intel HDA LUN #0! rc=%Rrc\n", rc));
3891 return rc;
3892 }
3893#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3894
3895 if (RT_SUCCESS(rc))
3896 {
3897 /* Construct codec. */
3898 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
3899 if (!pThis->pCodec)
3900 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state"));
3901
3902#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
3903 /* Audio driver callbacks for multiplexing. */
3904 pThis->pCodec->pfnCloseIn = hdaCloseIn;
3905 pThis->pCodec->pfnCloseOut = hdaCloseOut;
3906 pThis->pCodec->pfnOpenIn = hdaOpenIn;
3907 pThis->pCodec->pfnOpenOut = hdaOpenOut;
3908 pThis->pCodec->pfnSetVolume = hdaSetVolume;
3909#endif /* VBOX_WITH_PDM_AUDIO_DRIVER */
3910
3911 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */
3912
3913 /* Construct the codec. */
3914 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfgHandle);
3915 if (RT_FAILURE(rc))
3916 AssertRCReturn(rc, rc);
3917
3918 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
3919 verb F20 should provide device/codec recognition. */
3920 Assert(pThis->pCodec->u16VendorId);
3921 Assert(pThis->pCodec->u16DeviceId);
3922 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
3923 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
3924
3925#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
3926 pThis->pCodec->pfnTransfer = hdaTransfer;
3927#endif
3928 pThis->pCodec->pfnReset = hdaCodecReset;
3929 }
3930
3931 if (RT_SUCCESS(rc))
3932 {
3933 hdaReset(pDevIns);
3934
3935 /*
3936 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
3937 * hdaReset shouldn't affects these registers.
3938 */
3939 HDA_REG(pThis, WAKEEN) = 0x0;
3940 HDA_REG(pThis, STATESTS) = 0x0;
3941
3942 /*
3943 * Debug and string formatter types.
3944 */
3945 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaInfo);
3946 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm", "HDA stream info. (hdastrm [stream number])", hdaInfoStream);
3947 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaInfoCodecNodes);
3948 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaInfoCodecSelector);
3949
3950 rc = RTStrFormatTypeRegister("sdctl", hdaFormatStrmCtl, NULL);
3951 AssertRC(rc);
3952 rc = RTStrFormatTypeRegister("sdsts", hdaFormatStrmSts, NULL);
3953 AssertRC(rc);
3954 rc = RTStrFormatTypeRegister("sdfifos", hdaFormatStrmFifos, NULL);
3955 AssertRC(rc);
3956 rc = RTStrFormatTypeRegister("sdfifow", hdaFormatStrmFifow, NULL);
3957 AssertRC(rc);
3958 #if 0
3959 rc = RTStrFormatTypeRegister("sdfmt", printHdaStrmFmt, NULL);
3960 AssertRC(rc);
3961 #endif
3962
3963 /*
3964 * Some debug assertions.
3965 */
3966 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
3967 {
3968 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
3969 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
3970
3971 /* binary search order. */
3972 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
3973 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
3974 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
3975
3976 /* alignment. */
3977 AssertReleaseMsg( pReg->size == 1
3978 || (pReg->size == 2 && (pReg->offset & 1) == 0)
3979 || (pReg->size == 3 && (pReg->offset & 3) == 0)
3980 || (pReg->size == 4 && (pReg->offset & 3) == 0),
3981 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
3982
3983 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
3984 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
3985 if (pReg->offset & 3)
3986 {
3987 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL;
3988 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
3989 if (pPrevReg)
3990 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
3991 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
3992 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
3993 }
3994 #if 0
3995 if ((pReg->offset + pReg->size) & 3)
3996 {
3997 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
3998 if (pNextReg)
3999 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
4000 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
4001 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
4002 }
4003 #endif
4004
4005 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */
4006 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
4007 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
4008 }
4009 }
4010
4011#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
4012 if (RT_SUCCESS(rc))
4013 {
4014 /* Start the emulation timer. */
4015 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis,
4016 TMTIMER_FLAGS_NO_CRIT_SECT, "DevIchHda", &pThis->pTimer);
4017 AssertRCReturn(rc, rc);
4018
4019 if (RT_SUCCESS(rc))
4020 {
4021 /** @todo Investigate why sounds is getting corrupted if the "ticks" value is too
4022 * low, e.g. "PDMDevHlpTMTimeVirtGetFreq / 200". */
4023 pThis->uTicks = PDMDevHlpTMTimeVirtGetFreq(pDevIns) / 500; /** @todo Make this configurable! */
4024 if (pThis->uTicks < 100)
4025 pThis->uTicks = 100;
4026 LogFunc(("Timer ticks=%RU64\n", pThis->uTicks));
4027
4028 /* Fire off timer. */
4029 TMTimerSet(pThis->pTimer, TMTimerGet(pThis->pTimer) + pThis->uTicks);
4030 }
4031 }
4032
4033# ifdef VBOX_WITH_STATISTICS
4034 if (RT_SUCCESS(rc))
4035 {
4036 /*
4037 * Register statistics.
4038 */
4039 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer.");
4040 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation.");
4041 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation.");
4042 }
4043# endif
4044
4045#endif
4046
4047 LogFlowFuncLeaveRC(rc);
4048 return rc;
4049}
4050
4051/**
4052 * The device registration structure.
4053 */
4054const PDMDEVREG g_DeviceICH6_HDA =
4055{
4056 /* u32Version */
4057 PDM_DEVREG_VERSION,
4058 /* szName */
4059 "hda",
4060 /* szRCMod */
4061 "VBoxDDGC.gc",
4062 /* szR0Mod */
4063 "VBoxDDR0.r0",
4064 /* pszDescription */
4065 "Intel HD Audio Controller",
4066 /* fFlags */
4067 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
4068 /* fClass */
4069 PDM_DEVREG_CLASS_AUDIO,
4070 /* cMaxInstances */
4071 1,
4072 /* cbInstance */
4073 sizeof(HDASTATE),
4074 /* pfnConstruct */
4075 hdaConstruct,
4076 /* pfnDestruct */
4077 hdaDestruct,
4078 /* pfnRelocate */
4079 NULL,
4080 /* pfnMemSetup */
4081 NULL,
4082 /* pfnPowerOn */
4083 NULL,
4084 /* pfnReset */
4085 hdaReset,
4086 /* pfnSuspend */
4087 NULL,
4088 /* pfnResume */
4089 NULL,
4090 /* pfnAttach */
4091 NULL,
4092 /* pfnDetach */
4093 NULL,
4094 /* pfnQueryInterface. */
4095 NULL,
4096 /* pfnInitComplete */
4097 NULL,
4098 /* pfnPowerOff */
4099 NULL,
4100 /* pfnSoftReset */
4101 NULL,
4102 /* u32VersionEnd */
4103 PDM_DEVREG_VERSION
4104};
4105
4106#endif /* IN_RING3 */
4107#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

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