VirtualBox

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

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

Audio/HDA: posponed hda transfers removed on reset.
hdaWriteAudio cosmetic.
hdaTransfer returns to guest unconditionally.

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

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