VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp@ 39135

Last change on this file since 39135 was 39135, checked in by vboxsync, 13 years ago

Changed PDMDevHlpMMIORegister to take flags and drop pfnFill. Added PDMDevHlpMMIORegisterEx for the one user of pfnFill.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 115.4 KB
Line 
1/* $Id: DevIchIntelHDA.cpp 39135 2011-10-28 09:47:55Z vboxsync $ */
2/** @file
3 * DevIchIntelHD - VBox ICH Intel HD Audio Controller.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DEV_AUDIO
22#include <VBox/vmm/pdmdev.h>
23#include <iprt/assert.h>
24#include <iprt/uuid.h>
25#include <iprt/string.h>
26#include <iprt/mem.h>
27#include <iprt/asm.h>
28#include <iprt/asm-math.h>
29
30#include "VBoxDD.h"
31
32extern "C" {
33#include "audio.h"
34}
35#include "DevCodec.h"
36
37#define VBOX_WITH_INTEL_HDA
38
39#if defined(VBOX_WITH_HP_HDA)
40/* HP Pavilion dv4t-1300 */
41# define HDA_PCI_VENDOR_ID 0x103c
42# define HDA_PCI_DEICE_ID 0x30f7
43#elif defined(VBOX_WITH_INTEL_HDA)
44/* Intel HDA controller */
45# define HDA_PCI_VENDOR_ID 0x8086
46# define HDA_PCI_DEICE_ID 0x2668
47#elif defined(VBOX_WITH_NVIDIA_HDA)
48/* nVidia HDA controller */
49# define HDA_PCI_VENDOR_ID 0x10de
50# define HDA_PCI_DEICE_ID 0x0ac0
51#else
52# error "Please specify your HDA device vendor/device IDs"
53#endif
54
55PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
56PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb);
57static DECLCALLBACK(void) hdaReset (PPDMDEVINS pDevIns);
58
59#define HDA_NREGS 112
60/* Registers */
61#define HDA_REG_IND_NAME(x) ICH6_HDA_REG_##x
62#define HDA_REG_FIELD_NAME(reg, x) ICH6_HDA_##reg##_##x
63#define HDA_REG_FIELD_MASK(reg, x) ICH6_HDA_##reg##_##x##_MASK
64#define HDA_REG_FIELD_FLAG_MASK(reg, x) RT_BIT(ICH6_HDA_##reg##_##x##_SHIFT)
65#define HDA_REG_FIELD_SHIFT(reg, x) ICH6_HDA_##reg##_##x##_SHIFT
66#define HDA_REG_IND(pState, x) ((pState)->au32Regs[(x)])
67#define HDA_REG(pState, x) (HDA_REG_IND((pState), HDA_REG_IND_NAME(x)))
68#define HDA_REG_VALUE(pState, reg, val) (HDA_REG((pState),reg) & (((HDA_REG_FIELD_MASK(reg, val))) << (HDA_REG_FIELD_SHIFT(reg, val))))
69#define HDA_REG_FLAG_VALUE(pState, reg, val) (HDA_REG((pState),reg) & (((HDA_REG_FIELD_FLAG_MASK(reg, val)))))
70#define HDA_REG_SVALUE(pState, reg, val) (HDA_REG_VALUE(pState, reg, val) >> (HDA_REG_FIELD_SHIFT(reg, val)))
71
72#define ICH6_HDA_REG_GCAP 0 /* range 0x00-0x01*/
73#define GCAP(pState) (HDA_REG((pState), GCAP))
74/* GCAP HDASpec 3.3.2 This macro compact following information about HDA
75 * oss (15:12) - number of output streams supported
76 * iss (11:8) - number of input streams supported
77 * bss (7:3) - number of bidirection streams suppoted
78 * bds (2:1) - number of serial data out signals supported
79 * b64sup (0) - 64 bit addressing supported.
80 */
81#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
82 ( (((oss) & 0xF) << 12) \
83 | (((iss) & 0xF) << 8) \
84 | (((bss) & 0x1F) << 3) \
85 | (((bds) & 0x3) << 2) \
86 | ((b64sup) & 1))
87#define ICH6_HDA_REG_VMIN 1 /* range 0x02 */
88#define VMIN(pState) (HDA_REG((pState), VMIN))
89
90#define ICH6_HDA_REG_VMAJ 2 /* range 0x03 */
91#define VMAJ(pState) (HDA_REG((pState), VMAJ))
92
93#define ICH6_HDA_REG_OUTPAY 3 /* range 0x04-0x05 */
94#define OUTPAY(pState) (HDA_REG((pState), OUTPAY))
95
96#define ICH6_HDA_REG_INPAY 4 /* range 0x06-0x07 */
97#define INPAY(pState) (HDA_REG((pState), INPAY))
98
99#define ICH6_HDA_REG_GCTL (5)
100#define ICH6_HDA_GCTL_RST_SHIFT (0)
101#define ICH6_HDA_GCTL_FSH_SHIFT (1)
102#define ICH6_HDA_GCTL_UR_SHIFT (8)
103#define GCTL(pState) (HDA_REG((pState), GCTL))
104
105#define ICH6_HDA_REG_WAKEEN 6 /* 0x0C */
106#define WAKEEN(pState) (HDA_REG((pState), WAKEEN))
107
108#define ICH6_HDA_REG_STATESTS 7 /* range 0x0E */
109#define STATESTS(pState) (HDA_REG((pState), STATESTS))
110#define ICH6_HDA_STATES_SCSF 0x7
111
112#define ICH6_HDA_REG_GSTS 8 /* range 0x10-0x11*/
113#define ICH6_HDA_GSTS_FSH_SHIFT (1)
114#define GSTS(pState) (HDA_REG(pState, GSTS))
115
116#define ICH6_HDA_REG_INTCTL 9 /* 0x20 */
117#define ICH6_HDA_INTCTL_GIE_SHIFT 31
118#define ICH6_HDA_INTCTL_CIE_SHIFT 30
119#define ICH6_HDA_INTCTL_S0_SHIFT (0)
120#define ICH6_HDA_INTCTL_S1_SHIFT (1)
121#define ICH6_HDA_INTCTL_S2_SHIFT (2)
122#define ICH6_HDA_INTCTL_S3_SHIFT (3)
123#define ICH6_HDA_INTCTL_S4_SHIFT (4)
124#define ICH6_HDA_INTCTL_S5_SHIFT (5)
125#define ICH6_HDA_INTCTL_S6_SHIFT (6)
126#define ICH6_HDA_INTCTL_S7_SHIFT (7)
127#define INTCTL(pState) (HDA_REG((pState), INTCTL))
128#define INTCTL_GIE(pState) (HDA_REG_FLAG_VALUE(pState, INTCTL, GIE))
129#define INTCTL_CIE(pState) (HDA_REG_FLAG_VALUE(pState, INTCTL, CIE))
130#define INTCTL_SX(pState, X) (HDA_REG_FLAG_VALUE((pState), INTCTL, S##X))
131#define INTCTL_SALL(pState) (INTCTL((pState)) & 0xFF)
132
133/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
134 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
135 * the datasheet.
136 */
137#define ICH6_HDA_REG_SSYNC 12 /* 0x34 */
138#define SSYNC(pState) (HDA_REG((pState), SSYNC))
139
140#define ICH6_HDA_REG_INTSTS 10 /* 0x24 */
141#define ICH6_HDA_INTSTS_GIS_SHIFT (31)
142#define ICH6_HDA_INTSTS_CIS_SHIFT (30)
143#define ICH6_HDA_INTSTS_S0_SHIFT (0)
144#define ICH6_HDA_INTSTS_S1_SHIFT (1)
145#define ICH6_HDA_INTSTS_S2_SHIFT (2)
146#define ICH6_HDA_INTSTS_S3_SHIFT (3)
147#define ICH6_HDA_INTSTS_S4_SHIFT (4)
148#define ICH6_HDA_INTSTS_S5_SHIFT (5)
149#define ICH6_HDA_INTSTS_S6_SHIFT (6)
150#define ICH6_HDA_INTSTS_S7_SHIFT (7)
151#define ICH6_HDA_INTSTS_S_MASK(num) RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
152#define INTSTS(pState) (HDA_REG((pState), INTSTS))
153#define INTSTS_GIS(pState) (HDA_REG_FLAG_VALUE((pState), INTSTS, GIS)
154#define INTSTS_CIS(pState) (HDA_REG_FLAG_VALUE((pState), INTSTS, CIS)
155#define INTSTS_SX(pState, X) (HDA_REG_FLAG_VALUE(pState), INTSTS, S##X)
156#define INTSTS_SANY(pState) (INTSTS((pState)) & 0xFF)
157
158#define ICH6_HDA_REG_CORBLBASE 13 /* 0x40 */
159#define CORBLBASE(pState) (HDA_REG((pState), CORBLBASE))
160#define ICH6_HDA_REG_CORBUBASE 14 /* 0x44 */
161#define CORBUBASE(pState) (HDA_REG((pState), CORBUBASE))
162#define ICH6_HDA_REG_CORBWP 15 /* 48 */
163#define ICH6_HDA_REG_CORBRP 16 /* 4A */
164#define ICH6_HDA_CORBRP_RST_SHIFT 15
165#define ICH6_HDA_CORBRP_WP_SHIFT 0
166#define ICH6_HDA_CORBRP_WP_MASK 0xFF
167
168#define CORBRP(pState) (HDA_REG(pState, CORBRP))
169#define CORBWP(pState) (HDA_REG(pState, CORBWP))
170
171#define ICH6_HDA_REG_CORBCTL 17 /* 0x4C */
172#define ICH6_HDA_CORBCTL_DMA_SHIFT (1)
173#define ICH6_HDA_CORBCTL_CMEIE_SHIFT (0)
174
175#define CORBCTL(pState) (HDA_REG(pState, CORBCTL))
176
177
178#define ICH6_HDA_REG_CORBSTS 18 /* 0x4D */
179#define CORBSTS(pState) (HDA_REG(pState, CORBSTS))
180#define ICH6_HDA_CORBSTS_CMEI_SHIFT (0)
181
182#define ICH6_HDA_REG_CORBSIZE 19 /* 0x4E */
183#define ICH6_HDA_CORBSIZE_SZ_CAP 0xF0
184#define ICH6_HDA_CORBSIZE_SZ 0x3
185#define CORBSIZE_SZ(pState) (HDA_REG(pState, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ)
186#define CORBSIZE_SZ_CAP(pState) (HDA_REG(pState, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ_CAP)
187/* till ich 10 sizes of CORB and RIRB are hardcoded to 256 in real hw */
188
189#define ICH6_HDA_REG_RIRLBASE 20 /* 0x50 */
190#define RIRLBASE(pState) (HDA_REG((pState), RIRLBASE))
191
192#define ICH6_HDA_REG_RIRUBASE 21 /* 0x54 */
193#define RIRUBASE(pState) (HDA_REG((pState), RIRUBASE))
194
195#define ICH6_HDA_REG_RIRBWP 22 /* 0x58 */
196#define ICH6_HDA_RIRBWP_RST_SHIFT (15)
197#define ICH6_HDA_RIRBWP_WP_MASK 0xFF
198#define RIRBWP(pState) (HDA_REG(pState, RIRBWP))
199
200#define ICH6_HDA_REG_RINTCNT 23 /* 0x5A */
201#define RINTCNT(pState) (HDA_REG((pState), RINTCNT))
202#define RINTCNT_N(pState) (RINTCNT((pState)) & 0xff)
203
204#define ICH6_HDA_REG_RIRBCTL 24 /* 0x5C */
205#define ICH6_HDA_RIRBCTL_RIC_SHIFT (0)
206#define ICH6_HDA_RIRBCTL_DMA_SHIFT (1)
207#define ICH6_HDA_ROI_DMA_SHIFT (2)
208#define RIRBCTL(pState) (HDA_REG((pState), RIRBCTL))
209#define RIRBCTL_RIRB_RIC(pState) (HDA_REG_FLAG_VALUE(pState, RIRBCTL, RIC))
210#define RIRBCTL_RIRB_DMA(pState) (HDA_REG_FLAG_VALUE((pState), RIRBCTL, DMA)
211#define RIRBCTL_ROI(pState) (HDA_REG_FLAG_VALUE((pState), RIRBCTL, ROI))
212
213#define ICH6_HDA_REG_RIRBSTS 25 /* 0x5D */
214#define ICH6_HDA_RIRBSTS_RINTFL_SHIFT (0)
215#define ICH6_HDA_RIRBSTS_RIRBOIS_SHIFT (2)
216#define RIRBSTS(pState) (HDA_REG(pState, RIRBSTS))
217#define RIRBSTS_RINTFL(pState) (HDA_REG_FLAG_VALUE(pState, RIRBSTS, RINTFL))
218#define RIRBSTS_RIRBOIS(pState) (HDA_REG_FLAG_VALUE(pState, RIRBSTS, RIRBOIS))
219
220#define ICH6_HDA_REG_RIRBSIZE 26 /* 0x5E */
221#define ICH6_HDA_RIRBSIZE_SZ_CAP 0xF0
222#define ICH6_HDA_RIRBSIZE_SZ 0x3
223
224#define RIRBSIZE_SZ(pState) (HDA_REG(pState, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ)
225#define RIRBSIZE_SZ_CAP(pState) (HDA_REG(pState, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ_CAP)
226
227
228#define ICH6_HDA_REG_IC 27 /* 0x60 */
229#define IC(pState) (HDA_REG(pState, IC))
230#define ICH6_HDA_REG_IR 28 /* 0x64 */
231#define IR(pState) (HDA_REG(pState, IR))
232#define ICH6_HDA_REG_IRS 29 /* 0x68 */
233#define ICH6_HDA_IRS_ICB_SHIFT (0)
234#define ICH6_HDA_IRS_IRV_SHIFT (1)
235#define IRS(pState) (HDA_REG(pState, IRS))
236#define IRS_ICB(pState) (HDA_REG_FLAG_VALUE(pState, IRS, ICB))
237#define IRS_IRV(pState) (HDA_REG_FLAG_VALUE(pState, IRS, IRV))
238
239#define ICH6_HDA_REG_DPLBASE 30 /* 0x70 */
240#define DPLBASE(pState) (HDA_REG((pState), DPLBASE))
241#define ICH6_HDA_REG_DPUBASE 31 /* 0x74 */
242#define DPUBASE(pState) (HDA_REG((pState), DPUBASE))
243#define DPBASE_ENABLED 1
244#define DPBASE_ADDR_MASK (~0x7f)
245
246#define HDA_STREAM_REG_DEF(name, num) (ICH6_HDA_REG_SD##num##name)
247#define HDA_STREAM_REG(pState, name, num) (HDA_REG((pState), N_(HDA_STREAM_REG_DEF(name, num))))
248/* Note: sdnum here _MUST_ be stream reg number [0,7] */
249#define HDA_STREAM_REG2(pState, name, sdnum) (HDA_REG_IND((pState), ICH6_HDA_REG_SD0##name + (sdnum) * 10))
250
251#define ICH6_HDA_REG_SD0CTL 32 /* 0x80 */
252#define ICH6_HDA_REG_SD1CTL (HDA_STREAM_REG_DEF(CTL, 0) + 10) /* 0xA0 */
253#define ICH6_HDA_REG_SD2CTL (HDA_STREAM_REG_DEF(CTL, 0) + 20) /* 0xC0 */
254#define ICH6_HDA_REG_SD3CTL (HDA_STREAM_REG_DEF(CTL, 0) + 30) /* 0xE0 */
255#define ICH6_HDA_REG_SD4CTL (HDA_STREAM_REG_DEF(CTL, 0) + 40) /* 0x100 */
256#define ICH6_HDA_REG_SD5CTL (HDA_STREAM_REG_DEF(CTL, 0) + 50) /* 0x120 */
257#define ICH6_HDA_REG_SD6CTL (HDA_STREAM_REG_DEF(CTL, 0) + 60) /* 0x140 */
258#define ICH6_HDA_REG_SD7CTL (HDA_STREAM_REG_DEF(CTL, 0) + 70) /* 0x160 */
259
260#define SD(func, num) SD##num##func
261#define SDCTL(pState, num) HDA_REG((pState), SD(CTL, num))
262#define SDCTL_NUM(pState, num) ((SDCTL((pState), num) & HDA_REG_FIELD_MASK(SDCTL,NUM)) >> HDA_REG_FIELD_SHIFT(SDCTL, NUM))
263#define ICH6_HDA_SDCTL_NUM_MASK (0xF)
264#define ICH6_HDA_SDCTL_NUM_SHIFT (20)
265#define ICH6_HDA_SDCTL_DIR_SHIFT (19)
266#define ICH6_HDA_SDCTL_TP_SHIFT (18)
267#define ICH6_HDA_SDCTL_STRIPE_MASK (0x3)
268#define ICH6_HDA_SDCTL_STRIPE_SHIFT (16)
269#define ICH6_HDA_SDCTL_DEIE_SHIFT (4)
270#define ICH6_HDA_SDCTL_FEIE_SHIFT (3)
271#define ICH6_HDA_SDCTL_ICE_SHIFT (2)
272#define ICH6_HDA_SDCTL_RUN_SHIFT (1)
273#define ICH6_HDA_SDCTL_SRST_SHIFT (0)
274
275#define ICH6_HDA_REG_SD0STS 33 /* 0x83 */
276#define ICH6_HDA_REG_SD1STS (HDA_STREAM_REG_DEF(STS, 0) + 10) /* 0xA3 */
277#define ICH6_HDA_REG_SD2STS (HDA_STREAM_REG_DEF(STS, 0) + 20) /* 0xC3 */
278#define ICH6_HDA_REG_SD3STS (HDA_STREAM_REG_DEF(STS, 0) + 30) /* 0xE3 */
279#define ICH6_HDA_REG_SD4STS (HDA_STREAM_REG_DEF(STS, 0) + 40) /* 0x103 */
280#define ICH6_HDA_REG_SD5STS (HDA_STREAM_REG_DEF(STS, 0) + 50) /* 0x123 */
281#define ICH6_HDA_REG_SD6STS (HDA_STREAM_REG_DEF(STS, 0) + 60) /* 0x143 */
282#define ICH6_HDA_REG_SD7STS (HDA_STREAM_REG_DEF(STS, 0) + 70) /* 0x163 */
283
284#define SDSTS(pState, num) HDA_REG((pState), SD(STS, num))
285#define ICH6_HDA_SDSTS_FIFORDY_SHIFT (5)
286#define ICH6_HDA_SDSTS_DE_SHIFT (4)
287#define ICH6_HDA_SDSTS_FE_SHIFT (3)
288#define ICH6_HDA_SDSTS_BCIS_SHIFT (2)
289
290#define ICH6_HDA_REG_SD0LPIB 34 /* 0x84 */
291#define ICH6_HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
292#define ICH6_HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
293#define ICH6_HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
294#define ICH6_HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
295#define ICH6_HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
296#define ICH6_HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
297#define ICH6_HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
298
299#define SDLPIB(pState, num) HDA_REG((pState), SD(LPIB, num))
300
301#define ICH6_HDA_REG_SD0CBL 35 /* 0x88 */
302#define ICH6_HDA_REG_SD1CBL (HDA_STREAM_REG_DEF(CBL, 0) + 10) /* 0xA8 */
303#define ICH6_HDA_REG_SD2CBL (HDA_STREAM_REG_DEF(CBL, 0) + 20) /* 0xC8 */
304#define ICH6_HDA_REG_SD3CBL (HDA_STREAM_REG_DEF(CBL, 0) + 30) /* 0xE8 */
305#define ICH6_HDA_REG_SD4CBL (HDA_STREAM_REG_DEF(CBL, 0) + 40) /* 0x108 */
306#define ICH6_HDA_REG_SD5CBL (HDA_STREAM_REG_DEF(CBL, 0) + 50) /* 0x128 */
307#define ICH6_HDA_REG_SD6CBL (HDA_STREAM_REG_DEF(CBL, 0) + 60) /* 0x148 */
308#define ICH6_HDA_REG_SD7CBL (HDA_STREAM_REG_DEF(CBL, 0) + 70) /* 0x168 */
309
310#define SDLCBL(pState, num) HDA_REG((pState), SD(CBL, num))
311
312#define ICH6_HDA_REG_SD0LVI 36 /* 0x8C */
313#define ICH6_HDA_REG_SD1LVI (HDA_STREAM_REG_DEF(LVI, 0) + 10) /* 0xAC */
314#define ICH6_HDA_REG_SD2LVI (HDA_STREAM_REG_DEF(LVI, 0) + 20) /* 0xCC */
315#define ICH6_HDA_REG_SD3LVI (HDA_STREAM_REG_DEF(LVI, 0) + 30) /* 0xEC */
316#define ICH6_HDA_REG_SD4LVI (HDA_STREAM_REG_DEF(LVI, 0) + 40) /* 0x10C */
317#define ICH6_HDA_REG_SD5LVI (HDA_STREAM_REG_DEF(LVI, 0) + 50) /* 0x12C */
318#define ICH6_HDA_REG_SD6LVI (HDA_STREAM_REG_DEF(LVI, 0) + 60) /* 0x14C */
319#define ICH6_HDA_REG_SD7LVI (HDA_STREAM_REG_DEF(LVI, 0) + 70) /* 0x16C */
320
321#define SDLVI(pState, num) HDA_REG((pState), SD(LVI, num))
322
323#define ICH6_HDA_REG_SD0FIFOW 37 /* 0x8E */
324#define ICH6_HDA_REG_SD1FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 10) /* 0xAE */
325#define ICH6_HDA_REG_SD2FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 20) /* 0xCE */
326#define ICH6_HDA_REG_SD3FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 30) /* 0xEE */
327#define ICH6_HDA_REG_SD4FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 40) /* 0x10E */
328#define ICH6_HDA_REG_SD5FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 50) /* 0x12E */
329#define ICH6_HDA_REG_SD6FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 60) /* 0x14E */
330#define ICH6_HDA_REG_SD7FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 70) /* 0x16E */
331
332/*
333 * ICH6 datasheet defined limits for FIFOW values (18.2.38)
334 */
335#define HDA_SDFIFOW_8B (0x2)
336#define HDA_SDFIFOW_16B (0x3)
337#define HDA_SDFIFOW_32B (0x4)
338#define SDFIFOW(pState, num) HDA_REG((pState), SD(FIFOW, num))
339
340#define ICH6_HDA_REG_SD0FIFOS 38 /* 0x90 */
341#define ICH6_HDA_REG_SD1FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 10) /* 0xB0 */
342#define ICH6_HDA_REG_SD2FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 20) /* 0xD0 */
343#define ICH6_HDA_REG_SD3FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 30) /* 0xF0 */
344#define ICH6_HDA_REG_SD4FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 40) /* 0x110 */
345#define ICH6_HDA_REG_SD5FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 50) /* 0x130 */
346#define ICH6_HDA_REG_SD6FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 60) /* 0x150 */
347#define ICH6_HDA_REG_SD7FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 70) /* 0x170 */
348
349/*
350 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
351 * formula: size - 1
352 * Other values not listed are not supported.
353 */
354#define HDA_SDONFIFO_16B (0xF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
355#define HDA_SDONFIFO_32B (0x1F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
356#define HDA_SDONFIFO_64B (0x3F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
357#define HDA_SDONFIFO_128B (0x7F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
358#define HDA_SDONFIFO_192B (0xBF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
359#define HDA_SDONFIFO_256B (0xFF) /* 20-, 24-bit Output Streams */
360#define HDA_SDINFIFO_120B (0x77) /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
361#define HDA_SDINFIFO_160B (0x9F) /* 20-, 24-bit Input Streams Streams */
362#define SDFIFOS(pState, num) HDA_REG((pState), SD(FIFOS, num))
363
364#define ICH6_HDA_REG_SD0FMT 39 /* 0x92 */
365#define ICH6_HDA_REG_SD1FMT (HDA_STREAM_REG_DEF(FMT, 0) + 10) /* 0xB2 */
366#define ICH6_HDA_REG_SD2FMT (HDA_STREAM_REG_DEF(FMT, 0) + 20) /* 0xD2 */
367#define ICH6_HDA_REG_SD3FMT (HDA_STREAM_REG_DEF(FMT, 0) + 30) /* 0xF2 */
368#define ICH6_HDA_REG_SD4FMT (HDA_STREAM_REG_DEF(FMT, 0) + 40) /* 0x112 */
369#define ICH6_HDA_REG_SD5FMT (HDA_STREAM_REG_DEF(FMT, 0) + 50) /* 0x132 */
370#define ICH6_HDA_REG_SD6FMT (HDA_STREAM_REG_DEF(FMT, 0) + 60) /* 0x152 */
371#define ICH6_HDA_REG_SD7FMT (HDA_STREAM_REG_DEF(FMT, 0) + 70) /* 0x172 */
372
373#define SDFMT(pState, num) (HDA_REG((pState), SD(FMT, num)))
374#define ICH6_HDA_SDFMT_BASE_RATE_SHIFT (14)
375#define ICH6_HDA_SDFMT_MULT_SHIFT (11)
376#define ICH6_HDA_SDFMT_MULT_MASK (0x7)
377#define ICH6_HDA_SDFMT_DIV_SHIFT (8)
378#define ICH6_HDA_SDFMT_DIV_MASK (0x7)
379#define ICH6_HDA_SDFMT_BITS_SHIFT (4)
380#define ICH6_HDA_SDFMT_BITS_MASK (0x7)
381#define SDFMT_BASE_RATE(pState, num) ((SDFMT(pState, num) & HDA_REG_FIELD_FLAG_MASK(SDFMT, BASE_RATE)) >> HDA_REG_FIELD_SHIFT(SDFMT, BASE_RATE))
382#define SDFMT_MULT(pState, num) ((SDFMT((pState), num) & HDA_REG_FIELD_MASK(SDFMT,MULT)) >> HDA_REG_FIELD_SHIFT(SDFMT, MULT))
383#define SDFMT_DIV(pState, num) ((SDFMT((pState), num) & HDA_REG_FIELD_MASK(SDFMT,DIV)) >> HDA_REG_FIELD_SHIFT(SDFMT, DIV))
384
385#define ICH6_HDA_REG_SD0BDPL 40 /* 0x98 */
386#define ICH6_HDA_REG_SD1BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 10) /* 0xB8 */
387#define ICH6_HDA_REG_SD2BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 20) /* 0xD8 */
388#define ICH6_HDA_REG_SD3BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 30) /* 0xF8 */
389#define ICH6_HDA_REG_SD4BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 40) /* 0x118 */
390#define ICH6_HDA_REG_SD5BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 50) /* 0x138 */
391#define ICH6_HDA_REG_SD6BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 60) /* 0x158 */
392#define ICH6_HDA_REG_SD7BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 70) /* 0x178 */
393
394#define SDBDPL(pState, num) HDA_REG((pState), SD(BDPL, num))
395
396#define ICH6_HDA_REG_SD0BDPU 41 /* 0x9C */
397#define ICH6_HDA_REG_SD1BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 10) /* 0xBC */
398#define ICH6_HDA_REG_SD2BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 20) /* 0xDC */
399#define ICH6_HDA_REG_SD3BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 30) /* 0xFC */
400#define ICH6_HDA_REG_SD4BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 40) /* 0x11C */
401#define ICH6_HDA_REG_SD5BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 50) /* 0x13C */
402#define ICH6_HDA_REG_SD6BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 60) /* 0x15C */
403#define ICH6_HDA_REG_SD7BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 70) /* 0x17C */
404
405#define SDBDPU(pState, num) HDA_REG((pState), SD(BDPU, num))
406
407/* Predicates */
408
409typedef struct HDABDLEDESC
410{
411 uint64_t u64BdleCviAddr;
412 uint32_t u32BdleMaxCvi;
413 uint32_t u32BdleCvi;
414 uint32_t u32BdleCviLen;
415 uint32_t u32BdleCviPos;
416 bool fBdleCviIoc;
417 uint32_t cbUnderFifoW;
418 uint8_t au8HdaBuffer[HDA_SDONFIFO_256B + 1];
419} HDABDLEDESC, *PHDABDLEDESC;
420
421static SSMFIELD const g_aHdaBDLEDescFields[] =
422{
423 SSMFIELD_ENTRY( HDABDLEDESC, u64BdleCviAddr),
424 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleMaxCvi),
425 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCvi),
426 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviLen),
427 SSMFIELD_ENTRY( HDABDLEDESC, u32BdleCviPos),
428 SSMFIELD_ENTRY( HDABDLEDESC, fBdleCviIoc),
429 SSMFIELD_ENTRY( HDABDLEDESC, cbUnderFifoW),
430 SSMFIELD_ENTRY( HDABDLEDESC, au8HdaBuffer),
431 SSMFIELD_ENTRY_TERM()
432};
433
434typedef struct HDASTREAMTRANSFERDESC
435{
436 uint64_t u64BaseDMA;
437 uint32_t u32Ctl;
438 uint32_t *pu32Sts;
439 uint8_t u8Strm;
440 uint32_t *pu32Lpib;
441 uint32_t u32Cbl;
442 uint32_t u32Fifos;
443} HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC;
444
445typedef struct INTELHDLinkState
446{
447 /** Pointer to the device instance. */
448 PPDMDEVINSR3 pDevIns;
449 /** Pointer to the connector of the attached audio driver. */
450 PPDMIAUDIOCONNECTOR pDrv;
451 /** Pointer to the attached audio driver. */
452 PPDMIBASE pDrvBase;
453 /** The base interface for LUN\#0. */
454 PDMIBASE IBase;
455 RTGCPHYS addrMMReg;
456 uint32_t au32Regs[HDA_NREGS];
457 HDABDLEDESC stInBdle;
458 HDABDLEDESC stOutBdle;
459 HDABDLEDESC stMicBdle;
460 /* Interrupt on completion */
461 bool fCviIoc;
462 uint64_t u64CORBBase;
463 uint64_t u64RIRBBase;
464 uint64_t u64DPBase;
465 /* pointer on CORB buf */
466 uint32_t *pu32CorbBuf;
467 /* size in bytes of CORB buf */
468 uint32_t cbCorbBuf;
469 /* pointer on RIRB buf */
470 uint64_t *pu64RirbBuf;
471 /* size in bytes of RIRB buf */
472 uint32_t cbRirbBuf;
473 /* indicates if HDA in reset. */
474 bool fInReset;
475 CODECState Codec;
476 uint8_t u8Counter;
477 uint64_t u64BaseTS;
478} INTELHDLinkState, *PINTELHDLinkState;
479
480#define ICH6_HDASTATE_2_DEVINS(pINTELHD) ((pINTELHD)->pDevIns)
481#define PCIDEV_2_ICH6_HDASTATE(pPciDev) ((PCIINTELHDLinkState *)(pPciDev))
482
483#define ISD0FMT_TO_AUDIO_SELECTOR(pState) (AUDIO_FORMAT_SELECTOR(&(pState)->Codec, In, \
484 SDFMT_BASE_RATE(pState, 0), SDFMT_MULT(pState, 0), SDFMT_DIV(pState, 0)))
485#define OSD0FMT_TO_AUDIO_SELECTOR(pState) (AUDIO_FORMAT_SELECTOR(&(pState)->Codec, Out, \
486 SDFMT_BASE_RATE(pState, 4), SDFMT_MULT(pState, 4), SDFMT_DIV(pState, 4)))
487
488
489
490
491typedef struct PCIINTELHDLinkState
492{
493 PCIDevice dev;
494 INTELHDLinkState hda;
495} PCIINTELHDLinkState;
496
497
498DECLCALLBACK(int)hdaRegReadUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
499DECLCALLBACK(int)hdaRegWriteUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
500DECLCALLBACK(int)hdaRegReadGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
501DECLCALLBACK(int)hdaRegWriteGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
502DECLCALLBACK(int)hdaRegReadSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
503DECLCALLBACK(int)hdaRegWriteSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
504DECLCALLBACK(int)hdaRegReadGCAP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
505DECLCALLBACK(int)hdaRegReadINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
506DECLCALLBACK(int)hdaRegReadWALCLK(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
507DECLCALLBACK(int)hdaRegWriteINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
508DECLCALLBACK(int)hdaRegWriteCORBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
509DECLCALLBACK(int)hdaRegWriteCORBRP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
510DECLCALLBACK(int)hdaRegWriteCORBCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
511DECLCALLBACK(int)hdaRegWriteCORBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
512DECLCALLBACK(int)hdaRegWriteRIRBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
513DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
514DECLCALLBACK(int)hdaRegWriteIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
515DECLCALLBACK(int)hdaRegReadIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
516DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
517DECLCALLBACK(int)hdaRegReadSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
518
519DECLCALLBACK(int)hdaRegWriteSDSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
520DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
521DECLCALLBACK(int)hdaRegWriteSDFIFOW(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
522DECLCALLBACK(int)hdaRegWriteSDFIFOS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
523DECLCALLBACK(int)hdaRegWriteSDFMT(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
524DECLCALLBACK(int)hdaRegWriteSDBDPL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
525DECLCALLBACK(int)hdaRegWriteSDBDPU(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
526DECLCALLBACK(int)hdaRegWriteBase(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
527DECLCALLBACK(int)hdaRegReadU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
528DECLCALLBACK(int)hdaRegWriteU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
529DECLCALLBACK(int)hdaRegReadU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
530DECLCALLBACK(int)hdaRegWriteU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
531DECLCALLBACK(int)hdaRegReadU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
532DECLCALLBACK(int)hdaRegWriteU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
533DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
534DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
535
536static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc);
537static int hdaMMIORegLookup(INTELHDLinkState* pState, uint32_t u32Offset);
538static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc);
539#ifdef LOG_ENABLED
540static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
541#endif
542
543
544/* see 302349 p 6.2*/
545const static struct stIchIntelHDRegMap
546{
547 /** Register offset in the register space. */
548 uint32_t offset;
549 /** Size in bytes. Registers of size > 4 are in fact tables. */
550 uint32_t size;
551 /** Readable bits. */
552 uint32_t readable;
553 /** Writable bits. */
554 uint32_t writable;
555 /** Read callback. */
556 int (*pfnRead)(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
557 /** Write callback. */
558 int (*pfnWrite)(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
559 /** Abbreviated name. */
560 const char *abbrev;
561 /** Full name. */
562 const char *name;
563} s_ichIntelHDRegMap[HDA_NREGS] =
564{
565 /* offset size read mask write mask read callback write callback abbrev full name */
566 /*------- ------- ---------- ---------- ----------------------- ------------------------ ---------- ------------------------------*/
567 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, hdaRegReadGCAP , hdaRegWriteUnimplemented, "GCAP" , "Global Capabilities" },
568 { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "VMIN" , "Minor Version" },
569 { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "VMAJ" , "Major Version" },
570 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimplemented, "OUTPAY" , "Output Payload Capabilities" },
571 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimplemented, "INPAY" , "Input Payload Capabilities" },
572 { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadGCTL , hdaRegWriteGCTL , "GCTL" , "Global Control" },
573 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, hdaRegReadU16 , hdaRegWriteU16 , "WAKEEN" , "Wake Enable" },
574 { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteSTATESTS , "STATESTS" , "State Change Status" },
575 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimplemented, hdaRegWriteUnimplemented, "GSTS" , "Global Status" },
576 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWriteU32 , "INTCTL" , "Interrupt Control" },
577 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS , hdaRegWriteUnimplemented, "INTSTS" , "Interrupt Status" },
578 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK , hdaRegWriteUnimplemented, "WALCLK" , "Wall Clock Counter" },
579 /// @todo r=michaln: Doesn't the SSYNC register need to actually stop the stream(s)?
580 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32 , hdaRegWriteU32 , "SSYNC" , "Stream Synchronization" },
581 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , "CORBLBASE" , "CORB Lower Base Address" },
582 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "CORBUBASE" , "CORB Upper Base Address" },
583 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteCORBWP , "CORBWP" , "CORB Write Pointer" },
584 { 0x0004A, 0x00002, 0x000000FF, 0x000080FF, hdaRegReadU8 , hdaRegWriteCORBRP , "CORBRP" , "CORB Read Pointer" },
585 { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8 , hdaRegWriteCORBCTL , "CORBCTL" , "CORB Control" },
586 { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8 , hdaRegWriteCORBSTS , "CORBSTS" , "CORB Status" },
587 { 0x0004E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "CORBSIZE" , "CORB Size" },
588 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , "RIRBLBASE" , "RIRB Lower Base Address" },
589 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "RIRBUBASE" , "RIRB Upper Base Address" },
590 { 0x00058, 0x00002, 0x000000FF, 0x00008000, hdaRegReadU8, hdaRegWriteRIRBWP , "RIRBWP" , "RIRB Write Pointer" },
591 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteU16 , "RINTCNT" , "Response Interrupt Count" },
592 { 0x0005C, 0x00001, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteU8 , "RIRBCTL" , "RIRB Control" },
593 { 0x0005D, 0x00001, 0x00000005, 0x00000005, hdaRegReadU8 , hdaRegWriteRIRBSTS , "RIRBSTS" , "RIRB Status" },
594 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "RIRBSIZE" , "RIRB Size" },
595 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "IC" , "Immediate Command" },
596 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteUnimplemented, "IR" , "Immediate Response" },
597 { 0x00068, 0x00004, 0x00000002, 0x00000002, hdaRegReadIRS , hdaRegWriteIRS , "IRS" , "Immediate Command Status" },
598 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32 , hdaRegWriteBase , "DPLBASE" , "DMA Position Lower Base" },
599 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "DPUBASE" , "DMA Position Upper Base" },
600
601 { 0x00080, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD0CTL" , "Input Stream Descriptor 0 (ICD0) Control" },
602 { 0x00083, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD0STS" , "ISD0 Status" },
603 { 0x00084, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD0LPIB" , "ISD0 Link Position In Buffer" },
604 { 0x00088, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD0CBL" , "ISD0 Cyclic Buffer Length" },
605 { 0x0008C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD0LVI" , "ISD0 Last Valid Index" },
606 { 0x0008E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD0FIFOW", "ISD0 FIFO Watermark" },
607 { 0x00090, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD0FIFOS", "ISD0 FIFO Size" },
608 { 0x00092, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "ISD0FMT" , "ISD0 Format" },
609 { 0x00098, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD0BDPL" , "ISD0 Buffer Descriptor List Pointer-Lower Base Address" },
610 { 0x0009C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD0BDPU" , "ISD0 Buffer Descriptor List Pointer-Upper Base Address" },
611
612 { 0x000A0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD1CTL" , "Input Stream Descriptor 1 (ISD1) Control" },
613 { 0x000A3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD1STS" , "ISD1 Status" },
614 { 0x000A4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD1LPIB" , "ISD1 Link Position In Buffer" },
615 { 0x000A8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD1CBL" , "ISD1 Cyclic Buffer Length" },
616 { 0x000AC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD1LVI" , "ISD1 Last Valid Index" },
617 { 0x000AE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD1FIFOW", "ISD1 FIFO Watermark" },
618 { 0x000B0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD1FIFOS", "ISD1 FIFO Size" },
619 { 0x000B2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "ISD1FMT" , "ISD1 Format" },
620 { 0x000B8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD1BDPL" , "ISD1 Buffer Descriptor List Pointer-Lower Base Address" },
621 { 0x000BC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD1BDPU" , "ISD1 Buffer Descriptor List Pointer-Upper Base Address" },
622
623 { 0x000C0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD2CTL" , "Input Stream Descriptor 2 (ISD2) Control" },
624 { 0x000C3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD2STS" , "ISD2 Status" },
625 { 0x000C4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD2LPIB" , "ISD2 Link Position In Buffer" },
626 { 0x000C8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD2CBL" , "ISD2 Cyclic Buffer Length" },
627 { 0x000CC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD2LVI" , "ISD2 Last Valid Index" },
628 { 0x000CE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD2FIFOW", "ISD2 FIFO Watermark" },
629 { 0x000D0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD2FIFOS", "ISD2 FIFO Size" },
630 { 0x000D2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "ISD2FMT" , "ISD2 Format" },
631 { 0x000D8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD2BDPL" , "ISD2 Buffer Descriptor List Pointer-Lower Base Address" },
632 { 0x000DC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD2BDPU" , "ISD2 Buffer Descriptor List Pointer-Upper Base Address" },
633
634 { 0x000E0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD3CTL" , "Input Stream Descriptor 3 (ISD3) Control" },
635 { 0x000E3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD3STS" , "ISD3 Status" },
636 { 0x000E4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD3LPIB" , "ISD3 Link Position In Buffer" },
637 { 0x000E8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD3CBL" , "ISD3 Cyclic Buffer Length" },
638 { 0x000EC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD3LVI" , "ISD3 Last Valid Index" },
639 { 0x000EE, 0x00002, 0x00000005, 0x00000005, hdaRegReadU16 , hdaRegWriteU16 , "ISD3FIFOW", "ISD3 FIFO Watermark" },
640 { 0x000F0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD3FIFOS", "ISD3 FIFO Size" },
641 { 0x000F2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "ISD3FMT" , "ISD3 Format" },
642 { 0x000F8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD3BDPL" , "ISD3 Buffer Descriptor List Pointer-Lower Base Address" },
643 { 0x000FC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD3BDPU" , "ISD3 Buffer Descriptor List Pointer-Upper Base Address" },
644
645 { 0x00100, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadSDCTL , hdaRegWriteSDCTL , "OSD0CTL" , "Input Stream Descriptor 0 (OSD0) Control" },
646 { 0x00103, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD0STS" , "OSD0 Status" },
647 { 0x00104, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD0LPIB" , "OSD0 Link Position In Buffer" },
648 { 0x00108, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD0CBL" , "OSD0 Cyclic Buffer Length" },
649 { 0x0010C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD0LVI" , "OSD0 Last Valid Index" },
650 { 0x0010E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD0FIFOW", "OSD0 FIFO Watermark" },
651 { 0x00110, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD0FIFOS", "OSD0 FIFO Size" },
652 { 0x00112, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "OSD0FMT" , "OSD0 Format" },
653 { 0x00118, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD0BDPL" , "OSD0 Buffer Descriptor List Pointer-Lower Base Address" },
654 { 0x0011C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD0BDPU" , "OSD0 Buffer Descriptor List Pointer-Upper Base Address" },
655
656 { 0x00120, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD1CTL" , "Input Stream Descriptor 0 (OSD1) Control" },
657 { 0x00123, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD1STS" , "OSD1 Status" },
658 { 0x00124, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD1LPIB" , "OSD1 Link Position In Buffer" },
659 { 0x00128, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD1CBL" , "OSD1 Cyclic Buffer Length" },
660 { 0x0012C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD1LVI" , "OSD1 Last Valid Index" },
661 { 0x0012E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD1FIFOW", "OSD1 FIFO Watermark" },
662 { 0x00130, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD1FIFOS", "OSD1 FIFO Size" },
663 { 0x00132, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "OSD1FMT" , "OSD1 Format" },
664 { 0x00138, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD1BDPL" , "OSD1 Buffer Descriptor List Pointer-Lower Base Address" },
665 { 0x0013C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD1BDPU" , "OSD1 Buffer Descriptor List Pointer-Upper Base Address" },
666
667 { 0x00140, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD2CTL" , "Input Stream Descriptor 0 (OSD2) Control" },
668 { 0x00143, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD2STS" , "OSD2 Status" },
669 { 0x00144, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD2LPIB" , "OSD2 Link Position In Buffer" },
670 { 0x00148, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD2CBL" , "OSD2 Cyclic Buffer Length" },
671 { 0x0014C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD2LVI" , "OSD2 Last Valid Index" },
672 { 0x0014E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD2FIFOW", "OSD2 FIFO Watermark" },
673 { 0x00150, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD2FIFOS", "OSD2 FIFO Size" },
674 { 0x00152, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "OSD2FMT" , "OSD2 Format" },
675 { 0x00158, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD2BDPL" , "OSD2 Buffer Descriptor List Pointer-Lower Base Address" },
676 { 0x0015C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD2BDPU" , "OSD2 Buffer Descriptor List Pointer-Upper Base Address" },
677
678 { 0x00160, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD3CTL" , "Input Stream Descriptor 0 (OSD3) Control" },
679 { 0x00163, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD3STS" , "OSD3 Status" },
680 { 0x00164, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD3LPIB" , "OSD3 Link Position In Buffer" },
681 { 0x00168, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD3CBL" , "OSD3 Cyclic Buffer Length" },
682 { 0x0016C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD3LVI" , "OSD3 Last Valid Index" },
683 { 0x0016E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD3FIFOW", "OSD3 FIFO Watermark" },
684 { 0x00170, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD3FIFOS", "OSD3 FIFO Size" },
685 { 0x00172, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteSDFMT , "OSD3FMT" , "OSD3 Format" },
686 { 0x00178, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD3BDPL" , "OSD3 Buffer Descriptor List Pointer-Lower Base Address" },
687 { 0x0017C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD3BDPU" , "OSD3 Buffer Descriptor List Pointer-Upper Base Address" },
688};
689
690static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc)
691{
692 if (pState->u64DPBase & DPBASE_ENABLED)
693 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState),
694 (pState->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm*8, pStreamDesc->pu32Lpib, sizeof(uint32_t));
695}
696static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc)
697{
698#if 0
699 switch(HDA_STREAM_REG2(pState, FIFOW, pStreamDesc->u8Strm))
700 {
701 case HDA_SDFIFOW_8B: return 8;
702 case HDA_SDFIFOW_16B: return 16;
703 case HDA_SDFIFOW_32B: return 32;
704 default:
705 AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, pStreamDesc->u8Strm), pStreamDesc->u8Strm));
706 }
707#endif
708 return 0;
709}
710
711static int hdaProcessInterrupt(INTELHDLinkState* pState)
712{
713#define IS_INTERRUPT_OCCURED_AND_ENABLED(pState, num) \
714 ( INTCTL_SX((pState), num) \
715 && (SDSTS(pState, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
716 bool fIrq = false;
717 if ( INTCTL_CIE(pState)
718 && ( RIRBSTS_RINTFL(pState)
719 || RIRBSTS_RIRBOIS(pState)
720 || (STATESTS(pState) & WAKEEN(pState))))
721 fIrq = true;
722
723 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 0)
724 || IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 4))
725 fIrq = true;
726
727 if (INTCTL_GIE(pState))
728 {
729 Log(("hda: irq %s\n", fIrq ? "asserted" : "deasserted"));
730 PDMDevHlpPCISetIrq(ICH6_HDASTATE_2_DEVINS(pState), 0 , fIrq);
731 }
732 return VINF_SUCCESS;
733}
734
735static int hdaMMIORegLookup(INTELHDLinkState* pState, uint32_t u32Offset)
736{
737 int idxMiddle;
738 int idxHigh = RT_ELEMENTS(s_ichIntelHDRegMap);
739 int idxLow = 0;
740 /* Aliases HDA spec 3.3.45 */
741 switch(u32Offset)
742 {
743 case 0x2084:
744 return HDA_REG_IND_NAME(SD0LPIB);
745 case 0x20A4:
746 return HDA_REG_IND_NAME(SD1LPIB);
747 case 0x20C4:
748 return HDA_REG_IND_NAME(SD2LPIB);
749 case 0x20E4:
750 return HDA_REG_IND_NAME(SD3LPIB);
751 case 0x2104:
752 return HDA_REG_IND_NAME(SD4LPIB);
753 case 0x2124:
754 return HDA_REG_IND_NAME(SD5LPIB);
755 case 0x2144:
756 return HDA_REG_IND_NAME(SD6LPIB);
757 case 0x2164:
758 return HDA_REG_IND_NAME(SD7LPIB);
759 }
760 while (1)
761 {
762#ifdef DEBUG_vvl
763 Assert(( idxHigh >= 0
764 && idxLow >= 0));
765#endif
766 if ( idxHigh < idxLow
767 || idxHigh < 0)
768 break;
769 idxMiddle = idxLow + (idxHigh - idxLow)/2;
770 if (u32Offset < s_ichIntelHDRegMap[idxMiddle].offset)
771 {
772 idxHigh = idxMiddle - 1;
773 continue;
774 }
775 if (u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size)
776 {
777 idxLow = idxMiddle + 1;
778 continue;
779 }
780 if ( u32Offset >= s_ichIntelHDRegMap[idxMiddle].offset
781 && u32Offset < s_ichIntelHDRegMap[idxMiddle].offset + s_ichIntelHDRegMap[idxMiddle].size)
782 return idxMiddle;
783 }
784 return -1;
785}
786
787static int hdaCmdSync(INTELHDLinkState *pState, bool fLocal)
788{
789 int rc = VINF_SUCCESS;
790 if (fLocal)
791 {
792 Assert((HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)));
793 rc = PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pState->u64CORBBase, pState->pu32CorbBuf, pState->cbCorbBuf);
794 if (RT_FAILURE(rc))
795 AssertRCReturn(rc, rc);
796#ifdef DEBUG_CMD_BUFFER
797 uint8_t i = 0;
798 do
799 {
800 Log(("hda: corb%02x: ", i));
801 uint8_t j = 0;
802 do
803 {
804 const char *prefix;
805 if ((i + j) == CORBRP(pState))
806 prefix = "[R]";
807 else if ((i + j) == CORBWP(pState))
808 prefix = "[W]";
809 else
810 prefix = " "; /* three spaces */
811 Log(("%s%08x", prefix, pState->pu32CorbBuf[i + j]));
812 j++;
813 } while (j < 8);
814 Log(("\n"));
815 i += 8;
816 } while(i != 0);
817#endif
818 }
819 else
820 {
821 Assert((HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA)));
822 rc = PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pState->u64RIRBBase, pState->pu64RirbBuf, pState->cbRirbBuf);
823 if (RT_FAILURE(rc))
824 AssertRCReturn(rc, rc);
825#ifdef DEBUG_CMD_BUFFER
826 uint8_t i = 0;
827 do {
828 Log(("hda: rirb%02x: ", i));
829 uint8_t j = 0;
830 do {
831 const char *prefix;
832 if ((i + j) == RIRBWP(pState))
833 prefix = "[W]";
834 else
835 prefix = " ";
836 Log((" %s%016lx", prefix, pState->pu64RirbBuf[i + j]));
837 } while (++j < 8);
838 Log(("\n"));
839 i += 8;
840 } while (i != 0);
841#endif
842 }
843 return rc;
844}
845
846static int hdaCORBCmdProcess(INTELHDLinkState *pState)
847{
848 int rc;
849 uint8_t corbRp;
850 uint8_t corbWp;
851 uint8_t rirbWp;
852
853 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
854
855 rc = hdaCmdSync(pState, true);
856 if (RT_FAILURE(rc))
857 AssertRCReturn(rc, rc);
858 corbRp = CORBRP(pState);
859 corbWp = CORBWP(pState);
860 rirbWp = RIRBWP(pState);
861 Assert((corbWp != corbRp));
862 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
863 while (corbRp != corbWp)
864 {
865 uint32_t cmd;
866 uint64_t resp;
867 corbRp++;
868 cmd = pState->pu32CorbBuf[corbRp];
869 rc = (pState)->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
870 if (RT_FAILURE(rc))
871 AssertRCReturn(rc, rc);
872 Assert(pfn);
873 (rirbWp)++;
874 rc = pfn(&pState->Codec, cmd, &resp);
875 if (RT_FAILURE(rc))
876 AssertRCReturn(rc, rc);
877 Log(("hda: verb:%08x->%016lx\n", cmd, resp));
878 if ( (resp & CODEC_RESPONSE_UNSOLICITED)
879 && !HDA_REG_FLAG_VALUE(pState, GCTL, UR))
880 {
881 Log(("hda: unexpected unsolicited response.\n"));
882 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
883 return rc;
884 }
885 pState->pu64RirbBuf[rirbWp] = resp;
886 pState->u8Counter++;
887 if (pState->u8Counter == RINTCNT_N(pState))
888 break;
889 }
890 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
891 pState->au32Regs[ICH6_HDA_REG_RIRBWP] = rirbWp;
892 rc = hdaCmdSync(pState, false);
893 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
894 if (RIRBCTL_RIRB_RIC(pState))
895 {
896 RIRBSTS((pState)) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
897 pState->u8Counter = 0;
898 rc = hdaProcessInterrupt(pState);
899 }
900 if (RT_FAILURE(rc))
901 AssertRCReturn(rc, rc);
902 return rc;
903}
904
905static void hdaStreamReset(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm)
906{
907 Log(("hda: reset of stream (%d) started\n", u8Strm));
908 Assert(( pState
909 && pBdle
910 && pStreamDesc
911 && u8Strm <= 7));
912 memset(pBdle, 0, sizeof(HDABDLEDESC));
913 *pStreamDesc->pu32Lpib = 0;
914 *pStreamDesc->pu32Sts = 0;
915 /* According to ICH6 datasheet, 0x40000 is default value for stream descriptor register 23:20
916 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */
917 HDA_STREAM_REG2(pState, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG2(pState, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
918
919 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
920 HDA_STREAM_REG2(pState, FIFOS, u8Strm) = u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
921 HDA_STREAM_REG2(pState, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B;
922 HDA_STREAM_REG2(pState, CBL, u8Strm) = 0;
923 HDA_STREAM_REG2(pState, LVI, u8Strm) = 0;
924 HDA_STREAM_REG2(pState, FMT, u8Strm) = 0;
925 HDA_STREAM_REG2(pState, BDPU, u8Strm) = 0;
926 HDA_STREAM_REG2(pState, BDPL, u8Strm) = 0;
927 Log(("hda: reset of stream (%d) finished\n", u8Strm));
928}
929
930
931DECLCALLBACK(int)hdaRegReadUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
932{
933 *pu32Value = 0;
934 return VINF_SUCCESS;
935}
936DECLCALLBACK(int)hdaRegWriteUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
937{
938 return VINF_SUCCESS;
939}
940/* U8 */
941DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
942{
943 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffffff00) == 0);
944 return hdaRegReadU32(pState, offset, index, pu32Value);
945}
946
947DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
948{
949 Assert(((u32Value & 0xffffff00) == 0));
950 return hdaRegWriteU32(pState, offset, index, u32Value);
951}
952/* U16 */
953DECLCALLBACK(int)hdaRegReadU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
954{
955 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffff0000) == 0);
956 return hdaRegReadU32(pState, offset, index, pu32Value);
957}
958
959DECLCALLBACK(int)hdaRegWriteU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
960{
961 Assert(((u32Value & 0xffff0000) == 0));
962 return hdaRegWriteU32(pState, offset, index, u32Value);
963}
964
965/* U24 */
966DECLCALLBACK(int)hdaRegReadU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
967{
968 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xff000000) == 0);
969 return hdaRegReadU32(pState, offset, index, pu32Value);
970}
971
972DECLCALLBACK(int)hdaRegWriteU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
973{
974 Assert(((u32Value & 0xff000000) == 0));
975 return hdaRegWriteU32(pState, offset, index, u32Value);
976}
977/* U32 */
978DECLCALLBACK(int)hdaRegReadU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
979{
980 *pu32Value = pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable;
981 return VINF_SUCCESS;
982}
983
984DECLCALLBACK(int)hdaRegWriteU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
985{
986 pState->au32Regs[index] = (u32Value & s_ichIntelHDRegMap[index].writable)
987 | (pState->au32Regs[index] & ~s_ichIntelHDRegMap[index].writable);
988 return VINF_SUCCESS;
989}
990
991DECLCALLBACK(int)hdaRegReadGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
992{
993 return hdaRegReadU32(pState, offset, index, pu32Value);
994}
995
996DECLCALLBACK(int)hdaRegWriteGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
997{
998 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
999 {
1000 /* exit reset state */
1001 GCTL(pState) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
1002 pState->fInReset = false;
1003 }
1004 else
1005 {
1006 /* enter reset state*/
1007 if ( HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)
1008 || HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA))
1009 {
1010 Log(("hda: HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
1011 HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) ? "on" : "off",
1012 HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA) ? "on" : "off"));
1013 }
1014 hdaReset(ICH6_HDASTATE_2_DEVINS(pState));
1015 GCTL(pState) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
1016 pState->fInReset = true;
1017 }
1018 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
1019 {
1020 /* Flush: GSTS:1 set, see 6.2.6*/
1021 GSTS(pState) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
1022 /* DPLBASE and DPUBASE, should be initialized with initial value (see 6.2.6)*/
1023 }
1024 return VINF_SUCCESS;
1025}
1026
1027DECLCALLBACK(int)hdaRegWriteSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1028{
1029 uint32_t v = pState->au32Regs[index];
1030 uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
1031 pState->au32Regs[index] &= ~(v & nv); /* write of 1 clears corresponding bit */
1032 return VINF_SUCCESS;
1033}
1034
1035DECLCALLBACK(int)hdaRegReadINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1036{
1037 uint32_t v = 0;
1038 if ( RIRBSTS_RIRBOIS(pState)
1039 || RIRBSTS_RINTFL(pState)
1040 || HDA_REG_FLAG_VALUE(pState, CORBSTS, CMEI)
1041 || STATESTS(pState))
1042 v |= RT_BIT(30);
1043#define HDA_IS_STREAM_EVENT(pState, stream) \
1044 ( (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \
1045 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \
1046 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
1047#define MARK_STREAM(pState, stream, v) do {(v) |= HDA_IS_STREAM_EVENT((pState),stream) ? RT_BIT((stream)) : 0;}while(0)
1048 MARK_STREAM(pState, 0, v);
1049 MARK_STREAM(pState, 1, v);
1050 MARK_STREAM(pState, 2, v);
1051 MARK_STREAM(pState, 3, v);
1052 MARK_STREAM(pState, 4, v);
1053 MARK_STREAM(pState, 5, v);
1054 MARK_STREAM(pState, 6, v);
1055 MARK_STREAM(pState, 7, v);
1056 v |= v ? RT_BIT(31) : 0;
1057 *pu32Value = v;
1058 return VINF_SUCCESS;
1059}
1060
1061DECLCALLBACK(int)hdaRegReadWALCLK(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1062{
1063 /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
1064 *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(ICH6_HDASTATE_2_DEVINS(pState)) - pState->u64BaseTS, 24, 1000);
1065 return VINF_SUCCESS;
1066}
1067
1068DECLCALLBACK(int)hdaRegReadGCAP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1069{
1070 return hdaRegReadU16(pState, offset, index, pu32Value);
1071}
1072
1073DECLCALLBACK(int)hdaRegWriteCORBRP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1074{
1075 if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
1076 CORBRP(pState) = 0;
1077 else
1078 return hdaRegWriteU8(pState, offset, index, u32Value);
1079 return VINF_SUCCESS;
1080}
1081
1082DECLCALLBACK(int)hdaRegWriteCORBCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1083{
1084 int rc = hdaRegWriteU8(pState, offset, index, u32Value);
1085 AssertRC(rc);
1086 if ( CORBWP(pState) != CORBRP(pState)
1087 && HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) != 0)
1088 return hdaCORBCmdProcess(pState);
1089 return rc;
1090}
1091
1092DECLCALLBACK(int)hdaRegWriteCORBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1093{
1094 uint32_t v = CORBSTS(pState);
1095 CORBSTS(pState) &= ~(v & u32Value);
1096 return VINF_SUCCESS;
1097}
1098
1099DECLCALLBACK(int)hdaRegWriteCORBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1100{
1101 int rc;
1102 rc = hdaRegWriteU16(pState, offset, index, u32Value);
1103 if (RT_FAILURE(rc))
1104 AssertRCReturn(rc, rc);
1105 if (CORBWP(pState) == CORBRP(pState))
1106 return VINF_SUCCESS;
1107 if (!HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1108 return VINF_SUCCESS;
1109 rc = hdaCORBCmdProcess(pState);
1110 return rc;
1111}
1112
1113DECLCALLBACK(int)hdaRegReadSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1114{
1115 return hdaRegReadU24(pState, offset, index, pu32Value);
1116}
1117
1118DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1119{
1120 bool fRun = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
1121 bool fInRun = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
1122 bool fReset = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
1123 bool fInReset = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
1124 int rc = VINF_SUCCESS;
1125 if (fInReset)
1126 {
1127 /* Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit
1128 * from reset
1129 */
1130 Assert((!fReset));
1131 Log(("hda: guest initiate exit of stream reset.\n"));
1132 goto done;
1133 }
1134 else if (fReset)
1135 {
1136 /*
1137 * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset.
1138 */
1139 uint8_t u8Strm = 0;
1140 PHDABDLEDESC pBdle = NULL;
1141 HDASTREAMTRANSFERDESC stStreamDesc;
1142 Assert((!fInRun && !fRun));
1143 switch (index)
1144 {
1145 case ICH6_HDA_REG_SD0CTL:
1146 u8Strm = 0;
1147 pBdle = &pState->stInBdle;
1148 break;
1149 case ICH6_HDA_REG_SD4CTL:
1150 u8Strm = 4;
1151 pBdle = &pState->stOutBdle;
1152 break;
1153 default:
1154 Log(("hda: changing SRST bit on non-attached stream\n"));
1155 goto done;
1156 }
1157 Log(("hda: guest initiate enter to stream reset.\n"));
1158 hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc);
1159 hdaStreamReset(pState, pBdle, &stStreamDesc, u8Strm);
1160 goto done;
1161 }
1162
1163 /* we enter here to change DMA states only */
1164 if ( (fInRun && !fRun)
1165 || (fRun && !fInRun))
1166 {
1167 Assert((!fReset && !fInReset));
1168 switch (index)
1169 {
1170 case ICH6_HDA_REG_SD0CTL:
1171 AUD_set_active_in(pState->Codec.SwVoiceIn, fRun);
1172 break;
1173 case ICH6_HDA_REG_SD4CTL:
1174 AUD_set_active_out(pState->Codec.SwVoiceOut, fRun);
1175 break;
1176 default:
1177 Log(("hda: changing RUN bit on non-attached stream\n"));
1178 goto done;
1179 }
1180 }
1181
1182 done:
1183 rc = hdaRegWriteU24(pState, offset, index, u32Value);
1184 if (RT_FAILURE(rc))
1185 AssertRCReturn(rc, VINF_SUCCESS);
1186 return rc;
1187}
1188
1189DECLCALLBACK(int)hdaRegWriteSDSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1190{
1191 uint32_t v = HDA_REG_IND(pState, index);
1192 v &= ~(u32Value & v);
1193 HDA_REG_IND(pState, index) = v;
1194 hdaProcessInterrupt(pState);
1195 return VINF_SUCCESS;
1196}
1197
1198DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1199{
1200 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1201 if (RT_FAILURE(rc))
1202 AssertRCReturn(rc, VINF_SUCCESS);
1203 return rc;
1204}
1205
1206DECLCALLBACK(int)hdaRegWriteSDFIFOW(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1207{
1208 switch (u32Value)
1209 {
1210 case HDA_SDFIFOW_8B:
1211 case HDA_SDFIFOW_16B:
1212 case HDA_SDFIFOW_32B:
1213 return hdaRegWriteU16(pState, offset, index, u32Value);
1214 default:
1215 Log(("hda: Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
1216 return hdaRegWriteU16(pState, offset, index, HDA_SDFIFOW_32B);
1217 }
1218 return VINF_SUCCESS;
1219}
1220/*
1221 * Note this method could be called for changing value on Output Streams only (ICH6 datacheet 18.2.39)
1222 *
1223 */
1224DECLCALLBACK(int)hdaRegWriteSDFIFOS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1225{
1226 switch (index)
1227 {
1228 /* SDInFIFOS is RO, n=0-3 */
1229 case ICH6_HDA_REG_SD0FIFOS:
1230 case ICH6_HDA_REG_SD1FIFOS:
1231 case ICH6_HDA_REG_SD2FIFOS:
1232 case ICH6_HDA_REG_SD3FIFOS:
1233 Log(("hda: Guest tries change value of FIFO size of Input Stream\n"));
1234 return VINF_SUCCESS;
1235 case ICH6_HDA_REG_SD4FIFOS:
1236 case ICH6_HDA_REG_SD5FIFOS:
1237 case ICH6_HDA_REG_SD6FIFOS:
1238 case ICH6_HDA_REG_SD7FIFOS:
1239 switch(u32Value)
1240 {
1241 case HDA_SDONFIFO_16B:
1242 case HDA_SDONFIFO_32B:
1243 case HDA_SDONFIFO_64B:
1244 case HDA_SDONFIFO_128B:
1245 case HDA_SDONFIFO_192B:
1246 return hdaRegWriteU16(pState, offset, index, u32Value);
1247
1248 case HDA_SDONFIFO_256B:
1249 Log(("hda: 256 bit is unsupported, HDA is switched into 192B mode\n"));
1250 default:
1251 return hdaRegWriteU16(pState, offset, index, HDA_SDONFIFO_192B);
1252 }
1253 return VINF_SUCCESS;
1254 default:
1255 AssertMsgFailed(("Something wierd happens with register lookup routine"));
1256 }
1257 return VINF_SUCCESS;
1258}
1259
1260static void inline hdaSdFmtToAudSettings(uint32_t u32SdFmt, audsettings_t *pAudSetting)
1261{
1262 Assert((pAudSetting));
1263#define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
1264 uint32_t u32Hz = (u32SdFmt & ICH6_HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
1265 uint32_t u32HzMult = 1;
1266 uint32_t u32HzDiv = 1;
1267 switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_MULT_MASK, ICH6_HDA_SDFMT_MULT_SHIFT))
1268 {
1269 case 0: u32HzMult = 1; break;
1270 case 1: u32HzMult = 2; break;
1271 case 2: u32HzMult = 3; break;
1272 case 3: u32HzMult = 4; break;
1273 default:
1274 Log(("hda: unsupported multiplier %x\n", u32SdFmt));
1275 }
1276 switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_DIV_MASK, ICH6_HDA_SDFMT_DIV_SHIFT))
1277 {
1278 case 0: u32HzDiv = 1; break;
1279 case 1: u32HzDiv = 2; break;
1280 case 2: u32HzDiv = 3; break;
1281 case 3: u32HzDiv = 4; break;
1282 case 4: u32HzDiv = 5; break;
1283 case 5: u32HzDiv = 6; break;
1284 case 6: u32HzDiv = 7; break;
1285 case 7: u32HzDiv = 8; break;
1286 }
1287 pAudSetting->freq = u32Hz * u32HzMult / u32HzDiv;
1288
1289 switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_BITS_MASK, ICH6_HDA_SDFMT_BITS_SHIFT))
1290 {
1291 case 0:
1292 Log(("hda: %s requested 8 bit\n", __FUNCTION__));
1293 pAudSetting->fmt = AUD_FMT_S8;
1294 break;
1295 case 1:
1296 Log(("hda: %s requested 16 bit\n", __FUNCTION__));
1297 pAudSetting->fmt = AUD_FMT_S16;
1298 break;
1299 case 2:
1300 Log(("hda: %s requested 20 bit\n", __FUNCTION__));
1301 break;
1302 case 3:
1303 Log(("hda: %s requested 24 bit\n", __FUNCTION__));
1304 break;
1305 case 4:
1306 Log(("hda: %s requested 32 bit\n", __FUNCTION__));
1307 pAudSetting->fmt = AUD_FMT_S32;
1308 break;
1309 default:
1310 AssertMsgFailed(("Unsupported"));
1311 }
1312 pAudSetting->nchannels = (u32SdFmt & 0xf) + 1;
1313 pAudSetting->fmt = AUD_FMT_S16;
1314 pAudSetting->endianness = 0;
1315#undef EXTRACT_VALUE
1316}
1317
1318DECLCALLBACK(int)hdaRegWriteSDFMT(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1319{
1320#ifdef VBOX_WITH_HDA_CODEC_EMU
1321 /* @todo here some more investigations are required. */
1322 int rc = 0;
1323 audsettings_t as;
1324 /* no reason to reopen voice with same settings */
1325 if (u32Value == HDA_REG_IND(pState, index))
1326 return VINF_SUCCESS;
1327 hdaSdFmtToAudSettings(u32Value, &as);
1328 switch (index)
1329 {
1330 case ICH6_HDA_REG_SD0FMT:
1331 rc = codecOpenVoice(&pState->Codec, PI_INDEX, &as);
1332 break;
1333 case ICH6_HDA_REG_SD4FMT:
1334 rc = codecOpenVoice(&pState->Codec, PO_INDEX, &as);
1335 break;
1336 default:
1337 Log(("HDA: attempt to change format on %d\n", index));
1338 rc = 0;
1339 }
1340 return hdaRegWriteU16(pState, offset, index, u32Value);
1341#else
1342 return hdaRegWriteU16(pState, offset, index, u32Value);
1343#endif
1344}
1345
1346DECLCALLBACK(int)hdaRegWriteSDBDPL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1347{
1348 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1349 if (RT_FAILURE(rc))
1350 AssertRCReturn(rc, VINF_SUCCESS);
1351 return rc;
1352}
1353
1354DECLCALLBACK(int)hdaRegWriteSDBDPU(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1355{
1356 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1357 if (RT_FAILURE(rc))
1358 AssertRCReturn(rc, VINF_SUCCESS);
1359 return rc;
1360}
1361
1362DECLCALLBACK(int)hdaRegReadIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1363{
1364 int rc = VINF_SUCCESS;
1365 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
1366 if ( CORBWP(pState) != CORBRP(pState)
1367 || HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1368 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1369
1370 rc = hdaRegReadU32(pState, offset, index, pu32Value);
1371 return rc;
1372}
1373
1374DECLCALLBACK(int)hdaRegWriteIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1375{
1376 int rc = VINF_SUCCESS;
1377 uint64_t resp;
1378 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
1379 /*
1380 * if guest set ICB bit of IRS register HDA should process verb in IC register and
1381 * writes response in IR register and set IRV (valid in case of success) bit of IRS register.
1382 */
1383 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
1384 && !IRS_ICB(pState))
1385 {
1386 uint32_t cmd = IC(pState);
1387 if (CORBWP(pState) != CORBRP(pState))
1388 {
1389 /*
1390 * 3.4.3 defines behaviour of immediate Command status register.
1391 */
1392 LogRel(("hda: guest has tried process immediate verb (%x) with active CORB\n", cmd));
1393 return rc;
1394 }
1395 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1396 Log(("hda: IC:%x\n", cmd));
1397 rc = pState->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
1398 if (RT_FAILURE(rc))
1399 AssertRCReturn(rc, rc);
1400 rc = pfn(&pState->Codec, cmd, &resp);
1401 if (RT_FAILURE(rc))
1402 AssertRCReturn(rc, rc);
1403 IR(pState) = (uint32_t)resp;
1404 Log(("hda: IR:%x\n", IR(pState)));
1405 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */
1406 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
1407 return rc;
1408 }
1409 /*
1410 * when guest's read the response it should clean the IRV bit of the IRS register.
1411 */
1412 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
1413 && IRS_IRV(pState))
1414 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
1415 return rc;
1416}
1417
1418DECLCALLBACK(int)hdaRegWriteRIRBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1419{
1420 if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
1421 {
1422 RIRBWP(pState) = 0;
1423 }
1424 /*The rest of bits are O, see 6.2.22 */
1425 return VINF_SUCCESS;
1426}
1427
1428DECLCALLBACK(int)hdaRegWriteBase(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1429{
1430 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1431 if (RT_FAILURE(rc))
1432 AssertRCReturn(rc, rc);
1433 switch(index)
1434 {
1435 case ICH6_HDA_REG_CORBLBASE:
1436 pState->u64CORBBase &= 0xFFFFFFFF00000000ULL;
1437 pState->u64CORBBase |= pState->au32Regs[index];
1438 break;
1439 case ICH6_HDA_REG_CORBUBASE:
1440 pState->u64CORBBase &= 0x00000000FFFFFFFFULL;
1441 pState->u64CORBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1442 break;
1443 case ICH6_HDA_REG_RIRLBASE:
1444 pState->u64RIRBBase &= 0xFFFFFFFF00000000ULL;
1445 pState->u64RIRBBase |= pState->au32Regs[index];
1446 break;
1447 case ICH6_HDA_REG_RIRUBASE:
1448 pState->u64RIRBBase &= 0x00000000FFFFFFFFULL;
1449 pState->u64RIRBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1450 break;
1451 case ICH6_HDA_REG_DPLBASE:
1452 /* @todo: first bit has special meaning */
1453 pState->u64DPBase &= 0xFFFFFFFF00000000ULL;
1454 pState->u64DPBase |= pState->au32Regs[index];
1455 break;
1456 case ICH6_HDA_REG_DPUBASE:
1457 pState->u64DPBase &= 0x00000000FFFFFFFFULL;
1458 pState->u64DPBase |= ((uint64_t)pState->au32Regs[index] << 32);
1459 break;
1460 default:
1461 AssertMsgFailed(("Invalid index"));
1462 }
1463 Log(("hda: CORB base:%llx RIRB base: %llx DP base: %llx\n", pState->u64CORBBase, pState->u64RIRBBase, pState->u64DPBase));
1464 return rc;
1465}
1466
1467DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1468{
1469 uint8_t v = RIRBSTS(pState);
1470 RIRBSTS(pState) &= ~(v & u32Value);
1471
1472 return hdaProcessInterrupt(pState);
1473}
1474
1475#ifdef LOG_ENABLED
1476static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1477{
1478#if 0
1479 uint64_t addr;
1480 uint32_t len;
1481 uint32_t ioc;
1482 uint8_t bdle[16];
1483 uint32_t counter;
1484 uint32_t i;
1485 uint32_t sum = 0;
1486 Assert(pBdle && pBdle->u32BdleMaxCvi);
1487 for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
1488 {
1489 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + i*16, bdle, 16);
1490 addr = *(uint64_t *)bdle;
1491 len = *(uint32_t *)&bdle[8];
1492 ioc = *(uint32_t *)&bdle[12];
1493 Log(("hda: %s bdle[%d] a:%llx, len:%d, ioc:%d\n", (i == pBdle->u32BdleCvi? "[C]": " "), i, addr, len, ioc & 0x1));
1494 sum += len;
1495 }
1496 Log(("hda: sum: %d\n", sum));
1497 for (i = 0; i < 8; ++i)
1498 {
1499 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), (pState->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
1500 Log(("hda: %s stream[%d] counter=%x\n", i == SDCTL_NUM(pState, 4) || i == SDCTL_NUM(pState, 0)? "[C]": " ",
1501 i , counter));
1502 }
1503#endif
1504}
1505#endif
1506
1507static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
1508{
1509 uint8_t bdle[16];
1510 Assert(( pStreamDesc->u64BaseDMA
1511 && pBdle
1512 && pBdle->u32BdleMaxCvi));
1513 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
1514 pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
1515 pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
1516 pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
1517#ifdef LOG_ENABLED
1518 dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA);
1519#endif
1520}
1521
1522static inline uint32_t hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit)
1523{
1524 uint32_t cb2Copy;
1525 /*
1526 * Amounts of bytes depends on current position in buffer (u32BdleCviLen-u32BdleCviPos)
1527 */
1528 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
1529 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
1530 /*
1531 * we may increase the counter in range of [0, FIFOS + 1]
1532 */
1533 cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1);
1534 Assert((u32SoundBackendBufferBytesAvail > 0));
1535
1536 /* sanity check to avoid overriding sound backend buffer */
1537 cb2Copy = RT_MIN(cb2Copy, u32SoundBackendBufferBytesAvail);
1538 cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
1539
1540 if (cb2Copy <= pBdle->cbUnderFifoW)
1541 return 0;
1542 cb2Copy -= pBdle->cbUnderFifoW; /* forcely reserve amount of ureported bytes to copy */
1543 return cb2Copy;
1544}
1545
1546static inline void hdaBackendWriteTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied, uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
1547{
1548 Log(("hda:hdaBackendWriteTransferReported: cbArranged2Copy: %d, cbCopied: %d, pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
1549 cbArranged2Copy, cbCopied, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
1550 Assert((cbCopied));
1551 Assert((pu32BackendBufferCapacity && *pu32BackendBufferCapacity));
1552 /* Assertion!!! It was copied less than cbUnderFifoW
1553 * Probably we need to move the buffer, but it rather hard to imagine situation
1554 * why it may happen.
1555 */
1556 Assert((cbCopied == pBdle->cbUnderFifoW + cbArranged2Copy)); /* we assume that we write whole buffer including not reported bytes */
1557 if ( pBdle->cbUnderFifoW
1558 && pBdle->cbUnderFifoW <= cbCopied)
1559 Log(("hda:hdaBackendWriteTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1560
1561 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbCopied);
1562 Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Assumption failed */
1563
1564 /* We always increment position on DMA buffer counter because we're always reading to intermediate buffer */
1565 pBdle->u32BdleCviPos += cbArranged2Copy;
1566
1567 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32BackendBufferCapacity >= cbCopied)); /* sanity */
1568 /* We reports all bytes (including unreported previously) */
1569 *pu32DMACursor += cbCopied;
1570 /* reducing backend counter on amount of bytes we copied to backend */
1571 *pu32BackendBufferCapacity -= cbCopied;
1572 Log(("hda:hdaBackendWriteTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
1573 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, *pu32DMACursor, *pu32BackendBufferCapacity));
1574}
1575
1576static inline void hdaBackendReadTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied, uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
1577{
1578 Assert((cbCopied, cbArranged2Copy));
1579 *pu32BackendBufferCapacity -= cbCopied;
1580 pBdle->u32BdleCviPos += cbCopied;
1581 Log(("hda:hdaBackendReadTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1582 *pu32DMACursor += cbCopied + pBdle->cbUnderFifoW;
1583 pBdle->cbUnderFifoW = 0;
1584 Log(("hda:hdaBackendReadTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
1585 pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
1586}
1587
1588static inline void hdaBackendTransferUnreported(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
1589{
1590 Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1591 pBdle->u32BdleCviPos += cbCopied;
1592 pBdle->cbUnderFifoW += cbCopied;
1593 /* In case of read transaction we're always coping from backend buffer */
1594 if (pu32BackendBufferCapacity)
1595 *pu32BackendBufferCapacity -= cbCopied;
1596 Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1597 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, pStreamDesc)));
1598}
1599static inline bool hdaIsTransferCountersOverlapped(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
1600{
1601 bool fOnBufferEdge = ( *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl
1602 || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen);
1603
1604 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
1605
1606 if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
1607 *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl;
1608 hdaUpdatePosBuf(pState, pStreamDesc);
1609
1610 /* don't touch BdleCvi counter on uninitialized descriptor */
1611 if ( pBdle->u32BdleCviPos
1612 && pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
1613 {
1614 pBdle->u32BdleCviPos = 0;
1615 pBdle->u32BdleCvi++;
1616 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
1617 pBdle->u32BdleCvi = 0;
1618 }
1619 return fOnBufferEdge;
1620}
1621
1622static inline void hdaStreamCounterUpdate(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbInc)
1623{
1624 /*
1625 * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything.
1626 * (ICH6 datasheet 18.2.38)
1627 */
1628 if (!pBdle->cbUnderFifoW)
1629 {
1630 *pStreamDesc->pu32Lpib += cbInc;
1631
1632 /*
1633 * Assert. Overlapping of buffer counter shouldn't happen.
1634 */
1635 Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
1636
1637 hdaUpdatePosBuf(pState, pStreamDesc);
1638
1639 }
1640}
1641
1642static inline bool hdaDoNextTransferCycle(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
1643{
1644 bool fDoNextTransferLoop = true;
1645 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
1646 || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
1647 {
1648 if ( !pBdle->cbUnderFifoW
1649 && pBdle->fBdleCviIoc)
1650 {
1651 /*
1652 * @todo - more carefully investigate BCIS flag.
1653 * Speech synthesis works fine on Mac Guest if this bit isn't set
1654 * but in general sound quality becomes lesser.
1655 */
1656 *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
1657
1658 /*
1659 * we should generate the interrupt if ICE bit of SDCTL register is set.
1660 */
1661 if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
1662 hdaProcessInterrupt(pState);
1663 }
1664 fDoNextTransferLoop = false;
1665 }
1666 return fDoNextTransferLoop;
1667}
1668
1669/*
1670 * hdaReadAudio - copies samples from Qemu Sound back-end to DMA.
1671 * Note: this function writes immediately to DMA buffer, but "reports bytes" when all conditions meet (FIFOW)
1672 */
1673static uint32_t hdaReadAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
1674{
1675 PHDABDLEDESC pBdle = &pState->stInBdle;
1676 uint32_t cbTransfered = 0;
1677 uint32_t cb2Copy = 0;
1678 uint32_t cbBackendCopy = 0;
1679
1680 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1681
1682 cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
1683 if (!cb2Copy)
1684 {
1685 /* if we enter here we can't report "unreported bits" */
1686 *fStop = true;
1687 goto done;
1688 }
1689
1690
1691 /*
1692 * read from backend input line to last ureported position or at the begining.
1693 */
1694 cbBackendCopy = AUD_read (pState->Codec.SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);
1695 /*
1696 * write on the HDA DMA
1697 */
1698 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy);
1699
1700 /* Don't see reasons why cb2Copy could differ from cbBackendCopy */
1701 Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
1702
1703 if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pState, 0))
1704 hdaBackendReadTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransfered, pu32Avail);
1705 else
1706 {
1707 hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cbBackendCopy, pu32Avail);
1708 *fStop = true;
1709 }
1710 done:
1711 Assert((cbTransfered <= (SDFIFOS(pState, 0) + 1)));
1712 Log(("hda:ra: CVI(pos:%d, len:%d) cbTransfered: %d\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransfered));
1713 return cbTransfered;
1714}
1715
1716static uint32_t hdaWriteAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
1717{
1718 PHDABDLEDESC pBdle = &pState->stOutBdle;
1719 uint32_t cbTransfered = 0;
1720 uint32_t cb2Copy = 0; /* local byte counter (on local buffer) */
1721 uint32_t cbBackendCopy = 0; /* local byte counter, how many bytes copied to backend */
1722
1723 Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1724
1725 cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
1726
1727 /*
1728 * Copy from DMA to the corresponding hdaBuffer (if there exists some bytes from the previous not reported transfer we write to ''pBdle->cbUnderFifoW'' offset)
1729 */
1730 if (!cb2Copy)
1731 {
1732 *fStop = true;
1733 goto done;
1734 }
1735
1736 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
1737 /*
1738 * Write to audio backend. we should be sure whether we have enought bytes to copy to Audio backend.
1739 */
1740 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, pStreamDesc))
1741 {
1742 /*
1743 * We feed backend with new portion of fetched samples including not reported.
1744 */
1745 cbBackendCopy = AUD_write (pState->Codec.SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
1746 hdaBackendWriteTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransfered, pu32Avail);
1747 }
1748 else
1749 {
1750 /* Not enough bytes to be processed and reported, check luck on next enterence */
1751 hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cb2Copy, NULL);
1752 *fStop = true;
1753 }
1754
1755 done:
1756 Assert((cbTransfered <= (SDFIFOS(pState, 4) + 1)));
1757 Log(("hda:wa: CVI(pos:%d, len:%d, cbTransfered:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransfered));
1758 return cbTransfered;
1759}
1760
1761DECLCALLBACK(int) hdaCodecReset(CODECState *pCodecState)
1762{
1763 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1764 return VINF_SUCCESS;
1765}
1766
1767static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc)
1768{
1769 Assert(( pState
1770 && pBdle
1771 && pStreamDesc
1772 && u8Strm <= 7));
1773 memset(pStreamDesc, 0, sizeof(HDASTREAMTRANSFERDESC));
1774 pStreamDesc->u8Strm = u8Strm;
1775 pStreamDesc->u32Ctl = HDA_STREAM_REG2(pState, CTL, u8Strm);
1776 pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG2(pState, BDPL, u8Strm),
1777 HDA_STREAM_REG2(pState, BDPU, u8Strm));
1778 pStreamDesc->pu32Lpib = &HDA_STREAM_REG2(pState, LPIB, u8Strm);
1779 pStreamDesc->pu32Sts = &HDA_STREAM_REG2(pState, STS, u8Strm);
1780 pStreamDesc->u32Cbl = HDA_STREAM_REG2(pState, CBL, u8Strm);
1781 pStreamDesc->u32Fifos = HDA_STREAM_REG2(pState, FIFOS, u8Strm);
1782
1783 pBdle->u32BdleMaxCvi = HDA_STREAM_REG2(pState, LVI, u8Strm);
1784#ifdef LOG_ENABLED
1785 if ( pBdle
1786 && pBdle->u32BdleMaxCvi)
1787 {
1788 Log(("Initialization of transfer descriptor:\n"));
1789 dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA);
1790 }
1791#endif
1792}
1793
1794DECLCALLBACK(void) hdaTransfer(CODECState *pCodecState, ENMSOUNDSOURCE src, int avail)
1795{
1796 bool fStop = false;
1797 uint8_t u8Strm = 0;
1798 PHDABDLEDESC pBdle = NULL;
1799 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1800 HDASTREAMTRANSFERDESC stStreamDesc;
1801 uint32_t nBytes;
1802 switch (src)
1803 {
1804 case PO_INDEX:
1805 {
1806 u8Strm = 4;
1807 pBdle = &pState->stOutBdle;
1808 break;
1809 }
1810 case PI_INDEX:
1811 {
1812 u8Strm = 0;
1813 pBdle = &pState->stInBdle;
1814 break;
1815 }
1816 default:
1817 return;
1818 }
1819 hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc);
1820 while( avail && !fStop)
1821 {
1822 Assert ( (stStreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
1823 && avail
1824 && stStreamDesc.u64BaseDMA);
1825
1826 /* Fetch the Buffer Descriptor Entry (BDE). */
1827
1828 if (hdaIsTransferCountersOverlapped(pState, pBdle, &stStreamDesc))
1829 hdaFetchBdle(pState, pBdle, &stStreamDesc);
1830 *stStreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1831 Assert((avail >= 0 && (stStreamDesc.u32Cbl >= (*stStreamDesc.pu32Lpib)))); /* sanity */
1832 uint32_t u32CblLimit = stStreamDesc.u32Cbl - (*stStreamDesc.pu32Lpib);
1833 Assert((u32CblLimit > hdaFifoWToSz(pState, &stStreamDesc)));
1834 Log(("hda: CBL=%d, LPIB=%d\n", stStreamDesc.u32Cbl, *stStreamDesc.pu32Lpib));
1835 switch (src)
1836 {
1837 case PO_INDEX:
1838 nBytes = hdaWriteAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
1839 break;
1840 case PI_INDEX:
1841 nBytes = hdaReadAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
1842 break;
1843 default:
1844 nBytes = 0;
1845 fStop = true;
1846 AssertMsgFailed(("Unsupported"));
1847 }
1848 Assert(nBytes <= (stStreamDesc.u32Fifos + 1));
1849 *stStreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1850
1851 /* Process end of buffer condition. */
1852 hdaStreamCounterUpdate(pState, pBdle, &stStreamDesc, nBytes);
1853 fStop = !fStop ? !hdaDoNextTransferCycle(pState, pBdle, &stStreamDesc) : fStop;
1854 }
1855}
1856
1857/**
1858 * Handle register read operation.
1859 *
1860 * Looks up and calls appropriate handler.
1861 *
1862 * @note: while implementation was detected so called "forgotten" or "hole" registers
1863 * which description is missed in RPM, datasheet or spec.
1864 *
1865 * @returns VBox status code.
1866 *
1867 * @param pState The device state structure.
1868 * @param uOffset Register offset in memory-mapped frame.
1869 * @param pv Where to fetch the value.
1870 * @param cb Number of bytes to write.
1871 * @thread EMT
1872 */
1873PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
1874{
1875 int rc = VINF_SUCCESS;
1876 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1877 uint32_t offReg = GCPhysAddr - pThis->hda.addrMMReg;
1878 int idxReg = hdaMMIORegLookup(&pThis->hda, offReg);
1879 if (pThis->hda.fInReset && idxReg != ICH6_HDA_REG_GCTL)
1880 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1881
1882 if (idxReg == -1)
1883 LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", offReg, cb));
1884
1885 if (idxReg != -1)
1886 {
1887 /** @todo r=bird: Accesses crossing register boundraries aren't handled
1888 * right from what I can tell? If they are, please explain
1889 * what the rules are. */
1890 uint32_t mask = 0;
1891 uint32_t shift = (s_ichIntelHDRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
1892 uint32_t u32Value = 0;
1893 switch(cb)
1894 {
1895 case 1: mask = 0x000000ff; break;
1896 case 2: mask = 0x0000ffff; break;
1897 case 4:
1898 /* 18.2 of ICH6 datasheet defines wideness of the accesses byte, word and double word */
1899 case 8:
1900 mask = 0xffffffff;
1901 cb = 4;
1902 break;
1903 }
1904#if 0
1905 /* cross register access. Mac guest hit this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL
1906 */
1907 //Assert((cb <= s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset)));
1908 if (cb > s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset))
1909 {
1910 int off = cb - (s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset));
1911 rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off);
1912 if (RT_FAILURE(rc))
1913 AssertRCReturn (rc, rc);
1914 }
1915 //Assert(((offReg - s_ichIntelHDRegMap[idxReg].offset) == 0));
1916#endif
1917 mask <<= shift;
1918 rc = s_ichIntelHDRegMap[idxReg].pfnRead(&pThis->hda, offReg, idxReg, &u32Value);
1919 *(uint32_t *)pv |= (u32Value & mask);
1920 Log(("hda: read %s[%x/%x]\n", s_ichIntelHDRegMap[idxReg].abbrev, u32Value, *(uint32_t *)pv));
1921 return rc;
1922 }
1923 *(uint32_t *)pv = 0xFF;
1924 Log(("hda: hole at %x is accessed for read\n", offReg));
1925 return rc;
1926}
1927
1928/**
1929 * Handle register write operation.
1930 *
1931 * Looks up and calls appropriate handler.
1932 *
1933 * @returns VBox status code.
1934 *
1935 * @param pState The device state structure.
1936 * @param uOffset Register offset in memory-mapped frame.
1937 * @param pv Where to fetch the value.
1938 * @param cb Number of bytes to write.
1939 * @thread EMT
1940 */
1941PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
1942{
1943 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1944 uint32_t offReg = GCPhysAddr - pThis->hda.addrMMReg;
1945 int idxReg = hdaMMIORegLookup(&pThis->hda, offReg);
1946 int rc = VINF_SUCCESS;
1947
1948 if (pThis->hda.fInReset && idxReg != ICH6_HDA_REG_GCTL)
1949 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1950
1951 if ( idxReg == -1
1952 || cb > 4)
1953 LogRel(("hda: Invalid write access @0x%x(of bytes:%d)\n", offReg, cb));
1954
1955 if (idxReg != -1)
1956 {
1957 /** @todo r=bird: This looks like code for handling unalinged register
1958 * accesses. If it isn't then, add a comment explaing what you're
1959 * trying to do here. OTOH, if it is then it has the following
1960 * issues:
1961 * -# You're calculating the wrong new value for the register.
1962 * -# You're not handling cross register accesses. Imagine a
1963 * 4-byte write starting at CORBCTL, or a 8-byte write.
1964 *
1965 * PS! consider dropping the 'offset' argument to pfnWrite/pfnRead as
1966 * nobody seems to be using it and it just add complexity when reading
1967 * the code.
1968 *
1969 */
1970 uint32_t u32CurValue = pThis->hda.au32Regs[idxReg];
1971 uint32_t u32NewValue;
1972 uint32_t mask;
1973 switch (cb)
1974 {
1975 case 1:
1976 u32NewValue = *(uint8_t const *)pv;
1977 mask = 0xff;
1978 break;
1979 case 2:
1980 u32NewValue = *(uint16_t const *)pv;
1981 mask = 0xffff;
1982 break;
1983 case 4:
1984 case 8:
1985 /* 18.2 of ICH6 datasheet defines wideness of the accesses byte, word and double word */
1986 u32NewValue = *(uint32_t const *)pv;
1987 mask = 0xffffffff;
1988 cb = 4;
1989 break;
1990 default:
1991 AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */
1992 }
1993 /* cross register access, see corresponding comment in hdaMMIORead */
1994#if 0
1995 if (cb > s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset))
1996 {
1997 int off = cb - (s_ichIntelHDRegMap[idxReg].size - (offReg - s_ichIntelHDRegMap[idxReg].offset));
1998 rc = hdaMMIOWrite(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off);
1999 if (RT_FAILURE(rc))
2000 AssertRCReturn (rc, rc);
2001 }
2002#endif
2003 uint32_t shift = (s_ichIntelHDRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
2004 mask <<= shift;
2005 u32NewValue <<= shift;
2006 u32NewValue &= mask;
2007 u32NewValue |= (u32CurValue & ~mask);
2008
2009 rc = s_ichIntelHDRegMap[idxReg].pfnWrite(&pThis->hda, offReg, idxReg, u32NewValue);
2010 Log(("hda: write %s:(%x) %x => %x\n", s_ichIntelHDRegMap[idxReg].abbrev, u32NewValue,
2011 u32CurValue, pThis->hda.au32Regs[idxReg]));
2012 return rc;
2013 }
2014
2015 Log(("hda: hole at %x is accessed for write\n", offReg));
2016 return rc;
2017}
2018
2019/**
2020 * Callback function for mapping a PCI I/O region.
2021 *
2022 * @return VBox status code.
2023 * @param pPciDev Pointer to PCI device.
2024 * Use pPciDev->pDevIns to get the device instance.
2025 * @param iRegion The region number.
2026 * @param GCPhysAddress Physical address of the region.
2027 * If iType is PCI_ADDRESS_SPACE_IO, this is an
2028 * I/O port, else it's a physical address.
2029 * This address is *NOT* relative
2030 * to pci_mem_base like earlier!
2031 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
2032 */
2033static DECLCALLBACK(int) hdaMap (PPCIDEVICE pPciDev, int iRegion,
2034 RTGCPHYS GCPhysAddress, uint32_t cb,
2035 PCIADDRESSSPACE enmType)
2036{
2037 int rc;
2038 PPDMDEVINS pDevIns = pPciDev->pDevIns;
2039 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
2040 PCIINTELHDLinkState *pThis = PCIDEV_2_ICH6_HDASTATE(pPciDev);
2041
2042 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
2043 rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
2044 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
2045 hdaMMIOWrite, hdaMMIORead, "ICH6_HDA");
2046
2047 if (RT_FAILURE(rc))
2048 return rc;
2049
2050 pThis->hda.addrMMReg = GCPhysAddress;
2051 return VINF_SUCCESS;
2052}
2053
2054/**
2055 * Saves a state of the HDA device.
2056 *
2057 * @returns VBox status code.
2058 * @param pDevIns The device instance.
2059 * @param pSSMHandle The handle to save the state to.
2060 */
2061static DECLCALLBACK(int) hdaSaveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2062{
2063 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2064 /* Save Codec nodes states */
2065 codecSaveState(&pThis->hda.Codec, pSSMHandle);
2066 /* Save MMIO registers */
2067 SSMR3PutMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
2068 /* Save HDA dma counters */
2069 SSMR3PutStruct (pSSMHandle, &pThis->hda.stOutBdle, g_aHdaBDLEDescFields);
2070 SSMR3PutStruct (pSSMHandle, &pThis->hda.stMicBdle, g_aHdaBDLEDescFields);
2071 SSMR3PutStruct (pSSMHandle, &pThis->hda.stInBdle, g_aHdaBDLEDescFields);
2072 return VINF_SUCCESS;
2073}
2074
2075/**
2076 * Loads a saved HDA device state.
2077 *
2078 * @returns VBox status code.
2079 * @param pDevIns The device instance.
2080 * @param pSSMHandle The handle to the saved state.
2081 * @param uVersion The data unit version number.
2082 * @param uPass The data pass.
2083 */
2084static DECLCALLBACK(int) hdaLoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
2085 uint32_t uVersion, uint32_t uPass)
2086{
2087 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2088 /* Load Codec nodes states */
2089 Assert (uPass == SSM_PASS_FINAL); NOREF(uPass);
2090
2091 codecLoadState(&pThis->hda.Codec, pSSMHandle, uVersion);
2092 /* Load MMIO registers */
2093 SSMR3GetMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
2094 /* Load HDA dma counters */
2095 if ( uVersion == HDA_SSM_VERSION_1
2096 || uVersion == HDA_SSM_VERSION_2)
2097 {
2098 SSMR3GetMem (pSSMHandle, &pThis->hda.stOutBdle, sizeof (HDABDLEDESC));
2099 SSMR3GetMem (pSSMHandle, &pThis->hda.stMicBdle, sizeof (HDABDLEDESC));
2100 SSMR3GetMem (pSSMHandle, &pThis->hda.stInBdle, sizeof (HDABDLEDESC));
2101 }
2102 else
2103 {
2104 SSMR3GetStruct (pSSMHandle, &pThis->hda.stOutBdle, g_aHdaBDLEDescFields);
2105 SSMR3GetStruct (pSSMHandle, &pThis->hda.stMicBdle, g_aHdaBDLEDescFields);
2106 SSMR3GetStruct (pSSMHandle, &pThis->hda.stInBdle, g_aHdaBDLEDescFields);
2107 }
2108
2109
2110 AUD_set_active_in(pThis->hda.Codec.SwVoiceIn, SDCTL(&pThis->hda, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
2111 AUD_set_active_out(pThis->hda.Codec.SwVoiceOut, SDCTL(&pThis->hda, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
2112
2113 pThis->hda.u64CORBBase = CORBLBASE(&pThis->hda);
2114 pThis->hda.u64CORBBase |= ((uint64_t)CORBUBASE(&pThis->hda)) << 32;
2115 pThis->hda.u64RIRBBase = RIRLBASE(&pThis->hda);
2116 pThis->hda.u64RIRBBase |= ((uint64_t)RIRUBASE(&pThis->hda)) << 32;
2117 pThis->hda.u64DPBase = DPLBASE(&pThis->hda);
2118 pThis->hda.u64DPBase |= ((uint64_t)DPUBASE(&pThis->hda)) << 32;
2119 return VINF_SUCCESS;
2120}
2121
2122/**
2123 * Reset notification.
2124 *
2125 * @returns VBox status.
2126 * @param pDevIns The device instance data.
2127 *
2128 * @remark The original sources didn't install a reset handler, but it seems to
2129 * make sense to me so we'll do it.
2130 */
2131static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
2132{
2133 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2134 GCAP(&pThis->hda) = HDA_MAKE_GCAP(4,4,0,0,1); /* see 6.2.1 */
2135 VMIN(&pThis->hda) = 0x00; /* see 6.2.2 */
2136 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
2137 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
2138 OUTPAY(&pThis->hda) = 0x003C; /* see 6.2.4 */
2139 INPAY(&pThis->hda) = 0x001D; /* see 6.2.5 */
2140 pThis->hda.au32Regs[ICH6_HDA_REG_CORBSIZE] = 0x42; /* see 6.2.1 */
2141 pThis->hda.au32Regs[ICH6_HDA_REG_RIRBSIZE] = 0x42; /* see 6.2.1 */
2142 CORBRP(&pThis->hda) = 0x0;
2143 RIRBWP(&pThis->hda) = 0x0;
2144
2145 Log(("hda: inter HDA reset.\n"));
2146 pThis->hda.cbCorbBuf = 256 * sizeof(uint32_t);
2147
2148 if (pThis->hda.pu32CorbBuf)
2149 memset(pThis->hda.pu32CorbBuf, 0, pThis->hda.cbCorbBuf);
2150 else
2151 pThis->hda.pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->hda.cbCorbBuf);
2152
2153 pThis->hda.cbRirbBuf = 256 * sizeof(uint64_t);
2154 if (pThis->hda.pu64RirbBuf)
2155 memset(pThis->hda.pu64RirbBuf, 0, pThis->hda.cbRirbBuf);
2156 else
2157 pThis->hda.pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->hda.cbRirbBuf);
2158
2159 pThis->hda.u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
2160
2161 HDABDLEDESC stEmptyBdle;
2162 for(uint8_t u8Strm = 0; u8Strm < 8; ++u8Strm)
2163 {
2164 HDASTREAMTRANSFERDESC stStreamDesc;
2165 PHDABDLEDESC pBdle = NULL;
2166 if (u8Strm == 0)
2167 pBdle = &pThis->hda.stInBdle;
2168 else if(u8Strm == 4)
2169 pBdle = &pThis->hda.stOutBdle;
2170 else
2171 {
2172 memset(&stEmptyBdle, 0, sizeof(HDABDLEDESC));
2173 pBdle = &stEmptyBdle;
2174 }
2175 hdaInitTransferDescriptor(&pThis->hda, pBdle, u8Strm, &stStreamDesc);
2176 /* hdaStreamReset prevents changing SRST bit, so we zerro it here forcely. */
2177 HDA_STREAM_REG2(&pThis->hda, CTL, u8Strm) = 0;
2178 hdaStreamReset(&pThis->hda, pBdle, &stStreamDesc, u8Strm);
2179 }
2180
2181 /* emulateion of codec "wake up" HDA spec (5.5.1 and 6.5)*/
2182 STATESTS(&pThis->hda) = 0x1;
2183
2184 Log(("hda: reset finished\n"));
2185}
2186
2187/**
2188 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2189 */
2190static DECLCALLBACK(void *) hdaQueryInterface (struct PDMIBASE *pInterface,
2191 const char *pszIID)
2192{
2193 PCIINTELHDLinkState *pThis = RT_FROM_MEMBER(pInterface, PCIINTELHDLinkState, hda.IBase);
2194 Assert(&pThis->hda.IBase == pInterface);
2195
2196 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->hda.IBase);
2197 return NULL;
2198}
2199
2200static inline int hdaLookUpRegisterByName(INTELHDLinkState *pState, const char *pszArgs)
2201{
2202 int iReg = 0;
2203 for (; iReg < HDA_NREGS; ++iReg)
2204 if (!RTStrICmp(s_ichIntelHDRegMap[iReg].abbrev, pszArgs))
2205 return iReg;
2206 return -1;
2207}
2208static inline void hdaDbgPrintRegister(INTELHDLinkState *pState, PCDBGFINFOHLP pHlp, int iHdaIndex)
2209{
2210 Assert( pState
2211 && iHdaIndex >= 0
2212 && iHdaIndex < HDA_NREGS);
2213 pHlp->pfnPrintf(pHlp, "hda: %s: 0x%x\n", s_ichIntelHDRegMap[iHdaIndex].abbrev, pState->au32Regs[iHdaIndex]);
2214}
2215static DECLCALLBACK(void) hdaDbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2216{
2217 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2218 INTELHDLinkState *hda = &pThis->hda;
2219 int iHdaRegisterIndex = hdaLookUpRegisterByName(hda, pszArgs);
2220 if (iHdaRegisterIndex != -1)
2221 hdaDbgPrintRegister(hda, pHlp, iHdaRegisterIndex);
2222 else
2223 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NREGS; ++iHdaRegisterIndex)
2224 hdaDbgPrintRegister(hda, pHlp, iHdaRegisterIndex);
2225}
2226
2227static inline void hdaDbgPrintStream(INTELHDLinkState *pState, PCDBGFINFOHLP pHlp, int iHdaStrmIndex)
2228{
2229 Assert( pState
2230 && iHdaStrmIndex >= 0
2231 && iHdaStrmIndex < 7);
2232 pHlp->pfnPrintf(pHlp, "Dump of %d Hda Stream:\n", iHdaStrmIndex);
2233 pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n", iHdaStrmIndex, HDA_STREAM_REG2(pState, CTL, iHdaStrmIndex));
2234 pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n", iHdaStrmIndex, HDA_STREAM_REG2(pState, STS, iHdaStrmIndex));
2235 pHlp->pfnPrintf(pHlp, "SD%dFIFOS: %R[sdfifos]\n", iHdaStrmIndex, HDA_STREAM_REG2(pState, FIFOS, iHdaStrmIndex));
2236 pHlp->pfnPrintf(pHlp, "SD%dFIFOW: %R[sdfifow]\n", iHdaStrmIndex, HDA_STREAM_REG2(pState, FIFOW, iHdaStrmIndex));
2237}
2238
2239static inline int hdaLookUpStreamIndex(INTELHDLinkState *pState, const char *pszArgs)
2240{
2241 /* todo: add args parsing */
2242 return -1;
2243}
2244static DECLCALLBACK(void) hdaDbgStreamInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2245{
2246 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2247 INTELHDLinkState *hda = &pThis->hda;
2248 int iHdaStrmIndex = hdaLookUpStreamIndex(hda, pszArgs);
2249 if (iHdaStrmIndex != -1)
2250 hdaDbgPrintStream(hda, pHlp, iHdaStrmIndex);
2251 else
2252 for(iHdaStrmIndex = 0; iHdaStrmIndex < 7; ++iHdaStrmIndex)
2253 hdaDbgPrintStream(hda, pHlp, iHdaStrmIndex);
2254}
2255
2256/* Codec debugger interface */
2257static DECLCALLBACK(void) hdaCodecDbgNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2258{
2259 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2260 INTELHDLinkState *hda = &pThis->hda;
2261 if (hda->Codec.pfnCodecDbgListNodes)
2262 hda->Codec.pfnCodecDbgListNodes(&hda->Codec, pHlp, pszArgs);
2263 else
2264 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
2265}
2266
2267static DECLCALLBACK(void) hdaCodecDbgSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2268{
2269 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2270 INTELHDLinkState *hda = &pThis->hda;
2271 if (hda->Codec.pfnCodecDbgSelector)
2272 hda->Codec.pfnCodecDbgSelector(&hda->Codec, pHlp, pszArgs);
2273 else
2274 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
2275}
2276
2277//#define HDA_AS_PCI_EXPRESS
2278/* Misc routines */
2279static inline bool printHdaIsValid(const char *pszType, const char *pszExpectedFlag)
2280{
2281 return (RTStrCmp(pszType, pszExpectedFlag) == 0);
2282}
2283static const char *printHdaYesNo(bool fFlag)
2284{
2285 return fFlag ? "yes" : "no";
2286}
2287static DECLCALLBACK(size_t)
2288printHdaStrmCtl(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
2289 const char *pszType, void const *pvValue,
2290 int cchWidth, int cchPrecision, unsigned fFlags,
2291 void *pvUser)
2292{
2293 uint32_t sdCtl = (uint32_t)(uintptr_t)pvValue;
2294 size_t cb = 0;
2295 if (!printHdaIsValid(pszType, "sdctl"))
2296 return cb;
2297 cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
2298 "SDCTL(raw: %#0x, strm:0x%x, dir:%s, tp:%s strip:%x, deie:%s, ioce:%s, run:%s, srst:%s)",
2299 sdCtl,
2300 ((sdCtl & HDA_REG_FIELD_MASK(SDCTL, NUM)) >> ICH6_HDA_SDCTL_NUM_SHIFT),
2301 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DIR))),
2302 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, TP))),
2303 ((sdCtl & HDA_REG_FIELD_MASK(SDCTL, STRIPE)) >> ICH6_HDA_SDCTL_STRIPE_SHIFT),
2304 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DEIE))),
2305 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))),
2306 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))),
2307 printHdaYesNo(RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))));
2308 return cb;
2309}
2310
2311static DECLCALLBACK(size_t)
2312printHdaStrmFifos(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
2313 const char *pszType, void const *pvValue,
2314 int cchWidth, int cchPrecision, unsigned fFlags,
2315 void *pvUser)
2316{
2317 uint32_t sdFifos = (uint32_t)(uintptr_t)pvValue;
2318 uint32_t u32Bytes = 0;
2319 size_t cb = 0;
2320 if (!printHdaIsValid(pszType, "sdfifos"))
2321 return cb;
2322 switch(sdFifos)
2323 {
2324 case HDA_SDONFIFO_16B: u32Bytes = 16; break;
2325 case HDA_SDONFIFO_32B: u32Bytes = 32; break;
2326 case HDA_SDONFIFO_64B: u32Bytes = 64; break;
2327 case HDA_SDONFIFO_128B: u32Bytes = 128; break;
2328 case HDA_SDONFIFO_192B: u32Bytes = 192; break;
2329 case HDA_SDONFIFO_256B: u32Bytes = 256; break;
2330 case HDA_SDINFIFO_120B: u32Bytes = 120; break;
2331 case HDA_SDINFIFO_160B: u32Bytes = 160; break;
2332 default:;
2333 }
2334 cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
2335 "SDFIFOS(raw: %#0x, sdfifos:%d B)",
2336 sdFifos,
2337 u32Bytes);
2338 return cb;
2339}
2340
2341static DECLCALLBACK(size_t)
2342printHdaStrmFifow(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
2343 const char *pszType, void const *pvValue,
2344 int cchWidth, int cchPrecision, unsigned fFlags,
2345 void *pvUser)
2346{
2347 uint32_t sdFifow = (uint32_t)(uintptr_t)pvValue;
2348 uint32_t u32Bytes = 0;
2349 size_t cb = 0;
2350 if (!printHdaIsValid(pszType, "sdfifow"))
2351 return cb;
2352 switch(sdFifow)
2353 {
2354 case HDA_SDFIFOW_8B: u32Bytes = 8; break;
2355 case HDA_SDFIFOW_16B: u32Bytes = 16; break;
2356 case HDA_SDFIFOW_32B: u32Bytes = 32; break;
2357 }
2358 cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
2359 "SDFIFOW(raw: %#0x, sdfifow:%d B)",
2360 sdFifow,
2361 u32Bytes);
2362 return cb;
2363}
2364
2365static DECLCALLBACK(size_t)
2366printHdaStrmSts(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
2367 const char *pszType, void const *pvValue,
2368 int cchWidth, int cchPrecision, unsigned fFlags,
2369 void *pvUser)
2370{
2371 uint32_t sdSts = (uint32_t)(uintptr_t)pvValue;
2372 size_t cb = 0;
2373 if (!printHdaIsValid(pszType, "sdsts"))
2374 return cb;
2375 cb += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
2376 "SDSTS(raw: %#0x, fifordy:%s, dese:%s, fifoe:%s, bcis:%s)",
2377 sdSts,
2378 printHdaYesNo(RT_BOOL(sdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY))),
2379 printHdaYesNo(RT_BOOL(sdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))),
2380 printHdaYesNo(RT_BOOL(sdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))),
2381 printHdaYesNo(RT_BOOL(sdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS))));
2382 return cb;
2383}
2384/**
2385 * This routine registers debugger info extensions and custom printf formatters
2386 */
2387static inline int hdaInitMisc(PPDMDEVINS pDevIns)
2388{
2389 int rc;
2390 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaDbgInfo);
2391 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm", "HDA stream info. (hdastrm [stream number])", hdaDbgStreamInfo);
2392 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaCodecDbgNodes);
2393 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaCodecDbgSelector);
2394 rc = RTStrFormatTypeRegister("sdctl", printHdaStrmCtl, NULL);
2395 AssertRC(rc);
2396 rc = RTStrFormatTypeRegister("sdsts", printHdaStrmSts, NULL);
2397 AssertRC(rc);
2398 rc = RTStrFormatTypeRegister("sdfifos", printHdaStrmFifos, NULL);
2399 AssertRC(rc);
2400 rc = RTStrFormatTypeRegister("sdfifow", printHdaStrmFifow, NULL);
2401 AssertRC(rc);
2402#if 0
2403 rc = RTStrFormatTypeRegister("sdfmt", printHdaStrmFmt, NULL);
2404 AssertRC(rc);
2405#endif
2406 return rc;
2407}
2408
2409/**
2410 * @interface_method_impl{PDMDEVREG,pfnConstruct}
2411 */
2412static DECLCALLBACK(int) hdaConstruct (PPDMDEVINS pDevIns, int iInstance,
2413 PCFGMNODE pCfgHandle)
2414{
2415 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2416 INTELHDLinkState *s = &pThis->hda;
2417 int rc;
2418
2419 Assert(iInstance == 0);
2420 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
2421
2422 /*
2423 * Validations.
2424 */
2425 if (!CFGMR3AreValuesValid (pCfgHandle, "\0"))
2426 return PDMDEV_SET_ERROR (pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
2427 N_ ("Invalid configuration for the INTELHD device"));
2428
2429 // ** @todo r=michaln: This device may need R0/RC enabling, especially if guests
2430 // poll some register(s).
2431
2432 /*
2433 * Initialize data (most of it anyway).
2434 */
2435 s->pDevIns = pDevIns;
2436 /* IBase */
2437 s->IBase.pfnQueryInterface = hdaQueryInterface;
2438
2439 /* PCI Device (the assertions will be removed later) */
2440 PCIDevSetVendorId (&pThis->dev, HDA_PCI_VENDOR_ID); /* nVidia */
2441 PCIDevSetDeviceId (&pThis->dev, HDA_PCI_DEICE_ID); /* HDA */
2442
2443 PCIDevSetCommand (&pThis->dev, 0x0000); /* 04 rw,ro - pcicmd. */
2444 PCIDevSetStatus (&pThis->dev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
2445 PCIDevSetRevisionId (&pThis->dev, 0x01); /* 08 ro - rid. */
2446 PCIDevSetClassProg (&pThis->dev, 0x00); /* 09 ro - pi. */
2447 PCIDevSetClassSub (&pThis->dev, 0x03); /* 0a ro - scc; 03 == HDA. */
2448 PCIDevSetClassBase (&pThis->dev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
2449 PCIDevSetHeaderType (&pThis->dev, 0x00); /* 0e ro - headtyp. */
2450 PCIDevSetBaseAddress (&pThis->dev, 0, /* 10 rw - MMIO */
2451 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
2452 PCIDevSetInterruptLine (&pThis->dev, 0x00); /* 3c rw. */
2453 PCIDevSetInterruptPin (&pThis->dev, 0x01); /* 3d ro - INTA#. */
2454
2455#if defined(HDA_AS_PCI_EXPRESS)
2456 PCIDevSetCapabilityList (&pThis->dev, 0x80);
2457#elif defined(VBOX_WITH_MSI_DEVICES)
2458 PCIDevSetCapabilityList (&pThis->dev, 0x60);
2459#else
2460 PCIDevSetCapabilityList (&pThis->dev, 0x50); /* ICH6 datasheet 18.1.16 */
2461#endif
2462
2463 /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
2464 // of these values needs to be properly documented!
2465 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
2466 PCIDevSetByte(&pThis->dev, 0x40, 0x01);
2467
2468 /* Power Management */
2469 PCIDevSetByte(&pThis->dev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
2470 PCIDevSetByte(&pThis->dev, 0x50 + 1, 0x0); /* next */
2471 PCIDevSetWord(&pThis->dev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
2472
2473#ifdef HDA_AS_PCI_EXPRESS
2474 /* PCI Express */
2475 PCIDevSetByte (&pThis->dev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
2476 PCIDevSetByte (&pThis->dev, 0x80 + 1, 0x60); /* next */
2477 /* Device flags */
2478 PCIDevSetWord (&pThis->dev, 0x80 + 2,
2479 /* version */ 0x1 |
2480 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
2481 /* MSI */ (100) << 9
2482 );
2483 /* Device capabilities */
2484 PCIDevSetDWord (&pThis->dev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
2485 /* Device control */
2486 PCIDevSetWord (&pThis->dev, 0x80 + 8, 0);
2487 /* Device status */
2488 PCIDevSetWord (&pThis->dev, 0x80 + 10, 0);
2489 /* Link caps */
2490 PCIDevSetDWord (&pThis->dev, 0x80 + 12, 0);
2491 /* Link control */
2492 PCIDevSetWord (&pThis->dev, 0x80 + 16, 0);
2493 /* Link status */
2494 PCIDevSetWord (&pThis->dev, 0x80 + 18, 0);
2495 /* Slot capabilities */
2496 PCIDevSetDWord (&pThis->dev, 0x80 + 20, 0);
2497 /* Slot control */
2498 PCIDevSetWord (&pThis->dev, 0x80 + 24, 0);
2499 /* Slot status */
2500 PCIDevSetWord (&pThis->dev, 0x80 + 26, 0);
2501 /* Root control */
2502 PCIDevSetWord (&pThis->dev, 0x80 + 28, 0);
2503 /* Root capabilities */
2504 PCIDevSetWord (&pThis->dev, 0x80 + 30, 0);
2505 /* Root status */
2506 PCIDevSetDWord (&pThis->dev, 0x80 + 32, 0);
2507 /* Device capabilities 2 */
2508 PCIDevSetDWord (&pThis->dev, 0x80 + 36, 0);
2509 /* Device control 2 */
2510 PCIDevSetQWord (&pThis->dev, 0x80 + 40, 0);
2511 /* Link control 2 */
2512 PCIDevSetQWord (&pThis->dev, 0x80 + 48, 0);
2513 /* Slot control 2 */
2514 PCIDevSetWord (&pThis->dev, 0x80 + 56, 0);
2515#endif
2516
2517 /*
2518 * Register the PCI device.
2519 */
2520 rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
2521 if (RT_FAILURE (rc))
2522 return rc;
2523
2524 rc = PDMDevHlpPCIIORegionRegister (pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM,
2525 hdaMap);
2526 if (RT_FAILURE (rc))
2527 return rc;
2528
2529#ifdef VBOX_WITH_MSI_DEVICES
2530 PDMMSIREG aMsiReg;
2531
2532 RT_ZERO(aMsiReg);
2533 aMsiReg.cMsiVectors = 1;
2534 aMsiReg.iMsiCapOffset = 0x60;
2535 aMsiReg.iMsiNextOffset = 0x50;
2536 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg);
2537 if (RT_FAILURE (rc))
2538 {
2539 LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
2540 PCIDevSetCapabilityList (&pThis->dev, 0x50);
2541 }
2542#endif
2543
2544 rc = PDMDevHlpSSMRegister (pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
2545 if (RT_FAILURE (rc))
2546 return rc;
2547
2548 /*
2549 * Attach driver.
2550 */
2551 rc = PDMDevHlpDriverAttach (pDevIns, 0, &s->IBase,
2552 &s->pDrvBase, "Audio Driver Port");
2553 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2554 Log (("hda: No attached driver!\n"));
2555 else if (RT_FAILURE (rc))
2556 {
2557 AssertMsgFailed (("Failed to attach INTELHD LUN #0! rc=%Rrc\n", rc));
2558 return rc;
2559 }
2560
2561
2562
2563 pThis->hda.Codec.pHDAState = (void *)&pThis->hda;
2564 rc = codecConstruct(pDevIns, &pThis->hda.Codec, pCfgHandle);
2565 if (RT_FAILURE(rc))
2566 AssertRCReturn(rc, rc);
2567
2568 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
2569 verb F20 should provide device/codec recognition. */
2570 Assert(pThis->hda.Codec.u16VendorId);
2571 Assert(pThis->hda.Codec.u16DeviceId);
2572 PCIDevSetSubSystemVendorId (&pThis->dev, pThis->hda.Codec.u16VendorId); /* 2c ro - intel.) */
2573 PCIDevSetSubSystemId (&pThis->dev, pThis->hda.Codec.u16DeviceId); /* 2e ro. */
2574
2575 hdaReset (pDevIns);
2576 pThis->hda.Codec.id = 0;
2577 pThis->hda.Codec.pfnTransfer = hdaTransfer;
2578 pThis->hda.Codec.pfnReset = hdaCodecReset;
2579 /*
2580 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
2581 * hdaReset shouldn't affects these registers.
2582 */
2583 WAKEEN(&pThis->hda) = 0x0;
2584 STATESTS(&pThis->hda) = 0x0;
2585 hdaInitMisc(pDevIns);
2586
2587 return VINF_SUCCESS;
2588}
2589
2590/**
2591 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2592 */
2593static DECLCALLBACK(int) hdaDestruct (PPDMDEVINS pDevIns)
2594{
2595 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2596
2597 int rc = codecDestruct(&pThis->hda.Codec);
2598 AssertRC(rc);
2599 if (pThis->hda.pu32CorbBuf)
2600 RTMemFree(pThis->hda.pu32CorbBuf);
2601 if (pThis->hda.pu64RirbBuf)
2602 RTMemFree(pThis->hda.pu64RirbBuf);
2603 return VINF_SUCCESS;
2604}
2605
2606/**
2607 * The device registration structure.
2608 */
2609const PDMDEVREG g_DeviceICH6_HDA =
2610{
2611 /* u32Version */
2612 PDM_DEVREG_VERSION,
2613 /* szName */
2614 "hda",
2615 /* szRCMod */
2616 "",
2617 /* szR0Mod */
2618 "",
2619 /* pszDescription */
2620 "ICH IntelHD Audio Controller",
2621 /* fFlags */
2622 PDM_DEVREG_FLAGS_DEFAULT_BITS,
2623 /* fClass */
2624 PDM_DEVREG_CLASS_AUDIO,
2625 /* cMaxInstances */
2626 1,
2627 /* cbInstance */
2628 sizeof(PCIINTELHDLinkState),
2629 /* pfnConstruct */
2630 hdaConstruct,
2631 /* pfnDestruct */
2632 hdaDestruct,
2633 /* pfnRelocate */
2634 NULL,
2635 /* pfnIOCtl */
2636 NULL,
2637 /* pfnPowerOn */
2638 NULL,
2639 /* pfnReset */
2640 hdaReset,
2641 /* pfnSuspend */
2642 NULL,
2643 /* pfnResume */
2644 NULL,
2645 /* pfnAttach */
2646 NULL,
2647 /* pfnDetach */
2648 NULL,
2649 /* pfnQueryInterface. */
2650 NULL,
2651 /* pfnInitComplete */
2652 NULL,
2653 /* pfnPowerOff */
2654 NULL,
2655 /* pfnSoftReset */
2656 NULL,
2657 /* u32VersionEnd */
2658 PDM_DEVREG_VERSION
2659};
Note: See TracBrowser for help on using the repository browser.

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