VirtualBox

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

Last change on this file since 34226 was 34226, checked in by vboxsync, 14 years ago

Audio/HDA: removed unused flag.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 94.1 KB
Line 
1/* $Id: DevIchIntelHDA.cpp 34226 2010-11-22 03:41:53Z 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/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
29#include "../Builtins.h"
30
31extern "C" {
32#include "audio.h"
33}
34#include "DevCodec.h"
35
36#undef LOG_VOICES
37#ifndef VBOX
38//#define USE_MIXER
39#else
40#define USE_MIXER
41#endif
42#define VBOX_WITH_INTEL_HDA
43
44#define HDA_SSM_VERSION 1
45PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
46PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
47static DECLCALLBACK(void) hdaReset (PPDMDEVINS pDevIns);
48
49/* Registers */
50#define HDA_REG_IND_NAME(x) ICH6_HDA_REG_##x
51#define HDA_REG_FIELD_NAME(reg, x) ICH6_HDA_##reg##_##x
52#define HDA_REG_FIELD_MASK(reg, x) ICH6_HDA_##reg##_##x##_MASK
53#define HDA_REG_FIELD_FLAG_MASK(reg, x) RT_BIT(ICH6_HDA_##reg##_##x##_SHIFT)
54#define HDA_REG_FIELD_SHIFT(reg, x) ICH6_HDA_##reg##_##x##_SHIFT
55#define HDA_REG_IND(pState, x) ((pState)->au32Regs[(x)])
56#define HDA_REG(pState, x) (HDA_REG_IND((pState), HDA_REG_IND_NAME(x)))
57#define HDA_REG_VALUE(pState, reg, val) (HDA_REG((pState),reg) & (((HDA_REG_FIELD_MASK(reg, val))) << (HDA_REG_FIELD_SHIFT(reg, val))))
58#define HDA_REG_FLAG_VALUE(pState, reg, val) (HDA_REG((pState),reg) & (((HDA_REG_FIELD_FLAG_MASK(reg, val)))))
59#define HDA_REG_SVALUE(pState, reg, val) (HDA_REG_VALUE(pState, reg, val) >> (HDA_REG_FIELD_SHIFT(reg, val)))
60
61#define ICH6_HDA_REG_GCAP 0 /* range 0x00-0x01*/
62#define GCAP(pState) (HDA_REG((pState), GCAP))
63
64#define ICH6_HDA_REG_VMIN 1 /* range 0x02 */
65#define VMIN(pState) (HDA_REG((pState), VMIN))
66
67#define ICH6_HDA_REG_VMAJ 2 /* range 0x03 */
68#define VMAJ(pState) (HDA_REG((pState), VMAJ))
69
70#define ICH6_HDA_REG_OUTPAY 3 /* range 0x04-0x05 */
71#define OUTPAY(pState) (HDA_REG((pState), OUTPAY))
72
73#define ICH6_HDA_REG_INPAY 4 /* range 0x06-0x07 */
74#define INPAY(pState) (HDA_REG((pState), INPAY))
75
76#define ICH6_HDA_REG_GCTL (5)
77#define ICH6_HDA_GCTL_RST_SHIFT (0)
78#define ICH6_HDA_GCTL_FSH_SHIFT (1)
79#define ICH6_HDA_GCTL_UR_SHIFT (8)
80#define GCTL(pState) (HDA_REG((pState), GCTL))
81
82#define ICH6_HDA_REG_WAKEEN 6 /* 0x0C */
83#define WAKEEN(pState) (HDA_REG((pState), WAKEEN))
84
85#define ICH6_HDA_REG_STATESTS 7 /* range 0x0E */
86#define STATESTS(pState) (HDA_REG((pState), STATESTS))
87#define ICH6_HDA_STATES_SCSF 0x7
88
89#define ICH6_HDA_REG_GSTS 8 /* range 0x10-0x11*/
90#define ICH6_HDA_GSTS_FSH_SHIFT (1)
91#define GSTS(pState) (HDA_REG(pState, GSTS))
92
93#define ICH6_HDA_REG_INTCTL 9 /* 0x20 */
94#define ICH6_HDA_INTCTL_GIE_SHIFT 31
95#define ICH6_HDA_INTCTL_CIE_SHIFT 30
96#define ICH6_HDA_INTCTL_S0_SHIFT (0)
97#define ICH6_HDA_INTCTL_S1_SHIFT (1)
98#define ICH6_HDA_INTCTL_S2_SHIFT (2)
99#define ICH6_HDA_INTCTL_S3_SHIFT (3)
100#define ICH6_HDA_INTCTL_S4_SHIFT (4)
101#define ICH6_HDA_INTCTL_S5_SHIFT (5)
102#define ICH6_HDA_INTCTL_S6_SHIFT (6)
103#define ICH6_HDA_INTCTL_S7_SHIFT (7)
104#define INTCTL(pState) (HDA_REG((pState), INTCTL))
105#define INTCTL_GIE(pState) (HDA_REG_FLAG_VALUE(pState, INTCTL, GIE))
106#define INTCTL_CIE(pState) (HDA_REG_FLAG_VALUE(pState, INTCTL, CIE))
107#define INTCTL_SX(pState, X) (HDA_REG_FLAG_VALUE((pState), INTCTL, S##X))
108#define INTCTL_SALL(pState) (INTCTL((pState)) & 0xFF)
109
110/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
111 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
112 * the datasheet.
113 */
114#define ICH6_HDA_REG_SSYNC 12 /* 0x34 */
115#define SSYNC(pState) (HDA_REG((pState), SSYNC))
116
117#define ICH6_HDA_REG_INTSTS 10 /* 0x24 */
118#define ICH6_HDA_INTSTS_GIS_SHIFT (31)
119#define ICH6_HDA_INTSTS_CIS_SHIFT (30)
120#define ICH6_HDA_INTSTS_S0_SHIFT (0)
121#define ICH6_HDA_INTSTS_S1_SHIFT (1)
122#define ICH6_HDA_INTSTS_S2_SHIFT (2)
123#define ICH6_HDA_INTSTS_S3_SHIFT (3)
124#define ICH6_HDA_INTSTS_S4_SHIFT (4)
125#define ICH6_HDA_INTSTS_S5_SHIFT (5)
126#define ICH6_HDA_INTSTS_S6_SHIFT (6)
127#define ICH6_HDA_INTSTS_S7_SHIFT (7)
128#define ICH6_HDA_INTSTS_S_MASK(num) RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
129#define INTSTS(pState) (HDA_REG((pState), INTSTS))
130#define INTSTS_GIS(pState) (HDA_REG_FLAG_VALUE((pState), INTSTS, GIS)
131#define INTSTS_CIS(pState) (HDA_REG_FLAG_VALUE((pState), INTSTS, CIS)
132#define INTSTS_SX(pState, X) (HDA_REG_FLAG_VALUE(pState), INTSTS, S##X)
133#define INTSTS_SANY(pState) (INTSTS((pState)) & 0xFF)
134
135#define ICH6_HDA_REG_CORBLBASE 13 /* 0x40 */
136#define CORBLBASE(pState) (HDA_REG((pState), CORBLBASE))
137#define ICH6_HDA_REG_CORBUBASE 14 /* 0x44 */
138#define CORBUBASE(pState) (HDA_REG((pState), CORBUBASE))
139#define ICH6_HDA_REG_CORBWP 15 /* 48 */
140#define ICH6_HDA_REG_CORBRP 16 /* 4A */
141#define ICH6_HDA_CORBRP_RST_SHIFT 15
142#define ICH6_HDA_CORBRP_WP_SHIFT 0
143#define ICH6_HDA_CORBRP_WP_MASK 0xFF
144
145#define CORBRP(pState) (HDA_REG(pState, CORBRP))
146#define CORBWP(pState) (HDA_REG(pState, CORBWP))
147
148#define ICH6_HDA_REG_CORBCTL 17 /* 0x4C */
149#define ICH6_HDA_CORBCTL_DMA_SHIFT (1)
150#define ICH6_HDA_CORBCTL_CMEIE_SHIFT (0)
151
152#define CORBCTL(pState) (HDA_REG(pState, CORBCTL))
153
154
155#define ICH6_HDA_REG_CORBSTS 18 /* 0x4D */
156#define CORBSTS(pState) (HDA_REG(pState, CORBSTS))
157#define ICH6_HDA_CORBSTS_CMEI_SHIFT (0)
158
159#define ICH6_HDA_REG_CORBSIZE 19 /* 0x4E */
160#define ICH6_HDA_CORBSIZE_SZ_CAP 0xF0
161#define ICH6_HDA_CORBSIZE_SZ 0x3
162#define CORBSIZE_SZ(pState) (HDA_REG(pState, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ)
163#define CORBSIZE_SZ_CAP(pState) (HDA_REG(pState, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ_CAP)
164/* till ich 10 sizes of CORB and RIRB are hardcoded to 256 in real hw */
165
166#define ICH6_HDA_REG_RIRLBASE 20 /* 0x50 */
167#define RIRLBASE(pState) (HDA_REG((pState), RIRLBASE))
168
169#define ICH6_HDA_REG_RIRUBASE 21 /* 0x54 */
170#define RIRUBASE(pState) (HDA_REG((pState), RIRUBASE))
171
172#define ICH6_HDA_REG_RIRBWP 22 /* 0x58 */
173#define ICH6_HDA_RIRBWP_RST_SHIFT (15)
174#define ICH6_HDA_RIRBWP_WP_MASK 0xFF
175#define RIRBWP(pState) (HDA_REG(pState, RIRBWP))
176
177#define ICH6_HDA_REG_RINTCNT 23 /* 0x5A */
178#define RINTCNT(pState) (HDA_REG((pState), RINTCNT))
179#define RINTCNT_N(pState) (RINTCNT((pState)) & 0xff)
180
181#define ICH6_HDA_REG_RIRBCTL 24 /* 0x5C */
182#define ICH6_HDA_RIRBCTL_RIC_SHIFT (0)
183#define ICH6_HDA_RIRBCTL_DMA_SHIFT (1)
184#define ICH6_HDA_ROI_DMA_SHIFT (2)
185#define RIRBCTL(pState) (HDA_REG((pState), RIRBCTL))
186#define RIRBCTL_RIRB_RIC(pState) (HDA_REG_FLAG_VALUE(pState, RIRBCTL, RIC))
187#define RIRBCTL_RIRB_DMA(pState) (HDA_REG_FLAG_VALUE((pState), RIRBCTL, DMA)
188#define RIRBCTL_ROI(pState) (HDA_REG_FLAG_VALUE((pState), RIRBCTL, ROI))
189
190#define ICH6_HDA_REG_RIRBSTS 25 /* 0x5D */
191#define ICH6_HDA_RIRBSTS_RINTFL_SHIFT (0)
192#define ICH6_HDA_RIRBSTS_RIRBOIS_SHIFT (2)
193#define RIRBSTS(pState) (HDA_REG(pState, RIRBSTS))
194#define RIRBSTS_RINTFL(pState) (HDA_REG_FLAG_VALUE(pState, RIRBSTS, RINTFL))
195#define RIRBSTS_RIRBOIS(pState) (HDA_REG_FLAG_VALUE(pState, RIRBSTS, RIRBOIS))
196
197#define ICH6_HDA_REG_RIRBSIZE 26 /* 0x5E */
198#define ICH6_HDA_RIRBSIZE_SZ_CAP 0xF0
199#define ICH6_HDA_RIRBSIZE_SZ 0x3
200
201#define RIRBSIZE_SZ(pState) (HDA_REG(pState, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ)
202#define RIRBSIZE_SZ_CAP(pState) (HDA_REG(pState, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ_CAP)
203
204
205#define ICH6_HDA_REG_IC 27 /* 0x60 */
206#define IC(pState) (HDA_REG(pState, IC))
207#define ICH6_HDA_REG_IR 28 /* 0x64 */
208#define IR(pState) (HDA_REG(pState, IR))
209#define ICH6_HDA_REG_IRS 29 /* 0x68 */
210#define ICH6_HDA_IRS_ICB_SHIFT (0)
211#define ICH6_HDA_IRS_IRV_SHIFT (1)
212#define IRS(pState) (HDA_REG(pState, IRS))
213#define IRS_ICB(pState) (HDA_REG_FLAG_VALUE(pState, IRS, ICB))
214#define IRS_IRV(pState) (HDA_REG_FLAG_VALUE(pState, IRS, IRV))
215
216#define ICH6_HDA_REG_DPLBASE 30 /* 0x70 */
217#define DPLBASE(pState) (HDA_REG((pState), DPLBASE))
218#define ICH6_HDA_REG_DPUBASE 31 /* 0x74 */
219#define DPUBASE(pState) (HDA_REG((pState), DPUBASE))
220#define DPBASE_ENABLED 1
221#define DPBASE_ADDR_MASK (~0x7f)
222
223#define HDA_STREAM_REG_DEF(name, num) (ICH6_HDA_REG_SD##num##name)
224#define HDA_STREAM_REG(pState, name, num) (HDA_REG((pState), N_(HDA_STREAM_REG_DEF(name, num))))
225
226#define ICH6_HDA_REG_SD0CTL 32 /* 0x80 */
227#define ICH6_HDA_REG_SD1CTL (HDA_STREAM_REG_DEF(CTL, 0) + 10) /* 0xA0 */
228#define ICH6_HDA_REG_SD2CTL (HDA_STREAM_REG_DEF(CTL, 0) + 20) /* 0xC0 */
229#define ICH6_HDA_REG_SD3CTL (HDA_STREAM_REG_DEF(CTL, 0) + 30) /* 0xE0 */
230#define ICH6_HDA_REG_SD4CTL (HDA_STREAM_REG_DEF(CTL, 0) + 40) /* 0x100 */
231#define ICH6_HDA_REG_SD5CTL (HDA_STREAM_REG_DEF(CTL, 0) + 50) /* 0x120 */
232#define ICH6_HDA_REG_SD6CTL (HDA_STREAM_REG_DEF(CTL, 0) + 60) /* 0x140 */
233#define ICH6_HDA_REG_SD7CTL (HDA_STREAM_REG_DEF(CTL, 0) + 70) /* 0x160 */
234
235#define SD(func, num) SD##num##func
236#define SDCTL(pState, num) HDA_REG((pState), SD(CTL, num))
237#define SDCTL_NUM(pState, num) ((SDCTL((pState), num) & HDA_REG_FIELD_MASK(SDCTL,NUM)) >> HDA_REG_FIELD_SHIFT(SDCTL, NUM))
238#define ICH6_HDA_SDCTL_NUM_MASK (0xF)
239#define ICH6_HDA_SDCTL_NUM_SHIFT (20)
240#define ICH6_HDA_SDCTL_DEIE_SHIFT (4)
241#define ICH6_HDA_SDCTL_FEIE_SHIFT (3)
242#define ICH6_HDA_SDCTL_ICE_SHIFT (2)
243#define ICH6_HDA_SDCTL_RUN_SHIFT (1)
244#define ICH6_HDA_SDCTL_SRST_SHIFT (0)
245
246#define ICH6_HDA_REG_SD0STS 33 /* 0x83 */
247#define ICH6_HDA_REG_SD1STS (HDA_STREAM_REG_DEF(STS, 0) + 10) /* 0xA3 */
248#define ICH6_HDA_REG_SD2STS (HDA_STREAM_REG_DEF(STS, 0) + 20) /* 0xC3 */
249#define ICH6_HDA_REG_SD3STS (HDA_STREAM_REG_DEF(STS, 0) + 30) /* 0xE3 */
250#define ICH6_HDA_REG_SD4STS (HDA_STREAM_REG_DEF(STS, 0) + 40) /* 0x103 */
251#define ICH6_HDA_REG_SD5STS (HDA_STREAM_REG_DEF(STS, 0) + 50) /* 0x123 */
252#define ICH6_HDA_REG_SD6STS (HDA_STREAM_REG_DEF(STS, 0) + 60) /* 0x143 */
253#define ICH6_HDA_REG_SD7STS (HDA_STREAM_REG_DEF(STS, 0) + 70) /* 0x163 */
254
255#define SDSTS(pState, num) HDA_REG((pState), SD(STS, num))
256#define ICH6_HDA_SDSTS_FIFORDY_SHIFT (5)
257#define ICH6_HDA_SDSTS_DE_SHIFT (4)
258#define ICH6_HDA_SDSTS_FE_SHIFT (3)
259#define ICH6_HDA_SDSTS_BCIS_SHIFT (2)
260
261#define ICH6_HDA_REG_SD0LPIB 34 /* 0x84 */
262#define ICH6_HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
263#define ICH6_HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
264#define ICH6_HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
265#define ICH6_HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
266#define ICH6_HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
267#define ICH6_HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
268#define ICH6_HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
269
270#define SDLPIB(pState, num) HDA_REG((pState), SD(LPIB, num))
271
272#define ICH6_HDA_REG_SD0CBL 35 /* 0x88 */
273#define ICH6_HDA_REG_SD1CBL (HDA_STREAM_REG_DEF(CBL, 0) + 10) /* 0xA8 */
274#define ICH6_HDA_REG_SD2CBL (HDA_STREAM_REG_DEF(CBL, 0) + 20) /* 0xC8 */
275#define ICH6_HDA_REG_SD3CBL (HDA_STREAM_REG_DEF(CBL, 0) + 30) /* 0xE8 */
276#define ICH6_HDA_REG_SD4CBL (HDA_STREAM_REG_DEF(CBL, 0) + 40) /* 0x108 */
277#define ICH6_HDA_REG_SD5CBL (HDA_STREAM_REG_DEF(CBL, 0) + 50) /* 0x128 */
278#define ICH6_HDA_REG_SD6CBL (HDA_STREAM_REG_DEF(CBL, 0) + 60) /* 0x148 */
279#define ICH6_HDA_REG_SD7CBL (HDA_STREAM_REG_DEF(CBL, 0) + 70) /* 0x168 */
280
281#define SDLCBL(pState, num) HDA_REG((pState), SD(CBL, num))
282
283#define ICH6_HDA_REG_SD0LVI 36 /* 0x8C */
284#define ICH6_HDA_REG_SD1LVI (HDA_STREAM_REG_DEF(LVI, 0) + 10) /* 0xAC */
285#define ICH6_HDA_REG_SD2LVI (HDA_STREAM_REG_DEF(LVI, 0) + 20) /* 0xCC */
286#define ICH6_HDA_REG_SD3LVI (HDA_STREAM_REG_DEF(LVI, 0) + 30) /* 0xEC */
287#define ICH6_HDA_REG_SD4LVI (HDA_STREAM_REG_DEF(LVI, 0) + 40) /* 0x10C */
288#define ICH6_HDA_REG_SD5LVI (HDA_STREAM_REG_DEF(LVI, 0) + 50) /* 0x12C */
289#define ICH6_HDA_REG_SD6LVI (HDA_STREAM_REG_DEF(LVI, 0) + 60) /* 0x14C */
290#define ICH6_HDA_REG_SD7LVI (HDA_STREAM_REG_DEF(LVI, 0) + 70) /* 0x16C */
291
292#define SDLVI(pState, num) HDA_REG((pState), SD(LVI, num))
293
294#define ICH6_HDA_REG_SD0FIFOW 37 /* 0x8E */
295#define ICH6_HDA_REG_SD1FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 10) /* 0xAE */
296#define ICH6_HDA_REG_SD2FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 20) /* 0xCE */
297#define ICH6_HDA_REG_SD3FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 30) /* 0xEE */
298#define ICH6_HDA_REG_SD4FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 40) /* 0x10E */
299#define ICH6_HDA_REG_SD5FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 50) /* 0x12E */
300#define ICH6_HDA_REG_SD6FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 60) /* 0x14E */
301#define ICH6_HDA_REG_SD7FIFOW (HDA_STREAM_REG_DEF(FIFOW, 0) + 70) /* 0x16E */
302
303/*
304 * ICH6 datasheet defined limits for FIFOW values (18.2.38)
305 */
306#define HDA_SDFIFOW_8B (0x2)
307#define HDA_SDFIFOW_16B (0x3)
308#define HDA_SDFIFOW_32B (0x4)
309#define SDFIFOW(pState, num) HDA_REG((pState), SD(FIFOW, num))
310
311#define ICH6_HDA_REG_SD0FIFOS 38 /* 0x90 */
312#define ICH6_HDA_REG_SD1FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 10) /* 0xB0 */
313#define ICH6_HDA_REG_SD2FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 20) /* 0xD0 */
314#define ICH6_HDA_REG_SD3FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 30) /* 0xF0 */
315#define ICH6_HDA_REG_SD4FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 40) /* 0x110 */
316#define ICH6_HDA_REG_SD5FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 50) /* 0x130 */
317#define ICH6_HDA_REG_SD6FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 60) /* 0x150 */
318#define ICH6_HDA_REG_SD7FIFOS (HDA_STREAM_REG_DEF(FIFOS, 0) + 70) /* 0x170 */
319
320/*
321 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
322 * formula: size - 1
323 * Other values not listed are not supported.
324 */
325#define HDA_SDONFIFO_16B (0xF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
326#define HDA_SDONFIFO_32B (0x1F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
327#define HDA_SDONFIFO_64B (0x3F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
328#define HDA_SDONFIFO_128B (0x7F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
329#define HDA_SDONFIFO_192B (0xBF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
330#define HDA_SDONFIFO_256B (0xFF) /* 20-, 24-bit Output Streams */
331#define HDA_SDINFIFO_120B (0x77) /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
332#define HDA_SDINFIFO_160B (0x9F) /* 20-, 24-bit Input Streams Streams */
333#define SDFIFOS(pState, num) HDA_REG((pState), SD(FIFOS, num))
334
335#define ICH6_HDA_REG_SD0FMT 39 /* 0x92 */
336#define ICH6_HDA_REG_SD1FMT (HDA_STREAM_REG_DEF(FMT, 0) + 10) /* 0xB2 */
337#define ICH6_HDA_REG_SD2FMT (HDA_STREAM_REG_DEF(FMT, 0) + 20) /* 0xD2 */
338#define ICH6_HDA_REG_SD3FMT (HDA_STREAM_REG_DEF(FMT, 0) + 30) /* 0xF2 */
339#define ICH6_HDA_REG_SD4FMT (HDA_STREAM_REG_DEF(FMT, 0) + 40) /* 0x112 */
340#define ICH6_HDA_REG_SD5FMT (HDA_STREAM_REG_DEF(FMT, 0) + 50) /* 0x132 */
341#define ICH6_HDA_REG_SD6FMT (HDA_STREAM_REG_DEF(FMT, 0) + 60) /* 0x152 */
342#define ICH6_HDA_REG_SD7FMT (HDA_STREAM_REG_DEF(FMT, 0) + 70) /* 0x172 */
343
344#define SDFMT(pState, num) (HDA_REG((pState), SD(FMT, num)))
345#define ICH6_HDA_SDFMT_BASE_RATE_SHIFT (14)
346#define ICH6_HDA_SDFMT_MULT_SHIFT (11)
347#define ICH6_HDA_SDFMT_MULT_MASK (0x7)
348#define ICH6_HDA_SDFMT_DIV_SHIFT (8)
349#define ICH6_HDA_SDFMT_DIV_MASK (0x7)
350#define SDFMT_BASE_RATE(pState, num) ((SDFMT(pState, num) & HDA_REG_FIELD_FLAG_MASK(SDFMT, BASE_RATE)) >> HDA_REG_FIELD_SHIFT(SDFMT, BASE_RATE))
351#define SDFMT_MULT(pState, num) ((SDFMT((pState), num) & HDA_REG_FIELD_MASK(SDFMT,MULT)) >> HDA_REG_FIELD_SHIFT(SDFMT, MULT))
352#define SDFMT_DIV(pState, num) ((SDFMT((pState), num) & HDA_REG_FIELD_MASK(SDFMT,DIV)) >> HDA_REG_FIELD_SHIFT(SDFMT, DIV))
353
354#define ICH6_HDA_REG_SD0BDPL 40 /* 0x98 */
355#define ICH6_HDA_REG_SD1BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 10) /* 0xB8 */
356#define ICH6_HDA_REG_SD2BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 20) /* 0xD8 */
357#define ICH6_HDA_REG_SD3BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 30) /* 0xF8 */
358#define ICH6_HDA_REG_SD4BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 40) /* 0x118 */
359#define ICH6_HDA_REG_SD5BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 50) /* 0x138 */
360#define ICH6_HDA_REG_SD6BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 60) /* 0x158 */
361#define ICH6_HDA_REG_SD7BDPL (HDA_STREAM_REG_DEF(BDPL, 0) + 70) /* 0x178 */
362
363#define SDBDPL(pState, num) HDA_REG((pState), SD(BDPL, num))
364
365#define ICH6_HDA_REG_SD0BDPU 41 /* 0x9C */
366#define ICH6_HDA_REG_SD1BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 10) /* 0xBC */
367#define ICH6_HDA_REG_SD2BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 20) /* 0xDC */
368#define ICH6_HDA_REG_SD3BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 30) /* 0xFC */
369#define ICH6_HDA_REG_SD4BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 40) /* 0x11C */
370#define ICH6_HDA_REG_SD5BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 50) /* 0x13C */
371#define ICH6_HDA_REG_SD6BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 60) /* 0x15C */
372#define ICH6_HDA_REG_SD7BDPU (HDA_STREAM_REG_DEF(BDPU, 0) + 70) /* 0x17C */
373
374#define SDBDPU(pState, num) HDA_REG((pState), SD(BDPU, num))
375
376/* Predicates */
377
378typedef struct HDABDLEDESC
379{
380 uint64_t u64BdleCviAddr;
381 uint32_t u32BdleMaxCvi;
382 uint32_t u32BdleCvi;
383 uint32_t u32BdleCviLen;
384 uint32_t u32BdleCviPos;
385 bool fBdleCviIoc;
386 uint32_t cbUnderFifoW;
387 uint8_t au8HdaBuffer[HDA_SDONFIFO_256B + 1];
388} HDABDLEDESC, *PHDABDLEDESC;
389
390typedef struct INTELHDLinkState
391{
392 /** Pointer to the device instance. */
393 PPDMDEVINSR3 pDevIns;
394 /** Pointer to the connector of the attached audio driver. */
395 PPDMIAUDIOCONNECTOR pDrv;
396 /** Pointer to the attached audio driver. */
397 PPDMIBASE pDrvBase;
398 /** The base interface for LUN\#0. */
399 PDMIBASE IBase;
400 RTGCPHYS addrMMReg;
401 uint32_t au32Regs[113];
402 HDABDLEDESC stInBdle;
403 HDABDLEDESC stOutBdle;
404 HDABDLEDESC stMicBdle;
405 /* Interrupt on completion */
406 bool fCviIoc;
407 uint64_t u64CORBBase;
408 uint64_t u64RIRBBase;
409 uint64_t u64DPBase;
410 /* pointer on CORB buf */
411 uint32_t *pu32CorbBuf;
412 /* size in bytes of CORB buf */
413 uint32_t cbCorbBuf;
414 /* pointer on RIRB buf */
415 uint64_t *pu64RirbBuf;
416 /* size in bytes of RIRB buf */
417 uint32_t cbRirbBuf;
418 /* indicates if HDA in reset. */
419 bool fInReset;
420 CODECState Codec;
421 uint8_t u8Counter;
422 uint8_t u8StreamsInReset;
423} INTELHDLinkState;
424
425#define ICH6_HDASTATE_2_DEVINS(pINTELHD) ((pINTELHD)->pDevIns)
426#define PCIDEV_2_ICH6_HDASTATE(pPciDev) ((PCIINTELHDLinkState *)(pPciDev))
427
428#define ISD0FMT_TO_AUDIO_SELECTOR(pState) (AUDIO_FORMAT_SELECTOR(&(pState)->Codec, In, \
429 SDFMT_BASE_RATE(pState, 0), SDFMT_MULT(pState, 0), SDFMT_DIV(pState, 0)))
430#define OSD0FMT_TO_AUDIO_SELECTOR(pState) (AUDIO_FORMAT_SELECTOR(&(pState)->Codec, Out, \
431 SDFMT_BASE_RATE(pState, 4), SDFMT_MULT(pState, 4), SDFMT_DIV(pState, 4)))
432
433
434
435
436typedef struct PCIINTELHDLinkState
437{
438 PCIDevice dev;
439 INTELHDLinkState hda;
440} PCIINTELHDLinkState;
441
442
443DECLCALLBACK(int)hdaRegReadUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
444DECLCALLBACK(int)hdaRegWriteUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
445DECLCALLBACK(int)hdaRegReadGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
446DECLCALLBACK(int)hdaRegWriteGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
447DECLCALLBACK(int)hdaRegReadSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
448DECLCALLBACK(int)hdaRegWriteSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
449DECLCALLBACK(int)hdaRegReadGCAP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
450DECLCALLBACK(int)hdaRegReadINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
451DECLCALLBACK(int)hdaRegWriteINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
452DECLCALLBACK(int)hdaRegWriteCORBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
453DECLCALLBACK(int)hdaRegWriteCORBRP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
454DECLCALLBACK(int)hdaRegWriteCORBCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
455DECLCALLBACK(int)hdaRegWriteCORBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
456DECLCALLBACK(int)hdaRegWriteRIRBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
457DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
458DECLCALLBACK(int)hdaRegWriteIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
459DECLCALLBACK(int)hdaRegReadIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
460DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
461DECLCALLBACK(int)hdaRegReadSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
462
463DECLCALLBACK(int)hdaRegWriteSDSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
464DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
465DECLCALLBACK(int)hdaRegWriteSDFIFOW(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
466DECLCALLBACK(int)hdaRegWriteSDFIFOS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
467DECLCALLBACK(int)hdaRegWriteSDBDPL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
468DECLCALLBACK(int)hdaRegWriteSDBDPU(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
469DECLCALLBACK(int)hdaRegWriteBase(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
470DECLCALLBACK(int)hdaRegReadU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
471DECLCALLBACK(int)hdaRegWriteU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
472DECLCALLBACK(int)hdaRegReadU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
473DECLCALLBACK(int)hdaRegWriteU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
474DECLCALLBACK(int)hdaRegReadU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
475DECLCALLBACK(int)hdaRegWriteU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
476DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
477DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
478static int hdaLookup(INTELHDLinkState* pState, uint32_t u32Offset);
479static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
480
481/* see 302349 p 6.2*/
482const static struct stIchIntelHDRegMap
483{
484 /** Register offset in the register space. */
485 uint32_t offset;
486 /** Size in bytes. Registers of size > 4 are in fact tables. */
487 uint32_t size;
488 /** Readable bits. */
489 uint32_t readable;
490 /** Writable bits. */
491 uint32_t writable;
492 /** Read callback. */
493 int (*pfnRead)(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
494 /** Write callback. */
495 int (*pfnWrite)(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value);
496 /** Abbreviated name. */
497 const char *abbrev;
498 /** Full name. */
499 const char *name;
500} s_ichIntelHDRegMap[] =
501{
502 /* offset size read mask write mask read callback write callback abbrev full name */
503 /*------- ------- ---------- ---------- ----------------------- ------------------------ ---------- ------------------------------*/
504 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, hdaRegReadGCAP , hdaRegWriteUnimplemented, "GCAP" , "Global Capabilities" },
505 { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "VMIN" , "Minor Version" },
506 { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "VMAJ" , "Major Version" },
507 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimplemented, "OUTPAY" , "Output Payload Capabilities" },
508 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16 , hdaRegWriteUnimplemented, "INPAY" , "Input Payload Capabilities" },
509 { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadGCTL , hdaRegWriteGCTL , "GCTL" , "Global Control" },
510 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, hdaRegReadU16 , hdaRegWriteU16 , "WAKEEN" , "Wake Enable" },
511 { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteSTATESTS , "STATESTS" , "State Change Status" },
512 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimplemented, hdaRegWriteUnimplemented, "GSTS" , "Global Status" },
513 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32 , hdaRegWriteU32 , "INTCTL" , "Interrupt Control" },
514 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS , hdaRegWriteUnimplemented, "INTSTS" , "Interrupt Status" },
515 //** @todo r=michaln: Are guests really not reading the WALCLK register at all?
516 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimplemented, hdaRegWriteUnimplemented, "WALCLK" , "Wall Clock Counter" },
517 //** @todo r=michaln: Doesn't the SSYNC register need to actually stop the stream(s)?
518 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32 , hdaRegWriteU32 , "SSYNC" , "Stream Synchronization" },
519 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , "CORBLBASE" , "CORB Lower Base Address" },
520 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "CORBUBASE" , "CORB Upper Base Address" },
521 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteCORBWP , "CORBWP" , "CORB Write Pointer" },
522 { 0x0004A, 0x00002, 0x000000FF, 0x000080FF, hdaRegReadU8 , hdaRegWriteCORBRP , "CORBRP" , "CORB Read Pointer" },
523 { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8 , hdaRegWriteCORBCTL , "CORBCTL" , "CORB Control" },
524 { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8 , hdaRegWriteCORBSTS , "CORBSTS" , "CORB Status" },
525 { 0x0004E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "CORBSIZE" , "CORB Size" },
526 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteBase , "RIRBLBASE" , "RIRB Lower Base Address" },
527 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "RIRBUBASE" , "RIRB Upper Base Address" },
528 { 0x00058, 0x00002, 0x000000FF, 0x00008000, hdaRegReadU8, hdaRegWriteRIRBWP , "RIRBWP" , "RIRB Write Pointer" },
529 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteU16 , "RINTCNT" , "Response Interrupt Count" },
530 { 0x0005C, 0x00001, 0x00000007, 0x00000007, hdaRegReadU8 , hdaRegWriteU8 , "RIRBCTL" , "RIRB Control" },
531 { 0x0005D, 0x00001, 0x00000005, 0x00000005, hdaRegReadU8 , hdaRegWriteRIRBSTS , "RIRBSTS" , "RIRB Status" },
532 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8 , hdaRegWriteUnimplemented, "RIRBSIZE" , "RIRB Size" },
533 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "IC" , "Immediate Command" },
534 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteUnimplemented, "IR" , "Immediate Response" },
535 { 0x00068, 0x00004, 0x00000002, 0x00000002, hdaRegReadIRS , hdaRegWriteIRS , "IRS" , "Immediate Command Status" },
536 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32 , hdaRegWriteBase , "DPLBASE" , "DMA Position Lower Base" },
537 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteBase , "DPUBASE" , "DMA Position Upper Base" },
538
539 { 0x00080, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD0CTL" , "Input Stream Descriptor 0 (ICD0) Control" },
540 { 0x00083, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD0STS" , "ISD0 Status" },
541 { 0x00084, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD0LPIB" , "ISD0 Link Position In Buffer" },
542 { 0x00088, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD0CBL" , "ISD0 Cyclic Buffer Length" },
543 { 0x0008C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD0LVI" , "ISD0 Last Valid Index" },
544 { 0x0008E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD0FIFOW", "ISD0 FIFO Watermark" },
545 { 0x00090, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD0FIFOS", "ISD0 FIFO Size" },
546 { 0x00092, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "ISD0FMT" , "ISD0 Format" },
547 { 0x00098, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD0BDPL" , "ISD0 Buffer Descriptor List Pointer-Lower Base Address" },
548 { 0x0009C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD0BDPU" , "ISD0 Buffer Descriptor List Pointer-Upper Base Address" },
549
550 { 0x000A0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD1CTL" , "Input Stream Descriptor 1 (ISD1) Control" },
551 { 0x000A3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD1STS" , "ISD1 Status" },
552 { 0x000A4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD1LPIB" , "ISD1 Link Position In Buffer" },
553 { 0x000A8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD1CBL" , "ISD1 Cyclic Buffer Length" },
554 { 0x000AC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD1LVI" , "ISD1 Last Valid Index" },
555 { 0x000AE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD1FIFOW", "ISD1 FIFO Watermark" },
556 { 0x000B0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD1FIFOS", "ISD1 FIFO Size" },
557 { 0x000B2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "ISD1FMT" , "ISD1 Format" },
558 { 0x000B8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD1BDPL" , "ISD1 Buffer Descriptor List Pointer-Lower Base Address" },
559 { 0x000BC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD1BDPU" , "ISD1 Buffer Descriptor List Pointer-Upper Base Address" },
560
561 { 0x000C0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD2CTL" , "Input Stream Descriptor 2 (ISD2) Control" },
562 { 0x000C3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD2STS" , "ISD2 Status" },
563 { 0x000C4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD2LPIB" , "ISD2 Link Position In Buffer" },
564 { 0x000C8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD2CBL" , "ISD2 Cyclic Buffer Length" },
565 { 0x000CC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD2LVI" , "ISD2 Last Valid Index" },
566 { 0x000CE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "ISD2FIFOW", "ISD2 FIFO Watermark" },
567 { 0x000D0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD2FIFOS", "ISD2 FIFO Size" },
568 { 0x000D2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "ISD2FMT" , "ISD2 Format" },
569 { 0x000D8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD2BDPL" , "ISD2 Buffer Descriptor List Pointer-Lower Base Address" },
570 { 0x000DC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD2BDPU" , "ISD2 Buffer Descriptor List Pointer-Upper Base Address" },
571
572 { 0x000E0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "ISD3CTL" , "Input Stream Descriptor 3 (ISD3) Control" },
573 { 0x000E3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "ISD3STS" , "ISD3 Status" },
574 { 0x000E4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "ISD3LPIB" , "ISD3 Link Position In Buffer" },
575 { 0x000E8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "ISD3CBL" , "ISD3 Cyclic Buffer Length" },
576 { 0x000EC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "ISD3LVI" , "ISD3 Last Valid Index" },
577 { 0x000EE, 0x00002, 0x00000005, 0x00000005, hdaRegReadU16 , hdaRegWriteU16 , "ISD3FIFOW", "ISD3 FIFO Watermark" },
578 { 0x000F0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16 , hdaRegWriteU16 , "ISD3FIFOS", "ISD3 FIFO Size" },
579 { 0x000F2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "ISD3FMT" , "ISD3 Format" },
580 { 0x000F8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "ISD3BDPL" , "ISD3 Buffer Descriptor List Pointer-Lower Base Address" },
581 { 0x000FC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "ISD3BDPU" , "ISD3 Buffer Descriptor List Pointer-Upper Base Address" },
582
583 { 0x00100, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadSDCTL , hdaRegWriteSDCTL , "OSD0CTL" , "Input Stream Descriptor 0 (OSD0) Control" },
584 { 0x00103, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD0STS" , "OSD0 Status" },
585 { 0x00104, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD0LPIB" , "OSD0 Link Position In Buffer" },
586 { 0x00108, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD0CBL" , "OSD0 Cyclic Buffer Length" },
587 { 0x0010C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD0LVI" , "OSD0 Last Valid Index" },
588 { 0x0010E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD0FIFOW", "OSD0 FIFO Watermark" },
589 { 0x00110, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD0FIFOS", "OSD0 FIFO Size" },
590 { 0x00112, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "OSD0FMT" , "OSD0 Format" },
591 { 0x00118, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD0BDPL" , "OSD0 Buffer Descriptor List Pointer-Lower Base Address" },
592 { 0x0011C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD0BDPU" , "OSD0 Buffer Descriptor List Pointer-Upper Base Address" },
593
594 { 0x00120, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD1CTL" , "Input Stream Descriptor 0 (OSD1) Control" },
595 { 0x00123, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD1STS" , "OSD1 Status" },
596 { 0x00124, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD1LPIB" , "OSD1 Link Position In Buffer" },
597 { 0x00128, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD1CBL" , "OSD1 Cyclic Buffer Length" },
598 { 0x0012C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD1LVI" , "OSD1 Last Valid Index" },
599 { 0x0012E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD1FIFOW", "OSD1 FIFO Watermark" },
600 { 0x00130, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD1FIFOS", "OSD1 FIFO Size" },
601 { 0x00132, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "OSD1FMT" , "OSD1 Format" },
602 { 0x00138, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD1BDPL" , "OSD1 Buffer Descriptor List Pointer-Lower Base Address" },
603 { 0x0013C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD1BDPU" , "OSD1 Buffer Descriptor List Pointer-Upper Base Address" },
604
605 { 0x00140, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD2CTL" , "Input Stream Descriptor 0 (OSD2) Control" },
606 { 0x00143, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD2STS" , "OSD2 Status" },
607 { 0x00144, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD2LPIB" , "OSD2 Link Position In Buffer" },
608 { 0x00148, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD2CBL" , "OSD2 Cyclic Buffer Length" },
609 { 0x0014C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD2LVI" , "OSD2 Last Valid Index" },
610 { 0x0014E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD2FIFOW", "OSD2 FIFO Watermark" },
611 { 0x00150, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD2FIFOS", "OSD2 FIFO Size" },
612 { 0x00152, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "OSD2FMT" , "OSD2 Format" },
613 { 0x00158, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD2BDPL" , "OSD2 Buffer Descriptor List Pointer-Lower Base Address" },
614 { 0x0015C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD2BDPU" , "OSD2 Buffer Descriptor List Pointer-Upper Base Address" },
615
616 { 0x00160, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24 , hdaRegWriteSDCTL , "OSD3CTL" , "Input Stream Descriptor 0 (OSD3) Control" },
617 { 0x00163, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8 , hdaRegWriteSDSTS , "OSD3STS" , "OSD3 Status" },
618 { 0x00164, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32 , hdaRegWriteU32 , "OSD3LPIB" , "OSD3 Link Position In Buffer" },
619 { 0x00168, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteU32 , "OSD3CBL" , "OSD3 Cyclic Buffer Length" },
620 { 0x0016C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16 , hdaRegWriteSDLVI , "OSD3LVI" , "OSD3 Last Valid Index" },
621 { 0x0016E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16 , hdaRegWriteSDFIFOW , "OSD3FIFOW", "OSD3 FIFO Watermark" },
622 { 0x00170, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16 , hdaRegWriteSDFIFOS , "OSD3FIFOS", "OSD3 FIFO Size" },
623 { 0x00172, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16 , hdaRegWriteU16 , "OSD3FMT" , "OSD3 Format" },
624 { 0x00178, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32 , hdaRegWriteSDBDPL , "OSD3BDPL" , "OSD3 Buffer Descriptor List Pointer-Lower Base Address" },
625 { 0x0017C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32 , hdaRegWriteSDBDPU , "OSD3BDPU" , "OSD3 Buffer Descriptor List Pointer-Upper Base Address" },
626};
627
628static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, uint8_t u8Strm, uint32_t u32Value)
629{
630 if (pState->u64DPBase & DPBASE_ENABLED)
631 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState),
632 (pState->u64DPBase & DPBASE_ADDR_MASK) + u8Strm*8, &u32Value, sizeof(uint32_t));
633}
634static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, int iNum)
635{
636 switch (ICH6_HDA_REG_SD0FIFOW + 10*iNum)
637 {
638 case ICH6_HDA_REG_SD0FIFOW:
639 case ICH6_HDA_REG_SD1FIFOW:
640 case ICH6_HDA_REG_SD2FIFOW:
641 case ICH6_HDA_REG_SD3FIFOW:
642 case ICH6_HDA_REG_SD4FIFOW:
643 case ICH6_HDA_REG_SD5FIFOW:
644 case ICH6_HDA_REG_SD6FIFOW:
645 case ICH6_HDA_REG_SD7FIFOW:
646 switch(HDA_REG_IND(pState, ICH6_HDA_REG_SD0FIFOW + 10*iNum))
647 {
648 case HDA_SDFIFOW_8B: return 8;
649 case HDA_SDFIFOW_16B: return 16;
650 case HDA_SDFIFOW_32B: return 32;
651 default:
652 AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, iNum), iNum));
653 }
654 default:
655 AssertMsgFailed(("hda: Not SDnFIFOW register"));
656 return 0;
657 }
658}
659
660static int hdaProcessInterrupt(INTELHDLinkState* pState)
661{
662#define IS_INTERRUPT_OCCURED_AND_ENABLED(pState, num) \
663 ( INTCTL_SX((pState), num) \
664 && (SDSTS(pState, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
665 bool fIrq = false;
666 if( INTCTL_CIE(pState)
667 && ( RIRBSTS_RINTFL(pState)
668 || RIRBSTS_RIRBOIS(pState)
669 || STATESTS(pState)))
670 {
671 fIrq = true;
672 }
673 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 0)
674 || IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 4))
675 {
676 fIrq = true;
677 }
678 if (INTCTL_GIE(pState))
679 {
680 Log(("hda: irq %s\n", fIrq ? "asserted" : "deasserted"));
681 PDMDevHlpPCISetIrq(ICH6_HDASTATE_2_DEVINS(pState), 0 , fIrq);
682 }
683 return VINF_SUCCESS;
684}
685
686static int hdaLookup(INTELHDLinkState* pState, uint32_t u32Offset)
687{
688 int index = 0;
689 //** @todo r=michaln: A linear search of an array with over 100 elements is very inefficient.
690 for (;index < (int)(sizeof(s_ichIntelHDRegMap)/sizeof(s_ichIntelHDRegMap[0])); ++index)
691 {
692 if ( u32Offset >= s_ichIntelHDRegMap[index].offset
693 && u32Offset < s_ichIntelHDRegMap[index].offset + s_ichIntelHDRegMap[index].size)
694 {
695 return index;
696 }
697 }
698 /* Aliases HDA spec 3.3.45 */
699 switch(u32Offset)
700 {
701 case 0x2084:
702 return HDA_REG_IND_NAME(SD0LPIB);
703 case 0x20A4:
704 return HDA_REG_IND_NAME(SD1LPIB);
705 case 0x20C4:
706 return HDA_REG_IND_NAME(SD2LPIB);
707 case 0x20E4:
708 return HDA_REG_IND_NAME(SD3LPIB);
709 case 0x2104:
710 return HDA_REG_IND_NAME(SD4LPIB);
711 case 0x2124:
712 return HDA_REG_IND_NAME(SD5LPIB);
713 case 0x2144:
714 return HDA_REG_IND_NAME(SD6LPIB);
715 case 0x2164:
716 return HDA_REG_IND_NAME(SD7LPIB);
717 }
718 return -1;
719}
720
721static int hdaCmdSync(INTELHDLinkState *pState, bool fLocal)
722{
723 int rc = VINF_SUCCESS;
724 if (fLocal)
725 {
726 Assert((HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)));
727 rc = PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pState->u64CORBBase, pState->pu32CorbBuf, pState->cbCorbBuf);
728 if (RT_FAILURE(rc))
729 AssertRCReturn(rc, rc);
730#ifdef DEBUG_CMD_BUFFER
731 uint8_t i = 0;
732 do
733 {
734 Log(("hda: corb%02x: ", i));
735 uint8_t j = 0;
736 do
737 {
738 const char *prefix;
739 if ((i + j) == CORBRP(pState))
740 prefix = "[R]";
741 else if ((i + j) == CORBWP(pState))
742 prefix = "[W]";
743 else
744 prefix = " "; /* three spaces */
745 Log(("%s%08x", prefix, pState->pu32CorbBuf[i + j]));
746 j++;
747 } while (j < 8);
748 Log(("\n"));
749 i += 8;
750 } while(i != 0);
751#endif
752 }
753 else
754 {
755 Assert((HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA)));
756 rc = PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pState->u64RIRBBase, pState->pu64RirbBuf, pState->cbRirbBuf);
757 if (RT_FAILURE(rc))
758 AssertRCReturn(rc, rc);
759#ifdef DEBUG_CMD_BUFFER
760 uint8_t i = 0;
761 do {
762 Log(("hda: rirb%02x: ", i));
763 uint8_t j = 0;
764 do {
765 const char *prefix;
766 if ((i + j) == RIRBWP(pState))
767 prefix = "[W]";
768 else
769 prefix = " ";
770 Log((" %s%016lx", prefix, pState->pu64RirbBuf[i + j]));
771 } while (++j < 8);
772 Log(("\n"));
773 i += 8;
774 } while (i != 0);
775#endif
776 }
777 return rc;
778}
779
780static int hdaCORBCmdProcess(INTELHDLinkState *pState)
781{
782 int rc;
783 uint8_t corbRp;
784 uint8_t corbWp;
785 uint8_t rirbWp;
786
787 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
788
789 rc = hdaCmdSync(pState, true);
790 if (RT_FAILURE(rc))
791 AssertRCReturn(rc, rc);
792 corbRp = CORBRP(pState);
793 corbWp = CORBWP(pState);
794 rirbWp = RIRBWP(pState);
795 Assert((corbWp != corbRp));
796 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
797 while (corbRp != corbWp)
798 {
799 uint32_t cmd;
800 uint64_t resp;
801 corbRp++;
802 cmd = pState->pu32CorbBuf[corbRp];
803 rc = (pState)->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
804 if (RT_FAILURE(rc))
805 AssertRCReturn(rc, rc);
806 Assert(pfn);
807 (rirbWp)++;
808 rc = pfn(&pState->Codec, cmd, &resp);
809 if (RT_FAILURE(rc))
810 AssertRCReturn(rc, rc);
811 Log(("hda: verb:%08x->%016lx\n", cmd, resp));
812 if ( (resp & CODEC_RESPONSE_UNSOLICITED)
813 && !HDA_REG_FLAG_VALUE(pState, GCTL, UR))
814 {
815 Log(("hda: unexpected unsolicited response.\n"));
816 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
817 return rc;
818 }
819 pState->pu64RirbBuf[rirbWp] = resp;
820 pState->u8Counter++;
821 if (pState->u8Counter == RINTCNT_N(pState))
822 break;
823 }
824 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
825 pState->au32Regs[ICH6_HDA_REG_RIRBWP] = rirbWp;
826 rc = hdaCmdSync(pState, false);
827 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
828 if (RIRBCTL_RIRB_RIC(pState))
829 {
830 RIRBSTS((pState)) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
831 pState->u8Counter = 0;
832 rc = hdaProcessInterrupt(pState);
833 }
834 if (RT_FAILURE(rc))
835 AssertRCReturn(rc, rc);
836 return rc;
837}
838
839static void hdaStreamReset(INTELHDLinkState *pState, uint32_t u32Offset)
840{
841 Log(("hda: reset of stream (%x) started\n", u32Offset));
842 Log(("hda: reset of stream (%x) finished\n", u32Offset));
843}
844
845
846DECLCALLBACK(int)hdaRegReadUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
847{
848 *pu32Value = 0;
849 return VINF_SUCCESS;
850}
851DECLCALLBACK(int)hdaRegWriteUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
852{
853 return VINF_SUCCESS;
854}
855/* U8 */
856DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
857{
858 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffffff00) == 0);
859 return hdaRegReadU32(pState, offset, index, pu32Value);
860}
861
862DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
863{
864 Assert(((u32Value & 0xffffff00) == 0));
865 return hdaRegWriteU32(pState, offset, index, u32Value);
866}
867/* U16 */
868DECLCALLBACK(int)hdaRegReadU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
869{
870 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffff0000) == 0);
871 return hdaRegReadU32(pState, offset, index, pu32Value);
872}
873
874DECLCALLBACK(int)hdaRegWriteU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
875{
876 Assert(((u32Value & 0xffff0000) == 0));
877 return hdaRegWriteU32(pState, offset, index, u32Value);
878}
879
880/* U24 */
881DECLCALLBACK(int)hdaRegReadU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
882{
883 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xff000000) == 0);
884 return hdaRegReadU32(pState, offset, index, pu32Value);
885}
886
887DECLCALLBACK(int)hdaRegWriteU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
888{
889 Assert(((u32Value & 0xff000000) == 0));
890 return hdaRegWriteU32(pState, offset, index, u32Value);
891}
892/* U32 */
893DECLCALLBACK(int)hdaRegReadU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
894{
895 *pu32Value = pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable;
896 return VINF_SUCCESS;
897}
898
899DECLCALLBACK(int)hdaRegWriteU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
900{
901 pState->au32Regs[index] = (u32Value & s_ichIntelHDRegMap[index].writable)
902 | (pState->au32Regs[index] & ~s_ichIntelHDRegMap[index].writable);
903 return VINF_SUCCESS;
904}
905
906DECLCALLBACK(int)hdaRegReadGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
907{
908 return hdaRegReadU32(pState, offset, index, pu32Value);
909}
910
911DECLCALLBACK(int)hdaRegWriteGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
912{
913 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
914 {
915 /* exit reset state */
916 GCTL(pState) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
917 pState->fInReset = false;
918 }
919 else
920 {
921 /* enter reset state*/
922 if ( HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)
923 || HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA))
924 {
925 Log(("hda: HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
926 HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) ? "on" : "off",
927 HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA) ? "on" : "off"));
928 }
929 hdaReset(ICH6_HDASTATE_2_DEVINS(pState));
930 GCTL(pState) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
931 pState->fInReset = true;
932 }
933 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
934 {
935 /* Flush: GSTS:1 set, see 6.2.6*/
936 GSTS(pState) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
937 /* DPLBASE and DPUBASE, should be initialized with initial value (see 6.2.6)*/
938 }
939 return VINF_SUCCESS;
940}
941
942DECLCALLBACK(int)hdaRegWriteSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
943{
944 uint32_t v = pState->au32Regs[index];
945 uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
946 pState->au32Regs[index] = (v ^ nv) & v; /* write of 1 clears corresponding bit */
947 return VINF_SUCCESS;
948}
949
950DECLCALLBACK(int)hdaRegReadINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
951{
952 uint32_t v = 0;
953 if ( RIRBSTS_RIRBOIS(pState)
954 || RIRBSTS_RINTFL(pState)
955 || HDA_REG_FLAG_VALUE(pState, CORBSTS, CMEI)
956 || STATESTS(pState))
957 v |= RT_BIT(30);
958#define HDA_IS_STREAM_EVENT(pState, stream) \
959 ( (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \
960 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \
961 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
962#define MARK_STREAM(pState, stream, v) do {(v) |= HDA_IS_STREAM_EVENT((pState),stream) ? RT_BIT((stream)) : 0;}while(0)
963 MARK_STREAM(pState, 0, v);
964 MARK_STREAM(pState, 1, v);
965 MARK_STREAM(pState, 2, v);
966 MARK_STREAM(pState, 3, v);
967 MARK_STREAM(pState, 4, v);
968 MARK_STREAM(pState, 5, v);
969 MARK_STREAM(pState, 6, v);
970 MARK_STREAM(pState, 7, v);
971 v |= v ? RT_BIT(31) : 0;
972 *pu32Value = v;
973 return VINF_SUCCESS;
974}
975
976DECLCALLBACK(int)hdaRegReadGCAP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
977{
978 return hdaRegReadU16(pState, offset, index, pu32Value);
979}
980
981DECLCALLBACK(int)hdaRegWriteCORBRP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
982{
983 if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
984 CORBRP(pState) = 0;
985 else
986 return hdaRegWriteU8(pState, offset, index, u32Value);
987 return VINF_SUCCESS;
988}
989
990DECLCALLBACK(int)hdaRegWriteCORBCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
991{
992 int rc = hdaRegWriteU8(pState, offset, index, u32Value);
993 AssertRC(rc);
994 if ( CORBWP(pState) != CORBRP(pState)
995 && HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) != 0)
996 return hdaCORBCmdProcess(pState);
997 return rc;
998}
999
1000DECLCALLBACK(int)hdaRegWriteCORBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1001{
1002 uint32_t v = CORBSTS(pState);
1003 v = (v ^ u32Value) & v;
1004 CORBSTS(pState) = v;
1005 return VINF_SUCCESS;
1006}
1007
1008DECLCALLBACK(int)hdaRegWriteCORBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1009{
1010 int rc;
1011 rc = hdaRegWriteU16(pState, offset, index, u32Value);
1012 if (RT_FAILURE(rc))
1013 AssertRCReturn(rc, rc);
1014 if (CORBWP(pState) == CORBRP(pState))
1015 return VINF_SUCCESS;
1016 if (!HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1017 return VINF_SUCCESS;
1018 rc = hdaCORBCmdProcess(pState);
1019 return rc;
1020}
1021
1022DECLCALLBACK(int)hdaRegReadSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1023{
1024 return hdaRegReadU24(pState, offset, index, pu32Value);
1025}
1026#define HDA_STREAM_BITMASK(offset) (1 << (((offset) - 0x80) >> 5))
1027#define HDA_IS_STREAM_IN_RESET(pState, offset) ((pState)->u8StreamsInReset & HDA_STREAM_BITMASK((offset)))
1028DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1029{
1030 bool fOn = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
1031 int rc = VINF_SUCCESS;
1032 uint64_t u64BaseDMA = 0;
1033 uint8_t u8Strm = 0;
1034 PHDABDLEDESC pBdle = NULL;
1035 uint32_t *pu32Lpib = 0;
1036 if(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))
1037 {
1038 Log(("hda: guest has initiated hw stream reset\n"));
1039 pState->u8StreamsInReset |= HDA_STREAM_BITMASK(offset);
1040 hdaStreamReset(pState, offset);
1041 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
1042 }
1043 else if (HDA_IS_STREAM_IN_RESET(pState, offset))
1044 {
1045 Log(("hda: guest has initiated exit of stream reset\n"));
1046 pState->u8StreamsInReset &= ~HDA_STREAM_BITMASK(offset);
1047 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
1048 }
1049 /*
1050 * Stopping streams we postpone up to reset exit to let HDA complete the tasks
1051 */
1052 switch (index)
1053 {
1054 case ICH6_HDA_REG_SD0CTL:
1055 u8Strm = 0;
1056 pBdle = &pState->stInBdle;
1057 pu32Lpib = &SDLPIB(pState, 0);
1058 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), fOn);
1059 Log(("hda: DMA SD0CTL switched %s\n", fOn ? "on" : " off"));
1060 break;
1061 case ICH6_HDA_REG_SD4CTL:
1062 u8Strm = 4;
1063 pBdle = &pState->stOutBdle;
1064
1065 pu32Lpib = &SDLPIB(pState, 4);
1066 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
1067 fOn = fOn && u64BaseDMA;
1068 if (fOn)
1069 SDSTS(pState, 4) &= ~(1<<5);
1070 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), fOn);
1071 Log(("hda: DMA SD4CTL switched %s\n", fOn ? "on" : " off"));
1072 break;
1073 default:
1074 Log(("Attempt to modify DMA state on unattached SDI(%s), ignored\n", s_ichIntelHDRegMap[index].abbrev));
1075 break;
1076 }
1077 if ( !fOn
1078 && pBdle
1079 && pu32Lpib)
1080 {
1081 memset(pBdle, 0, sizeof(HDABDLEDESC));
1082 *pu32Lpib = 0;
1083 hdaUpdatePosBuf(pState, u8Strm, 0);
1084 }
1085 rc = hdaRegWriteU24(pState, offset, index, u32Value);
1086 if (RT_FAILURE(rc))
1087 AssertRCReturn(rc, VINF_SUCCESS);
1088 return rc;
1089}
1090
1091DECLCALLBACK(int)hdaRegWriteSDSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1092{
1093 uint32_t v = HDA_REG_IND(pState, index);
1094 v ^= (u32Value & v);
1095 HDA_REG_IND(pState, index) = v;
1096 hdaProcessInterrupt(pState);
1097#if 0
1098 if ( v != u32Value
1099 && (INTCTL_SALL(pState) & (1 << ((offset - 0x83) >> 5))))
1100 {
1101 int rc;
1102 rc = hdaProcessInterrupt(pState);
1103 if (RT_FAILURE(rc))
1104 AssertRCReturn(rc, rc);
1105 }
1106#endif
1107 return VINF_SUCCESS;
1108}
1109DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1110{
1111 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1112 if (RT_FAILURE(rc))
1113 AssertRCReturn(rc, VINF_SUCCESS);
1114 return rc;
1115}
1116
1117DECLCALLBACK(int)hdaRegWriteSDFIFOW(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1118{
1119 switch (u32Value)
1120 {
1121 case HDA_SDFIFOW_8B:
1122 case HDA_SDFIFOW_16B:
1123 case HDA_SDFIFOW_32B:
1124 return hdaRegWriteU16(pState, offset, index, u32Value);
1125 default:
1126 Log(("hda: Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
1127 return hdaRegWriteU16(pState, offset, index, HDA_SDFIFOW_32B);
1128 }
1129 return VINF_SUCCESS;
1130}
1131/*
1132 * Note this method could be called for changing value on Output Streams only (ICH6 datacheet 18.2.39)
1133 *
1134 */
1135DECLCALLBACK(int)hdaRegWriteSDFIFOS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1136{
1137 switch (index)
1138 {
1139 /* SDInFIFOS is RO, n=0-3 */
1140 case ICH6_HDA_REG_SD0FIFOS:
1141 case ICH6_HDA_REG_SD1FIFOS:
1142 case ICH6_HDA_REG_SD2FIFOS:
1143 case ICH6_HDA_REG_SD3FIFOS:
1144 Log(("hda: Guest tries change value of FIFO size of Input Stream\n"));
1145 return VINF_SUCCESS;
1146 case ICH6_HDA_REG_SD4FIFOS:
1147 case ICH6_HDA_REG_SD5FIFOS:
1148 case ICH6_HDA_REG_SD6FIFOS:
1149 case ICH6_HDA_REG_SD7FIFOS:
1150 switch(u32Value)
1151 {
1152 case HDA_SDONFIFO_16B:
1153 case HDA_SDONFIFO_32B:
1154 case HDA_SDONFIFO_64B:
1155 case HDA_SDONFIFO_128B:
1156 case HDA_SDONFIFO_192B:
1157 return hdaRegWriteU16(pState, offset, index, u32Value);
1158
1159 case HDA_SDONFIFO_256B:
1160 Log(("hda: 256 bit is unsupported, HDA is switched into 192B mode\n"));
1161 default:
1162 return hdaRegWriteU16(pState, offset, index, HDA_SDONFIFO_192B);
1163 }
1164 return VINF_SUCCESS;
1165 default:
1166 AssertMsgFailed(("Something wierd happens with register lookup routine"));
1167 }
1168 return VINF_SUCCESS;
1169}
1170
1171DECLCALLBACK(int)hdaRegWriteSDBDPL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1172{
1173 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1174 if (RT_FAILURE(rc))
1175 AssertRCReturn(rc, VINF_SUCCESS);
1176 return rc;
1177}
1178
1179DECLCALLBACK(int)hdaRegWriteSDBDPU(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1180{
1181 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1182 if (RT_FAILURE(rc))
1183 AssertRCReturn(rc, VINF_SUCCESS);
1184 return rc;
1185}
1186
1187DECLCALLBACK(int)hdaRegReadIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1188{
1189 int rc = VINF_SUCCESS;
1190 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
1191 if ( CORBWP(pState) != CORBRP(pState)
1192 || HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1193 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1194
1195 rc = hdaRegReadU32(pState, offset, index, pu32Value);
1196 return rc;
1197}
1198
1199DECLCALLBACK(int)hdaRegWriteIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1200{
1201 int rc = VINF_SUCCESS;
1202 uint64_t resp;
1203 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
1204 /*
1205 * if guest set ICB bit of IRS register HDA should process verb in IC register and
1206 * writes response in IR register and set IRV (valid in case of success) bit of IRS register.
1207 */
1208 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
1209 && !IRS_ICB(pState))
1210 {
1211 uint32_t cmd = IC(pState);
1212 if (CORBWP(pState) != CORBRP(pState))
1213 {
1214 /*
1215 * 3.4.3 defines behaviour of immediate Command status register.
1216 */
1217 LogRel(("hda: guest has tried process immediate verb (%x) with active CORB\n", cmd));
1218 return rc;
1219 }
1220 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1221 Log(("hda: IC:%x\n", cmd));
1222 rc = pState->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
1223 if (RT_FAILURE(rc))
1224 AssertRCReturn(rc, rc);
1225 rc = pfn(&pState->Codec, cmd, &resp);
1226 if (RT_FAILURE(rc))
1227 AssertRCReturn(rc, rc);
1228 IR(pState) = (uint32_t)resp;
1229 Log(("hda: IR:%x\n", IR(pState)));
1230 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */
1231 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
1232 return rc;
1233 }
1234 /*
1235 * when guest's read the response it should clean the IRV bit of the IRS register.
1236 */
1237 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
1238 && IRS_IRV(pState))
1239 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
1240 return rc;
1241}
1242
1243DECLCALLBACK(int)hdaRegWriteRIRBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1244{
1245 if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
1246 {
1247 RIRBWP(pState) = 0;
1248 }
1249 /*The rest of bits are O, see 6.2.22 */
1250 return VINF_SUCCESS;
1251}
1252
1253DECLCALLBACK(int)hdaRegWriteBase(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1254{
1255 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1256 if (RT_FAILURE(rc))
1257 AssertRCReturn(rc, rc);
1258 switch(index)
1259 {
1260 case ICH6_HDA_REG_CORBLBASE:
1261 pState->u64CORBBase &= 0xFFFFFFFF00000000ULL;
1262 pState->u64CORBBase |= pState->au32Regs[index];
1263 break;
1264 case ICH6_HDA_REG_CORBUBASE:
1265 pState->u64CORBBase &= 0x00000000FFFFFFFFULL;
1266 pState->u64CORBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1267 break;
1268 case ICH6_HDA_REG_RIRLBASE:
1269 pState->u64RIRBBase &= 0xFFFFFFFF00000000ULL;
1270 pState->u64RIRBBase |= pState->au32Regs[index];
1271 break;
1272 case ICH6_HDA_REG_RIRUBASE:
1273 pState->u64RIRBBase &= 0x00000000FFFFFFFFULL;
1274 pState->u64RIRBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1275 break;
1276 case ICH6_HDA_REG_DPLBASE:
1277 /* @todo: first bit has special meaning */
1278 pState->u64DPBase &= 0xFFFFFFFF00000000ULL;
1279 pState->u64DPBase |= pState->au32Regs[index];
1280 break;
1281 case ICH6_HDA_REG_DPUBASE:
1282 pState->u64DPBase &= 0x00000000FFFFFFFFULL;
1283 pState->u64DPBase |= ((uint64_t)pState->au32Regs[index] << 32);
1284 break;
1285 default:
1286 AssertMsgFailed(("Invalid index"));
1287 }
1288 Log(("hda: CORB base:%llx RIRB base: %llx DP base: %llx\n", pState->u64CORBBase, pState->u64RIRBBase, pState->u64DPBase));
1289 return rc;
1290}
1291
1292DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1293{
1294 uint8_t nv = u32Value;
1295 uint8_t v = RIRBSTS(pState);
1296 RIRBSTS(pState) = (v ^ nv) & v;
1297
1298 return hdaProcessInterrupt(pState);
1299}
1300
1301static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1302{
1303 uint64_t addr;
1304 uint32_t len;
1305 uint32_t ioc;
1306 uint8_t bdle[16];
1307 uint32_t counter;
1308 uint32_t i;
1309 uint32_t sum = 0;
1310 Assert(pBdle && pBdle->u32BdleMaxCvi);
1311 for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
1312 {
1313 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + i*16, bdle, 16);
1314 addr = *(uint64_t *)bdle;
1315 len = *(uint32_t *)&bdle[8];
1316 ioc = *(uint32_t *)&bdle[12];
1317 Log(("hda: %s bdle[%d] a:%llx, len:%d, ioc:%d\n", (i == pBdle->u32BdleCvi? "[C]": " "), i, addr, len, ioc & 0x1));
1318 sum += len;
1319 }
1320 Log(("hda: sum: %d\n", sum));
1321 for (i = 0; i < 8; ++i)
1322 {
1323 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), (pState->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
1324 Log(("hda: %s stream[%d] counter=%x\n", i == SDCTL_NUM(pState, 4) || i == SDCTL_NUM(pState, 0)? "[C]": " ",
1325 i , counter));
1326 }
1327}
1328static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1329{
1330 uint8_t bdle[16];
1331 Assert((u64BaseDMA && pBdle && pBdle->u32BdleMaxCvi));
1332 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
1333 pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
1334 pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
1335 pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
1336 dump_bd(pState, pBdle, u64BaseDMA);
1337}
1338
1339static uint32_t hdaReadAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, uint32_t u32CblLimit)
1340{
1341 PHDABDLEDESC pBdle = &pState->stInBdle;
1342 uint32_t cbTransfered = 0;
1343 while( *pu32Avail
1344 && pBdle->u32BdleCviPos < pBdle->u32BdleCviLen)
1345 {
1346 uint32_t cb2Copy = 0;
1347 uint32_t cbBackendCopy = 0;
1348 bool fUnderFifoCleared = false;
1349 if ( !pBdle->u32BdleCviLen
1350 || (*pu32Avail < hdaFifoWToSz(pState, 0)))
1351 {
1352 return 0;
1353 }
1354 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1355 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
1356 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
1357 cb2Copy = RT_MIN(cb2Copy, SDFIFOS(pState, 0) + 1 - pBdle->cbUnderFifoW); /* we may increase the counter in range of [0, FIFOS(pState, 4) + 1] */
1358 Assert((*pu32Avail > 0));
1359 cb2Copy = RT_MIN(cb2Copy, *pu32Avail); /* sanity check to avoid overriding sound backend buffer */
1360 cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
1361 if ( !cb2Copy
1362 || cb2Copy < pBdle->cbUnderFifoW)
1363 {
1364 return 0;
1365 }
1366
1367 /*
1368 * read from backend input line
1369 */
1370 cbBackendCopy = AUD_read (ISD0FMT_TO_AUDIO_SELECTOR(pState), pBdle->au8HdaBuffer, cb2Copy);
1371 /*
1372 * write on the HDA DMA
1373 */
1374 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy);
1375
1376 Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
1377 *pu32Avail -= cb2Copy;
1378 pBdle->u32BdleCviPos += RT_MIN(cb2Copy, cbBackendCopy);
1379 if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pState, 0))
1380 {
1381 Log(("hda:ra: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1382 cbTransfered += cbBackendCopy + pBdle->cbUnderFifoW;
1383 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbBackendCopy);
1384 Assert(!pBdle->cbUnderFifoW); /* we assume, we've read Under FIFO W fully */
1385 }
1386 else
1387 {
1388 Log(("hda:ra: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1389 pBdle->cbUnderFifoW += RT_MIN(cbBackendCopy, cb2Copy);
1390 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, 0)));
1391 break;
1392 }
1393 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1394 if ( cbTransfered == (SDFIFOS(pState, 0) + 1)
1395 || pBdle->u32BdleCviLen == pBdle->u32BdleCviPos)
1396 break;
1397 }
1398 Assert((cbTransfered <= (SDFIFOS(pState, 0) + 1)));
1399 Log(("hda:ra: cbTransfered: %d\n", cbTransfered));
1400 return cbTransfered;
1401}
1402
1403static uint32_t hdaWriteAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, uint32_t u32CblLimit)
1404{
1405 PHDABDLEDESC pBdle = &pState->stOutBdle;
1406 uint32_t cbTransfered = 0;
1407 uint32_t cb2Copy = 0; /* local byte counter (on local buffer) */
1408 uint32_t cbBackendCopy = 0; /* local byte counter, how many bytes copied to backend */
1409
1410 Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1411
1412 /*
1413 * Amounts of bytes depends on current position in buffer (u32BdleCviLen-u32BdleCviPos)
1414 */
1415 if (pBdle->u32BdleCviLen)
1416 {
1417 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
1418 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos; /* align copy buffer to size of trailing space in BDLE buffer */
1419 cb2Copy = RT_MIN(cb2Copy, SDFIFOS(pState, 4) + 1); /* we may increase the counter in range of [0, FIFOS(pState, 4) + 1] */
1420 cb2Copy = RT_MIN(cb2Copy, *pu32Avail); /* align copying buffer size up to size of back end buffer */
1421 cb2Copy = RT_MIN(cb2Copy, u32CblLimit); /* avoid LCBL overrun */
1422 }
1423 if (cb2Copy <= pBdle->cbUnderFifoW)
1424 {
1425 Log(("hda:wa: amount of unreported bytes is less than room may be transfered (cbUnderFifoW:%d < %d)\n", pBdle->cbUnderFifoW, cb2Copy));
1426 goto done;
1427 }
1428 cb2Copy -= pBdle->cbUnderFifoW; /* force reserve "Unreported bits" */
1429
1430 /*
1431 * Copy from DMA to the corresponding hdaBuffer (if there exists some bytes from the previous not reported transfer we write to ''pBdle->cbUnderFifoW'' offset)
1432 */
1433 if (cb2Copy)
1434 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
1435 /*
1436 * Write to audio backend.
1437 */
1438 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, 4))
1439 {
1440 /*
1441 * We feed backend with new portion of fetched samples including not reported.
1442 */
1443 cbBackendCopy = AUD_write (OSD0FMT_TO_AUDIO_SELECTOR(pState), pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
1444 Assert((cbBackendCopy));
1445 /* Assertion!!! It was copied less than cbUnderFifoW
1446 * Probably we need to move the buffer, but it rather hard to imagine situation
1447 * why it may happen.
1448 */
1449 Assert((cbBackendCopy == pBdle->cbUnderFifoW + cb2Copy)); /* we assume that we write whole buffer including not reported bytes */
1450 if ( pBdle->cbUnderFifoW
1451 && pBdle->cbUnderFifoW <= cbBackendCopy)
1452 Log(("hda:wa: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1453
1454 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbBackendCopy);
1455 pBdle->u32BdleCviPos += RT_MIN(cb2Copy, cbBackendCopy);
1456 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32Avail >= cbBackendCopy)); /* sanity */
1457 Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Assumption failed */
1458 *pu32Avail -= cbBackendCopy;
1459 cbTransfered += cbBackendCopy;
1460 }
1461 else
1462 {
1463 Log(("hda:wa: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1464 pBdle->cbUnderFifoW += cb2Copy;
1465 pBdle->u32BdleCviPos += cb2Copy;
1466 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, 4)));
1467 goto done;
1468 }
1469
1470 done:
1471 Assert((cbTransfered <= (SDFIFOS(pState, 4) + 1)));
1472 Log(("hda:wa: CVI(pos:%d, len:%d, cbTransfered:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransfered));
1473 return cbTransfered;
1474}
1475
1476DECLCALLBACK(int) hdaCodecReset(CODECState *pCodecState)
1477{
1478 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1479 return VINF_SUCCESS;
1480}
1481
1482DECLCALLBACK(void) hdaTransfer(CODECState *pCodecState, ENMSOUNDSOURCE src, int avail)
1483{
1484 uint64_t u64BaseDMA = 0;
1485 PHDABDLEDESC pBdle = NULL;
1486 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1487 uint32_t nBytes;
1488 uint32_t u32Ctl;
1489 uint32_t *pu32Sts;
1490 uint8_t u8Strm;
1491 uint32_t *pu32Lpib;
1492 uint32_t u32Cbl;
1493 uint32_t u32Fifos;
1494 uint32_t u32Fifow;
1495 switch (src)
1496 {
1497 case PO_INDEX:
1498 {
1499 u8Strm = 4;
1500 u32Ctl = SDCTL(pState, 4);
1501 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
1502 pu32Lpib = &SDLPIB(pState, 4);
1503 pu32Sts = &SDSTS(pState, 4);
1504 u32Cbl = SDLCBL(pState, 4);
1505 pBdle = &pState->stOutBdle;
1506 pBdle->u32BdleMaxCvi = SDLVI(pState, 4);
1507 u32Fifos = SDFIFOS(pState, 4);
1508 u32Fifow = hdaFifoWToSz(pState, 4);
1509 break;
1510 }
1511 case PI_INDEX:
1512 {
1513 u8Strm = 0;
1514 u32Ctl = SDCTL(pState, 0);
1515 pu32Lpib = &SDLPIB(pState, 0);
1516 pu32Sts = &SDSTS(pState, 0);
1517 u32Cbl = SDLCBL(pState, 0);
1518 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 0), SDBDPU(pState, 0));
1519 pBdle = &pState->stInBdle;
1520 pBdle->u32BdleMaxCvi = SDLVI(pState, 0);
1521 u32Fifos = SDFIFOS(pState, 0);
1522 u32Fifow = hdaFifoWToSz(pState, 0);
1523 break;
1524 }
1525 default:
1526 return;
1527 }
1528 if ( !(u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
1529 || !avail
1530 || !u64BaseDMA)
1531 return;
1532 /* Fetch the Buffer Descriptor Entry (BDE). */
1533 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1534 fetch_bd(pState, pBdle, u64BaseDMA);
1535 while(avail)
1536 {
1537 Assert((avail >= 0 && (u32Cbl >= (*pu32Lpib)))); /* sanity */
1538 uint32_t u32CblLimit = u32Cbl - (*pu32Lpib);
1539 Log(("hda: CBL=%d, LPIB=%d\n", u32Cbl, *pu32Lpib));
1540 switch (src)
1541 {
1542 case PO_INDEX:
1543 nBytes = hdaWriteAudio(pState, (uint32_t *)&avail, u32CblLimit);
1544 break;
1545 case PI_INDEX:
1546 nBytes = hdaReadAudio(pState, (uint32_t *)&avail, u32CblLimit);
1547 break;
1548 default:
1549 nBytes = 0;
1550 AssertMsgFailed(("Unsupported"));
1551 break;
1552 }
1553 /*
1554 * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything.
1555 * (ICH6 datasheet 18.2.38)
1556 */
1557 Assert(nBytes <= (u32Fifos + 1));
1558 if (!pBdle->cbUnderFifoW)
1559 {
1560 *pu32Lpib += nBytes;
1561
1562 /*
1563 * Assert. Overlapping of buffer counter shouldn't happen.
1564 */
1565 Assert((*pu32Lpib <= u32Cbl));
1566
1567 /* Optionally write back the current DMA position. */
1568 hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib);
1569
1570 }
1571 /* Process end of buffer condition. */
1572 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
1573 || *pu32Lpib == u32Cbl)
1574 {
1575 if ( !pBdle->cbUnderFifoW
1576 && pBdle->fBdleCviIoc)
1577 {
1578 *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1579 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
1580 hdaProcessInterrupt(pState);
1581 }
1582 if (*pu32Lpib == u32Cbl)
1583 *pu32Lpib -= u32Cbl;
1584 hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib);
1585
1586 if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
1587 {
1588 pBdle->u32BdleCviPos = 0;
1589 pBdle->u32BdleCvi++;
1590 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
1591 pBdle->u32BdleCvi = 0;
1592
1593 }
1594 break;
1595 }
1596 }
1597 *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1598}
1599
1600/**
1601 * Handle register read operation.
1602 *
1603 * Looks up and calls appropriate handler.
1604 *
1605 * @note: while implementation was detected so called "forgotten" or "hole" registers
1606 * which description is missed in RPM, datasheet or spec.
1607 *
1608 * @returns VBox status code.
1609 *
1610 * @param pState The device state structure.
1611 * @param uOffset Register offset in memory-mapped frame.
1612 * @param pv Where to fetch the value.
1613 * @param cb Number of bytes to write.
1614 * @thread EMT
1615 */
1616PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
1617{
1618 int rc = VINF_SUCCESS;
1619 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1620 uint32_t u32Offset = GCPhysAddr - pThis->hda.addrMMReg;
1621 int index = hdaLookup(&pThis->hda, u32Offset);
1622 if (pThis->hda.fInReset && index != ICH6_HDA_REG_GCTL)
1623 {
1624 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1625 }
1626 if ( index == -1
1627 || cb > 4)
1628 {
1629 LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", u32Offset, cb));
1630 }
1631 if (index != -1)
1632 {
1633 uint32_t mask = 0;
1634 uint32_t shift = (u32Offset - s_ichIntelHDRegMap[index].offset) % sizeof(uint32_t) * 8;
1635 uint32_t v = 0;
1636 switch(cb)
1637 {
1638 case 1: mask = 0x000000ff; break;
1639 case 2: mask = 0x0000ffff; break;
1640 case 3: mask = 0x00ffffff; break;
1641 case 4: mask = 0xffffffff; break;
1642 }
1643 mask <<= shift;
1644 rc = s_ichIntelHDRegMap[index].pfnRead(&pThis->hda, u32Offset, index, &v);
1645 *(uint32_t *)pv = (v & mask) >> shift;
1646 Log(("hda: read %s[%x/%x]\n", s_ichIntelHDRegMap[index].abbrev, v, *(uint32_t *)pv));
1647 return rc;
1648 }
1649 *(uint32_t *)pv = 0xFF;
1650 Log(("hda: hole at %X is accessed for read\n", u32Offset));
1651 return rc;
1652}
1653
1654/**
1655 * Handle register write operation.
1656 *
1657 * Looks up and calls appropriate handler.
1658 *
1659 * @returns VBox status code.
1660 *
1661 * @param pState The device state structure.
1662 * @param uOffset Register offset in memory-mapped frame.
1663 * @param pv Where to fetch the value.
1664 * @param cb Number of bytes to write.
1665 * @thread EMT
1666 */
1667PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
1668{
1669 int rc = VINF_SUCCESS;
1670 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1671 uint32_t u32Offset = GCPhysAddr - pThis->hda.addrMMReg;
1672 int index = hdaLookup(&pThis->hda, u32Offset);
1673 if (pThis->hda.fInReset && index != ICH6_HDA_REG_GCTL)
1674 {
1675 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1676 }
1677 if ( index == -1
1678 || cb > 4)
1679 {
1680 LogRel(("hda: Invalid write access @0x%x(of bytes:%d)\n", u32Offset, cb));
1681 }
1682 if (index != -1)
1683 {
1684 uint32_t v = pThis->hda.au32Regs[index];
1685 uint32_t mask = 0;
1686 uint32_t shift = (u32Offset - s_ichIntelHDRegMap[index].offset) % sizeof(uint32_t) * 8;
1687 switch(cb)
1688 {
1689 case 1: mask = 0xffffff00; break;
1690 case 2: mask = 0xffff0000; break;
1691 case 3: mask = 0xff000000; break;
1692 case 4: mask = 0x00000000; break;
1693 }
1694 mask <<= shift;
1695 *(uint32_t *)pv = ((v & mask) | (*(uint32_t *)pv & ~mask)) >> shift;
1696 rc = s_ichIntelHDRegMap[index].pfnWrite(&pThis->hda, u32Offset, index, *(uint32_t *)pv);
1697 Log(("hda: write %s:(%x) %x => %x\n", s_ichIntelHDRegMap[index].abbrev, *(uint32_t *)pv, v, pThis->hda.au32Regs[index]));
1698 return rc;
1699 }
1700 Log(("hda: hole at %X is accessed for write\n", u32Offset));
1701 return rc;
1702}
1703
1704/**
1705 * Callback function for mapping a PCI I/O region.
1706 *
1707 * @return VBox status code.
1708 * @param pPciDev Pointer to PCI device.
1709 * Use pPciDev->pDevIns to get the device instance.
1710 * @param iRegion The region number.
1711 * @param GCPhysAddress Physical address of the region.
1712 * If iType is PCI_ADDRESS_SPACE_IO, this is an
1713 * I/O port, else it's a physical address.
1714 * This address is *NOT* relative
1715 * to pci_mem_base like earlier!
1716 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1717 */
1718static DECLCALLBACK(int) hdaMap (PPCIDEVICE pPciDev, int iRegion,
1719 RTGCPHYS GCPhysAddress, uint32_t cb,
1720 PCIADDRESSSPACE enmType)
1721{
1722 int rc;
1723 PPDMDEVINS pDevIns = pPciDev->pDevIns;
1724 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
1725 PCIINTELHDLinkState *pThis = PCIDEV_2_ICH6_HDASTATE(pPciDev);
1726
1727 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
1728 rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, 0,
1729 hdaMMIOWrite, hdaMMIORead, NULL, "ICH6_HDA");
1730
1731 if (RT_FAILURE(rc))
1732 return rc;
1733
1734 pThis->hda.addrMMReg = GCPhysAddress;
1735 return VINF_SUCCESS;
1736}
1737
1738/**
1739 * Saves a state of the HDA device.
1740 *
1741 * @returns VBox status code.
1742 * @param pDevIns The device instance.
1743 * @param pSSMHandle The handle to save the state to.
1744 */
1745static DECLCALLBACK(int) hdaSaveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1746{
1747 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1748 /* Save Codec nodes states */
1749 codecSaveState(&pThis->hda.Codec, pSSMHandle);
1750 /* Save MMIO registers */
1751 SSMR3PutMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
1752 /* Save HDA dma counters */
1753 SSMR3PutMem (pSSMHandle, &pThis->hda.stOutBdle, sizeof (HDABDLEDESC));
1754 SSMR3PutMem (pSSMHandle, &pThis->hda.stMicBdle, sizeof (HDABDLEDESC));
1755 SSMR3PutMem (pSSMHandle, &pThis->hda.stInBdle, sizeof (HDABDLEDESC));
1756 return VINF_SUCCESS;
1757}
1758
1759/**
1760 * Loads a saved HDA device state.
1761 *
1762 * @returns VBox status code.
1763 * @param pDevIns The device instance.
1764 * @param pSSMHandle The handle to the saved state.
1765 * @param uVersion The data unit version number.
1766 * @param uPass The data pass.
1767 */
1768static DECLCALLBACK(int) hdaLoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
1769 uint32_t uVersion, uint32_t uPass)
1770{
1771 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1772 /* Load Codec nodes states */
1773 AssertMsgReturn (uVersion == HDA_SSM_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1774 Assert (uPass == SSM_PASS_FINAL); NOREF(uPass);
1775
1776 codecLoadState(&pThis->hda.Codec, pSSMHandle);
1777 /* Load MMIO registers */
1778 SSMR3GetMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
1779 /* Load HDA dma counters */
1780 SSMR3GetMem (pSSMHandle, &pThis->hda.stOutBdle, sizeof (HDABDLEDESC));
1781 SSMR3GetMem (pSSMHandle, &pThis->hda.stMicBdle, sizeof (HDABDLEDESC));
1782 SSMR3GetMem (pSSMHandle, &pThis->hda.stInBdle, sizeof (HDABDLEDESC));
1783
1784 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(&pThis->hda), SDCTL(&pThis->hda, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1785 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(&pThis->hda), SDCTL(&pThis->hda, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1786
1787 pThis->hda.u64CORBBase = CORBLBASE(&pThis->hda);
1788 pThis->hda.u64CORBBase |= ((uint64_t)CORBUBASE(&pThis->hda)) << 32;
1789 pThis->hda.u64RIRBBase = RIRLBASE(&pThis->hda);
1790 pThis->hda.u64RIRBBase |= ((uint64_t)RIRUBASE(&pThis->hda)) << 32;
1791 pThis->hda.u64DPBase = DPLBASE(&pThis->hda);
1792 pThis->hda.u64DPBase |= ((uint64_t)DPUBASE(&pThis->hda)) << 32;
1793 return VINF_SUCCESS;
1794}
1795
1796/**
1797 * Reset notification.
1798 *
1799 * @returns VBox status.
1800 * @param pDevIns The device instance data.
1801 *
1802 * @remark The original sources didn't install a reset handler, but it seems to
1803 * make sense to me so we'll do it.
1804 */
1805static DECLCALLBACK(void) hdaReset (PPDMDEVINS pDevIns)
1806{
1807 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1808 GCAP(&pThis->hda) = 0x4401; /* see 6.2.1 */
1809 VMIN(&pThis->hda) = 0x00; /* see 6.2.2 */
1810 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
1811 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
1812 OUTPAY(&pThis->hda) = 0x003C; /* see 6.2.4 */
1813 INPAY(&pThis->hda) = 0x001D; /* see 6.2.5 */
1814 pThis->hda.au32Regs[ICH6_HDA_REG_CORBSIZE] = 0x42; /* see 6.2.1 */
1815 pThis->hda.au32Regs[ICH6_HDA_REG_RIRBSIZE] = 0x42; /* see 6.2.1 */
1816 CORBRP(&pThis->hda) = 0x0;
1817 RIRBWP(&pThis->hda) = 0x0;
1818
1819 Log(("hda: inter HDA reset.\n"));
1820 pThis->hda.cbCorbBuf = 256 * sizeof(uint32_t);
1821
1822 if (pThis->hda.pu32CorbBuf)
1823 memset(pThis->hda.pu32CorbBuf, 0, pThis->hda.cbCorbBuf);
1824 else
1825 pThis->hda.pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->hda.cbCorbBuf);
1826
1827 pThis->hda.cbRirbBuf = 256 * sizeof(uint64_t);
1828 if (pThis->hda.pu64RirbBuf)
1829 memset(pThis->hda.pu64RirbBuf, 0, pThis->hda.cbRirbBuf);
1830 else
1831 pThis->hda.pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->hda.cbRirbBuf);
1832
1833 /* According to ICH6 datasheet, 0x40000 is default value for stream descriptor register 23:20
1834 * bits are reserved for stream number 18.2.33 */
1835 SDCTL(&pThis->hda, 0) = 0x40000;
1836 SDCTL(&pThis->hda, 1) = 0x40000;
1837 SDCTL(&pThis->hda, 2) = 0x40000;
1838 SDCTL(&pThis->hda, 3) = 0x40000;
1839 SDCTL(&pThis->hda, 4) = 0x40000;
1840 SDCTL(&pThis->hda, 5) = 0x40000;
1841 SDCTL(&pThis->hda, 6) = 0x40000;
1842 SDCTL(&pThis->hda, 7) = 0x40000;
1843
1844 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
1845 SDFIFOS(&pThis->hda, 0) = HDA_SDINFIFO_120B;
1846 SDFIFOS(&pThis->hda, 1) = HDA_SDINFIFO_120B;
1847 SDFIFOS(&pThis->hda, 2) = HDA_SDINFIFO_120B;
1848 SDFIFOS(&pThis->hda, 3) = HDA_SDINFIFO_120B;
1849
1850 SDFIFOS(&pThis->hda, 4) = HDA_SDONFIFO_192B;
1851 SDFIFOS(&pThis->hda, 5) = HDA_SDONFIFO_192B;
1852 SDFIFOS(&pThis->hda, 6) = HDA_SDONFIFO_192B;
1853 SDFIFOS(&pThis->hda, 7) = HDA_SDONFIFO_192B;
1854
1855 SDFIFOW(&pThis->hda, 0) = HDA_SDFIFOW_8B;
1856 SDFIFOW(&pThis->hda, 4) = HDA_SDFIFOW_32B;
1857
1858 /* emulateion of codec "wake up" HDA spec (5.5.1 and 6.5)*/
1859 STATESTS(&pThis->hda) = 0x1;
1860
1861 Log(("hda: reset finished\n"));
1862}
1863
1864/**
1865 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1866 */
1867static DECLCALLBACK(void *) hdaQueryInterface (struct PDMIBASE *pInterface,
1868 const char *pszIID)
1869{
1870 PCIINTELHDLinkState *pThis = RT_FROM_MEMBER(pInterface, PCIINTELHDLinkState, hda.IBase);
1871 Assert(&pThis->hda.IBase == pInterface);
1872
1873 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->hda.IBase);
1874 return NULL;
1875}
1876
1877//#define HDA_AS_PCI_EXPRESS
1878
1879/**
1880 * @interface_method_impl{PDMDEVREG,pfnConstruct}
1881 */
1882static DECLCALLBACK(int) hdaConstruct (PPDMDEVINS pDevIns, int iInstance,
1883 PCFGMNODE pCfgHandle)
1884{
1885 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1886 INTELHDLinkState *s = &pThis->hda;
1887 int rc;
1888
1889 Assert(iInstance == 0);
1890 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1891
1892 /*
1893 * Validations.
1894 */
1895 if (!CFGMR3AreValuesValid (pCfgHandle, "\0"))
1896 return PDMDEV_SET_ERROR (pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1897 N_ ("Invalid configuration for the INTELHD device"));
1898
1899 // ** @todo r=michaln: This device may need R0/RC enabling, especially if guests
1900 // poll some register(s).
1901
1902 /*
1903 * Initialize data (most of it anyway).
1904 */
1905 s->pDevIns = pDevIns;
1906 /* IBase */
1907 s->IBase.pfnQueryInterface = hdaQueryInterface;
1908
1909 /* PCI Device (the assertions will be removed later) */
1910#if defined(VBOX_WITH_HP_HDA)
1911 /* Linux kernel has whitelist for MSI-enabled HDA, this card seems to be there. */
1912 PCIDevSetVendorId (&pThis->dev, 0x103c); /* HP. */
1913 PCIDevSetDeviceId (&pThis->dev, 0x30f7); /* HP Pavilion dv4t-1300 */
1914#elif defined(VBOX_WITH_INTEL_HDA)
1915 PCIDevSetVendorId (&pThis->dev, 0x8086); /* 00 ro - intel. */
1916 PCIDevSetDeviceId (&pThis->dev, 0x2668); /* 02 ro - 82801 / 82801aa(?). */
1917#elif defined(VBOX_WITH_NVIDIA_HDA)
1918 PCIDevSetVendorId (&pThis->dev, 0x10de); /* nVidia */
1919 PCIDevSetDeviceId (&pThis->dev, 0x0ac0); /* HDA */
1920#else
1921# error "Please specify your HDA device vendor/device IDs"
1922#endif
1923 PCIDevSetCommand (&pThis->dev, 0x0000); /* 04 rw,ro - pcicmd. */
1924 PCIDevSetStatus (&pThis->dev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
1925 PCIDevSetRevisionId (&pThis->dev, 0x01); /* 08 ro - rid. */
1926 PCIDevSetClassProg (&pThis->dev, 0x00); /* 09 ro - pi. */
1927 PCIDevSetClassSub (&pThis->dev, 0x03); /* 0a ro - scc; 03 == HDA. */
1928 PCIDevSetClassBase (&pThis->dev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
1929 PCIDevSetHeaderType (&pThis->dev, 0x00); /* 0e ro - headtyp. */
1930 PCIDevSetBaseAddress (&pThis->dev, 0, /* 10 rw - MMIO */
1931 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
1932 PCIDevSetInterruptLine (&pThis->dev, 0x00); /* 3c rw. */
1933 PCIDevSetInterruptPin (&pThis->dev, 0x01); /* 3d ro - INTA#. */
1934
1935#if defined(HDA_AS_PCI_EXPRESS)
1936 PCIDevSetCapabilityList (&pThis->dev, 0x80);
1937#elif defined(VBOX_WITH_MSI_DEVICES)
1938 PCIDevSetCapabilityList (&pThis->dev, 0x60);
1939#else
1940 PCIDevSetCapabilityList (&pThis->dev, 0x50); /* ICH6 datasheet 18.1.16 */
1941#endif
1942
1943 //** @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
1944 // of these values needs to be properly documented!
1945 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
1946 PCIDevSetByte(&pThis->dev, 0x40, 0x01);
1947
1948 /* Power Management */
1949 PCIDevSetByte(&pThis->dev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
1950 PCIDevSetByte(&pThis->dev, 0x50 + 1, 0x0); /* next */
1951 PCIDevSetWord(&pThis->dev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
1952
1953#ifdef HDA_AS_PCI_EXPRESS
1954 /* PCI Express */
1955 PCIDevSetByte (&pThis->dev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
1956 PCIDevSetByte (&pThis->dev, 0x80 + 1, 0x60); /* next */
1957 /* Device flags */
1958 PCIDevSetWord (&pThis->dev, 0x80 + 2,
1959 /* version */ 0x1 |
1960 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
1961 /* MSI */ (100) << 9
1962 );
1963 /* Device capabilities */
1964 PCIDevSetDWord (&pThis->dev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
1965 /* Device control */
1966 PCIDevSetWord (&pThis->dev, 0x80 + 8, 0);
1967 /* Device status */
1968 PCIDevSetWord (&pThis->dev, 0x80 + 10, 0);
1969 /* Link caps */
1970 PCIDevSetDWord (&pThis->dev, 0x80 + 12, 0);
1971 /* Link control */
1972 PCIDevSetWord (&pThis->dev, 0x80 + 16, 0);
1973 /* Link status */
1974 PCIDevSetWord (&pThis->dev, 0x80 + 18, 0);
1975 /* Slot capabilities */
1976 PCIDevSetDWord (&pThis->dev, 0x80 + 20, 0);
1977 /* Slot control */
1978 PCIDevSetWord (&pThis->dev, 0x80 + 24, 0);
1979 /* Slot status */
1980 PCIDevSetWord (&pThis->dev, 0x80 + 26, 0);
1981 /* Root control */
1982 PCIDevSetWord (&pThis->dev, 0x80 + 28, 0);
1983 /* Root capabilities */
1984 PCIDevSetWord (&pThis->dev, 0x80 + 30, 0);
1985 /* Root status */
1986 PCIDevSetDWord (&pThis->dev, 0x80 + 32, 0);
1987 /* Device capabilities 2 */
1988 PCIDevSetDWord (&pThis->dev, 0x80 + 36, 0);
1989 /* Device control 2 */
1990 PCIDevSetQWord (&pThis->dev, 0x80 + 40, 0);
1991 /* Link control 2 */
1992 PCIDevSetQWord (&pThis->dev, 0x80 + 48, 0);
1993 /* Slot control 2 */
1994 PCIDevSetWord (&pThis->dev, 0x80 + 56, 0);
1995#endif
1996
1997 /*
1998 * Register the PCI device.
1999 */
2000 rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
2001 if (RT_FAILURE (rc))
2002 return rc;
2003
2004 rc = PDMDevHlpPCIIORegionRegister (pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM,
2005 hdaMap);
2006 if (RT_FAILURE (rc))
2007 return rc;
2008
2009#ifdef VBOX_WITH_MSI_DEVICES
2010 PDMMSIREG aMsiReg;
2011
2012 RT_ZERO(aMsiReg);
2013 aMsiReg.cMsiVectors = 1;
2014 aMsiReg.iMsiCapOffset = 0x60;
2015 aMsiReg.iMsiNextOffset = 0x50;
2016 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg);
2017 if (RT_FAILURE (rc))
2018 {
2019 LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
2020 PCIDevSetCapabilityList (&pThis->dev, 0x50);
2021 }
2022#endif
2023
2024 rc = PDMDevHlpSSMRegister (pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
2025 if (RT_FAILURE (rc))
2026 return rc;
2027
2028 /*
2029 * Attach driver.
2030 */
2031 rc = PDMDevHlpDriverAttach (pDevIns, 0, &s->IBase,
2032 &s->pDrvBase, "Audio Driver Port");
2033 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2034 Log (("hda: No attached driver!\n"));
2035 else if (RT_FAILURE (rc))
2036 {
2037 AssertMsgFailed (("Failed to attach INTELHD LUN #0! rc=%Rrc\n", rc));
2038 return rc;
2039 }
2040
2041
2042
2043 pThis->hda.Codec.pHDAState = (void *)&pThis->hda;
2044 rc = codecConstruct(&pThis->hda.Codec, /* ALC885_CODEC */ STAC9220_CODEC);
2045 if (RT_FAILURE(rc))
2046 AssertRCReturn(rc, rc);
2047
2048 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
2049 verb F20 should provide device/codec recognition. */
2050 Assert(pThis->hda.Codec.u16VendorId);
2051 Assert(pThis->hda.Codec.u16DeviceId);
2052 PCIDevSetSubSystemVendorId (&pThis->dev, pThis->hda.Codec.u16VendorId); /* 2c ro - intel.) */
2053 PCIDevSetSubSystemId (&pThis->dev, pThis->hda.Codec.u16DeviceId); /* 2e ro. */
2054
2055 hdaReset (pDevIns);
2056 pThis->hda.Codec.id = 0;
2057 pThis->hda.Codec.pfnTransfer = hdaTransfer;
2058 pThis->hda.Codec.pfnReset = hdaCodecReset;
2059 /*
2060 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
2061 * hdaReset shouldn't affects these registers.
2062 */
2063 WAKEEN(&pThis->hda) = 0x0;
2064 STATESTS(&pThis->hda) = 0x0;
2065
2066 return VINF_SUCCESS;
2067}
2068
2069/**
2070 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2071 */
2072static DECLCALLBACK(int) hdaDestruct (PPDMDEVINS pDevIns)
2073{
2074 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2075
2076 int rc = codecDestruct(&pThis->hda.Codec);
2077 AssertRC(rc);
2078 if (pThis->hda.pu32CorbBuf)
2079 RTMemFree(pThis->hda.pu32CorbBuf);
2080 if (pThis->hda.pu64RirbBuf)
2081 RTMemFree(pThis->hda.pu64RirbBuf);
2082 return VINF_SUCCESS;
2083}
2084
2085/**
2086 * The device registration structure.
2087 */
2088const PDMDEVREG g_DeviceICH6_HDA =
2089{
2090 /* u32Version */
2091 PDM_DEVREG_VERSION,
2092 /* szName */
2093 "hda",
2094 /* szRCMod */
2095 "",
2096 /* szR0Mod */
2097 "",
2098 /* pszDescription */
2099 "ICH IntelHD Audio Controller",
2100 /* fFlags */
2101 PDM_DEVREG_FLAGS_DEFAULT_BITS,
2102 /* fClass */
2103 PDM_DEVREG_CLASS_AUDIO,
2104 /* cMaxInstances */
2105 1,
2106 /* cbInstance */
2107 sizeof(PCIINTELHDLinkState),
2108 /* pfnConstruct */
2109 hdaConstruct,
2110 /* pfnDestruct */
2111 hdaDestruct,
2112 /* pfnRelocate */
2113 NULL,
2114 /* pfnIOCtl */
2115 NULL,
2116 /* pfnPowerOn */
2117 NULL,
2118 /* pfnReset */
2119 hdaReset,
2120 /* pfnSuspend */
2121 NULL,
2122 /* pfnResume */
2123 NULL,
2124 /* pfnAttach */
2125 NULL,
2126 /* pfnDetach */
2127 NULL,
2128 /* pfnQueryInterface. */
2129 NULL,
2130 /* pfnInitComplete */
2131 NULL,
2132 /* pfnPowerOff */
2133 NULL,
2134 /* pfnSoftReset */
2135 NULL,
2136 /* u32VersionEnd */
2137 PDM_DEVREG_VERSION
2138};
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