VirtualBox

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

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

Audio/HDA: drop counters on stream reset. postpons stopping back-end voices to let complete the tasks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 95.8 KB
Line 
1/* $Id: DevIchIntelHDA.cpp 34153 2010-11-18 07:28:16Z 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 uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, int iNum)
629{
630 switch (ICH6_HDA_REG_SD0FIFOW + 10*iNum)
631 {
632 case ICH6_HDA_REG_SD0FIFOW:
633 case ICH6_HDA_REG_SD1FIFOW:
634 case ICH6_HDA_REG_SD2FIFOW:
635 case ICH6_HDA_REG_SD3FIFOW:
636 case ICH6_HDA_REG_SD4FIFOW:
637 case ICH6_HDA_REG_SD5FIFOW:
638 case ICH6_HDA_REG_SD6FIFOW:
639 case ICH6_HDA_REG_SD7FIFOW:
640 switch(HDA_REG_IND(pState, ICH6_HDA_REG_SD0FIFOW + 10*iNum))
641 {
642 case HDA_SDFIFOW_8B: return 8;
643 case HDA_SDFIFOW_16B: return 16;
644 case HDA_SDFIFOW_32B: return 32;
645 default:
646 AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, iNum), iNum));
647 }
648 default:
649 AssertMsgFailed(("hda: Not SDnFIFOW register"));
650 return 0;
651 }
652}
653
654static int hdaProcessInterrupt(INTELHDLinkState* pState)
655{
656#define IS_INTERRUPT_OCCURED_AND_ENABLED(pState, num) \
657 ( INTCTL_SX((pState), num) \
658 && (SDSTS(pState, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
659 bool fIrq = false;
660 if( INTCTL_CIE(pState)
661 && ( RIRBSTS_RINTFL(pState)
662 || RIRBSTS_RIRBOIS(pState)
663 || STATESTS(pState)))
664 {
665 fIrq = true;
666 }
667 if ( IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 0)
668 || IS_INTERRUPT_OCCURED_AND_ENABLED(pState, 4))
669 {
670 fIrq = true;
671 }
672 if (INTCTL_GIE(pState))
673 {
674 Log(("hda: irq %s\n", fIrq ? "asserted" : "deasserted"));
675 PDMDevHlpPCISetIrq(ICH6_HDASTATE_2_DEVINS(pState), 0 , fIrq);
676 }
677 return VINF_SUCCESS;
678}
679
680static int hdaLookup(INTELHDLinkState* pState, uint32_t u32Offset)
681{
682 int index = 0;
683 //** @todo r=michaln: A linear search of an array with over 100 elements is very inefficient.
684 for (;index < (int)(sizeof(s_ichIntelHDRegMap)/sizeof(s_ichIntelHDRegMap[0])); ++index)
685 {
686 if ( u32Offset >= s_ichIntelHDRegMap[index].offset
687 && u32Offset < s_ichIntelHDRegMap[index].offset + s_ichIntelHDRegMap[index].size)
688 {
689 return index;
690 }
691 }
692 /* Aliases HDA spec 3.3.45 */
693 switch(u32Offset)
694 {
695 case 0x2084:
696 return HDA_REG_IND_NAME(SD0LPIB);
697 case 0x20A4:
698 return HDA_REG_IND_NAME(SD1LPIB);
699 case 0x20C4:
700 return HDA_REG_IND_NAME(SD2LPIB);
701 case 0x20E4:
702 return HDA_REG_IND_NAME(SD3LPIB);
703 case 0x2104:
704 return HDA_REG_IND_NAME(SD4LPIB);
705 case 0x2124:
706 return HDA_REG_IND_NAME(SD5LPIB);
707 case 0x2144:
708 return HDA_REG_IND_NAME(SD6LPIB);
709 case 0x2164:
710 return HDA_REG_IND_NAME(SD7LPIB);
711 }
712 return -1;
713}
714
715static int hdaCmdSync(INTELHDLinkState *pState, bool fLocal)
716{
717 int rc = VINF_SUCCESS;
718 if (fLocal)
719 {
720 Assert((HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)));
721 rc = PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pState->u64CORBBase, pState->pu32CorbBuf, pState->cbCorbBuf);
722 if (RT_FAILURE(rc))
723 AssertRCReturn(rc, rc);
724#ifdef DEBUG_CMD_BUFFER
725 uint8_t i = 0;
726 do
727 {
728 Log(("hda: corb%02x: ", i));
729 uint8_t j = 0;
730 do
731 {
732 const char *prefix;
733 if ((i + j) == CORBRP(pState))
734 prefix = "[R]";
735 else if ((i + j) == CORBWP(pState))
736 prefix = "[W]";
737 else
738 prefix = " "; /* three spaces */
739 Log(("%s%08x", prefix, pState->pu32CorbBuf[i + j]));
740 j++;
741 } while (j < 8);
742 Log(("\n"));
743 i += 8;
744 } while(i != 0);
745#endif
746 }
747 else
748 {
749 Assert((HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA)));
750 rc = PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pState->u64RIRBBase, pState->pu64RirbBuf, pState->cbRirbBuf);
751 if (RT_FAILURE(rc))
752 AssertRCReturn(rc, rc);
753#ifdef DEBUG_CMD_BUFFER
754 uint8_t i = 0;
755 do {
756 Log(("hda: rirb%02x: ", i));
757 uint8_t j = 0;
758 do {
759 const char *prefix;
760 if ((i + j) == RIRBWP(pState))
761 prefix = "[W]";
762 else
763 prefix = " ";
764 Log((" %s%016lx", prefix, pState->pu64RirbBuf[i + j]));
765 } while (++j < 8);
766 Log(("\n"));
767 i += 8;
768 } while (i != 0);
769#endif
770 }
771 return rc;
772}
773
774static int hdaCORBCmdProcess(INTELHDLinkState *pState)
775{
776 int rc;
777 uint8_t corbRp;
778 uint8_t corbWp;
779 uint8_t rirbWp;
780
781 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
782
783 rc = hdaCmdSync(pState, true);
784 if (RT_FAILURE(rc))
785 AssertRCReturn(rc, rc);
786 corbRp = CORBRP(pState);
787 corbWp = CORBWP(pState);
788 rirbWp = RIRBWP(pState);
789 Assert((corbWp != corbRp));
790 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
791 while (corbRp != corbWp)
792 {
793 uint32_t cmd;
794 uint64_t resp;
795 corbRp++;
796 cmd = pState->pu32CorbBuf[corbRp];
797 rc = (pState)->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
798 if (RT_FAILURE(rc))
799 AssertRCReturn(rc, rc);
800 Assert(pfn);
801 (rirbWp)++;
802 rc = pfn(&pState->Codec, cmd, &resp);
803 if (RT_FAILURE(rc))
804 AssertRCReturn(rc, rc);
805 Log(("hda: verb:%08x->%016lx\n", cmd, resp));
806 if ( (resp & CODEC_RESPONSE_UNSOLICITED)
807 && !HDA_REG_FLAG_VALUE(pState, GCTL, UR))
808 {
809 Log(("hda: unexpected unsolicited response.\n"));
810 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
811 return rc;
812 }
813 pState->pu64RirbBuf[rirbWp] = resp;
814 pState->u8Counter++;
815 if (pState->u8Counter == RINTCNT_N(pState))
816 break;
817 }
818 pState->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
819 pState->au32Regs[ICH6_HDA_REG_RIRBWP] = rirbWp;
820 rc = hdaCmdSync(pState, false);
821 Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pState), CORBWP(pState), RIRBWP(pState)));
822 if (RIRBCTL_RIRB_RIC(pState))
823 {
824 RIRBSTS((pState)) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
825 pState->u8Counter = 0;
826 rc = hdaProcessInterrupt(pState);
827 }
828 if (RT_FAILURE(rc))
829 AssertRCReturn(rc, rc);
830 return rc;
831}
832
833static void hdaStreamReset(INTELHDLinkState *pState, uint32_t u32Offset)
834{
835 Log(("hda: reset of stream (%x) started\n", u32Offset));
836 Log(("hda: reset of stream (%x) finished\n", u32Offset));
837}
838
839
840DECLCALLBACK(int)hdaRegReadUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
841{
842 *pu32Value = 0;
843 return VINF_SUCCESS;
844}
845DECLCALLBACK(int)hdaRegWriteUnimplemented(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
846{
847 return VINF_SUCCESS;
848}
849/* U8 */
850DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
851{
852 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffffff00) == 0);
853 return hdaRegReadU32(pState, offset, index, pu32Value);
854}
855
856DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
857{
858 Assert(((u32Value & 0xffffff00) == 0));
859 return hdaRegWriteU32(pState, offset, index, u32Value);
860}
861/* U16 */
862DECLCALLBACK(int)hdaRegReadU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
863{
864 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xffff0000) == 0);
865 return hdaRegReadU32(pState, offset, index, pu32Value);
866}
867
868DECLCALLBACK(int)hdaRegWriteU16(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
869{
870 Assert(((u32Value & 0xffff0000) == 0));
871 return hdaRegWriteU32(pState, offset, index, u32Value);
872}
873
874/* U24 */
875DECLCALLBACK(int)hdaRegReadU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
876{
877 Assert(((pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable) & 0xff000000) == 0);
878 return hdaRegReadU32(pState, offset, index, pu32Value);
879}
880
881DECLCALLBACK(int)hdaRegWriteU24(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
882{
883 Assert(((u32Value & 0xff000000) == 0));
884 return hdaRegWriteU32(pState, offset, index, u32Value);
885}
886/* U32 */
887DECLCALLBACK(int)hdaRegReadU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
888{
889 *pu32Value = pState->au32Regs[index] & s_ichIntelHDRegMap[index].readable;
890 return VINF_SUCCESS;
891}
892
893DECLCALLBACK(int)hdaRegWriteU32(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
894{
895 pState->au32Regs[index] = (u32Value & s_ichIntelHDRegMap[index].writable)
896 | (pState->au32Regs[index] & ~s_ichIntelHDRegMap[index].writable);
897 return VINF_SUCCESS;
898}
899
900DECLCALLBACK(int)hdaRegReadGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
901{
902 return hdaRegReadU32(pState, offset, index, pu32Value);
903}
904
905DECLCALLBACK(int)hdaRegWriteGCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
906{
907 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
908 {
909 /* exit reset state */
910 GCTL(pState) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
911 pState->fInReset = false;
912 }
913 else
914 {
915 /* enter reset state*/
916 if ( HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA)
917 || HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA))
918 {
919 Log(("hda: HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
920 HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) ? "on" : "off",
921 HDA_REG_FLAG_VALUE(pState, RIRBCTL, DMA) ? "on" : "off"));
922 }
923 hdaReset(ICH6_HDASTATE_2_DEVINS(pState));
924 GCTL(pState) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
925 pState->fInReset = true;
926 }
927 if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
928 {
929 /* Flush: GSTS:1 set, see 6.2.6*/
930 GSTS(pState) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
931 /* DPLBASE and DPUBASE, should be initialized with initial value (see 6.2.6)*/
932 }
933 return VINF_SUCCESS;
934}
935
936DECLCALLBACK(int)hdaRegWriteSTATESTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
937{
938 uint32_t v = pState->au32Regs[index];
939 uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
940 pState->au32Regs[index] = (v ^ nv) & v; /* write of 1 clears corresponding bit */
941 return VINF_SUCCESS;
942}
943
944DECLCALLBACK(int)hdaRegReadINTSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
945{
946 uint32_t v = 0;
947 if ( RIRBSTS_RIRBOIS(pState)
948 || RIRBSTS_RINTFL(pState)
949 || HDA_REG_FLAG_VALUE(pState, CORBSTS, CMEI)
950 || STATESTS(pState))
951 v |= RT_BIT(30);
952#define HDA_IS_STREAM_EVENT(pState, stream) \
953 ( (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)) \
954 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)) \
955 || (SDSTS((pState),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
956#define MARK_STREAM(pState, stream, v) do {(v) |= HDA_IS_STREAM_EVENT((pState),stream) ? RT_BIT((stream)) : 0;}while(0)
957 MARK_STREAM(pState, 0, v);
958 MARK_STREAM(pState, 1, v);
959 MARK_STREAM(pState, 2, v);
960 MARK_STREAM(pState, 3, v);
961 MARK_STREAM(pState, 4, v);
962 MARK_STREAM(pState, 5, v);
963 MARK_STREAM(pState, 6, v);
964 MARK_STREAM(pState, 7, v);
965 v |= v ? RT_BIT(31) : 0;
966 *pu32Value = v;
967 return VINF_SUCCESS;
968}
969
970DECLCALLBACK(int)hdaRegReadGCAP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
971{
972 return hdaRegReadU16(pState, offset, index, pu32Value);
973}
974
975DECLCALLBACK(int)hdaRegWriteCORBRP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
976{
977 if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
978 CORBRP(pState) = 0;
979 else
980 return hdaRegWriteU8(pState, offset, index, u32Value);
981 return VINF_SUCCESS;
982}
983
984DECLCALLBACK(int)hdaRegWriteCORBCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
985{
986 int rc = hdaRegWriteU8(pState, offset, index, u32Value);
987 AssertRC(rc);
988 if ( CORBWP(pState) != CORBRP(pState)
989 && HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA) != 0)
990 return hdaCORBCmdProcess(pState);
991 return rc;
992}
993
994DECLCALLBACK(int)hdaRegWriteCORBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
995{
996 uint32_t v = CORBSTS(pState);
997 v = (v ^ u32Value) & v;
998 CORBSTS(pState) = v;
999 return VINF_SUCCESS;
1000}
1001
1002DECLCALLBACK(int)hdaRegWriteCORBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1003{
1004 int rc;
1005 rc = hdaRegWriteU16(pState, offset, index, u32Value);
1006 if (RT_FAILURE(rc))
1007 AssertRCReturn(rc, rc);
1008 if (CORBWP(pState) == CORBRP(pState))
1009 return VINF_SUCCESS;
1010 if (!HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1011 return VINF_SUCCESS;
1012 rc = hdaCORBCmdProcess(pState);
1013 return rc;
1014}
1015
1016DECLCALLBACK(int)hdaRegReadSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1017{
1018 return hdaRegReadU24(pState, offset, index, pu32Value);
1019}
1020#define HDA_STREAM_BITMASK(offset) (1 << (((offset) - 0x80) >> 5))
1021#define HDA_IS_STREAM_IN_RESET(pState, offset) ((pState)->u8StreamsInReset & HDA_STREAM_BITMASK((offset)))
1022DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1023{
1024 bool fOn = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
1025 int rc = VINF_SUCCESS;
1026 uint64_t u64BaseDMA = 0;
1027 if(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))
1028 {
1029 Log(("hda: guest has initiated hw stream reset\n"));
1030 pState->u8StreamsInReset |= HDA_STREAM_BITMASK(offset);
1031 hdaStreamReset(pState, offset);
1032 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
1033 }
1034 else if (HDA_IS_STREAM_IN_RESET(pState, offset))
1035 {
1036 PHDABDLEDESC pBdle = NULL;
1037 uint32_t *pu32Lpib = NULL;
1038 Log(("hda: guest has initiated exit of stream reset\n"));
1039 pState->u8StreamsInReset &= ~HDA_STREAM_BITMASK(offset);
1040 HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
1041 switch (index)
1042 {
1043 case ICH6_HDA_REG_SD0CTL:
1044 pBdle = &pState->stInBdle;
1045 pu32Lpib = &SDLPIB(pState, 0);
1046 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), 0);
1047 break;
1048 case ICH6_HDA_REG_SD4CTL:
1049 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
1050 fOn = fOn && u64BaseDMA;
1051 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), 0);
1052 pBdle = &pState->stOutBdle;
1053 pu32Lpib = &SDLPIB(pState, 4);
1054 break;
1055 default:
1056 Log(("Attempt to reset DMA state on unattached SDI(%s), ignored\n", s_ichIntelHDRegMap[index].abbrev));
1057 }
1058 if ( pBdle
1059 && pu32Lpib)
1060 {
1061 memset(pBdle, 0, sizeof(HDABDLEDESC));
1062 *pu32Lpib = 0;
1063 }
1064 }
1065 /*
1066 * Stopping streams we postpone up to reset exit to let HDA complete the tasks
1067 */
1068 switch (index)
1069 {
1070 case ICH6_HDA_REG_SD0CTL:
1071 if (fOn)
1072 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), 1);
1073 Log(("hda: DMA SD0CTL switched %s\n", fOn ? "on" : " off"));
1074 break;
1075 case ICH6_HDA_REG_SD4CTL:
1076 if (fOn)
1077 SDSTS(pState, 4) &= ~(1<<5);
1078 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
1079 fOn = fOn && u64BaseDMA;
1080 if (fOn)
1081 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), 1);
1082 Log(("hda: DMA SD4CTL switched %s\n", fOn ? "on" : " off"));
1083 break;
1084 default:
1085 Log(("Attempt to modify DMA state on unattached SDI(%s), ignored\n", s_ichIntelHDRegMap[index].abbrev));
1086 break;
1087 }
1088 rc = hdaRegWriteU24(pState, offset, index, u32Value);
1089 if (RT_FAILURE(rc))
1090 AssertRCReturn(rc, VINF_SUCCESS);
1091 return rc;
1092}
1093
1094DECLCALLBACK(int)hdaRegWriteSDSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1095{
1096 uint32_t v = HDA_REG_IND(pState, index);
1097 v ^= (u32Value & v);
1098 HDA_REG_IND(pState, index) = v;
1099 hdaProcessInterrupt(pState);
1100#if 0
1101 if ( v != u32Value
1102 && (INTCTL_SALL(pState) & (1 << ((offset - 0x83) >> 5))))
1103 {
1104 int rc;
1105 rc = hdaProcessInterrupt(pState);
1106 if (RT_FAILURE(rc))
1107 AssertRCReturn(rc, rc);
1108 }
1109#endif
1110 return VINF_SUCCESS;
1111}
1112DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1113{
1114 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1115 if (RT_FAILURE(rc))
1116 AssertRCReturn(rc, VINF_SUCCESS);
1117 return rc;
1118}
1119
1120DECLCALLBACK(int)hdaRegWriteSDFIFOW(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1121{
1122 switch (u32Value)
1123 {
1124 case HDA_SDFIFOW_8B:
1125 case HDA_SDFIFOW_16B:
1126 case HDA_SDFIFOW_32B:
1127 return hdaRegWriteU16(pState, offset, index, u32Value);
1128 default:
1129 Log(("hda: Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
1130 return hdaRegWriteU16(pState, offset, index, HDA_SDFIFOW_32B);
1131 }
1132 return VINF_SUCCESS;
1133}
1134/*
1135 * Note this method could be called for changing value on Output Streams only (ICH6 datacheet 18.2.39)
1136 *
1137 */
1138DECLCALLBACK(int)hdaRegWriteSDFIFOS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1139{
1140 switch (index)
1141 {
1142 /* SDInFIFOS is RO, n=0-3 */
1143 case ICH6_HDA_REG_SD0FIFOS:
1144 case ICH6_HDA_REG_SD1FIFOS:
1145 case ICH6_HDA_REG_SD2FIFOS:
1146 case ICH6_HDA_REG_SD3FIFOS:
1147 Log(("hda: Guest tries change value of FIFO size of Input Stream\n"));
1148 return VINF_SUCCESS;
1149 case ICH6_HDA_REG_SD4FIFOS:
1150 case ICH6_HDA_REG_SD5FIFOS:
1151 case ICH6_HDA_REG_SD6FIFOS:
1152 case ICH6_HDA_REG_SD7FIFOS:
1153 switch(u32Value)
1154 {
1155 case HDA_SDONFIFO_16B:
1156 case HDA_SDONFIFO_32B:
1157 case HDA_SDONFIFO_64B:
1158 case HDA_SDONFIFO_128B:
1159 case HDA_SDONFIFO_192B:
1160 return hdaRegWriteU16(pState, offset, index, u32Value);
1161
1162 case HDA_SDONFIFO_256B:
1163 Log(("hda: 256 bit is unsupported, HDA is switched into 192B mode\n"));
1164 default:
1165 return hdaRegWriteU16(pState, offset, index, HDA_SDONFIFO_192B);
1166 }
1167 return VINF_SUCCESS;
1168 default:
1169 AssertMsgFailed(("Something wierd happens with register lookup routine"));
1170 }
1171 return VINF_SUCCESS;
1172}
1173
1174DECLCALLBACK(int)hdaRegWriteSDBDPL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1175{
1176 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1177 if (RT_FAILURE(rc))
1178 AssertRCReturn(rc, VINF_SUCCESS);
1179 return rc;
1180}
1181
1182DECLCALLBACK(int)hdaRegWriteSDBDPU(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1183{
1184 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1185 if (RT_FAILURE(rc))
1186 AssertRCReturn(rc, VINF_SUCCESS);
1187 return rc;
1188}
1189
1190DECLCALLBACK(int)hdaRegReadIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value)
1191{
1192 int rc = VINF_SUCCESS;
1193 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
1194 if ( CORBWP(pState) != CORBRP(pState)
1195 || HDA_REG_FLAG_VALUE(pState, CORBCTL, DMA))
1196 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1197
1198 rc = hdaRegReadU32(pState, offset, index, pu32Value);
1199 return rc;
1200}
1201
1202DECLCALLBACK(int)hdaRegWriteIRS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1203{
1204 int rc = VINF_SUCCESS;
1205 uint64_t resp;
1206 PFNCODECVERBPROCESSOR pfn = (PFNCODECVERBPROCESSOR)NULL;
1207 /*
1208 * if guest set ICB bit of IRS register HDA should process verb in IC register and
1209 * writes response in IR register and set IRV (valid in case of success) bit of IRS register.
1210 */
1211 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
1212 && !IRS_ICB(pState))
1213 {
1214 uint32_t cmd = IC(pState);
1215 if (CORBWP(pState) != CORBRP(pState))
1216 {
1217 /*
1218 * 3.4.3 defines behaviour of immediate Command status register.
1219 */
1220 LogRel(("hda: guest has tried process immediate verb (%x) with active CORB\n", cmd));
1221 return rc;
1222 }
1223 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy */
1224 Log(("hda: IC:%x\n", cmd));
1225 rc = pState->Codec.pfnLookup(&pState->Codec, cmd, &pfn);
1226 if (RT_FAILURE(rc))
1227 AssertRCReturn(rc, rc);
1228 rc = pfn(&pState->Codec, cmd, &resp);
1229 if (RT_FAILURE(rc))
1230 AssertRCReturn(rc, rc);
1231 IR(pState) = (uint32_t)resp;
1232 Log(("hda: IR:%x\n", IR(pState)));
1233 IRS(pState) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV); /* result is ready */
1234 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
1235 return rc;
1236 }
1237 /*
1238 * when guest's read the response it should clean the IRV bit of the IRS register.
1239 */
1240 if ( u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
1241 && IRS_IRV(pState))
1242 IRS(pState) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
1243 return rc;
1244}
1245
1246DECLCALLBACK(int)hdaRegWriteRIRBWP(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1247{
1248 if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
1249 {
1250 RIRBWP(pState) = 0;
1251 }
1252 /*The rest of bits are O, see 6.2.22 */
1253 return VINF_SUCCESS;
1254}
1255
1256DECLCALLBACK(int)hdaRegWriteBase(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1257{
1258 int rc = hdaRegWriteU32(pState, offset, index, u32Value);
1259 if (RT_FAILURE(rc))
1260 AssertRCReturn(rc, rc);
1261 switch(index)
1262 {
1263 case ICH6_HDA_REG_CORBLBASE:
1264 pState->u64CORBBase &= 0xFFFFFFFF00000000ULL;
1265 pState->u64CORBBase |= pState->au32Regs[index];
1266 break;
1267 case ICH6_HDA_REG_CORBUBASE:
1268 pState->u64CORBBase &= 0x00000000FFFFFFFFULL;
1269 pState->u64CORBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1270 break;
1271 case ICH6_HDA_REG_RIRLBASE:
1272 pState->u64RIRBBase &= 0xFFFFFFFF00000000ULL;
1273 pState->u64RIRBBase |= pState->au32Regs[index];
1274 break;
1275 case ICH6_HDA_REG_RIRUBASE:
1276 pState->u64RIRBBase &= 0x00000000FFFFFFFFULL;
1277 pState->u64RIRBBase |= ((uint64_t)pState->au32Regs[index] << 32);
1278 break;
1279 case ICH6_HDA_REG_DPLBASE:
1280 /* @todo: first bit has special meaning */
1281 pState->u64DPBase &= 0xFFFFFFFF00000000ULL;
1282 pState->u64DPBase |= pState->au32Regs[index];
1283 break;
1284 case ICH6_HDA_REG_DPUBASE:
1285 pState->u64DPBase &= 0x00000000FFFFFFFFULL;
1286 pState->u64DPBase |= ((uint64_t)pState->au32Regs[index] << 32);
1287 break;
1288 default:
1289 AssertMsgFailed(("Invalid index"));
1290 }
1291 Log(("hda: CORB base:%llx RIRB base: %llx DP base: %llx\n", pState->u64CORBBase, pState->u64RIRBBase, pState->u64DPBase));
1292 return rc;
1293}
1294
1295DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
1296{
1297 uint8_t nv = u32Value;
1298 uint8_t v = RIRBSTS(pState);
1299 RIRBSTS(pState) = (v ^ nv) & v;
1300
1301 return hdaProcessInterrupt(pState);
1302}
1303
1304static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1305{
1306 uint64_t addr;
1307 uint32_t len;
1308 uint32_t ioc;
1309 uint8_t bdle[16];
1310 uint32_t counter;
1311 uint32_t i;
1312 uint32_t sum = 0;
1313 Assert(pBdle && pBdle->u32BdleMaxCvi);
1314 for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
1315 {
1316 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + i*16, bdle, 16);
1317 addr = *(uint64_t *)bdle;
1318 len = *(uint32_t *)&bdle[8];
1319 ioc = *(uint32_t *)&bdle[12];
1320 Log(("hda: %s bdle[%d] a:%llx, len:%d, ioc:%d\n", (i == pBdle->u32BdleCvi? "[C]": " "), i, addr, len, ioc & 0x1));
1321 sum += len;
1322 }
1323 Log(("hda: sum: %d\n", sum));
1324 for (i = 0; i < 8; ++i)
1325 {
1326 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), (pState->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
1327 Log(("hda: %s stream[%d] counter=%x\n", i == SDCTL_NUM(pState, 4) || i == SDCTL_NUM(pState, 0)? "[C]": " ",
1328 i , counter));
1329 }
1330}
1331static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
1332{
1333 uint8_t bdle[16];
1334 Assert((u64BaseDMA && pBdle && pBdle->u32BdleMaxCvi));
1335 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
1336 pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
1337 pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
1338 pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
1339 dump_bd(pState, pBdle, u64BaseDMA);
1340}
1341
1342static uint32_t hdaReadAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
1343{
1344 PHDABDLEDESC pBdle = &pState->stInBdle;
1345 uint32_t cbTransfered = 0;
1346 while( *pu32Avail
1347 && pBdle->u32BdleCviPos < pBdle->u32BdleCviLen)
1348 {
1349 uint32_t cb2Copy = 0;
1350 uint32_t cbBackendCopy = 0;
1351 bool fUnderFifoCleared = false;
1352 if ( !pBdle->u32BdleCviLen
1353 || (*pu32Avail < hdaFifoWToSz(pState, 0)))
1354 {
1355 *fStop = true;
1356 return 0;
1357 }
1358 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1359 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
1360 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
1361 cb2Copy = RT_MIN(cb2Copy, SDFIFOS(pState, 0) + 1 - pBdle->cbUnderFifoW); /* we may increase the counter in range of [0, FIFOS(pState, 4) + 1] */
1362 Assert((*pu32Avail > 0));
1363 cb2Copy = RT_MIN(cb2Copy, *pu32Avail); /* sanity check to avoid overriding sound backend buffer */
1364 cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
1365 if ( !cb2Copy
1366 || cb2Copy < pBdle->cbUnderFifoW)
1367 {
1368 *fStop = true;
1369 return 0;
1370 }
1371
1372 /*
1373 * read from backend input line
1374 */
1375 cbBackendCopy = AUD_read (ISD0FMT_TO_AUDIO_SELECTOR(pState), pBdle->au8HdaBuffer, cb2Copy);
1376 /*
1377 * write on the HDA DMA
1378 */
1379 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy);
1380
1381 Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
1382 *pu32Avail -= cb2Copy;
1383 pBdle->u32BdleCviPos += RT_MIN(cb2Copy, cbBackendCopy);
1384 if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pState, 0))
1385 {
1386 Log(("hda:ra: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1387 cbTransfered += cbBackendCopy + pBdle->cbUnderFifoW;
1388 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbBackendCopy);
1389 Assert(!pBdle->cbUnderFifoW); /* we assume, we've read Under FIFO W fully */
1390 }
1391 else
1392 {
1393 Log(("hda:ra: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1394 pBdle->cbUnderFifoW += RT_MIN(cbBackendCopy, cb2Copy);
1395 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, 0)));
1396 *fStop = true;
1397 break;
1398 }
1399 Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1400 if ( cbTransfered == (SDFIFOS(pState, 0) + 1)
1401 || pBdle->u32BdleCviLen == pBdle->u32BdleCviPos)
1402 break;
1403 }
1404 Assert((cbTransfered <= (SDFIFOS(pState, 0) + 1)));
1405 Log(("hda:ra: cbTransfered: %d\n", cbTransfered));
1406 return cbTransfered;
1407}
1408
1409static uint32_t hdaWriteAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
1410{
1411 PHDABDLEDESC pBdle = &pState->stOutBdle;
1412 uint32_t cbTransfered = 0;
1413 /*
1414 * We're coping data from DMA using chuks of size FIFOS(pState, 4) + 1
1415 */
1416 while( *pu32Avail
1417 && pBdle->u32BdleCviPos < pBdle->u32BdleCviLen)
1418 {
1419 uint32_t cb2Copy = 0; /* local byte counter (on local buffer) */
1420 uint32_t cbBackendCopy = 0; /* local byte counter, how many bytes copied to backend */
1421 Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1422 /* border check assert */
1423 if ( ( !pBdle->u32BdleCviLen
1424 && (pBdle->cbUnderFifoW < hdaFifoWToSz(pState, 4)))
1425 || *pu32Avail < hdaFifoWToSz(pState, 4))
1426 {
1427 /* buffer length is 0, to little data on marked as "under FIFOW" to send to backed.*/
1428 Log(("hda:wa: exits CVI(iAvail:%d, cbUnderFifoW:%d, cvi:%d, len:%d)\n", *pu32Avail, pBdle->u32BdleCviLen, pBdle->u32BdleCvi, pBdle->cbUnderFifoW));
1429 *fStop = true;
1430 return 0;
1431 }
1432 /*
1433 * Amounts of bytes depends on current position in buffer (u32BdleCviLen-u32BdleCviPos)
1434 */
1435 if (pBdle->u32BdleCviLen)
1436 {
1437 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
1438 cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos; /* align copy buffer to size of trailing space in BDLE buffer */
1439 cb2Copy = RT_MIN(cb2Copy, SDFIFOS(pState, 4) + 1 - pBdle->cbUnderFifoW); /* we may increase the counter in range of [0, FIFOS(pState, 4) + 1] */
1440 cb2Copy = RT_MIN(cb2Copy, *pu32Avail); /* align copying buffer size up to size of back end buffer */
1441 cb2Copy = RT_MIN(cb2Copy, u32CblLimit); /* avoid LCBL overrun */
1442 }
1443 if ( cb2Copy == 0
1444 && pBdle->cbUnderFifoW < hdaFifoWToSz(pState, 4))
1445 {
1446 Log(("hda:wa: amount of bytes to copy is zero and (cbUnderFifoW:%d < %d)\n", pBdle->cbUnderFifoW, hdaFifoWToSz(pState, 4)));
1447 *fStop = true;
1448 return 0;
1449 }
1450
1451 /*
1452 * Copy from DMA to the corresponding hdaBuffer (if there exists some bytes from the previous not reported transfer we write to ''pBdle->cbUnderFifoW'' offset)
1453 */
1454 if (cb2Copy)
1455 PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
1456 /*
1457 * Write to audio backend.
1458 */
1459 if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, 4))
1460 {
1461 /*
1462 * We feed backend with new portion of fetched samples including not reported.
1463 */
1464 cbBackendCopy = AUD_write (OSD0FMT_TO_AUDIO_SELECTOR(pState), pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
1465 Assert((cbBackendCopy));
1466 /* Assertion!!! It was copied less than cbUnderFifoW
1467 * Probably we need to move the buffer, but it rather hard to imagine situation
1468 * why it may happen.
1469 */
1470 Assert((cbBackendCopy == pBdle->cbUnderFifoW + cb2Copy)); /* we assume that we write whole buffer including not reported bytes */
1471 if ( pBdle->cbUnderFifoW
1472 && pBdle->cbUnderFifoW <= cbBackendCopy)
1473 Log(("hda:wa: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1474
1475 pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbBackendCopy);
1476 pBdle->u32BdleCviPos += RT_MIN(cb2Copy, cbBackendCopy);
1477 Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32Avail >= cbBackendCopy)); /* sanity */
1478 Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Assumption failed */
1479 *pu32Avail -= cbBackendCopy;
1480 cbTransfered += cbBackendCopy;
1481 }
1482 else
1483 {
1484 Log(("hda:wa: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
1485 pBdle->cbUnderFifoW += cb2Copy;
1486 pBdle->u32BdleCviPos += cb2Copy;
1487 Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, 4)));
1488 break;
1489 }
1490 Log(("hda:wa: CVI(pos:%d, len:%d, cbTransfered:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransfered));
1491
1492 Assert((cbTransfered <= (SDFIFOS(pState, 4) + 1)));
1493 if ( cbTransfered == (SDFIFOS(pState, 4) + 1)
1494 || pBdle->u32BdleCviLen == pBdle->u32BdleCviPos)
1495 break;
1496 }
1497 Assert((cbTransfered <= (SDFIFOS(pState, 4) + 1)));
1498 Log(("hda:wa: cbTransfered: %d\n", cbTransfered));
1499 return cbTransfered;
1500}
1501
1502DECLCALLBACK(int) hdaCodecReset(CODECState *pCodecState)
1503{
1504 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1505 return VINF_SUCCESS;
1506}
1507
1508DECLCALLBACK(void) hdaTransfer(CODECState *pCodecState, ENMSOUNDSOURCE src, int avail)
1509{
1510 bool fStop = false;
1511 uint64_t u64BaseDMA = 0;
1512 PHDABDLEDESC pBdle = NULL;
1513 INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
1514 uint32_t nBytes;
1515 uint32_t u32Ctl;
1516 uint32_t *pu32Sts;
1517 uint8_t u8Strm;
1518 uint32_t *pu32Lpib;
1519 uint32_t u32Cbl;
1520 uint32_t u32Fifos;
1521 uint32_t u32Fifow;
1522 switch (src)
1523 {
1524 case PO_INDEX:
1525 {
1526 u8Strm = 4;
1527 u32Ctl = SDCTL(pState, 4);
1528 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
1529 pu32Lpib = &SDLPIB(pState, 4);
1530 pu32Sts = &SDSTS(pState, 4);
1531 u32Cbl = SDLCBL(pState, 4);
1532 pBdle = &pState->stOutBdle;
1533 pBdle->u32BdleMaxCvi = SDLVI(pState, 4);
1534 u32Fifos = SDFIFOS(pState, 4);
1535 u32Fifow = hdaFifoWToSz(pState, 4);
1536 break;
1537 }
1538 case PI_INDEX:
1539 {
1540 u8Strm = 0;
1541 u32Ctl = SDCTL(pState, 0);
1542 pu32Lpib = &SDLPIB(pState, 0);
1543 pu32Sts = &SDSTS(pState, 0);
1544 u32Cbl = SDLCBL(pState, 0);
1545 u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 0), SDBDPU(pState, 0));
1546 pBdle = &pState->stInBdle;
1547 pBdle->u32BdleMaxCvi = SDLVI(pState, 0);
1548 u32Fifos = SDFIFOS(pState, 0);
1549 u32Fifow = hdaFifoWToSz(pState, 0);
1550 break;
1551 }
1552 default:
1553 return;
1554 }
1555 if ( !(u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
1556 || !avail
1557 || !u64BaseDMA)
1558 return;
1559 /* Fetch the Buffer Descriptor Entry (BDE). */
1560 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1561 fetch_bd(pState, pBdle, u64BaseDMA);
1562 while( avail && !fStop)
1563 {
1564 Assert((avail >= 0 && (u32Cbl >= (*pu32Lpib)))); /* sanity */
1565 uint32_t u32CblLimit = u32Cbl - (*pu32Lpib);
1566 Log(("hda: CBL=%d, LPIB=%d\n", u32Cbl, *pu32Lpib));
1567 switch (src)
1568 {
1569 case PO_INDEX:
1570 nBytes = hdaWriteAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit);
1571 break;
1572 case PI_INDEX:
1573 nBytes = hdaReadAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit);
1574 break;
1575 default:
1576 nBytes = 0;
1577 fStop = true;
1578 AssertMsgFailed(("Unsupported"));
1579 }
1580 /*
1581 * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything.
1582 * (ICH6 datasheet 18.2.38)
1583 */
1584 Assert(nBytes <= (u32Fifos + 1));
1585 if (!pBdle->cbUnderFifoW)
1586 {
1587 *pu32Lpib += nBytes;
1588
1589 /*
1590 * Assert. Overlapping of buffer counter shouldn't happen.
1591 */
1592 Assert((*pu32Lpib <= u32Cbl));
1593
1594 /* Optionally write back the current DMA position. */
1595 if (pState->u64DPBase & DPBASE_ENABLED)
1596 PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState),
1597 (pState->u64DPBase & DPBASE_ADDR_MASK) + u8Strm*8, pu32Lpib, sizeof(*pu32Lpib));
1598
1599 }
1600 /* Process end of buffer condition. */
1601 if ( pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
1602 || *pu32Lpib == u32Cbl)
1603 {
1604 if ( !pBdle->cbUnderFifoW
1605 && pBdle->fBdleCviIoc)
1606 {
1607 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
1608 hdaProcessInterrupt(pState);
1609 *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1610 }
1611 if (*pu32Lpib == u32Cbl)
1612 *pu32Lpib -= u32Cbl;
1613
1614 if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
1615 {
1616 pBdle->u32BdleCviPos = 0;
1617 pBdle->u32BdleCvi++;
1618 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
1619 pBdle->u32BdleCvi = 0;
1620
1621 fetch_bd(pState, pBdle, u64BaseDMA);
1622 }
1623 if (nBytes > (u32Fifow))
1624 fStop = true;
1625 }
1626 }
1627 *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
1628}
1629
1630/**
1631 * Handle register read operation.
1632 *
1633 * Looks up and calls appropriate handler.
1634 *
1635 * @note: while implementation was detected so called "forgotten" or "hole" registers
1636 * which description is missed in RPM, datasheet or spec.
1637 *
1638 * @returns VBox status code.
1639 *
1640 * @param pState The device state structure.
1641 * @param uOffset Register offset in memory-mapped frame.
1642 * @param pv Where to fetch the value.
1643 * @param cb Number of bytes to write.
1644 * @thread EMT
1645 */
1646PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
1647{
1648 int rc = VINF_SUCCESS;
1649 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1650 uint32_t u32Offset = GCPhysAddr - pThis->hda.addrMMReg;
1651 int index = hdaLookup(&pThis->hda, u32Offset);
1652 if (pThis->hda.fInReset && index != ICH6_HDA_REG_GCTL)
1653 {
1654 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1655 }
1656 if ( index == -1
1657 || cb > 4)
1658 {
1659 LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", u32Offset, cb));
1660 }
1661 if (index != -1)
1662 {
1663 uint32_t mask = 0;
1664 uint32_t shift = (u32Offset - s_ichIntelHDRegMap[index].offset) % sizeof(uint32_t) * 8;
1665 uint32_t v = 0;
1666 switch(cb)
1667 {
1668 case 1: mask = 0x000000ff; break;
1669 case 2: mask = 0x0000ffff; break;
1670 case 3: mask = 0x00ffffff; break;
1671 case 4: mask = 0xffffffff; break;
1672 }
1673 mask <<= shift;
1674 rc = s_ichIntelHDRegMap[index].pfnRead(&pThis->hda, u32Offset, index, &v);
1675 *(uint32_t *)pv = (v & mask) >> shift;
1676 Log(("hda: read %s[%x/%x]\n", s_ichIntelHDRegMap[index].abbrev, v, *(uint32_t *)pv));
1677 return rc;
1678 }
1679 *(uint32_t *)pv = 0xFF;
1680 Log(("hda: hole at %X is accessed for read\n", u32Offset));
1681 return rc;
1682}
1683
1684/**
1685 * Handle register write operation.
1686 *
1687 * Looks up and calls appropriate handler.
1688 *
1689 * @returns VBox status code.
1690 *
1691 * @param pState The device state structure.
1692 * @param uOffset Register offset in memory-mapped frame.
1693 * @param pv Where to fetch the value.
1694 * @param cb Number of bytes to write.
1695 * @thread EMT
1696 */
1697PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
1698{
1699 int rc = VINF_SUCCESS;
1700 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1701 uint32_t u32Offset = GCPhysAddr - pThis->hda.addrMMReg;
1702 int index = hdaLookup(&pThis->hda, u32Offset);
1703 if (pThis->hda.fInReset && index != ICH6_HDA_REG_GCTL)
1704 {
1705 Log(("hda: access to registers except GCTL is blocked while reset\n"));
1706 }
1707 if ( index == -1
1708 || cb > 4)
1709 {
1710 LogRel(("hda: Invalid write access @0x%x(of bytes:%d)\n", u32Offset, cb));
1711 }
1712 if (index != -1)
1713 {
1714 uint32_t v = pThis->hda.au32Regs[index];
1715 uint32_t mask = 0;
1716 uint32_t shift = (u32Offset - s_ichIntelHDRegMap[index].offset) % sizeof(uint32_t) * 8;
1717 switch(cb)
1718 {
1719 case 1: mask = 0xffffff00; break;
1720 case 2: mask = 0xffff0000; break;
1721 case 3: mask = 0xff000000; break;
1722 case 4: mask = 0x00000000; break;
1723 }
1724 mask <<= shift;
1725 *(uint32_t *)pv = ((v & mask) | (*(uint32_t *)pv & ~mask)) >> shift;
1726 rc = s_ichIntelHDRegMap[index].pfnWrite(&pThis->hda, u32Offset, index, *(uint32_t *)pv);
1727 Log(("hda: write %s:(%x) %x => %x\n", s_ichIntelHDRegMap[index].abbrev, *(uint32_t *)pv, v, pThis->hda.au32Regs[index]));
1728 return rc;
1729 }
1730 Log(("hda: hole at %X is accessed for write\n", u32Offset));
1731 return rc;
1732}
1733
1734/**
1735 * Callback function for mapping a PCI I/O region.
1736 *
1737 * @return VBox status code.
1738 * @param pPciDev Pointer to PCI device.
1739 * Use pPciDev->pDevIns to get the device instance.
1740 * @param iRegion The region number.
1741 * @param GCPhysAddress Physical address of the region.
1742 * If iType is PCI_ADDRESS_SPACE_IO, this is an
1743 * I/O port, else it's a physical address.
1744 * This address is *NOT* relative
1745 * to pci_mem_base like earlier!
1746 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
1747 */
1748static DECLCALLBACK(int) hdaMap (PPCIDEVICE pPciDev, int iRegion,
1749 RTGCPHYS GCPhysAddress, uint32_t cb,
1750 PCIADDRESSSPACE enmType)
1751{
1752 int rc;
1753 PPDMDEVINS pDevIns = pPciDev->pDevIns;
1754 RTIOPORT Port = (RTIOPORT)GCPhysAddress;
1755 PCIINTELHDLinkState *pThis = PCIDEV_2_ICH6_HDASTATE(pPciDev);
1756
1757 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
1758 rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, 0,
1759 hdaMMIOWrite, hdaMMIORead, NULL, "ICH6_HDA");
1760
1761 if (RT_FAILURE(rc))
1762 return rc;
1763
1764 pThis->hda.addrMMReg = GCPhysAddress;
1765 return VINF_SUCCESS;
1766}
1767
1768/**
1769 * Saves a state of the HDA device.
1770 *
1771 * @returns VBox status code.
1772 * @param pDevIns The device instance.
1773 * @param pSSMHandle The handle to save the state to.
1774 */
1775static DECLCALLBACK(int) hdaSaveExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
1776{
1777 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1778 /* Save Codec nodes states */
1779 codecSaveState(&pThis->hda.Codec, pSSMHandle);
1780 /* Save MMIO registers */
1781 SSMR3PutMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
1782 /* Save HDA dma counters */
1783 SSMR3PutMem (pSSMHandle, &pThis->hda.stOutBdle, sizeof (HDABDLEDESC));
1784 SSMR3PutMem (pSSMHandle, &pThis->hda.stMicBdle, sizeof (HDABDLEDESC));
1785 SSMR3PutMem (pSSMHandle, &pThis->hda.stInBdle, sizeof (HDABDLEDESC));
1786 return VINF_SUCCESS;
1787}
1788
1789/**
1790 * Loads a saved HDA device state.
1791 *
1792 * @returns VBox status code.
1793 * @param pDevIns The device instance.
1794 * @param pSSMHandle The handle to the saved state.
1795 * @param uVersion The data unit version number.
1796 * @param uPass The data pass.
1797 */
1798static DECLCALLBACK(int) hdaLoadExec (PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
1799 uint32_t uVersion, uint32_t uPass)
1800{
1801 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1802 /* Load Codec nodes states */
1803 AssertMsgReturn (uVersion == HDA_SSM_VERSION, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1804 Assert (uPass == SSM_PASS_FINAL); NOREF(uPass);
1805
1806 codecLoadState(&pThis->hda.Codec, pSSMHandle);
1807 /* Load MMIO registers */
1808 SSMR3GetMem (pSSMHandle, pThis->hda.au32Regs, sizeof (pThis->hda.au32Regs));
1809 /* Load HDA dma counters */
1810 SSMR3GetMem (pSSMHandle, &pThis->hda.stOutBdle, sizeof (HDABDLEDESC));
1811 SSMR3GetMem (pSSMHandle, &pThis->hda.stMicBdle, sizeof (HDABDLEDESC));
1812 SSMR3GetMem (pSSMHandle, &pThis->hda.stInBdle, sizeof (HDABDLEDESC));
1813
1814 AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(&pThis->hda), SDCTL(&pThis->hda, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1815 AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(&pThis->hda), SDCTL(&pThis->hda, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
1816
1817 pThis->hda.u64CORBBase = CORBLBASE(&pThis->hda);
1818 pThis->hda.u64CORBBase |= ((uint64_t)CORBUBASE(&pThis->hda)) << 32;
1819 pThis->hda.u64RIRBBase = RIRLBASE(&pThis->hda);
1820 pThis->hda.u64RIRBBase |= ((uint64_t)RIRUBASE(&pThis->hda)) << 32;
1821 pThis->hda.u64DPBase = DPLBASE(&pThis->hda);
1822 pThis->hda.u64DPBase |= ((uint64_t)DPUBASE(&pThis->hda)) << 32;
1823 return VINF_SUCCESS;
1824}
1825
1826/**
1827 * Reset notification.
1828 *
1829 * @returns VBox status.
1830 * @param pDevIns The device instance data.
1831 *
1832 * @remark The original sources didn't install a reset handler, but it seems to
1833 * make sense to me so we'll do it.
1834 */
1835static DECLCALLBACK(void) hdaReset (PPDMDEVINS pDevIns)
1836{
1837 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1838 GCAP(&pThis->hda) = 0x4401; /* see 6.2.1 */
1839 VMIN(&pThis->hda) = 0x00; /* see 6.2.2 */
1840 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
1841 VMAJ(&pThis->hda) = 0x01; /* see 6.2.3 */
1842 OUTPAY(&pThis->hda) = 0x003C; /* see 6.2.4 */
1843 INPAY(&pThis->hda) = 0x001D; /* see 6.2.5 */
1844 pThis->hda.au32Regs[ICH6_HDA_REG_CORBSIZE] = 0x42; /* see 6.2.1 */
1845 pThis->hda.au32Regs[ICH6_HDA_REG_RIRBSIZE] = 0x42; /* see 6.2.1 */
1846 CORBRP(&pThis->hda) = 0x0;
1847 RIRBWP(&pThis->hda) = 0x0;
1848
1849 Log(("hda: inter HDA reset.\n"));
1850 pThis->hda.cbCorbBuf = 256 * sizeof(uint32_t);
1851
1852 if (pThis->hda.pu32CorbBuf)
1853 memset(pThis->hda.pu32CorbBuf, 0, pThis->hda.cbCorbBuf);
1854 else
1855 pThis->hda.pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->hda.cbCorbBuf);
1856
1857 pThis->hda.cbRirbBuf = 256 * sizeof(uint64_t);
1858 if (pThis->hda.pu64RirbBuf)
1859 memset(pThis->hda.pu64RirbBuf, 0, pThis->hda.cbRirbBuf);
1860 else
1861 pThis->hda.pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->hda.cbRirbBuf);
1862
1863 /* According to ICH6 datasheet, 0x40000 is default value for stream descriptor register 23:20
1864 * bits are reserved for stream number 18.2.33 */
1865 SDCTL(&pThis->hda, 0) = 0x40000;
1866 SDCTL(&pThis->hda, 1) = 0x40000;
1867 SDCTL(&pThis->hda, 2) = 0x40000;
1868 SDCTL(&pThis->hda, 3) = 0x40000;
1869 SDCTL(&pThis->hda, 4) = 0x40000;
1870 SDCTL(&pThis->hda, 5) = 0x40000;
1871 SDCTL(&pThis->hda, 6) = 0x40000;
1872 SDCTL(&pThis->hda, 7) = 0x40000;
1873
1874 /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
1875 SDFIFOS(&pThis->hda, 0) = HDA_SDINFIFO_120B;
1876 SDFIFOS(&pThis->hda, 1) = HDA_SDINFIFO_120B;
1877 SDFIFOS(&pThis->hda, 2) = HDA_SDINFIFO_120B;
1878 SDFIFOS(&pThis->hda, 3) = HDA_SDINFIFO_120B;
1879
1880 SDFIFOS(&pThis->hda, 4) = HDA_SDONFIFO_192B;
1881 SDFIFOS(&pThis->hda, 5) = HDA_SDONFIFO_192B;
1882 SDFIFOS(&pThis->hda, 6) = HDA_SDONFIFO_192B;
1883 SDFIFOS(&pThis->hda, 7) = HDA_SDONFIFO_192B;
1884
1885 SDFIFOW(&pThis->hda, 0) = HDA_SDFIFOW_8B;
1886 SDFIFOW(&pThis->hda, 4) = HDA_SDFIFOW_32B;
1887
1888 /* emulateion of codec "wake up" HDA spec (5.5.1 and 6.5)*/
1889 STATESTS(&pThis->hda) = 0x1;
1890
1891 Log(("hda: reset finished\n"));
1892}
1893
1894/**
1895 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1896 */
1897static DECLCALLBACK(void *) hdaQueryInterface (struct PDMIBASE *pInterface,
1898 const char *pszIID)
1899{
1900 PCIINTELHDLinkState *pThis = RT_FROM_MEMBER(pInterface, PCIINTELHDLinkState, hda.IBase);
1901 Assert(&pThis->hda.IBase == pInterface);
1902
1903 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->hda.IBase);
1904 return NULL;
1905}
1906
1907//#define HDA_AS_PCI_EXPRESS
1908
1909/**
1910 * @interface_method_impl{PDMDEVREG,pfnConstruct}
1911 */
1912static DECLCALLBACK(int) hdaConstruct (PPDMDEVINS pDevIns, int iInstance,
1913 PCFGMNODE pCfgHandle)
1914{
1915 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
1916 INTELHDLinkState *s = &pThis->hda;
1917 int rc;
1918
1919 Assert(iInstance == 0);
1920 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1921
1922 /*
1923 * Validations.
1924 */
1925 if (!CFGMR3AreValuesValid (pCfgHandle, "\0"))
1926 return PDMDEV_SET_ERROR (pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
1927 N_ ("Invalid configuration for the INTELHD device"));
1928
1929 // ** @todo r=michaln: This device may need R0/RC enabling, especially if guests
1930 // poll some register(s).
1931
1932 /*
1933 * Initialize data (most of it anyway).
1934 */
1935 s->pDevIns = pDevIns;
1936 /* IBase */
1937 s->IBase.pfnQueryInterface = hdaQueryInterface;
1938
1939 /* PCI Device (the assertions will be removed later) */
1940#if defined(VBOX_WITH_HP_HDA)
1941 /* Linux kernel has whitelist for MSI-enabled HDA, this card seems to be there. */
1942 PCIDevSetVendorId (&pThis->dev, 0x103c); /* HP. */
1943 PCIDevSetDeviceId (&pThis->dev, 0x30f7); /* HP Pavilion dv4t-1300 */
1944#elif defined(VBOX_WITH_INTEL_HDA)
1945 PCIDevSetVendorId (&pThis->dev, 0x8086); /* 00 ro - intel. */
1946 PCIDevSetDeviceId (&pThis->dev, 0x2668); /* 02 ro - 82801 / 82801aa(?). */
1947#elif defined(VBOX_WITH_NVIDIA_HDA)
1948 PCIDevSetVendorId (&pThis->dev, 0x10de); /* nVidia */
1949 PCIDevSetDeviceId (&pThis->dev, 0x0ac0); /* HDA */
1950#else
1951# error "Please specify your HDA device vendor/device IDs"
1952#endif
1953 PCIDevSetCommand (&pThis->dev, 0x0000); /* 04 rw,ro - pcicmd. */
1954 PCIDevSetStatus (&pThis->dev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
1955 PCIDevSetRevisionId (&pThis->dev, 0x01); /* 08 ro - rid. */
1956 PCIDevSetClassProg (&pThis->dev, 0x00); /* 09 ro - pi. */
1957 PCIDevSetClassSub (&pThis->dev, 0x03); /* 0a ro - scc; 03 == HDA. */
1958 PCIDevSetClassBase (&pThis->dev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
1959 PCIDevSetHeaderType (&pThis->dev, 0x00); /* 0e ro - headtyp. */
1960 PCIDevSetBaseAddress (&pThis->dev, 0, /* 10 rw - MMIO */
1961 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
1962 PCIDevSetInterruptLine (&pThis->dev, 0x00); /* 3c rw. */
1963 PCIDevSetInterruptPin (&pThis->dev, 0x01); /* 3d ro - INTA#. */
1964
1965#if defined(HDA_AS_PCI_EXPRESS)
1966 PCIDevSetCapabilityList (&pThis->dev, 0x80);
1967#elif defined(VBOX_WITH_MSI_DEVICES)
1968 PCIDevSetCapabilityList (&pThis->dev, 0x60);
1969#else
1970 PCIDevSetCapabilityList (&pThis->dev, 0x50); /* ICH6 datasheet 18.1.16 */
1971#endif
1972
1973 //** @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
1974 // of these values needs to be properly documented!
1975 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
1976 PCIDevSetByte(&pThis->dev, 0x40, 0x01);
1977
1978 /* Power Management */
1979 PCIDevSetByte(&pThis->dev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
1980 PCIDevSetByte(&pThis->dev, 0x50 + 1, 0x0); /* next */
1981 PCIDevSetWord(&pThis->dev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
1982
1983#ifdef HDA_AS_PCI_EXPRESS
1984 /* PCI Express */
1985 PCIDevSetByte (&pThis->dev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
1986 PCIDevSetByte (&pThis->dev, 0x80 + 1, 0x60); /* next */
1987 /* Device flags */
1988 PCIDevSetWord (&pThis->dev, 0x80 + 2,
1989 /* version */ 0x1 |
1990 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
1991 /* MSI */ (100) << 9
1992 );
1993 /* Device capabilities */
1994 PCIDevSetDWord (&pThis->dev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
1995 /* Device control */
1996 PCIDevSetWord (&pThis->dev, 0x80 + 8, 0);
1997 /* Device status */
1998 PCIDevSetWord (&pThis->dev, 0x80 + 10, 0);
1999 /* Link caps */
2000 PCIDevSetDWord (&pThis->dev, 0x80 + 12, 0);
2001 /* Link control */
2002 PCIDevSetWord (&pThis->dev, 0x80 + 16, 0);
2003 /* Link status */
2004 PCIDevSetWord (&pThis->dev, 0x80 + 18, 0);
2005 /* Slot capabilities */
2006 PCIDevSetDWord (&pThis->dev, 0x80 + 20, 0);
2007 /* Slot control */
2008 PCIDevSetWord (&pThis->dev, 0x80 + 24, 0);
2009 /* Slot status */
2010 PCIDevSetWord (&pThis->dev, 0x80 + 26, 0);
2011 /* Root control */
2012 PCIDevSetWord (&pThis->dev, 0x80 + 28, 0);
2013 /* Root capabilities */
2014 PCIDevSetWord (&pThis->dev, 0x80 + 30, 0);
2015 /* Root status */
2016 PCIDevSetDWord (&pThis->dev, 0x80 + 32, 0);
2017 /* Device capabilities 2 */
2018 PCIDevSetDWord (&pThis->dev, 0x80 + 36, 0);
2019 /* Device control 2 */
2020 PCIDevSetQWord (&pThis->dev, 0x80 + 40, 0);
2021 /* Link control 2 */
2022 PCIDevSetQWord (&pThis->dev, 0x80 + 48, 0);
2023 /* Slot control 2 */
2024 PCIDevSetWord (&pThis->dev, 0x80 + 56, 0);
2025#endif
2026
2027 /*
2028 * Register the PCI device.
2029 */
2030 rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
2031 if (RT_FAILURE (rc))
2032 return rc;
2033
2034 rc = PDMDevHlpPCIIORegionRegister (pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM,
2035 hdaMap);
2036 if (RT_FAILURE (rc))
2037 return rc;
2038
2039#ifdef VBOX_WITH_MSI_DEVICES
2040 PDMMSIREG aMsiReg;
2041
2042 RT_ZERO(aMsiReg);
2043 aMsiReg.cMsiVectors = 1;
2044 aMsiReg.iMsiCapOffset = 0x60;
2045 aMsiReg.iMsiNextOffset = 0x50;
2046 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg);
2047 if (RT_FAILURE (rc))
2048 {
2049 LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
2050 PCIDevSetCapabilityList (&pThis->dev, 0x50);
2051 }
2052#endif
2053
2054 rc = PDMDevHlpSSMRegister (pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
2055 if (RT_FAILURE (rc))
2056 return rc;
2057
2058 /*
2059 * Attach driver.
2060 */
2061 rc = PDMDevHlpDriverAttach (pDevIns, 0, &s->IBase,
2062 &s->pDrvBase, "Audio Driver Port");
2063 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
2064 Log (("hda: No attached driver!\n"));
2065 else if (RT_FAILURE (rc))
2066 {
2067 AssertMsgFailed (("Failed to attach INTELHD LUN #0! rc=%Rrc\n", rc));
2068 return rc;
2069 }
2070
2071
2072
2073 pThis->hda.Codec.pHDAState = (void *)&pThis->hda;
2074 rc = codecConstruct(&pThis->hda.Codec, /* ALC885_CODEC */ STAC9220_CODEC);
2075 if (RT_FAILURE(rc))
2076 AssertRCReturn(rc, rc);
2077
2078 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
2079 verb F20 should provide device/codec recognition. */
2080 Assert(pThis->hda.Codec.u16VendorId);
2081 Assert(pThis->hda.Codec.u16DeviceId);
2082 PCIDevSetSubSystemVendorId (&pThis->dev, pThis->hda.Codec.u16VendorId); /* 2c ro - intel.) */
2083 PCIDevSetSubSystemId (&pThis->dev, pThis->hda.Codec.u16DeviceId); /* 2e ro. */
2084
2085 hdaReset (pDevIns);
2086 pThis->hda.Codec.id = 0;
2087 pThis->hda.Codec.pfnTransfer = hdaTransfer;
2088 pThis->hda.Codec.pfnReset = hdaCodecReset;
2089 /*
2090 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
2091 * hdaReset shouldn't affects these registers.
2092 */
2093 WAKEEN(&pThis->hda) = 0x0;
2094 STATESTS(&pThis->hda) = 0x0;
2095
2096 return VINF_SUCCESS;
2097}
2098
2099/**
2100 * @interface_method_impl{PDMDEVREG,pfnDestruct}
2101 */
2102static DECLCALLBACK(int) hdaDestruct (PPDMDEVINS pDevIns)
2103{
2104 PCIINTELHDLinkState *pThis = PDMINS_2_DATA(pDevIns, PCIINTELHDLinkState *);
2105
2106 int rc = codecDestruct(&pThis->hda.Codec);
2107 AssertRC(rc);
2108 if (pThis->hda.pu32CorbBuf)
2109 RTMemFree(pThis->hda.pu32CorbBuf);
2110 if (pThis->hda.pu64RirbBuf)
2111 RTMemFree(pThis->hda.pu64RirbBuf);
2112 return VINF_SUCCESS;
2113}
2114
2115/**
2116 * The device registration structure.
2117 */
2118const PDMDEVREG g_DeviceICH6_HDA =
2119{
2120 /* u32Version */
2121 PDM_DEVREG_VERSION,
2122 /* szName */
2123 "hda",
2124 /* szRCMod */
2125 "",
2126 /* szR0Mod */
2127 "",
2128 /* pszDescription */
2129 "ICH IntelHD Audio Controller",
2130 /* fFlags */
2131 PDM_DEVREG_FLAGS_DEFAULT_BITS,
2132 /* fClass */
2133 PDM_DEVREG_CLASS_AUDIO,
2134 /* cMaxInstances */
2135 1,
2136 /* cbInstance */
2137 sizeof(PCIINTELHDLinkState),
2138 /* pfnConstruct */
2139 hdaConstruct,
2140 /* pfnDestruct */
2141 hdaDestruct,
2142 /* pfnRelocate */
2143 NULL,
2144 /* pfnIOCtl */
2145 NULL,
2146 /* pfnPowerOn */
2147 NULL,
2148 /* pfnReset */
2149 hdaReset,
2150 /* pfnSuspend */
2151 NULL,
2152 /* pfnResume */
2153 NULL,
2154 /* pfnAttach */
2155 NULL,
2156 /* pfnDetach */
2157 NULL,
2158 /* pfnQueryInterface. */
2159 NULL,
2160 /* pfnInitComplete */
2161 NULL,
2162 /* pfnPowerOff */
2163 NULL,
2164 /* pfnSoftReset */
2165 NULL,
2166 /* u32VersionEnd */
2167 PDM_DEVREG_VERSION
2168};
Note: See TracBrowser for help on using the repository browser.

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