VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DevHDA.cpp@ 67388

Last change on this file since 67388 was 67387, checked in by vboxsync, 8 years ago

Audio/DevHDA: Forward ported / integrated saved state handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 253.6 KB
Line 
1/* $Id: DevHDA.cpp 67387 2017-06-14 10:14:06Z vboxsync $ */
2/** @file
3 * DevHDA - VBox Intel HD Audio Controller.
4 *
5 * Implemented against the specifications found in "High Definition Audio
6 * Specification", Revision 1.0a June 17, 2010, and "Intel I/O Controller
7 * HUB 6 (ICH6) Family, Datasheet", document number 301473-002.
8 */
9
10/*
11 * Copyright (C) 2006-2017 Oracle Corporation
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License (GPL) as published by the Free Software
17 * Foundation, in version 2 as it comes in the "COPYING" file of the
18 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20 */
21
22
23/*********************************************************************************************************************************
24* Header Files *
25*********************************************************************************************************************************/
26#define LOG_GROUP LOG_GROUP_DEV_HDA
27#include <VBox/log.h>
28#include <VBox/vmm/pdmdev.h>
29#include <VBox/vmm/pdmaudioifs.h>
30#include <VBox/version.h>
31
32#include <iprt/assert.h>
33#include <iprt/asm.h>
34#include <iprt/asm-math.h>
35#include <iprt/file.h>
36#include <iprt/list.h>
37#ifdef IN_RING3
38# include <iprt/mem.h>
39# include <iprt/semaphore.h>
40# include <iprt/string.h>
41# include <iprt/uuid.h>
42#endif
43
44#include "VBoxDD.h"
45
46#include "AudioMixBuffer.h"
47#include "AudioMixer.h"
48#include "HDACodec.h"
49#include "DevHDACommon.h"
50#include "DrvAudio.h"
51
52
53/*********************************************************************************************************************************
54* Defined Constants And Macros *
55*********************************************************************************************************************************/
56//#define HDA_AS_PCI_EXPRESS
57#define VBOX_WITH_INTEL_HDA
58
59/* Installs a DMA access handler (via PGM callback) to monitor
60 * HDA's DMA operations, that is, writing / reading audio stream data.
61 *
62 * !!! Note: Certain guests are *that* timing sensitive that when enabling !!!
63 * !!! such a handler will mess up audio completely (e.g. Windows 7). !!! */
64//#define HDA_USE_DMA_ACCESS_HANDLER
65#ifdef HDA_USE_DMA_ACCESS_HANDLER
66# include <VBox/vmm/pgm.h>
67#endif
68
69/* Uses the DMA access handler to read the written DMA audio (output) data.
70 * Only valid if HDA_USE_DMA_ACCESS_HANDLER is set.
71 *
72 * Also see the note / warning for HDA_USE_DMA_ACCESS_HANDLER. */
73//# define HDA_USE_DMA_ACCESS_HANDLER_WRITING
74
75#if defined(VBOX_WITH_HP_HDA)
76/* HP Pavilion dv4t-1300 */
77# define HDA_PCI_VENDOR_ID 0x103c
78# define HDA_PCI_DEVICE_ID 0x30f7
79#elif defined(VBOX_WITH_INTEL_HDA)
80/* Intel HDA controller */
81# define HDA_PCI_VENDOR_ID 0x8086
82# define HDA_PCI_DEVICE_ID 0x2668
83#elif defined(VBOX_WITH_NVIDIA_HDA)
84/* nVidia HDA controller */
85# define HDA_PCI_VENDOR_ID 0x10de
86# define HDA_PCI_DEVICE_ID 0x0ac0
87#else
88# error "Please specify your HDA device vendor/device IDs"
89#endif
90
91/** @todo r=bird: Looking at what the linux driver (accidentally?) does when
92 * updating CORBWP, I belive that the ICH6 datahsheet is wrong and that CORBRP
93 * is read only except for bit 15 like the HDA spec states.
94 *
95 * Btw. the CORBRPRST implementation is incomplete according to both docs (sw
96 * writes 1, hw sets it to 1 (after completion), sw reads 1, sw writes 0). */
97#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
98
99/* Make sure that interleaving streams support is enabled if the 5.1 surround code is being used. */
100#if defined (VBOX_WITH_AUDIO_HDA_51_SURROUND) && !defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT)
101# define VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT
102#endif
103
104/** Default timer frequency (in Hz). */
105#define HDA_TIMER_HZ 100
106
107/**
108 * At the moment we support 4 input + 4 output streams max, which is 8 in total.
109 * Bidirectional streams are currently *not* supported.
110 *
111 * Note: When changing any of those values, be prepared for some saved state
112 * fixups / trouble!
113 */
114#define HDA_MAX_SDI 4
115#define HDA_MAX_SDO 4
116#define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO)
117AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);
118
119/** Number of general registers. */
120#define HDA_NUM_GENERAL_REGS 34
121/** Number of total registers in the HDA's register map. */
122#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
123/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
124#define HDA_MAX_TAGS 16
125
126/**
127 * NB: Register values stored in memory (au32Regs[]) are indexed through
128 * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
129 * register descriptors in g_aHdaRegMap[] are indexed through the
130 * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
131 *
132 * The au32Regs[] layout is kept unchanged for saved state
133 * compatibility.
134 */
135
136/* Registers */
137#define HDA_REG_IND_NAME(x) HDA_REG_##x
138#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
139#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
140#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
141
142
143#define HDA_REG_GCAP 0 /* range 0x00-0x01*/
144#define HDA_RMX_GCAP 0
145/* GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
146 * oss (15:12) - number of output streams supported
147 * iss (11:8) - number of input streams supported
148 * bss (7:3) - number of bidirectional streams supported
149 * bds (2:1) - number of serial data out (SDO) signals supported
150 * b64sup (0) - 64 bit addressing supported.
151 */
152#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
153 ( (((oss) & 0xF) << 12) \
154 | (((iss) & 0xF) << 8) \
155 | (((bss) & 0x1F) << 3) \
156 | (((bds) & 0x3) << 1) \
157 | ((b64sup) & 1))
158
159#define HDA_REG_VMIN 1 /* 0x02 */
160#define HDA_RMX_VMIN 1
161
162#define HDA_REG_VMAJ 2 /* 0x03 */
163#define HDA_RMX_VMAJ 2
164
165#define HDA_REG_OUTPAY 3 /* 0x04-0x05 */
166#define HDA_RMX_OUTPAY 3
167
168#define HDA_REG_INPAY 4 /* 0x06-0x07 */
169#define HDA_RMX_INPAY 4
170
171#define HDA_REG_GCTL 5 /* 0x08-0x0B */
172#define HDA_RMX_GCTL 5
173#define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */
174#define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */
175#define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */
176
177#define HDA_REG_WAKEEN 6 /* 0x0C */
178#define HDA_RMX_WAKEEN 6
179
180#define HDA_REG_STATESTS 7 /* 0x0E */
181#define HDA_RMX_STATESTS 7
182#define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */
183
184#define HDA_REG_GSTS 8 /* 0x10-0x11*/
185#define HDA_RMX_GSTS 8
186#define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */
187
188#define HDA_REG_OUTSTRMPAY 9 /* 0x18 */
189#define HDA_RMX_OUTSTRMPAY 112
190
191#define HDA_REG_INSTRMPAY 10 /* 0x1a */
192#define HDA_RMX_INSTRMPAY 113
193
194#define HDA_REG_INTCTL 11 /* 0x20 */
195#define HDA_RMX_INTCTL 9
196#define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */
197#define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */
198/* Bits 0-29 correspond to streams 0-29. */
199#define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
200
201#define HDA_REG_INTSTS 12 /* 0x24 */
202#define HDA_RMX_INTSTS 10
203#define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */
204#define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */
205/* Bits 0-29 correspond to streams 0-29. */
206
207#define HDA_REG_WALCLK 13 /* 0x30 */
208/* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
209
210/* Note: The HDA specification defines a SSYNC register at offset 0x38. The
211 * ICH6/ICH9 datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches
212 * the datasheet.
213 */
214#define HDA_REG_SSYNC 14 /* 0x34 */
215#define HDA_RMX_SSYNC 12
216
217#define HDA_REG_CORBLBASE 15 /* 0x40 */
218#define HDA_RMX_CORBLBASE 13
219
220#define HDA_REG_CORBUBASE 16 /* 0x44 */
221#define HDA_RMX_CORBUBASE 14
222
223#define HDA_REG_CORBWP 17 /* 0x48 */
224#define HDA_RMX_CORBWP 15
225
226#define HDA_REG_CORBRP 18 /* 0x4A */
227#define HDA_RMX_CORBRP 16
228#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
229
230#define HDA_REG_CORBCTL 19 /* 0x4C */
231#define HDA_RMX_CORBCTL 17
232#define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */
233#define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */
234
235#define HDA_REG_CORBSTS 20 /* 0x4D */
236#define HDA_RMX_CORBSTS 18
237
238#define HDA_REG_CORBSIZE 21 /* 0x4E */
239#define HDA_RMX_CORBSIZE 19
240/* NB: Up to and including ICH 10, sizes of CORB and RIRB are fixed at 256 entries. */
241
242#define HDA_REG_RIRBLBASE 22 /* 0x50 */
243#define HDA_RMX_RIRBLBASE 20
244
245#define HDA_REG_RIRBUBASE 23 /* 0x54 */
246#define HDA_RMX_RIRBUBASE 21
247
248#define HDA_REG_RIRBWP 24 /* 0x58 */
249#define HDA_RMX_RIRBWP 22
250#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
251
252#define HDA_REG_RINTCNT 25 /* 0x5A */
253#define HDA_RMX_RINTCNT 23
254#define RINTCNT_N(pThis) (HDA_REG(pThis, RINTCNT) & 0xff)
255
256#define HDA_REG_RIRBCTL 26 /* 0x5C */
257#define HDA_RMX_RIRBCTL 24
258#define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */
259#define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */
260#define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */
261
262#define HDA_REG_RIRBSTS 27 /* 0x5D */
263#define HDA_RMX_RIRBSTS 25
264#define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */
265#define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */
266
267#define HDA_REG_RIRBSIZE 28 /* 0x5E */
268#define HDA_RMX_RIRBSIZE 26
269
270#define HDA_REG_IC 29 /* 0x60 */
271#define HDA_RMX_IC 27
272
273#define HDA_REG_IR 30 /* 0x64 */
274#define HDA_RMX_IR 28
275
276#define HDA_REG_IRS 31 /* 0x68 */
277#define HDA_RMX_IRS 29
278#define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */
279#define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */
280
281#define HDA_REG_DPLBASE 32 /* 0x70 */
282#define HDA_RMX_DPLBASE 30
283
284#define HDA_REG_DPUBASE 33 /* 0x74 */
285#define HDA_RMX_DPUBASE 31
286
287#define DPBASE_ADDR_MASK (~(uint64_t)0x7f)
288
289#define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)
290#define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)
291/* Note: sdnum here _MUST_ be stream reg number [0,7]. */
292#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
293
294#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
295
296/** @todo Condense marcos! */
297
298#define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
299#define HDA_RMX_SD0CTL 32
300#define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
301#define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
302#define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
303#define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
304#define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
305#define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
306#define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
307
308#define HDA_SDCTL_NUM_MASK 0xF
309#define HDA_SDCTL_NUM_SHIFT 20
310#define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */
311#define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */
312#define HDA_SDCTL_STRIPE_MASK 0x3
313#define HDA_SDCTL_STRIPE_SHIFT 16
314#define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */
315#define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */
316#define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */
317#define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */
318#define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */
319
320#define HDA_REG_SD0STS 35 /* 0x83; other streams offset by 0x20 */
321#define HDA_RMX_SD0STS 33
322#define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)
323#define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)
324#define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)
325#define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)
326#define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)
327#define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)
328#define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)
329
330#define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */
331#define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */
332#define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */
333#define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */
334
335#define HDA_REG_SD0LPIB 36 /* 0x84; other streams offset by 0x20 */
336#define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
337#define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
338#define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
339#define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
340#define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
341#define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
342#define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
343#define HDA_RMX_SD0LPIB 34
344#define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
345#define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
346#define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
347#define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
348#define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
349#define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
350#define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
351
352#define HDA_REG_SD0CBL 37 /* 0x88; other streams offset by 0x20 */
353#define HDA_RMX_SD0CBL 35
354#define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
355#define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
356#define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
357#define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
358#define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
359#define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
360#define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
361
362#define HDA_REG_SD0LVI 38 /* 0x8C; other streams offset by 0x20 */
363#define HDA_RMX_SD0LVI 36
364#define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
365#define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
366#define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
367#define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
368#define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
369#define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
370#define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
371
372#define HDA_REG_SD0FIFOW 39 /* 0x8E; other streams offset by 0x20 */
373#define HDA_RMX_SD0FIFOW 37
374#define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
375#define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
376#define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
377#define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
378#define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
379#define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
380#define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
381
382/*
383 * ICH6 datasheet defined limits for FIFOW values (18.2.38).
384 */
385#define HDA_SDFIFOW_8B 0x2
386#define HDA_SDFIFOW_16B 0x3
387#define HDA_SDFIFOW_32B 0x4
388
389#define HDA_REG_SD0FIFOS 40 /* 0x90; other streams offset by 0x20 */
390#define HDA_RMX_SD0FIFOS 38
391#define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
392#define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
393#define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
394#define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
395#define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
396#define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
397#define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
398
399/*
400 * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
401 * formula: size - 1
402 * Other values not listed are not supported.
403 */
404/** Maximum FIFO size (in bytes). */
405#define HDA_FIFO_MAX 256
406
407#define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
408#define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */
409
410#define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
411#define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
412#define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
413#define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
414#define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
415#define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */
416
417#define HDA_REG_SD0FMT 41 /* 0x92; other streams offset by 0x20 */
418#define HDA_RMX_SD0FMT 39
419#define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
420#define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
421#define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
422#define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
423#define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
424#define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
425#define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
426
427#define HDA_REG_SD0BDPL 42 /* 0x98; other streams offset by 0x20 */
428#define HDA_RMX_SD0BDPL 40
429#define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
430#define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
431#define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
432#define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
433#define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
434#define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
435#define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
436
437#define HDA_REG_SD0BDPU 43 /* 0x9C; other streams offset by 0x20 */
438#define HDA_RMX_SD0BDPU 41
439#define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
440#define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
441#define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
442#define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
443#define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
444#define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
445#define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
446
447#define HDA_BDLE_FLAG_IOC RT_BIT(0) /* Interrupt on completion (IOC). */
448
449#define HDA_CODEC_CAD_SHIFT 28
450/* Encodes the (required) LUN into a codec command. */
451#define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
452
453
454
455/*********************************************************************************************************************************
456* Structures and Typedefs *
457*********************************************************************************************************************************/
458
459/**
460 * Internal state of a Buffer Descriptor List Entry (BDLE),
461 * needed to keep track of the data needed for the actual device
462 * emulation.
463 */
464typedef struct HDABDLESTATE
465{
466 /** Own index within the BDL (Buffer Descriptor List). */
467 uint32_t u32BDLIndex;
468 /** Number of bytes below the stream's FIFO watermark (SDFIFOW).
469 * Used to check if we need fill up the FIFO again. */
470 uint32_t cbBelowFIFOW;
471 /** Current offset in DMA buffer (in bytes).*/
472 uint32_t u32BufOff;
473 uint32_t Padding;
474} HDABDLESTATE, *PHDABDLESTATE;
475
476/**
477 * BDL description structure.
478 * Do not touch this, as this must match to the HDA specs.
479 */
480typedef struct HDABDLEDESC
481{
482 /** Starting address of the actual buffer. Must be 128-bit aligned. */
483 uint64_t u64BufAdr;
484 /** Size of the actual buffer (in bytes). */
485 uint32_t u32BufSize;
486 /** Bit 0: Interrupt on completion; the controller will generate
487 * an interrupt when the last byte of the buffer has been
488 * fetched by the DMA engine.
489 *
490 * Rest is reserved for further use and must be 0. */
491 uint32_t fFlags;
492} HDABDLEDESC, *PHDABDLEDESC;
493AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
494
495/**
496 * Buffer Descriptor List Entry (BDLE) (3.6.3).
497 */
498typedef struct HDABDLE
499{
500 /** The actual BDL description. */
501 HDABDLEDESC Desc;
502 /** Internal state of this BDLE.
503 * Not part of the actual BDLE registers. */
504 HDABDLESTATE State;
505} HDABDLE, *PHDABDLE;
506
507/**
508 * Structure for keeping an audio stream data mapping.
509 */
510typedef struct HDASTREAMMAPPING
511{
512 /** The stream's layout. */
513 PDMAUDIOSTREAMLAYOUT enmLayout;
514 /** Number of audio channels in this stream. */
515 uint8_t cChannels;
516 /** Array of audio channels. */
517 R3PTRTYPE(PPDMAUDIOSTREAMCHANNEL) paChannels;
518 /** Circular buffer holding for holding audio data for this mapping. */
519 R3PTRTYPE(PRTCIRCBUF) pCircBuf;
520} HDASTREAMMAPPING, *PHDASTREAMMAPPING;
521
522#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
523/**
524 * Structure keeping the HDA stream's state for asynchronous I/O.
525 */
526typedef struct HDASTREAMSTATEAIO
527{
528 /** Thread handle for the actual I/O thread. */
529 RTTHREAD Thread;
530 /** Event for letting the thread know there is some data to process. */
531 RTSEMEVENT Event;
532 /** Critical section for synchronizing access. */
533 RTCRITSECT CritSect;
534 /** Started indicator. */
535 volatile bool fStarted;
536 /** Shutdown indicator. */
537 volatile bool fShutdown;
538 /** Whether the thread should do any data processing or not. */
539 volatile bool fEnabled;
540 uint32_t Padding1;
541} HDASTREAMSTATEAIO, *PHDASTREAMSTATEAIO;
542#endif
543
544/**
545 * Internal state of a HDA stream.
546 */
547typedef struct HDASTREAMSTATE
548{
549 /** Current BDLE to use. Wraps around to 0 if
550 * maximum (cBDLE) is reached. */
551 uint16_t uCurBDLE;
552 /** Flag indicating whether this stream currently is
553 * in reset mode and therefore not acccessible by the guest. */
554 volatile bool fInReset;
555 /** Unused, padding. */
556 uint32_t Padding0;
557 /** Critical section to serialize access. */
558 RTCRITSECT CritSect;
559#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
560 /** Asynchronous I/O state members. */
561 HDASTREAMSTATEAIO AIO;
562#endif
563 /** This stream's data mapping. */
564 HDASTREAMMAPPING Mapping;
565 /** Current BDLE (Buffer Descriptor List Entry). */
566 HDABDLE BDLE;
567 /** Circular buffer (FIFO) for holding DMA'ed data. */
568 R3PTRTYPE(PRTCIRCBUF) pCircBuf;
569 /** Timestamp of the last success DMA data transfer.
570 * Used to calculate the time actually elapsed between two transfers. */
571 uint64_t uTimerTS;
572 /** The stream's current configuration.
573 * Should match SDFMT. */
574 PDMAUDIOSTREAMCFG strmCfg;
575#ifdef HDA_USE_DMA_ACCESS_HANDLER
576 /** List of DMA handlers. */
577 RTLISTANCHORR3 lstDMAHandlers;
578#endif
579 /** Unused, padding. */
580 uint8_t Padding1[3];
581} HDASTREAMSTATE, *PHDASTREAMSTATE;
582
583/**
584 * Structure defining an HDA mixer sink.
585 * Its purpose is to know which audio mixer sink is bound to
586 * which SDn (SDI/SDO) device stream.
587 *
588 * This is needed in order to handle interleaved streams
589 * (that is, multiple channels in one stream) or non-interleaved
590 * streams (each channel has a dedicated stream).
591 *
592 * This is only known to the actual device emulation level.
593 */
594typedef struct HDAMIXERSINK
595{
596 /** SDn ID this sink is assigned to. 0 if not assigned. */
597 uint8_t uSD;
598 /** Channel ID of SDn ID. Only valid if SDn ID is valid. */
599 uint8_t uChannel;
600 uint8_t Padding[3];
601 /** Pointer to the actual audio mixer sink. */
602 R3PTRTYPE(PAUDMIXSINK) pMixSink;
603} HDAMIXERSINK, *PHDAMIXERSINK;
604
605#if defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER)
606typedef struct HDASTREAMDBGINFO
607{
608 /** Critical section to serialize access if needed. */
609 RTCRITSECT CritSect;
610 uint32_t Padding1[2];
611 /** Number of total read accesses. */
612 uint64_t cReadsTotal;
613 /** Number of total DMA bytes read. */
614 uint64_t cbReadTotal;
615 /** Timestamp (in ns) of last read access. */
616 uint64_t tsLastReadNs;
617 /** Number of total write accesses. */
618 uint64_t cWritesTotal;
619 /** Number of total DMA bytes written. */
620 uint64_t cbWrittenTotal;
621 /** Number of total write accesses since last iteration (Hz). */
622 uint64_t cWritesHz;
623 /** Number of total DMA bytes written since last iteration (Hz). */
624 uint64_t cbWrittenHz;
625 /** Timestamp (in ns) of beginning a new write slot. */
626 uint64_t tsWriteSlotBegin;
627 /** Number of current silence samples in a (consecutive) row. */
628 uint64_t csSilence;
629 /** Number of silent samples in a row to consider an audio block as audio gap (silence). */
630 uint64_t cSilenceThreshold;
631 /** How many bytes to skip in an audio stream before detecting silence.
632 * (useful for intros and silence at the beginning of a song). */
633 uint64_t cbSilenceReadMin;
634} HDASTREAMDBGINFO ,*PHDASTREAMDBGINFO;
635#endif /* defined (DEBUG) || defined(HDA_USE_DMA_ACCESS_HANDLER) */
636
637/**
638 * Structure for keeping a HDA stream (SDI / SDO).
639 *
640 * Note: This HDA stream has nothing to do with a regular audio stream handled
641 * by the audio connector or the audio mixer. This HDA stream is a serial data in/out
642 * stream (SDI/SDO) defined in hardware and can contain multiple audio streams
643 * in one single SDI/SDO (interleaving streams).
644 *
645 * How a specific SDI/SDO is mapped to our internal audio streams relies on the
646 * stream channel mappings.
647 *
648 * Contains only register values which do *not* change until a
649 * stream reset occurs.
650 */
651typedef struct HDASTREAM
652{
653 /** Stream descriptor number (SDn). */
654 uint8_t u8SD;
655 uint8_t Padding0[7];
656 /** DMA base address (SDnBDPU - SDnBDPL). */
657 uint64_t u64BDLBase;
658 /** Cyclic Buffer Length (SDnCBL).
659 * Represents the size of the ring buffer. */
660 uint32_t u32CBL;
661 /** Format (SDnFMT). */
662 uint16_t u16FMT;
663 /** FIFO Size (FIFOS).
664 * Maximum number of bytes that may have been DMA'd into
665 * memory but not yet transmitted on the link. */
666 uint16_t u16FIFOS;
667 /** FIFO Watermark. */
668 uint16_t u16FIFOW;
669 /** Last Valid Index (SDnLVI). */
670 uint16_t u16LVI;
671 uint16_t Padding1[2];
672 /** Pointer to HDA sink this stream is attached to. */
673 R3PTRTYPE(PHDAMIXERSINK) pMixSink;
674 /** Internal state of this stream. */
675 HDASTREAMSTATE State;
676#ifdef DEBUG
677 /** Debug information. */
678 HDASTREAMDBGINFO Dbg;
679#endif
680} HDASTREAM, *PHDASTREAM;
681
682#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
683/**
684 * Structure for keeping a HDA stream thread context.
685 */
686typedef struct HDASTREAMTHREADCTX
687{
688 PHDASTATE pThis;
689 PHDASTREAM pStream;
690} HDASTREAMTHREADCTX, *PHDASTREAMTHREADCTX;
691#endif
692
693/**
694 * Structure for mapping a stream tag to an HDA stream.
695 */
696typedef struct HDATAG
697{
698 /** Own stream tag. */
699 uint8_t uTag;
700 uint8_t Padding[7];
701 /** Pointer to associated stream. */
702 R3PTRTYPE(PHDASTREAM) pStrm;
703} HDATAG, *PHDATAG;
704
705/**
706 * Structure defining a (host backend) driver stream.
707 * Each driver has its own instances of audio mixer streams, which then
708 * can go into the same (or even different) audio mixer sinks.
709 */
710typedef struct HDADRIVERSTREAM
711{
712 union
713 {
714 /** Desired playback destination (for an output stream). */
715 PDMAUDIOPLAYBACKDEST Dest;
716 /** Desired recording source (for an input stream). */
717 PDMAUDIORECSOURCE Source;
718 } DestSource;
719 uint8_t Padding1[4];
720 /** Associated mixer handle. */
721 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;
722} HDADRIVERSTREAM, *PHDADRIVERSTREAM;
723
724#ifdef HDA_USE_DMA_ACCESS_HANDLER
725typedef struct HDADMAACCESSHANDLER
726{
727 /** Node for storing this handler in our list in HDASTREAMSTATE. */
728 RTLISTNODER3 Node;
729 /** Pointer to stream to which this access handler is assigned to. */
730 R3PTRTYPE(PHDASTREAM) pStream;
731 /** Access handler type handle. */
732 PGMPHYSHANDLERTYPE hAccessHandlerType;
733 /** First address this handler uses. */
734 RTGCPHYS GCPhysFirst;
735 /** Last address this handler uses. */
736 RTGCPHYS GCPhysLast;
737 /** Actual BDLE address to handle. */
738 RTGCPHYS BDLEAddr;
739 /** Actual BDLE buffer size to handle. */
740 RTGCPHYS BDLESize;
741 /** Whether the access handler has been registered or not. */
742 bool fRegistered;
743 uint8_t Padding[3];
744} HDADMAACCESSHANDLER, *PHDADMAACCESSHANDLER;
745#endif
746
747/**
748 * Struct for maintaining a host backend driver.
749 * This driver must be associated to one, and only one,
750 * HDA codec. The HDA controller does the actual multiplexing
751 * of HDA codec data to various host backend drivers then.
752 *
753 * This HDA device uses a timer in order to synchronize all
754 * read/write accesses across all attached LUNs / backends.
755 */
756typedef struct HDADRIVER
757{
758 /** Node for storing this driver in our device driver list of HDASTATE. */
759 RTLISTNODER3 Node;
760 /** Pointer to HDA controller (state). */
761 R3PTRTYPE(PHDASTATE) pHDAState;
762 /** Driver flags. */
763 PDMAUDIODRVFLAGS fFlags;
764 uint8_t u32Padding0[2];
765 /** LUN to which this driver has been assigned. */
766 uint8_t uLUN;
767 /** Whether this driver is in an attached state or not. */
768 bool fAttached;
769 /** Pointer to attached driver base interface. */
770 R3PTRTYPE(PPDMIBASE) pDrvBase;
771 /** Audio connector interface to the underlying host backend. */
772 R3PTRTYPE(PPDMIAUDIOCONNECTOR) pConnector;
773 /** Mixer stream for line input. */
774 HDADRIVERSTREAM LineIn;
775#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
776 /** Mixer stream for mic input. */
777 HDADRIVERSTREAM MicIn;
778#endif
779 /** Mixer stream for front output. */
780 HDADRIVERSTREAM Front;
781#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
782 /** Mixer stream for center/LFE output. */
783 HDADRIVERSTREAM CenterLFE;
784 /** Mixer stream for rear output. */
785 HDADRIVERSTREAM Rear;
786#endif
787} HDADRIVER;
788
789/**
790 * ICH Intel HD Audio Controller state.
791 */
792typedef struct HDASTATE
793{
794 /** The PCI device structure. */
795 PDMPCIDEV PciDev;
796 /** R3 Pointer to the device instance. */
797 PPDMDEVINSR3 pDevInsR3;
798 /** R0 Pointer to the device instance. */
799 PPDMDEVINSR0 pDevInsR0;
800 /** R0 Pointer to the device instance. */
801 PPDMDEVINSRC pDevInsRC;
802 /** Padding for alignment. */
803 uint32_t u32Padding;
804 /** The base interface for LUN\#0. */
805 PDMIBASE IBase;
806 RTGCPHYS MMIOBaseAddr;
807 /** The HDA's register set. */
808 uint32_t au32Regs[HDA_NUM_REGS];
809 /** Internal stream states. */
810 HDASTREAM aStreams[HDA_MAX_STREAMS];
811 /** Mapping table between stream tags and stream states. */
812 HDATAG aTags[HDA_MAX_TAGS];
813 /** CORB buffer base address. */
814 uint64_t u64CORBBase;
815 /** RIRB buffer base address. */
816 uint64_t u64RIRBBase;
817 /** DMA base address.
818 * Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */
819 uint64_t u64DPBase;
820 /** DMA position buffer enable bit. */
821 bool fDMAPosition;
822 /** Padding for alignment. */
823 uint8_t u8Padding0[7];
824 /** Pointer to CORB buffer. */
825 R3PTRTYPE(uint32_t *) pu32CorbBuf;
826 /** Size in bytes of CORB buffer. */
827 uint32_t cbCorbBuf;
828 /** Padding for alignment. */
829 uint32_t u32Padding1;
830 /** Pointer to RIRB buffer. */
831 R3PTRTYPE(uint64_t *) pu64RirbBuf;
832 /** Size in bytes of RIRB buffer. */
833 uint32_t cbRirbBuf;
834 /** Indicates if HDA controller is in reset mode. */
835 bool fInReset;
836 /** Flag whether the R0 part is enabled. */
837 bool fR0Enabled;
838 /** Flag whether the RC part is enabled. */
839 bool fRCEnabled;
840 /** Number of active (running) SDn streams. */
841 uint8_t cStreamsActive;
842#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
843 /** The timer for pumping data thru the attached LUN drivers. */
844 PTMTIMERR3 pTimer;
845 /** Flag indicating whether the timer is active or not. */
846 bool fTimerActive;
847 uint8_t u8Padding1[7];
848 /** Timer ticks per Hz. */
849 uint64_t cTimerTicks;
850 /** The current timer expire time (in timer ticks). */
851 uint64_t tsTimerExpire;
852 /** Timestamp of the last timer callback (hdaTimer).
853 * Used to calculate the time actually elapsed between two timer callbacks. */
854 uint64_t uTimerTS;
855 uint64_t uTimerMS;
856#endif
857#ifdef VBOX_WITH_STATISTICS
858# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
859 STAMPROFILE StatTimer;
860# endif
861 STAMPROFILE StatIn;
862 STAMPROFILE StatOut;
863 STAMCOUNTER StatBytesRead;
864 STAMCOUNTER StatBytesWritten;
865#endif
866 /** Pointer to HDA codec to use. */
867 R3PTRTYPE(PHDACODEC) pCodec;
868 /** List of associated LUN drivers (HDADRIVER). */
869 RTLISTANCHORR3 lstDrv;
870 /** The device' software mixer. */
871 R3PTRTYPE(PAUDIOMIXER) pMixer;
872 /** HDA sink for (front) output. */
873 HDAMIXERSINK SinkFront;
874#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
875 /** HDA sink for center / LFE output. */
876 HDAMIXERSINK SinkCenterLFE;
877 /** HDA sink for rear output. */
878 HDAMIXERSINK SinkRear;
879#endif
880 /** HDA mixer sink for line input. */
881 HDAMIXERSINK SinkLineIn;
882#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
883 /** Audio mixer sink for microphone input. */
884 HDAMIXERSINK SinkMicIn;
885#endif
886 uint64_t u64BaseTS;
887 /** Response Interrupt Count (RINTCNT). */
888 uint8_t u8RespIntCnt;
889 /** Padding for alignment. */
890 uint8_t au8Padding2[7];
891} HDASTATE;
892/** Pointer to the ICH Intel HD Audio Controller state. */
893typedef HDASTATE *PHDASTATE;
894
895#ifdef VBOX_WITH_AUDIO_HDA_CALLBACKS
896typedef struct HDACALLBACKCTX
897{
898 PHDASTATE pThis;
899 PHDADRIVER pDriver;
900} HDACALLBACKCTX, *PHDACALLBACKCTX;
901#endif
902
903
904/*********************************************************************************************************************************
905* Internal Functions *
906*********************************************************************************************************************************/
907#ifndef VBOX_DEVICE_STRUCT_TESTCASE
908#ifdef IN_RING3
909static FNPDMDEVRESET hdaReset;
910#endif
911
912/** @name Register read/write stubs.
913 * @{
914 */
915static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
916static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
917/** @} */
918
919/** @name Global register set read/write functions.
920 * @{
921 */
922static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
923static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
924static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
925static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
926static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
927static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
928static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
929static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
930static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
931static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
932static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
933static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
934static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
935static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
936/** @} */
937
938/** @name {IOB}SDn write functions.
939 * @{
940 */
941static int hdaRegWriteSDCBL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
942static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
943static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
944static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
945static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
946static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
947static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
948static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
949static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
950/** @} */
951
952/** @name Generic register read/write functions.
953 * @{
954 */
955static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
956static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
957static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
958#ifdef IN_RING3
959static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
960#endif
961static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
962static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
963static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
964static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
965/** @} */
966
967/** @name Stream functions.
968 * @{
969 */
970#ifdef IN_RING3
971static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream);
972static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf, uint32_t cbToProcess, uint32_t *pcbProcessed);
973static int hdaStreamEnable(PHDASTATE pThis, PHDASTREAM pStream, bool fEnable);
974static int hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream);
975DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB);
976static void hdaStreamLock(PHDASTREAM pStream);
977static void hdaStreamUnlock(PHDASTREAM pStream);
978# ifdef HDA_USE_DMA_ACCESS_HANDLER
979static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
980static void hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream);
981# endif
982#endif /* IN_RING3 */
983/** @} */
984
985/** @name Async I/O stream functions.
986 * @{
987 */
988#ifdef IN_RING3
989# ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
990static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
991static int hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream);
992static int hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream);
993static int hdaStreamAsyncIONotify(PHDASTATE pThis, PHDASTREAM pStream);
994static void hdaStreamAsyncIOLock(PHDASTREAM pStream);
995static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream);
996static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable);
997# endif
998#endif
999/** @} */
1000
1001/** @name Stream mapping functions.
1002 * @{
1003 */
1004#ifdef IN_RING3
1005static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg);
1006static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping);
1007static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping);
1008#endif /* IN_RING3 */
1009/** @} */
1010
1011/** @name HDA device functions.
1012 * @{
1013 */
1014#ifdef IN_RING3
1015# ifdef HDA_USE_DMA_ACCESS_HANDLER
1016static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser);
1017# endif
1018static void hdaDoTransfers(PHDASTATE pThis);
1019#endif /* IN_RING3 */
1020/** @} */
1021
1022/** @name BDLE (Buffer Descriptor List Entry) functions.
1023 * @{
1024 */
1025#ifdef IN_RING3
1026static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry);
1027# ifdef LOG_ENABLED
1028static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BaseDMA, uint16_t cBDLE);
1029# endif
1030#endif /* IN_RING3 */
1031/** @} */
1032
1033/** @name Timer functions.
1034 * @{
1035 */
1036#if !defined(VBOX_WITH_AUDIO_HDA_CALLBACKS) && defined(IN_RING3)
1037static void hdaTimerMaybeStart(PHDASTATE pThis);
1038static void hdaTimerMaybeStop(PHDASTATE pThis);
1039static void hdaTimerMain(PHDASTATE pThis);
1040#endif
1041/** @} */
1042
1043
1044/*********************************************************************************************************************************
1045* Global Variables *
1046*********************************************************************************************************************************/
1047
1048/** Offset of the SD0 register map. */
1049#define HDA_REG_DESC_SD0_BASE 0x80
1050
1051/** Turn a short global register name into an memory index and a stringized name. */
1052#define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
1053
1054/** Turns a short stream register name into an memory index and a stringized name. */
1055#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
1056
1057/** Same as above for a register *not* stored in memory. */
1058#define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev
1059
1060/** No register description (RD) flags defined. */
1061#define HDA_RD_FLAG_NONE 0
1062/** Writes to SD are allowed while RUN bit is set. */
1063#define HDA_RD_FLAG_SD_WRITE_RUN RT_BIT(0)
1064
1065/** Emits a single audio stream register set (e.g. OSD0) at a specified offset. */
1066#define HDA_REG_MAP_STRM(offset, name) \
1067 /* offset size read mask write mask flags read callback write callback index + abbrev description */ \
1068 /* ------- ------- ---------- ---------- ------------------------- -------------- ----------------- ----------------------------- ----------- */ \
1069 /* Offset 0x80 (SD0) */ \
1070 { offset, 0x00003, 0x00FF001F, 0x00F0001F, HDA_RD_FLAG_SD_WRITE_RUN, hdaRegReadU24 , hdaRegWriteSDCTL , HDA_REG_IDX_STRM(name, CTL) , #name " Stream Descriptor Control" }, \
1071 /* Offset 0x83 (SD0) */ \
1072 { offset + 0x3, 0x00001, 0x0000003C, 0x0000001C, HDA_RD_FLAG_SD_WRITE_RUN, hdaRegReadU8 , hdaRegWriteSDSTS , HDA_REG_IDX_STRM(name, STS) , #name " Status" }, \
1073 /* Offset 0x84 (SD0) */ \
1074 { offset + 0x4, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadLPIB, hdaRegWriteU32 , HDA_REG_IDX_STRM(name, LPIB) , #name " Link Position In Buffer" }, \
1075 /* Offset 0x88 (SD0) */ \
1076 { offset + 0x8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteSDCBL , HDA_REG_IDX_STRM(name, CBL) , #name " Cyclic Buffer Length" }, \
1077 /* Offset 0x8C (SD0) */ \
1078 { offset + 0xC, 0x00002, 0x0000FFFF, 0x0000FFFF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDLVI , HDA_REG_IDX_STRM(name, LVI) , #name " Last Valid Index" }, \
1079 /* Reserved: FIFO Watermark. ** @todo Document this! */ \
1080 { offset + 0xE, 0x00002, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOW, HDA_REG_IDX_STRM(name, FIFOW), #name " FIFO Watermark" }, \
1081 /* Offset 0x90 (SD0) */ \
1082 { offset + 0x10, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFIFOS, HDA_REG_IDX_STRM(name, FIFOS), #name " FIFO Size" }, \
1083 /* Offset 0x92 (SD0) */ \
1084 { offset + 0x12, 0x00002, 0x00007F7F, 0x00007F7F, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteSDFMT , HDA_REG_IDX_STRM(name, FMT) , #name " Stream Format" }, \
1085 /* Reserved: 0x94 - 0x98. */ \
1086 /* Offset 0x98 (SD0) */ \
1087 { offset + 0x18, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteSDBDPL , HDA_REG_IDX_STRM(name, BDPL) , #name " Buffer Descriptor List Pointer-Lower Base Address" }, \
1088 /* Offset 0x9C (SD0) */ \
1089 { offset + 0x1C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteSDBDPU , HDA_REG_IDX_STRM(name, BDPU) , #name " Buffer Descriptor List Pointer-Upper Base Address" }
1090
1091/** Defines a single audio stream register set (e.g. OSD0). */
1092#define HDA_REG_MAP_DEF_STREAM(index, name) \
1093 HDA_REG_MAP_STRM(HDA_REG_DESC_SD0_BASE + (index * 32 /* 0x20 */), name)
1094
1095/* See 302349 p 6.2. */
1096static const struct HDAREGDESC
1097{
1098 /** Register offset in the register space. */
1099 uint32_t offset;
1100 /** Size in bytes. Registers of size > 4 are in fact tables. */
1101 uint32_t size;
1102 /** Readable bits. */
1103 uint32_t readable;
1104 /** Writable bits. */
1105 uint32_t writable;
1106 /** Register descriptor (RD) flags of type HDA_RD_FLAG_.
1107 * These are used to specify the handling (read/write)
1108 * policy of the register. */
1109 uint32_t fFlags;
1110 /** Read callback. */
1111 int (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
1112 /** Write callback. */
1113 int (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
1114 /** Index into the register storage array. */
1115 uint32_t mem_idx;
1116 /** Abbreviated name. */
1117 const char *abbrev;
1118 /** Descripton. */
1119 const char *desc;
1120} g_aHdaRegMap[HDA_NUM_REGS] =
1121
1122{
1123 /* offset size read mask write mask flags read callback write callback index + abbrev */
1124 /*------- ------- ---------- ---------- ----------------- ---------------- ------------------- ------------------------ */
1125 { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(GCAP) }, /* Global Capabilities */
1126 { 0x00002, 0x00001, 0x000000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMIN) }, /* Minor Version */
1127 { 0x00003, 0x00001, 0x000000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(VMAJ) }, /* Major Version */
1128 { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTPAY) }, /* Output Payload Capabilities */
1129 { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INPAY) }, /* Input Payload Capabilities */
1130 { 0x00008, 0x00004, 0x00000103, 0x00000103, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteGCTL , HDA_REG_IDX(GCTL) }, /* Global Control */
1131 { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(WAKEEN) }, /* Wake Enable */
1132 { 0x0000e, 0x00002, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteSTATESTS, HDA_REG_IDX(STATESTS) }, /* State Change Status */
1133 { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadUnimpl, hdaRegWriteUnimpl , HDA_REG_IDX(GSTS) }, /* Global Status */
1134 { 0x00018, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(OUTSTRMPAY) }, /* Output Stream Payload Capability */
1135 { 0x0001A, 0x00002, 0x0000FFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteUnimpl , HDA_REG_IDX(INSTRMPAY) }, /* Input Stream Payload Capability */
1136 { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteINTCTL , HDA_REG_IDX(INTCTL) }, /* Interrupt Control */
1137 { 0x00024, 0x00004, 0xC00000FF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(INTSTS) }, /* Interrupt Status */
1138 { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadWALCLK, hdaRegWriteUnimpl , HDA_REG_IDX_NOMEM(WALCLK) }, /* Wall Clock Counter */
1139 { 0x00034, 0x00004, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(SSYNC) }, /* Stream Synchronization */
1140 { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBLBASE) }, /* CORB Lower Base Address */
1141 { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(CORBUBASE) }, /* CORB Upper Base Address */
1142 { 0x00048, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteCORBWP , HDA_REG_IDX(CORBWP) }, /* CORB Write Pointer */
1143 { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteCORBRP , HDA_REG_IDX(CORBRP) }, /* CORB Read Pointer */
1144 { 0x0004C, 0x00001, 0x00000003, 0x00000003, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteCORBCTL , HDA_REG_IDX(CORBCTL) }, /* CORB Control */
1145 { 0x0004D, 0x00001, 0x00000001, 0x00000001, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteCORBSTS , HDA_REG_IDX(CORBSTS) }, /* CORB Status */
1146 { 0x0004E, 0x00001, 0x000000F3, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(CORBSIZE) }, /* CORB Size */
1147 { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBLBASE) }, /* RIRB Lower Base Address */
1148 { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(RIRBUBASE) }, /* RIRB Upper Base Address */
1149 { 0x00058, 0x00002, 0x000000FF, 0x00008000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteRIRBWP , HDA_REG_IDX(RIRBWP) }, /* RIRB Write Pointer */
1150 { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, HDA_RD_FLAG_NONE, hdaRegReadU16 , hdaRegWriteU16 , HDA_REG_IDX(RINTCNT) }, /* Response Interrupt Count */
1151 { 0x0005C, 0x00001, 0x00000007, 0x00000007, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteU8 , HDA_REG_IDX(RIRBCTL) }, /* RIRB Control */
1152 { 0x0005D, 0x00001, 0x00000005, 0x00000005, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteRIRBSTS , HDA_REG_IDX(RIRBSTS) }, /* RIRB Status */
1153 { 0x0005E, 0x00001, 0x000000F3, 0x00000000, HDA_RD_FLAG_NONE, hdaRegReadU8 , hdaRegWriteUnimpl , HDA_REG_IDX(RIRBSIZE) }, /* RIRB Size */
1154 { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteU32 , HDA_REG_IDX(IC) }, /* Immediate Command */
1155 { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteUnimpl , HDA_REG_IDX(IR) }, /* Immediate Response */
1156 { 0x00068, 0x00002, 0x00000002, 0x00000002, HDA_RD_FLAG_NONE, hdaRegReadIRS , hdaRegWriteIRS , HDA_REG_IDX(IRS) }, /* Immediate Command Status */
1157 { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPLBASE) }, /* DMA Position Lower Base */
1158 { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, HDA_RD_FLAG_NONE, hdaRegReadU32 , hdaRegWriteBase , HDA_REG_IDX(DPUBASE) }, /* DMA Position Upper Base */
1159 /* 4 Serial Data In (SDI). */
1160 HDA_REG_MAP_DEF_STREAM(0, SD0),
1161 HDA_REG_MAP_DEF_STREAM(1, SD1),
1162 HDA_REG_MAP_DEF_STREAM(2, SD2),
1163 HDA_REG_MAP_DEF_STREAM(3, SD3),
1164 /* 4 Serial Data Out (SDO). */
1165 HDA_REG_MAP_DEF_STREAM(4, SD4),
1166 HDA_REG_MAP_DEF_STREAM(5, SD5),
1167 HDA_REG_MAP_DEF_STREAM(6, SD6),
1168 HDA_REG_MAP_DEF_STREAM(7, SD7)
1169};
1170
1171/**
1172 * HDA register aliases (HDA spec 3.3.45).
1173 * @remarks Sorted by offReg.
1174 */
1175static const struct
1176{
1177 /** The alias register offset. */
1178 uint32_t offReg;
1179 /** The register index. */
1180 int idxAlias;
1181} g_aHdaRegAliases[] =
1182{
1183 { 0x2084, HDA_REG_SD0LPIB },
1184 { 0x20a4, HDA_REG_SD1LPIB },
1185 { 0x20c4, HDA_REG_SD2LPIB },
1186 { 0x20e4, HDA_REG_SD3LPIB },
1187 { 0x2104, HDA_REG_SD4LPIB },
1188 { 0x2124, HDA_REG_SD5LPIB },
1189 { 0x2144, HDA_REG_SD6LPIB },
1190 { 0x2164, HDA_REG_SD7LPIB },
1191};
1192
1193#ifdef IN_RING3
1194/** HDABDLEDESC field descriptors for the v7 saved state. */
1195static SSMFIELD const g_aSSMBDLEDescFields7[] =
1196{
1197 SSMFIELD_ENTRY(HDABDLEDESC, u64BufAdr),
1198 SSMFIELD_ENTRY(HDABDLEDESC, u32BufSize),
1199 SSMFIELD_ENTRY(HDABDLEDESC, fFlags),
1200 SSMFIELD_ENTRY_TERM()
1201};
1202
1203/** HDABDLESTATE field descriptors for the v6+ saved state. */
1204static SSMFIELD const g_aSSMBDLEStateFields6[] =
1205{
1206 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
1207 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
1208 SSMFIELD_ENTRY_OLD(FIFO, HDA_FIFO_MAX), /* Deprecated; now is handled in the stream's circular buffer. */
1209 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
1210 SSMFIELD_ENTRY_TERM()
1211};
1212
1213/** HDABDLESTATE field descriptors for the v7 saved state. */
1214static SSMFIELD const g_aSSMBDLEStateFields7[] =
1215{
1216 SSMFIELD_ENTRY(HDABDLESTATE, u32BDLIndex),
1217 SSMFIELD_ENTRY(HDABDLESTATE, cbBelowFIFOW),
1218 SSMFIELD_ENTRY(HDABDLESTATE, u32BufOff),
1219 SSMFIELD_ENTRY_TERM()
1220};
1221
1222/** HDASTREAMSTATE field descriptors for the v6 saved state. */
1223static SSMFIELD const g_aSSMStreamStateFields6[] =
1224{
1225 SSMFIELD_ENTRY_OLD(cBDLE, sizeof(uint16_t)), /* Deprecated. */
1226 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
1227 SSMFIELD_ENTRY_OLD(fStop, 1), /* Deprecated; see SSMR3PutBool(). */
1228 SSMFIELD_ENTRY_OLD(fActive, 1),
1229 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
1230 SSMFIELD_ENTRY_TERM()
1231};
1232
1233/** HDASTREAMSTATE field descriptors for the v7 saved state. */
1234static SSMFIELD const g_aSSMStreamStateFields7[] =
1235{
1236 SSMFIELD_ENTRY(HDASTREAMSTATE, uCurBDLE),
1237 SSMFIELD_ENTRY(HDASTREAMSTATE, fInReset),
1238 SSMFIELD_ENTRY(HDASTREAMSTATE, uTimerTS),
1239 SSMFIELD_ENTRY_TERM()
1240};
1241#endif
1242
1243/**
1244 * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
1245 */
1246static uint32_t const g_afMasks[5] =
1247{
1248 UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0x00ffffff), UINT32_C(0xffffffff)
1249};
1250
1251
1252#ifdef IN_RING3
1253/**
1254 * Retrieves the number of bytes of a FIFOW register.
1255 *
1256 * @return Number of bytes of a given FIFOW register.
1257 */
1258DECLINLINE(uint8_t) hdaSDFIFOWToBytes(uint32_t u32RegFIFOW)
1259{
1260 uint32_t cb;
1261 switch (u32RegFIFOW)
1262 {
1263 case HDA_SDFIFOW_8B: cb = 8; break;
1264 case HDA_SDFIFOW_16B: cb = 16; break;
1265 case HDA_SDFIFOW_32B: cb = 32; break;
1266 default: cb = 0; break;
1267 }
1268
1269 Assert(RT_IS_POWER_OF_TWO(cb));
1270 return cb;
1271}
1272
1273
1274DECLINLINE(uint32_t) hdaStreamUpdateLPIB(PHDASTATE pThis, PHDASTREAM pStream, uint32_t u32LPIB)
1275{
1276 AssertPtrReturn(pThis, 0);
1277 AssertPtrReturn(pStream, 0);
1278
1279 AssertMsg(u32LPIB <= pStream->u32CBL,
1280 ("[SD%RU8] New LPIB (%RU32) exceeds CBL (%RU32)\n", pStream->u8SD, u32LPIB, pStream->u32CBL));
1281
1282 u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
1283
1284 LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
1285 pStream->u8SD, u32LPIB, pThis->fDMAPosition));
1286
1287 /* Update LPIB in any case. */
1288 HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) = u32LPIB;
1289
1290 /* Do we need to tell the current DMA position? */
1291 if (pThis->fDMAPosition)
1292 {
1293 int rc2 = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns),
1294 (pThis->u64DPBase & DPBASE_ADDR_MASK) + (pStream->u8SD * 2 * sizeof(uint32_t)),
1295 (void *)&u32LPIB, sizeof(uint32_t));
1296 AssertRC(rc2);
1297 }
1298
1299 return u32LPIB;
1300}
1301
1302
1303/**
1304 * Locks an HDA stream for serialized access.
1305 *
1306 * @returns IPRT status code.
1307 * @param pStream HDA stream to lock.
1308 */
1309static void hdaStreamLock(PHDASTREAM pStream)
1310{
1311 AssertPtrReturnVoid(pStream);
1312 int rc2 = RTCritSectEnter(&pStream->State.CritSect);
1313 AssertRC(rc2);
1314}
1315
1316
1317/**
1318 * Unlocks a formerly locked HDA stream.
1319 *
1320 * @returns IPRT status code.
1321 * @param pStream HDA stream to unlock.
1322 */
1323static void hdaStreamUnlock(PHDASTREAM pStream)
1324{
1325 AssertPtrReturnVoid(pStream);
1326 int rc2 = RTCritSectLeave(&pStream->State.CritSect);
1327 AssertRC(rc2);
1328}
1329
1330
1331/**
1332 * Fetches the next BDLE to use for a stream.
1333 *
1334 * @return IPRT status code.
1335 */
1336DECLINLINE(int) hdaStreamGetNextBDLE(PHDASTATE pThis, PHDASTREAM pStream, bool *pfWrapAround)
1337{
1338 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1339 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1340
1341 NOREF(pThis);
1342
1343 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
1344
1345 LogFlowFuncEnter();
1346
1347# ifdef LOG_ENABLED
1348 uint32_t const uOldBDLE = pStream->State.uCurBDLE;
1349# endif
1350
1351 PHDABDLE pBDLE = &pStream->State.BDLE;
1352 bool fWrapAround = false;
1353
1354 AssertMsg(pBDLE->State.u32BufOff == pBDLE->Desc.u32BufSize, ("BDLE not finished yet: %R[bdle]\n", pBDLE));
1355
1356 /*
1357 * Switch to the next BDLE entry and do a wrap around
1358 * if we reached the end of the Buffer Descriptor List (BDL).
1359 */
1360 pStream->State.uCurBDLE++;
1361 if (pStream->State.uCurBDLE == pStream->u16LVI + 1)
1362 {
1363 pStream->State.uCurBDLE = 0;
1364 fWrapAround = true;
1365 }
1366
1367 Assert(pStream->State.uCurBDLE < pStream->u16LVI + 1);
1368
1369 /* Fetch the next BDLE entry. */
1370 int rc = hdaBDLEFetch(pThis, pBDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
1371 if (RT_SUCCESS(rc))
1372 {
1373 LogFlowFunc(("[SD%RU8]: uOldBDLE=%RU16, uCurBDLE=%RU16, LVI=%RU32, rc=%Rrc, %R[bdle]\n",
1374 pStream->u8SD, uOldBDLE, pStream->State.uCurBDLE, pStream->u16LVI, rc, pBDLE));
1375
1376 if (pfWrapAround)
1377 *pfWrapAround = fWrapAround;
1378 }
1379
1380 return rc;
1381}
1382
1383
1384/**
1385 * Returns the HDA stream of specified stream descriptor number.
1386 *
1387 * @return Pointer to HDA stream, or NULL if none found.
1388 */
1389DECLINLINE(PHDASTREAM) hdaStreamGetFromSD(PHDASTATE pThis, uint8_t uSD)
1390{
1391 AssertPtrReturn(pThis, NULL);
1392 AssertReturn(uSD <= HDA_MAX_STREAMS, NULL);
1393
1394 if (uSD >= HDA_MAX_STREAMS)
1395 {
1396 AssertMsgFailed(("Invalid / non-handled SD%RU8\n", uSD));
1397 return NULL;
1398 }
1399
1400 return &pThis->aStreams[uSD];
1401}
1402
1403
1404/**
1405 * Returns the HDA stream of specified HDA sink.
1406 *
1407 * @return Pointer to HDA stream, or NULL if none found.
1408 */
1409DECLINLINE(PHDASTREAM) hdaSinkGetStream(PHDASTATE pThis, PHDAMIXERSINK pSink)
1410{
1411 AssertPtrReturn(pThis, NULL);
1412 AssertPtrReturn(pSink, NULL);
1413
1414 /** @todo Do something with the channel mapping here? */
1415 return hdaStreamGetFromSD(pThis, pSink->uSD);
1416}
1417
1418
1419/**
1420 * Returns the audio direction of a specified stream descriptor.
1421 *
1422 * The register layout specifies that input streams (SDI) come first,
1423 * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
1424 * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
1425 *
1426 * Note: SDnFMT register does not provide that information, so we have to judge
1427 * for ourselves.
1428 *
1429 * @return Audio direction.
1430 */
1431DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)
1432{
1433 AssertReturn(uSD <= HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
1434
1435 if (uSD < HDA_MAX_SDI)
1436 return PDMAUDIODIR_IN;
1437
1438 return PDMAUDIODIR_OUT;
1439}
1440#endif /* IN_RING3 */
1441
1442
1443static void hdaUpdateINTSTS(PHDASTATE pThis)
1444{
1445 uint32_t intSts = 0;
1446
1447 /* Check controller interrupts (RIRB, STATEST) */
1448 if ( (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
1449 /* SDIN State Change Status Flags (SCSF) */
1450 || (HDA_REG(pThis, STATESTS) & HDA_STATESTS_SCSF_MASK))
1451 {
1452 intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
1453 }
1454
1455 /* For each stream, check if any interrupt status bit is set and enabled. */
1456 for (int iStrm = 0; iStrm < 8; ++iStrm)
1457 {
1458 if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE | HDA_SDCTL_IOCE))
1459 {
1460 Log3Func(("[SD%d] interrupt status set\n", iStrm));
1461 intSts |= RT_BIT(iStrm);
1462 }
1463 }
1464
1465 if (intSts)
1466 intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
1467
1468 HDA_REG(pThis, INTSTS) = intSts;
1469 Log3Func(("INTSTS=%x\n", intSts));
1470}
1471
1472/* Update INTSTS register and the hardware interrupt signal. This function must be called
1473 * after changing any interrupt status or enable bits.
1474 */
1475static int hdaUpdateInterrupt(PHDASTATE pThis)
1476{
1477 hdaUpdateINTSTS(pThis);
1478
1479 int iLevel = 0;
1480
1481 /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
1482 * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
1483 */
1484
1485 /* If global interrupt enable (GIE) is set, check if any enabled interrupts are set. */
1486 if (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
1487 if (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK))
1488 iLevel = 1;
1489
1490 Log3Func(("INTCTL=%x, INTSTS=%x, Level=%d\n", HDA_REG(pThis, INTCTL), HDA_REG(pThis, INTSTS), iLevel));
1491
1492 PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, iLevel);
1493
1494 return VINF_SUCCESS;
1495}
1496
1497/**
1498 * Looks up a register at the exact offset given by @a offReg.
1499 *
1500 * @returns Register index on success, -1 if not found.
1501 * @param offReg The register offset.
1502 */
1503static int hdaRegLookup(uint32_t offReg)
1504{
1505 /*
1506 * Aliases.
1507 */
1508 if (offReg >= g_aHdaRegAliases[0].offReg)
1509 {
1510 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1511 if (offReg == g_aHdaRegAliases[i].offReg)
1512 return g_aHdaRegAliases[i].idxAlias;
1513 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1514 return -1;
1515 }
1516
1517 /*
1518 * Binary search the
1519 */
1520 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1521 int idxLow = 0;
1522 for (;;)
1523 {
1524 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1525 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1526 {
1527 if (idxLow == idxMiddle)
1528 break;
1529 idxEnd = idxMiddle;
1530 }
1531 else if (offReg > g_aHdaRegMap[idxMiddle].offset)
1532 {
1533 idxLow = idxMiddle + 1;
1534 if (idxLow >= idxEnd)
1535 break;
1536 }
1537 else
1538 return idxMiddle;
1539 }
1540
1541#ifdef RT_STRICT
1542 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1543 Assert(g_aHdaRegMap[i].offset != offReg);
1544#endif
1545 return -1;
1546}
1547
1548/**
1549 * Looks up a register covering the offset given by @a offReg.
1550 *
1551 * @returns Register index on success, -1 if not found.
1552 * @param offReg The register offset.
1553 */
1554static int hdaRegLookupWithin(uint32_t offReg)
1555{
1556 /*
1557 * Aliases.
1558 */
1559 if (offReg >= g_aHdaRegAliases[0].offReg)
1560 {
1561 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
1562 {
1563 uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
1564 if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
1565 return g_aHdaRegAliases[i].idxAlias;
1566 }
1567 Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
1568 return -1;
1569 }
1570
1571 /*
1572 * Binary search the register map.
1573 */
1574 int idxEnd = RT_ELEMENTS(g_aHdaRegMap);
1575 int idxLow = 0;
1576 for (;;)
1577 {
1578 int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
1579 if (offReg < g_aHdaRegMap[idxMiddle].offset)
1580 {
1581 if (idxLow == idxMiddle)
1582 break;
1583 idxEnd = idxMiddle;
1584 }
1585 else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
1586 {
1587 idxLow = idxMiddle + 1;
1588 if (idxLow >= idxEnd)
1589 break;
1590 }
1591 else
1592 return idxMiddle;
1593 }
1594
1595#ifdef RT_STRICT
1596 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
1597 Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
1598#endif
1599 return -1;
1600}
1601
1602#ifdef IN_RING3
1603
1604static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
1605{
1606 int rc = VINF_SUCCESS;
1607 if (fLocal)
1608 {
1609 Assert((HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA));
1610 Assert(pThis->u64CORBBase);
1611 AssertPtr(pThis->pu32CorbBuf);
1612 Assert(pThis->cbCorbBuf);
1613
1614 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
1615 if (RT_FAILURE(rc))
1616 AssertRCReturn(rc, rc);
1617# ifdef DEBUG_CMD_BUFFER
1618 uint8_t i = 0;
1619 do
1620 {
1621 LogFunc(("CORB%02x: ", i));
1622 uint8_t j = 0;
1623 do
1624 {
1625 const char *pszPrefix;
1626 if ((i + j) == HDA_REG(pThis, CORBRP));
1627 pszPrefix = "[R]";
1628 else if ((i + j) == HDA_REG(pThis, CORBWP));
1629 pszPrefix = "[W]";
1630 else
1631 pszPrefix = " "; /* three spaces */
1632 LogFunc(("%s%08x", pszPrefix, pThis->pu32CorbBuf[i + j]));
1633 j++;
1634 } while (j < 8);
1635 LogFunc(("\n"));
1636 i += 8;
1637 } while(i != 0);
1638# endif
1639 }
1640 else
1641 {
1642 Assert((HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RDMAEN));
1643 rc = PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
1644 if (RT_FAILURE(rc))
1645 AssertRCReturn(rc, rc);
1646# ifdef DEBUG_CMD_BUFFER
1647 uint8_t i = 0;
1648 do {
1649 LogFunc(("RIRB%02x: ", i));
1650 uint8_t j = 0;
1651 do {
1652 const char *prefix;
1653 if ((i + j) == HDA_REG(pThis, RIRBWP))
1654 prefix = "[W]";
1655 else
1656 prefix = " ";
1657 LogFunc((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
1658 } while (++j < 8);
1659 LogFunc(("\n"));
1660 i += 8;
1661 } while (i != 0);
1662# endif
1663 }
1664 return rc;
1665}
1666
1667static int hdaCORBCmdProcess(PHDASTATE pThis)
1668{
1669 int rc = hdaCmdSync(pThis, true);
1670 if (RT_FAILURE(rc))
1671 AssertRCReturn(rc, rc);
1672
1673 uint8_t corbRp = HDA_REG(pThis, CORBRP);
1674 uint8_t corbWp = HDA_REG(pThis, CORBWP);
1675 uint8_t rirbWp = HDA_REG(pThis, RIRBWP);
1676
1677 Assert((corbWp != corbRp));
1678 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1679
1680 while (corbRp != corbWp)
1681 {
1682 uint64_t uResp;
1683 uint32_t uCmd = pThis->pu32CorbBuf[++corbRp];
1684
1685 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec, HDA_CODEC_CMD(uCmd, 0 /* Codec index */), &uResp);
1686 if (RT_FAILURE(rc2))
1687 LogFunc(("Codec lookup failed with rc=%Rrc\n", rc2));
1688
1689 (rirbWp)++;
1690
1691 if ( (uResp & CODEC_RESPONSE_UNSOLICITED)
1692 && !(HDA_REG(pThis, GCTL) & HDA_GCTL_UNSOL))
1693 {
1694 LogFunc(("Unexpected unsolicited response\n"));
1695 HDA_REG(pThis, CORBRP) = corbRp;
1696 return rc;
1697 }
1698
1699 pThis->pu64RirbBuf[rirbWp] = uResp;
1700
1701 pThis->u8RespIntCnt++;
1702 if (pThis->u8RespIntCnt == RINTCNT_N(pThis))
1703 break;
1704 }
1705
1706 HDA_REG(pThis, CORBRP) = corbRp;
1707 HDA_REG(pThis, RIRBWP) = rirbWp;
1708
1709 rc = hdaCmdSync(pThis, false);
1710
1711 Log3Func(("CORB(RP:%x, WP:%x) RIRBWP:%x\n", HDA_REG(pThis, CORBRP), HDA_REG(pThis, CORBWP), HDA_REG(pThis, RIRBWP)));
1712
1713 HDA_REG(pThis, RIRBSTS) |= HDA_RIRBSTS_RINTFL;
1714
1715 pThis->u8RespIntCnt = 0;
1716 rc = hdaUpdateInterrupt(pThis);
1717
1718 if (RT_FAILURE(rc))
1719 AssertRCReturn(rc, rc);
1720 return rc;
1721}
1722
1723static int hdaStreamCreate(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
1724{
1725 RT_NOREF(pThis);
1726 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1727 AssertReturn(uSD <= HDA_MAX_STREAMS, VERR_INVALID_PARAMETER);
1728
1729#ifdef HDA_USE_DMA_ACCESS_HANDLER
1730 RTListInit(&pStream->State.lstDMAHandlers);
1731#endif
1732
1733 int rc = RTCritSectInit(&pStream->State.CritSect);
1734 if (RT_SUCCESS(rc))
1735 {
1736 pStream->u8SD = uSD;
1737 pStream->pMixSink = NULL;
1738
1739 pStream->State.fInReset = false;
1740 }
1741
1742 if (RT_SUCCESS(rc))
1743 rc = RTCircBufCreate(&pStream->State.pCircBuf, _4K); /** @todo Make this configurable. */
1744
1745 LogFlowFunc(("uSD=%RU8\n", uSD));
1746 return rc;
1747}
1748
1749static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream)
1750{
1751 AssertPtrReturnVoid(pStream);
1752
1753 LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
1754
1755 hdaStreamMapDestroy(&pStream->State.Mapping);
1756
1757 int rc2;
1758
1759#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1760 rc2 = hdaStreamAsyncIODestroy(pThis, pStream);
1761 AssertRC(rc2);
1762#else
1763 RT_NOREF(pThis);
1764#endif
1765
1766 rc2 = RTCritSectDelete(&pStream->State.CritSect);
1767 AssertRC(rc2);
1768
1769 if (pStream->State.pCircBuf)
1770 {
1771 RTCircBufDestroy(pStream->State.pCircBuf);
1772 pStream->State.pCircBuf = NULL;
1773 }
1774
1775 LogFlowFuncLeave();
1776}
1777
1778static int hdaStreamInit(PHDASTATE pThis, PHDASTREAM pStream, uint8_t u8SD)
1779{
1780 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1781 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1782
1783 pStream->u8SD = u8SD;
1784 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
1785 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
1786 pStream->u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
1787 pStream->u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
1788 pStream->u16FIFOS = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
1789
1790 RT_ZERO(pStream->State.BDLE);
1791 pStream->State.uCurBDLE = 0;
1792
1793 hdaStreamMapReset(&pStream->State.Mapping);
1794
1795 LogFlowFunc(("[SD%RU8]: DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
1796 pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS));
1797
1798# ifdef DEBUG
1799 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
1800 HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
1801 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
1802 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
1803
1804 LogFlowFunc(("\t-> DMA @ 0x%x, LVI=%RU16, CBL=%RU32\n", u64BaseDMA, u16LVI, u32CBL));
1805
1806 hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);
1807# endif
1808
1809 return VINF_SUCCESS;
1810}
1811
1812/**
1813 * Resets an HDA stream.
1814 *
1815 * @param pThis HDA state.
1816 * @param pStream HDA stream to reset.
1817 */
1818static void hdaStreamReset(PHDASTATE pThis, PHDASTREAM pStream)
1819{
1820 AssertPtrReturnVoid(pThis);
1821 AssertPtrReturnVoid(pStream);
1822
1823 const uint8_t uSD = pStream->u8SD;
1824
1825# ifdef VBOX_STRICT
1826 AssertReleaseMsg(!RT_BOOL(HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_RUN),
1827 ("[SD%RU8] Cannot reset stream while in running state\n", uSD));
1828# endif
1829
1830 LogFunc(("[SD%RU8]: Reset\n", uSD));
1831
1832 /*
1833 * First, reset the internal stream state.
1834 */
1835 RT_ZERO(pStream->State.BDLE);
1836 pStream->State.uCurBDLE = 0;
1837
1838 if (pStream->State.pCircBuf)
1839 RTCircBufReset(pStream->State.pCircBuf);
1840
1841 /*
1842 * Second, initialize the registers.
1843 */
1844 HDA_STREAM_REG(pThis, STS, uSD) = HDA_SDSTS_FIFORDY;
1845 /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
1846 * bits are reserved for stream number 18.2.33, resets SDnCTL except SRST bit. */
1847 HDA_STREAM_REG(pThis, CTL, uSD) = 0x40000 | (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_SRST);
1848 /*
1849 * ICH6 defines default values (120 bytes for input and 192 bytes for output descriptors) of FIFO size. 18.2.39.
1850 * BUT: Windows guests seem to read the FIFOS but define a DMA region which does not fit to that FIFO size
1851 * (e.g. 1792 bytes DMA region vs. 192 bytes FIFOS).
1852 * This will lead to crackling and corrupted sound -- so define a 256 bytes FIOS for output streams here per default.
1853 */
1854 HDA_STREAM_REG(pThis, FIFOS, uSD) = hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN ? HDA_SDIFIFO_120B : HDA_SDOFIFO_256B;
1855 /* See 18.2.38: Always defaults to 0x4 (32 bytes). */
1856 HDA_STREAM_REG(pThis, FIFOW, uSD) = HDA_SDFIFOW_32B;
1857 HDA_STREAM_REG(pThis, LPIB, uSD) = 0;
1858 HDA_STREAM_REG(pThis, CBL, uSD) = 0;
1859 HDA_STREAM_REG(pThis, LVI, uSD) = 0;
1860 HDA_STREAM_REG(pThis, FMT, uSD) = HDA_SDFMT_MAKE(HDA_SDFMT_TYPE_PCM, HDA_SDFMT_BASE_44KHZ,
1861 HDA_SDFMT_MULT_1X, HDA_SDFMT_DIV_1X, HDA_SDFMT_16_BIT,
1862 HDA_SDFMT_CHAN_STEREO);
1863 HDA_STREAM_REG(pThis, BDPU, uSD) = 0;
1864 HDA_STREAM_REG(pThis, BDPL, uSD) = 0;
1865
1866#ifdef HDA_USE_DMA_ACCESS_HANDLER
1867 hdaStreamUnregisterDMAHandlers(pThis, pStream);
1868#endif
1869
1870 int rc2 = hdaStreamInit(pThis, pStream, uSD);
1871 AssertRC(rc2);
1872}
1873
1874/**
1875 * Enables or disables an HDA audio stream.
1876 *
1877 * @returns IPRT status code.
1878 * @param pThis HDA state.
1879 * @param pStream HDA stream to enable or disable.
1880 * @param fEnable Whether to enable or disble the stream.
1881 */
1882static int hdaStreamEnable(PHDASTATE pThis, PHDASTREAM pStream, bool fEnable)
1883{
1884 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
1885 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
1886
1887 LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
1888
1889 int rc = VINF_SUCCESS;
1890
1891 hdaStreamLock(pStream);
1892
1893#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1894 hdaStreamAsyncIOLock(pStream);
1895 hdaStreamAsyncIOEnable(pStream, fEnable);
1896#endif
1897
1898 if (pStream->pMixSink) /* Stream attached to a sink? */
1899 {
1900 AUDMIXSINKCMD enmCmd = fEnable
1901 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE;
1902
1903 /* First, enable or disable the stream and the stream's sink, if any. */
1904 if (pStream->pMixSink->pMixSink)
1905 rc = AudioMixerSinkCtl(pStream->pMixSink->pMixSink, enmCmd);
1906 }
1907
1908#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
1909 hdaStreamAsyncIOUnlock(pStream);
1910#endif
1911
1912 /* Make sure to leave the lock before (eventually) starting the timer. */
1913 hdaStreamUnlock(pStream);
1914
1915#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
1916 /* Second, see if we need to start or stop the timer. */
1917 if (!fEnable)
1918 hdaTimerMaybeStop(pThis);
1919 else
1920 hdaTimerMaybeStart(pThis);
1921#endif
1922
1923 LogFunc(("[SD%RU8]: cStreamsActive=%RU8, rc=%Rrc\n", pStream->u8SD, pThis->cStreamsActive, rc));
1924 return rc;
1925}
1926
1927# if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)
1928static int hdaStreamChannelExtract(PPDMAUDIOSTREAMCHANNEL pChan, const void *pvBuf, size_t cbBuf)
1929{
1930 AssertPtrReturn(pChan, VERR_INVALID_POINTER);
1931 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
1932 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
1933
1934 AssertRelease(pChan->cbOff <= cbBuf);
1935
1936 const uint8_t *pu8Buf = (const uint8_t *)pvBuf;
1937
1938 size_t cbSrc = cbBuf - pChan->cbOff;
1939 const uint8_t *pvSrc = &pu8Buf[pChan->cbOff];
1940
1941 size_t cbDst;
1942 uint8_t *pvDst;
1943 RTCircBufAcquireWriteBlock(pChan->Data.pCircBuf, cbBuf, (void **)&pvDst, &cbDst);
1944
1945 cbSrc = RT_MIN(cbSrc, cbDst);
1946
1947 while (cbSrc)
1948 {
1949 AssertBreak(cbDst >= cbSrc);
1950
1951 /* Enough data for at least one next frame? */
1952 if (cbSrc < pChan->cbFrame)
1953 break;
1954
1955 memcpy(pvDst, pvSrc, pChan->cbFrame);
1956
1957 /* Advance to next channel frame in stream. */
1958 pvSrc += pChan->cbStep;
1959 Assert(cbSrc >= pChan->cbStep);
1960 cbSrc -= pChan->cbStep;
1961
1962 /* Advance destination by one frame. */
1963 pvDst += pChan->cbFrame;
1964 Assert(cbDst >= pChan->cbFrame);
1965 cbDst -= pChan->cbFrame;
1966
1967 /* Adjust offset. */
1968 pChan->cbOff += pChan->cbFrame;
1969 }
1970
1971 RTCircBufReleaseWriteBlock(pChan->Data.pCircBuf, cbDst);
1972
1973 return VINF_SUCCESS;
1974}
1975# endif /* defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND) */
1976
1977# if 0 /** @todo hdaStreamChannelAdvance is unused */
1978static int hdaStreamChannelAdvance(PPDMAUDIOSTREAMCHANNEL pChan, size_t cbAdv)
1979{
1980 AssertPtrReturn(pChan, VERR_INVALID_POINTER);
1981
1982 if (!cbAdv)
1983 return VINF_SUCCESS;
1984
1985 return VINF_SUCCESS;
1986}
1987# endif
1988
1989static int hdaStreamChannelDataInit(PPDMAUDIOSTREAMCHANNELDATA pChanData, uint32_t fFlags)
1990{
1991 int rc = RTCircBufCreate(&pChanData->pCircBuf, 256); /** @todo Make this configurable? */
1992 if (RT_SUCCESS(rc))
1993 {
1994 pChanData->fFlags = fFlags;
1995 }
1996
1997 return rc;
1998}
1999
2000/**
2001 * Frees a stream channel data block again.
2002 *
2003 * @param pChanData Pointer to channel data to free.
2004 */
2005static void hdaStreamChannelDataDestroy(PPDMAUDIOSTREAMCHANNELDATA pChanData)
2006{
2007 if (!pChanData)
2008 return;
2009
2010 if (pChanData->pCircBuf)
2011 {
2012 RTCircBufDestroy(pChanData->pCircBuf);
2013 pChanData->pCircBuf = NULL;
2014 }
2015
2016 pChanData->fFlags = PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE;
2017}
2018
2019# if defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND)
2020
2021static int hdaStreamChannelAcquireData(PPDMAUDIOSTREAMCHANNELDATA pChanData, void *pvData, size_t *pcbData)
2022{
2023 AssertPtrReturn(pChanData, VERR_INVALID_POINTER);
2024 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2025 AssertPtrReturn(pcbData, VERR_INVALID_POINTER);
2026
2027 RTCircBufAcquireReadBlock(pChanData->pCircBuf, 256 /** @todo Make this configurarble? */, &pvData, &pChanData->cbAcq);
2028
2029 *pcbData = pChanData->cbAcq;
2030 return VINF_SUCCESS;
2031}
2032
2033static int hdaStreamChannelReleaseData(PPDMAUDIOSTREAMCHANNELDATA pChanData)
2034{
2035 AssertPtrReturn(pChanData, VERR_INVALID_POINTER);
2036 RTCircBufReleaseReadBlock(pChanData->pCircBuf, pChanData->cbAcq);
2037
2038 return VINF_SUCCESS;
2039}
2040
2041# endif /* defined(VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT) || defined(VBOX_WITH_AUDIO_HDA_51_SURROUND) */
2042
2043# if 0 /* currently unused */
2044static int hdaStreamWaitForStateChange(PHDASTREAM pStream, RTMSINTERVAL msTimeout)
2045{
2046 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
2047
2048 LogFlowFunc(("[SD%RU8]: msTimeout=%RU32\n", pStream->u8SD, msTimeout));
2049 return RTSemEventWait(pStream->State.hStateChangedEvent, msTimeout);
2050}
2051# endif /* currently unused */
2052
2053#endif /* IN_RING3 */
2054
2055/* Register access handlers. */
2056
2057static int hdaRegReadUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2058{
2059 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg);
2060 *pu32Value = 0;
2061 return VINF_SUCCESS;
2062}
2063
2064static int hdaRegWriteUnimpl(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2065{
2066 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2067 return VINF_SUCCESS;
2068}
2069
2070/* U8 */
2071static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2072{
2073 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
2074 return hdaRegReadU32(pThis, iReg, pu32Value);
2075}
2076
2077static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2078{
2079 Assert((u32Value & 0xffffff00) == 0);
2080 return hdaRegWriteU32(pThis, iReg, u32Value);
2081}
2082
2083/* U16 */
2084static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2085{
2086 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
2087 return hdaRegReadU32(pThis, iReg, pu32Value);
2088}
2089
2090static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2091{
2092 Assert((u32Value & 0xffff0000) == 0);
2093 return hdaRegWriteU32(pThis, iReg, u32Value);
2094}
2095
2096/* U24 */
2097static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2098{
2099 Assert(((pThis->au32Regs[g_aHdaRegMap[iReg].mem_idx] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
2100 return hdaRegReadU32(pThis, iReg, pu32Value);
2101}
2102
2103#ifdef IN_RING3
2104static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2105{
2106 Assert((u32Value & 0xff000000) == 0);
2107 return hdaRegWriteU32(pThis, iReg, u32Value);
2108}
2109#endif
2110
2111/* U32 */
2112static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2113{
2114 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
2115
2116 *pu32Value = pThis->au32Regs[iRegMem] & g_aHdaRegMap[iReg].readable;
2117 return VINF_SUCCESS;
2118}
2119
2120static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2121{
2122 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
2123
2124 pThis->au32Regs[iRegMem] = (u32Value & g_aHdaRegMap[iReg].writable)
2125 | (pThis->au32Regs[iRegMem] & ~g_aHdaRegMap[iReg].writable);
2126 return VINF_SUCCESS;
2127}
2128
2129static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2130{
2131 RT_NOREF_PV(iReg);
2132
2133 if (u32Value & HDA_GCTL_CRST)
2134 {
2135 /* Set the CRST bit to indicate that we're leaving reset mode. */
2136 HDA_REG(pThis, GCTL) |= HDA_GCTL_CRST;
2137
2138 if (pThis->fInReset)
2139 {
2140 LogFunc(("Guest leaving HDA reset\n"));
2141 pThis->fInReset = false;
2142 }
2143 }
2144 else
2145 {
2146#ifdef IN_RING3
2147 /* Enter reset state. */
2148 LogFunc(("Guest entering HDA reset with DMA(RIRB:%s, CORB:%s)\n",
2149 HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA ? "on" : "off",
2150 HDA_REG(pThis, RIRBCTL) & HDA_RIRBCTL_RDMAEN ? "on" : "off"));
2151
2152 /* Clear the CRST bit to indicate that we're in reset state. */
2153 HDA_REG(pThis, GCTL) &= ~HDA_GCTL_CRST;
2154 pThis->fInReset = true;
2155
2156 hdaReset(pThis->CTX_SUFF(pDevIns));
2157#else
2158 return VINF_IOM_R3_MMIO_WRITE;
2159#endif
2160 }
2161
2162 if (u32Value & HDA_GCTL_FCNTRL)
2163 {
2164 /* Flush: GSTS:1 set, see 6.2.6. */
2165 HDA_REG(pThis, GSTS) |= HDA_GSTS_FSTS; /* Set the flush status. */
2166 /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6). */
2167 }
2168 return VINF_SUCCESS;
2169}
2170
2171static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2172{
2173 uint32_t v = HDA_REG_IND(pThis, iReg);
2174 uint32_t nv = u32Value & HDA_STATESTS_SCSF_MASK;
2175
2176 HDA_REG(pThis, STATESTS) &= ~(v & nv); /* Write of 1 clears corresponding bit. */
2177
2178 return hdaUpdateInterrupt(pThis);
2179}
2180
2181static int hdaRegWriteINTCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2182{
2183 RT_NOREF(iReg);
2184
2185 int rc;
2186
2187 HDA_REG(pThis, INTCTL) = u32Value;
2188
2189 rc = hdaUpdateInterrupt(pThis);
2190
2191 return rc;
2192}
2193
2194static int hdaRegReadLPIB(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2195{
2196 const uint8_t u8Strm = HDA_SD_NUM_FROM_REG(pThis, LPIB, iReg);
2197 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, u8Strm);
2198#ifdef LOG_ENABLED
2199 const uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, u8Strm);
2200 LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32\n", u8Strm, u32LPIB, u32CBL));
2201#endif
2202
2203 *pu32Value = u32LPIB;
2204 return VINF_SUCCESS;
2205}
2206
2207static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2208{
2209 RT_NOREF_PV(iReg);
2210
2211 /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
2212 *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->CTX_SUFF(pDevIns))
2213 - pThis->u64BaseTS, 24, 1000);
2214 LogFlowFunc(("%RU32\n", *pu32Value));
2215 return VINF_SUCCESS;
2216}
2217
2218static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2219{
2220 RT_NOREF_PV(iReg);
2221
2222 if (u32Value & HDA_CORBRP_RST)
2223 {
2224 HDA_REG(pThis, CORBRP) = 0;
2225 }
2226#ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO
2227 else
2228 return hdaRegWriteU8(pThis, iReg, u32Value);
2229#endif
2230 return VINF_SUCCESS;
2231}
2232
2233static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2234{
2235#ifdef IN_RING3
2236 int rc = hdaRegWriteU8(pThis, iReg, u32Value);
2237 AssertRC(rc);
2238 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
2239 && (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
2240 {
2241 return hdaCORBCmdProcess(pThis);
2242 }
2243 return rc;
2244#else
2245 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2246 return VINF_IOM_R3_MMIO_WRITE;
2247#endif
2248}
2249
2250static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2251{
2252 RT_NOREF_PV(iReg);
2253
2254 uint32_t v = HDA_REG(pThis, CORBSTS);
2255 HDA_REG(pThis, CORBSTS) &= ~(v & u32Value);
2256 return VINF_SUCCESS;
2257}
2258
2259static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2260{
2261#ifdef IN_RING3
2262 int rc;
2263 rc = hdaRegWriteU16(pThis, iReg, u32Value);
2264 if (RT_FAILURE(rc))
2265 AssertRCReturn(rc, rc);
2266 if (HDA_REG(pThis, CORBWP) == HDA_REG(pThis, CORBRP))
2267 return VINF_SUCCESS;
2268 if (!(HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
2269 return VINF_SUCCESS;
2270 rc = hdaCORBCmdProcess(pThis);
2271 return rc;
2272#else /* !IN_RING3 */
2273 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2274 return VINF_IOM_R3_MMIO_WRITE;
2275#endif /* IN_RING3 */
2276}
2277
2278static int hdaRegWriteSDCBL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2279{
2280#ifdef IN_RING3
2281 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
2282 return VINF_SUCCESS;
2283
2284 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, CBL, iReg));
2285 if (!pStream)
2286 {
2287 LogFunc(("[SD%RU8]: Warning: Changing SDCBL on non-attached stream (0x%x)\n",
2288 HDA_SD_NUM_FROM_REG(pThis, CTL, iReg), u32Value));
2289 return hdaRegWriteU32(pThis, iReg, u32Value);
2290 }
2291
2292 pStream->u32CBL = u32Value;
2293
2294 /* Reset BDLE state. */
2295 RT_ZERO(pStream->State.BDLE);
2296 pStream->State.uCurBDLE = 0;
2297
2298 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
2299 AssertRC(rc2);
2300
2301 LogFlowFunc(("[SD%RU8]: CBL=%RU32\n", pStream->u8SD, u32Value));
2302
2303 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2304#else /* !IN_RING3 */
2305 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2306 return VINF_IOM_R3_MMIO_WRITE;
2307#endif /* IN_RING3 */
2308}
2309
2310static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2311{
2312#ifdef IN_RING3
2313 /*
2314 * Some guests write too much (that is, 32-bit with the top 8 bit being junk)
2315 * instead of 24-bit required for SDCTL. So just mask this here to be safe.
2316 */
2317 u32Value = (u32Value & 0x00ffffff);
2318
2319 bool fRun = RT_BOOL(u32Value & HDA_SDCTL_RUN);
2320 bool fInRun = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_RUN);
2321
2322 bool fReset = RT_BOOL(u32Value & HDA_SDCTL_SRST);
2323 bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
2324
2325 /* Get the stream descriptor. */
2326 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, CTL, iReg);
2327
2328 LogFunc(("[SD%RU8]: fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
2329 uSD, fRun, fInRun, fReset, fInReset, u32Value));
2330
2331 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
2332 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2333
2334 /*
2335 * Extract the stream tag the guest wants to use for this specific
2336 * stream descriptor (SDn). This only can happen if the stream is in a non-running
2337 * state, so we're doing the lookup and assignment here.
2338 *
2339 * So depending on the guest OS, SD3 can use stream tag 4, for example.
2340 */
2341 uint8_t uTag = (u32Value >> HDA_SDCTL_NUM_SHIFT) & HDA_SDCTL_NUM_MASK;
2342 if (uTag > HDA_MAX_TAGS)
2343 {
2344 LogFunc(("[SD%RU8]: Warning: Invalid stream tag %RU8 specified!\n", uSD, uTag));
2345 return hdaRegWriteU24(pThis, iReg, u32Value);
2346 }
2347
2348 PHDATAG pTag = &pThis->aTags[uTag];
2349 AssertPtr(pTag);
2350
2351 LogFunc(("[SD%RU8]: Using stream tag=%RU8\n", uSD, uTag));
2352
2353 /* Assign new values. */
2354 pTag->uTag = uTag;
2355 pTag->pStrm = hdaStreamGetFromSD(pThis, uSD);
2356
2357 PHDASTREAM pStream = pTag->pStrm;
2358 AssertPtr(pStream);
2359
2360 if (fInReset)
2361 {
2362 Assert(!fReset);
2363 Assert(!fInRun && !fRun);
2364
2365 /* Exit reset state. */
2366 ASMAtomicXchgBool(&pStream->State.fInReset, false);
2367
2368 /* Report that we're done resetting this stream by clearing SRST. */
2369 HDA_STREAM_REG(pThis, CTL, uSD) &= ~HDA_SDCTL_SRST;
2370
2371 LogFunc(("[SD%RU8]: Reset exit\n", uSD));
2372 }
2373 else if (fReset)
2374 {
2375 /* ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset. */
2376 Assert(!fInRun && !fRun);
2377
2378 LogFunc(("[SD%RU8]: Reset enter\n", pStream->u8SD));
2379
2380 /* Enter reset state. */
2381 Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
2382 ASMAtomicXchgBool(&pStream->State.fInReset, true);
2383
2384 hdaStreamLock(pStream);
2385
2386 hdaStreamReset(pThis, pStream);
2387
2388 hdaStreamUnlock(pStream);
2389 }
2390 else
2391 {
2392 /*
2393 * We enter here to change DMA states only.
2394 */
2395 if (fInRun != fRun)
2396 {
2397 Assert(!fReset && !fInReset);
2398 LogFunc(("[SD%RU8]: State changed (fRun=%RTbool)\n", pStream->u8SD, fRun));
2399
2400 if (fRun)
2401 {
2402 /* Make sure to first fetch the current BDLE before enabling the stream below. */
2403 int rc2 = hdaBDLEFetch(pThis, &pStream->State.BDLE, pStream->u64BDLBase, pStream->State.uCurBDLE);
2404 AssertRC(rc2);
2405 }
2406
2407 hdaStreamEnable(pThis, pStream, fRun /* fEnable */);
2408 }
2409 }
2410
2411 int rc2 = hdaRegWriteU24(pThis, iReg, u32Value);
2412 AssertRC(rc2);
2413
2414 /* Make sure to handle interrupts here as well. */
2415 hdaUpdateInterrupt(pThis);
2416
2417 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2418#else /* !IN_RING3 */
2419 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2420 return VINF_IOM_R3_MMIO_WRITE;
2421#endif /* IN_RING3 */
2422}
2423
2424static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2425{
2426 uint32_t v = HDA_REG_IND(pThis, iReg);
2427
2428 /* Clear (zero) FIFOE, DESE and BCIS bits when writing 1 to it (6.2.33). */
2429 HDA_REG_IND(pThis, iReg) &= ~(u32Value & v);
2430
2431 LogFunc(("SDSTS 0x%x -> 0x%x\n", v, HDA_REG_IND(pThis, iReg)));
2432
2433 hdaUpdateInterrupt(pThis);
2434 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2435}
2436
2437static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2438{
2439#ifdef IN_RING3
2440 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
2441 return VINF_SUCCESS;
2442
2443 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, LVI, iReg);
2444
2445 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
2446 if (!pStream)
2447 {
2448 AssertMsgFailed(("[SD%RU8]: Warning: Changing SDLVI on non-attached stream (0x%x)\n", uSD, u32Value));
2449 return hdaRegWriteU16(pThis, iReg, u32Value);
2450 }
2451
2452 /** @todo Validate LVI. */
2453 pStream->u16LVI = u32Value;
2454 LogFunc(("[SD%RU8]: Updating LVI to %RU16\n", uSD, pStream->u16LVI));
2455
2456# ifdef HDA_USE_DMA_ACCESS_HANDLER
2457 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
2458 {
2459 /* Try registering the DMA handlers.
2460 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
2461 if (hdaStreamRegisterDMAHandlers(pThis, pStream))
2462 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
2463 }
2464# endif
2465
2466 /* Reset BDLE state. */
2467 RT_ZERO(pStream->State.BDLE);
2468 pStream->State.uCurBDLE = 0;
2469
2470 int rc2 = hdaRegWriteU16(pThis, iReg, u32Value);
2471 AssertRC(rc2);
2472
2473 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2474#else /* !IN_RING3 */
2475 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2476 return VINF_IOM_R3_MMIO_WRITE;
2477#endif /* IN_RING3 */
2478}
2479
2480static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2481{
2482#ifdef IN_RING3
2483 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
2484
2485 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_IN) /* FIFOW for input streams only. */
2486 {
2487 LogRel(("HDA: Warning: Guest tried to write read-only FIFOW to output stream #%RU8, ignoring\n", uSD));
2488 return VINF_SUCCESS;
2489 }
2490
2491 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg));
2492 if (!pStream)
2493 {
2494 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOW on non-attached stream (0x%x)\n", uSD, u32Value));
2495 return hdaRegWriteU16(pThis, iReg, u32Value);
2496 }
2497
2498 uint32_t u32FIFOW = 0;
2499
2500 switch (u32Value)
2501 {
2502 case HDA_SDFIFOW_8B:
2503 case HDA_SDFIFOW_16B:
2504 case HDA_SDFIFOW_32B:
2505 u32FIFOW = u32Value;
2506 break;
2507 default:
2508 LogRel(("HDA: Warning: Guest tried write unsupported FIFOW (0x%x) to stream #%RU8, defaulting to 32 bytes\n",
2509 u32Value, uSD));
2510 AssertFailed();
2511 u32FIFOW = HDA_SDFIFOW_32B;
2512 break;
2513 }
2514
2515 if (u32FIFOW)
2516 {
2517 pStream->u16FIFOW = hdaSDFIFOWToBytes(u32FIFOW);
2518 LogFunc(("[SD%RU8]: Updating FIFOW to %RU32 bytes\n", uSD, pStream->u16FIFOW));
2519
2520 int rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOW);
2521 AssertRC(rc2);
2522 }
2523
2524 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2525#else /* !IN_RING3 */
2526 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2527 return VINF_IOM_R3_MMIO_WRITE;
2528#endif /* IN_RING3 */
2529}
2530
2531/**
2532 * @note This method could be called for changing value on Output Streams only (ICH6 datasheet 18.2.39).
2533 */
2534static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2535{
2536#ifdef IN_RING3
2537 uint8_t uSD = HDA_SD_NUM_FROM_REG(pThis, FIFOS, iReg);
2538
2539 if (hdaGetDirFromSD(uSD) != PDMAUDIODIR_OUT) /* FIFOS for output streams only. */
2540 {
2541 LogRel(("HDA: Warning: Guest tried to write read-only FIFOS to input stream #%RU8, ignoring\n", uSD));
2542 return VINF_SUCCESS;
2543 }
2544
2545 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
2546 if (!pStream)
2547 {
2548 AssertMsgFailed(("[SD%RU8]: Warning: Changing FIFOS on non-attached stream (0x%x)\n", uSD, u32Value));
2549 return hdaRegWriteU16(pThis, iReg, u32Value);
2550 }
2551
2552 uint32_t u32FIFOS = 0;
2553
2554 switch(u32Value)
2555 {
2556 case HDA_SDOFIFO_16B:
2557 case HDA_SDOFIFO_32B:
2558 case HDA_SDOFIFO_64B:
2559 case HDA_SDOFIFO_128B:
2560 case HDA_SDOFIFO_192B:
2561 case HDA_SDOFIFO_256B:
2562 u32FIFOS = u32Value;
2563 break;
2564
2565 default:
2566 LogRel(("HDA: Warning: Guest tried write unsupported FIFOS (0x%x) to stream #%RU8, defaulting to 192 bytes\n",
2567 u32Value, uSD));
2568 AssertFailed();
2569 u32FIFOS = HDA_SDOFIFO_192B;
2570 break;
2571 }
2572
2573 if (u32FIFOS)
2574 {
2575 pStream->u16FIFOS = u32FIFOS + 1;
2576 LogFunc(("[SD%RU8]: Updating FIFOS to %RU32 bytes\n", uSD, pStream->u16FIFOS));
2577
2578 int rc2 = hdaRegWriteU16(pThis, iReg, u32FIFOS);
2579 AssertRC(rc2);
2580 }
2581
2582 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2583#else /* !IN_RING3 */
2584 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2585 return VINF_IOM_R3_MMIO_WRITE;
2586#endif /* IN_RING3 */
2587}
2588
2589#ifdef IN_RING3
2590static int hdaSDFMTToStrmCfg(uint32_t u32SDFMT, PPDMAUDIOSTREAMCFG pStrmCfg)
2591{
2592 AssertPtrReturn(pStrmCfg, VERR_INVALID_POINTER);
2593
2594# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
2595
2596 int rc = VINF_SUCCESS;
2597
2598 uint32_t u32Hz = EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
2599 ? 44100 : 48000;
2600 uint32_t u32HzMult = 1;
2601 uint32_t u32HzDiv = 1;
2602
2603 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
2604 {
2605 case 0: u32HzMult = 1; break;
2606 case 1: u32HzMult = 2; break;
2607 case 2: u32HzMult = 3; break;
2608 case 3: u32HzMult = 4; break;
2609 default:
2610 LogFunc(("Unsupported multiplier %x\n",
2611 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
2612 rc = VERR_NOT_SUPPORTED;
2613 break;
2614 }
2615 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
2616 {
2617 case 0: u32HzDiv = 1; break;
2618 case 1: u32HzDiv = 2; break;
2619 case 2: u32HzDiv = 3; break;
2620 case 3: u32HzDiv = 4; break;
2621 case 4: u32HzDiv = 5; break;
2622 case 5: u32HzDiv = 6; break;
2623 case 6: u32HzDiv = 7; break;
2624 case 7: u32HzDiv = 8; break;
2625 default:
2626 LogFunc(("Unsupported divisor %x\n",
2627 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
2628 rc = VERR_NOT_SUPPORTED;
2629 break;
2630 }
2631
2632 uint8_t cBits = 0;
2633 switch (EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
2634 {
2635 case 0:
2636 cBits = 8;
2637 break;
2638 case 1:
2639 cBits = 16;
2640 break;
2641 case 4:
2642 cBits = 32;
2643 break;
2644 default:
2645 AssertMsgFailed(("Unsupported bits per sample %x\n",
2646 EXTRACT_VALUE(u32SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
2647 rc = VERR_NOT_SUPPORTED;
2648 break;
2649 }
2650
2651 if (RT_SUCCESS(rc))
2652 {
2653 RT_ZERO(pStrmCfg->Props);
2654
2655 pStrmCfg->Props.uHz = u32Hz * u32HzMult / u32HzDiv;
2656 pStrmCfg->Props.cChannels = (u32SDFMT & 0xf) + 1;
2657 pStrmCfg->Props.cBits = cBits;
2658 pStrmCfg->Props.fSigned = true;
2659 pStrmCfg->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pStrmCfg->Props.cBits, pStrmCfg->Props.cChannels);
2660 }
2661
2662# undef EXTRACT_VALUE
2663 return rc;
2664}
2665
2666static int hdaAddStreamOut(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
2667{
2668 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2669 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2670
2671 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
2672
2673 LogFlowFunc(("Stream=%s\n", pCfg->szName));
2674
2675 int rc = VINF_SUCCESS;
2676
2677 bool fUseFront = true; /* Always use front out by default. */
2678#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2679 bool fUseRear;
2680 bool fUseCenter;
2681 bool fUseLFE;
2682
2683 fUseRear = fUseCenter = fUseLFE = false;
2684
2685 /*
2686 * Use commonly used setups for speaker configurations.
2687 */
2688
2689 /** @todo Make the following configurable through mixer API and/or CFGM? */
2690 switch (pCfg->cChannels)
2691 {
2692 case 3: /* 2.1: Front (Stereo) + LFE. */
2693 {
2694 fUseLFE = true;
2695 break;
2696 }
2697
2698 case 4: /* Quadrophonic: Front (Stereo) + Rear (Stereo). */
2699 {
2700 fUseRear = true;
2701 break;
2702 }
2703
2704 case 5: /* 4.1: Front (Stereo) + Rear (Stereo) + LFE. */
2705 {
2706 fUseRear = true;
2707 fUseLFE = true;
2708 break;
2709 }
2710
2711 case 6: /* 5.1: Front (Stereo) + Rear (Stereo) + Center/LFE. */
2712 {
2713 fUseRear = true;
2714 fUseCenter = true;
2715 fUseLFE = true;
2716 break;
2717 }
2718
2719 default: /* Unknown; fall back to 2 front channels (stereo). */
2720 {
2721 rc = VERR_NOT_SUPPORTED;
2722 break;
2723 }
2724 }
2725#else /* !VBOX_WITH_AUDIO_HDA_51_SURROUND */
2726 /* Only support mono or stereo channels. */
2727 if ( pCfg->Props.cChannels != 1 /* Mono */
2728 && pCfg->Props.cChannels != 2 /* Stereo */)
2729 {
2730 rc = VERR_NOT_SUPPORTED;
2731 }
2732#endif
2733
2734 if (rc == VERR_NOT_SUPPORTED)
2735 {
2736 LogRel(("HDA: Unsupported channel count (%RU8), falling back to stereo channels\n", pCfg->Props.cChannels));
2737 pCfg->Props.cChannels = 2;
2738
2739 rc = VINF_SUCCESS;
2740 }
2741
2742 do
2743 {
2744 if (RT_FAILURE(rc))
2745 break;
2746
2747 if (fUseFront)
2748 {
2749 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Front");
2750 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
2751 pCfg->Props.cChannels = 2;
2752
2753 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT);
2754 if (RT_SUCCESS(rc))
2755 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_FRONT, pCfg);
2756 }
2757
2758#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
2759 if ( RT_SUCCESS(rc)
2760 && (fUseCenter || fUseLFE))
2761 {
2762 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Center/LFE");
2763 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_CENTER_LFE;
2764 pCfg->Props.cChannels = (fUseCenter && fUseLFE) ? 2 : 1;
2765
2766 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE);
2767 if (RT_SUCCESS(rc))
2768 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_CENTER_LFE, pCfg);
2769 }
2770
2771 if ( RT_SUCCESS(rc)
2772 && fUseRear)
2773 {
2774 RTStrPrintf(pCfg->szName, RT_ELEMENTS(pCfg->szName), "Rear");
2775 pCfg->DestSource.Dest = PDMAUDIOPLAYBACKDEST_REAR;
2776 pCfg->Props.cChannels = 2;
2777
2778 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR);
2779 if (RT_SUCCESS(rc))
2780 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_REAR, pCfg);
2781 }
2782#endif /* VBOX_WITH_AUDIO_HDA_51_SURROUND */
2783
2784 } while (0);
2785
2786 LogFlowFuncLeaveRC(rc);
2787 return rc;
2788}
2789
2790static int hdaAddStreamIn(PHDASTATE pThis, PPDMAUDIOSTREAMCFG pCfg)
2791{
2792 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
2793 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2794
2795 AssertReturn(pCfg->enmDir == PDMAUDIODIR_IN, VERR_INVALID_PARAMETER);
2796
2797 LogFlowFunc(("Stream=%s, Source=%ld\n", pCfg->szName, pCfg->DestSource.Source));
2798
2799 int rc;
2800
2801 switch (pCfg->DestSource.Source)
2802 {
2803 case PDMAUDIORECSOURCE_LINE:
2804 {
2805 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN);
2806 if (RT_SUCCESS(rc))
2807 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_LINE_IN, pCfg);
2808 break;
2809 }
2810#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2811 case PDMAUDIORECSOURCE_MIC:
2812 {
2813 rc = hdaCodecRemoveStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN);
2814 if (RT_SUCCESS(rc))
2815 rc = hdaCodecAddStream(pThis->pCodec, PDMAUDIOMIXERCTL_MIC_IN, pCfg);
2816 break;
2817 }
2818#endif
2819 default:
2820 rc = VERR_NOT_SUPPORTED;
2821 break;
2822 }
2823
2824 LogFlowFuncLeaveRC(rc);
2825 return rc;
2826}
2827#endif /* IN_RING3 */
2828
2829static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2830{
2831#ifdef IN_RING3
2832 PDMAUDIOSTREAMCFG strmCfg;
2833 RT_ZERO(strmCfg);
2834
2835 int rc = hdaSDFMTToStrmCfg(u32Value, &strmCfg);
2836 if (RT_FAILURE(rc))
2837 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2838
2839 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, HDA_SD_NUM_FROM_REG(pThis, FMT, iReg));
2840 if (!pStream)
2841 {
2842 LogFunc(("[SD%RU8]: Warning: Changing SDFMT on non-attached stream (0x%x)\n",
2843 HDA_SD_NUM_FROM_REG(pThis, FMT, iReg), u32Value));
2844 return hdaRegWriteU16(pThis, iReg, u32Value);
2845 }
2846
2847 LogFunc(("[SD%RU8]: Hz=%RU32, Channels=%RU8, cBits=%RU8\n",
2848 pStream->u8SD, strmCfg.Props.uHz, strmCfg.Props.cChannels, strmCfg.Props.cBits));
2849
2850 /* Set audio direction. */
2851 strmCfg.enmDir = hdaGetDirFromSD(pStream->u8SD);
2852 switch (strmCfg.enmDir)
2853 {
2854 case PDMAUDIODIR_IN:
2855# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
2856# error "Implement me!"
2857# else
2858 strmCfg.DestSource.Source = PDMAUDIORECSOURCE_LINE;
2859 RTStrCopy(strmCfg.szName, sizeof(strmCfg.szName), "Line In");
2860# endif
2861 break;
2862
2863 case PDMAUDIODIR_OUT:
2864 /* Destination(s) will be set in hdaAddStreamOut(),
2865 * based on the channels / stream layout. */
2866 break;
2867
2868 default:
2869 rc = VERR_NOT_SUPPORTED;
2870 break;
2871 }
2872
2873#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
2874 if (RT_SUCCESS(rc))
2875 {
2876 rc = hdaStreamAsyncIOCreate(pThis, pStream);
2877 AssertRC(rc);
2878 }
2879#endif
2880
2881 /*
2882 * Initialize the stream mapping in any case, regardless if
2883 * we support surround audio or not. This is needed to handle
2884 * the supported channels within a single audio stream, e.g. mono/stereo.
2885 *
2886 * In other words, the stream mapping *always* knowns the real
2887 * number of channels in a single audio stream.
2888 */
2889 if (RT_SUCCESS(rc))
2890 {
2891 rc = hdaStreamMapInit(&pStream->State.Mapping, &strmCfg);
2892 AssertRC(rc);
2893 }
2894
2895 if (RT_SUCCESS(rc))
2896 {
2897 PHDADRIVER pDrv;
2898 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
2899 {
2900 int rc2;
2901 switch (strmCfg.enmDir)
2902 {
2903 case PDMAUDIODIR_OUT:
2904 rc2 = hdaAddStreamOut(pThis, &strmCfg);
2905 break;
2906
2907 case PDMAUDIODIR_IN:
2908 rc2 = hdaAddStreamIn(pThis, &strmCfg);
2909 break;
2910
2911 default:
2912 rc2 = VERR_NOT_SUPPORTED;
2913 AssertFailed();
2914 break;
2915 }
2916
2917 if ( RT_FAILURE(rc2)
2918 && (pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY)) /* We only care about primary drivers here, the rest may fail. */
2919 {
2920 if (RT_SUCCESS(rc))
2921 rc = rc2;
2922 /* Keep going. */
2923 }
2924 }
2925
2926 /* If (re-)opening the stream by the codec above failed, don't write the new
2927 * format to the register so that the guest is aware it didn't work. */
2928 if (RT_SUCCESS(rc))
2929 {
2930 rc = hdaRegWriteU16(pThis, iReg, u32Value);
2931 AssertRC(rc);
2932 }
2933 else
2934 LogFunc(("[SD%RU8]: (Re-)Opening stream failed with rc=%Rrc\n", pStream->u8SD, rc));
2935 }
2936
2937 return VINF_SUCCESS; /* Never return failure. */
2938#else /* !IN_RING3 */
2939 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value);
2940 return VINF_IOM_R3_MMIO_WRITE;
2941#endif
2942}
2943
2944/* Note: Will be called for both, BDPL and BDPU, registers. */
2945DECLINLINE(int) hdaRegWriteSDBDPX(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value, uint8_t uSD)
2946{
2947#ifdef IN_RING3
2948 if (HDA_REG_IND(pThis, iReg) == u32Value) /* Value already set? */
2949 return VINF_SUCCESS;
2950
2951 int rc2 = hdaRegWriteU32(pThis, iReg, u32Value);
2952 AssertRC(rc2);
2953
2954 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
2955 if (!pStream)
2956 return VINF_SUCCESS;
2957
2958 /* Update BDL base. */
2959 pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
2960 HDA_STREAM_REG(pThis, BDPU, uSD));
2961 AssertMsg(pStream->u64BDLBase, ("BDL base invalid\n"));
2962
2963 /* Reset BDLE state. */
2964 RT_ZERO(pStream->State.BDLE);
2965 pStream->State.uCurBDLE = 0;
2966
2967# ifdef HDA_USE_DMA_ACCESS_HANDLER
2968 if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
2969 {
2970 /* Try registering the DMA handlers.
2971 * As we can't be sure in which order LVI + BDL base are set, try registering in both routines. */
2972 if (hdaStreamRegisterDMAHandlers(pThis, pStream))
2973 LogFunc(("[SD%RU8] DMA logging enabled\n", pStream->u8SD));
2974 }
2975# endif
2976
2977 LogFlowFunc(("[SD%RU8]: BDLBase=0x%x\n", pStream->u8SD, pStream->u64BDLBase));
2978
2979 return VINF_SUCCESS; /* Always return success to the MMIO handler. */
2980#else /* !IN_RING3 */
2981 RT_NOREF_PV(pThis); RT_NOREF_PV(iReg); RT_NOREF_PV(u32Value); RT_NOREF_PV(uSD);
2982 return VINF_IOM_R3_MMIO_WRITE;
2983#endif /* IN_RING3 */
2984}
2985
2986static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2987{
2988 return hdaRegWriteSDBDPX(pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPL, iReg));
2989}
2990
2991static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
2992{
2993 return hdaRegWriteSDBDPX(pThis, iReg, u32Value, HDA_SD_NUM_FROM_REG(pThis, BDPU, iReg));
2994}
2995
2996static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
2997{
2998 /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
2999 if ( HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP)
3000 || (HDA_REG(pThis, CORBCTL) & HDA_CORBCTL_DMA))
3001 {
3002 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
3003 }
3004
3005 return hdaRegReadU32(pThis, iReg, pu32Value);
3006}
3007
3008static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3009{
3010 RT_NOREF_PV(iReg);
3011
3012 /*
3013 * If the guest set the ICB bit of IRS register, HDA should process the verb in IC register,
3014 * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
3015 */
3016 if ( (u32Value & HDA_IRS_ICB)
3017 && !(HDA_REG(pThis, IRS) & HDA_IRS_ICB))
3018 {
3019#ifdef IN_RING3
3020 uint32_t uCmd = HDA_REG(pThis, IC);
3021
3022 if (HDA_REG(pThis, CORBWP) != HDA_REG(pThis, CORBRP))
3023 {
3024 /*
3025 * 3.4.3: Defines behavior of immediate Command status register.
3026 */
3027 LogRel(("HDA: Guest attempted process immediate verb (%x) with active CORB\n", uCmd));
3028 return VINF_SUCCESS;
3029 }
3030
3031 HDA_REG(pThis, IRS) = HDA_IRS_ICB; /* busy */
3032
3033 uint64_t uResp;
3034 int rc2 = pThis->pCodec->pfnLookup(pThis->pCodec,
3035 HDA_CODEC_CMD(uCmd, 0 /* LUN */), &uResp);
3036 if (RT_FAILURE(rc2))
3037 LogFunc(("Codec lookup failed with rc2=%Rrc\n", rc2));
3038
3039 HDA_REG(pThis, IR) = (uint32_t)uResp; /** @todo r=andy Do we need a 64-bit response? */
3040 HDA_REG(pThis, IRS) = HDA_IRS_IRV; /* result is ready */
3041 /** @todo r=michaln We just set the IRS value, why are we clearing unset bits? */
3042 HDA_REG(pThis, IRS) &= ~HDA_IRS_ICB; /* busy is clear */
3043 return VINF_SUCCESS;
3044#else /* !IN_RING3 */
3045 return VINF_IOM_R3_MMIO_WRITE;
3046#endif /* !IN_RING3 */
3047 }
3048
3049 /*
3050 * Once the guest read the response, it should clear the IRV bit of the IRS register.
3051 */
3052 HDA_REG(pThis, IRS) &= ~(u32Value & HDA_IRS_IRV);
3053 return VINF_SUCCESS;
3054}
3055
3056static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3057{
3058 RT_NOREF_PV(iReg);
3059
3060 if (u32Value & HDA_RIRBWP_RST)
3061 HDA_REG(pThis, RIRBWP) = 0;
3062
3063 /* The remaining bits are O, see 6.2.22. */
3064 return VINF_SUCCESS;
3065}
3066
3067static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3068{
3069 uint32_t iRegMem = g_aHdaRegMap[iReg].mem_idx;
3070 int rc = hdaRegWriteU32(pThis, iReg, u32Value);
3071 if (RT_FAILURE(rc))
3072 AssertRCReturn(rc, rc);
3073
3074 switch(iReg)
3075 {
3076 case HDA_REG_CORBLBASE:
3077 pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
3078 pThis->u64CORBBase |= pThis->au32Regs[iRegMem];
3079 break;
3080 case HDA_REG_CORBUBASE:
3081 pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
3082 pThis->u64CORBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
3083 break;
3084 case HDA_REG_RIRBLBASE:
3085 pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
3086 pThis->u64RIRBBase |= pThis->au32Regs[iRegMem];
3087 break;
3088 case HDA_REG_RIRBUBASE:
3089 pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
3090 pThis->u64RIRBBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
3091 break;
3092 case HDA_REG_DPLBASE:
3093 {
3094 pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
3095 pThis->u64DPBase |= pThis->au32Regs[iRegMem];
3096
3097 /* Also make sure to handle the DMA position enable bit. */
3098 pThis->fDMAPosition = RT_BOOL(pThis->u64DPBase & RT_BIT_64(0));
3099 LogRel2(("HDA: %s DMA position buffer\n", pThis->fDMAPosition ? "Enabled" : "Disabled"));
3100 break;
3101 }
3102 case HDA_REG_DPUBASE:
3103 pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
3104 pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iRegMem] << 32);
3105 break;
3106 default:
3107 AssertMsgFailed(("Invalid index\n"));
3108 break;
3109 }
3110
3111 LogFunc(("CORB base:%llx RIRB base: %llx DP base: %llx\n",
3112 pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
3113 return rc;
3114}
3115
3116static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
3117{
3118 RT_NOREF_PV(iReg);
3119
3120 uint8_t v = HDA_REG(pThis, RIRBSTS);
3121 HDA_REG(pThis, RIRBSTS) &= ~(v & u32Value);
3122
3123 return hdaUpdateInterrupt(pThis);
3124}
3125
3126#ifdef IN_RING3
3127# ifdef HDA_USE_DMA_ACCESS_HANDLER
3128/**
3129 * Registers access handlers for a stream's BDLE DMA accesses.
3130 *
3131 * @returns @true if registration was successful, @false if not.
3132 * @param pThis HDA state.
3133 * @param pStream HDA stream to register BDLE access handlers for.
3134 */
3135static bool hdaStreamRegisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
3136{
3137 /* At least LVI and the BDL base must be set. */
3138 if ( !pStream->u16LVI
3139 || !pStream->u64BDLBase)
3140 {
3141 return false;
3142 }
3143
3144 hdaStreamUnregisterDMAHandlers(pThis, pStream);
3145
3146 LogFunc(("Registering ...\n"));
3147
3148 int rc = VINF_SUCCESS;
3149
3150 /*
3151 * Create BDLE ranges.
3152 */
3153
3154 struct BDLERANGE
3155 {
3156 RTGCPHYS uAddr;
3157 uint32_t uSize;
3158 } arrRanges[16]; /** @todo Use a define. */
3159
3160 size_t cRanges = 0;
3161
3162 for (uint16_t i = 0; i < pStream->u16LVI + 1; i++)
3163 {
3164 HDABDLE BDLE;
3165 rc = hdaBDLEFetch(pThis, &BDLE, pStream->u64BDLBase, i /* Index */);
3166 if (RT_FAILURE(rc))
3167 break;
3168
3169 bool fAddRange = true;
3170 BDLERANGE *pRange;
3171
3172 if (cRanges)
3173 {
3174 pRange = &arrRanges[cRanges - 1];
3175
3176 /* Is the current range a direct neighbor of the current BLDE? */
3177 if ((pRange->uAddr + pRange->uSize) == BDLE.Desc.u64BufAdr)
3178 {
3179 /* Expand the current range by the current BDLE's size. */
3180 pRange->uSize += BDLE.Desc.u32BufSize;
3181
3182 /* Adding a new range in this case is not needed anymore. */
3183 fAddRange = false;
3184
3185 LogFunc(("Expanding range %zu by %RU32 (%RU32 total now)\n", cRanges - 1, BDLE.Desc.u32BufSize, pRange->uSize));
3186 }
3187 }
3188
3189 /* Do we need to add a new range? */
3190 if ( fAddRange
3191 && cRanges < RT_ELEMENTS(arrRanges))
3192 {
3193 pRange = &arrRanges[cRanges];
3194
3195 pRange->uAddr = BDLE.Desc.u64BufAdr;
3196 pRange->uSize = BDLE.Desc.u32BufSize;
3197
3198 LogFunc(("Adding range %zu - 0x%x (%RU32)\n", cRanges, pRange->uAddr, pRange->uSize));
3199
3200 cRanges++;
3201 }
3202 }
3203
3204 LogFunc(("%zu ranges total\n", cRanges));
3205
3206 /*
3207 * Register all ranges as DMA access handlers.
3208 */
3209
3210 for (size_t i = 0; i < cRanges; i++)
3211 {
3212 BDLERANGE *pRange = &arrRanges[i];
3213
3214 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)RTMemAllocZ(sizeof(HDADMAACCESSHANDLER));
3215 if (!pHandler)
3216 {
3217 rc = VERR_NO_MEMORY;
3218 break;
3219 }
3220
3221 RTListAppend(&pStream->State.lstDMAHandlers, &pHandler->Node);
3222
3223 pHandler->pStream = pStream; /* Save a back reference to the owner. */
3224
3225 char szDesc[32];
3226 RTStrPrintf(szDesc, sizeof(szDesc), "HDA[SD%RU8 - RANGE%02zu]", pStream->u8SD, i);
3227
3228 int rc2 = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
3229 hdaDMAAccessHandler,
3230 NULL, NULL, NULL,
3231 NULL, NULL, NULL,
3232 szDesc, &pHandler->hAccessHandlerType);
3233 AssertRCBreak(rc2);
3234
3235 pHandler->BDLEAddr = pRange->uAddr;
3236 pHandler->BDLESize = pRange->uSize;
3237
3238 /* Get first and last pages of the BDLE range. */
3239 RTGCPHYS pgFirst = pRange->uAddr & ~PAGE_OFFSET_MASK;
3240 RTGCPHYS pgLast = RT_ALIGN(pgFirst + pRange->uSize, PAGE_SIZE);
3241
3242 /* Calculate the region size (in pages). */
3243 RTGCPHYS regionSize = RT_ALIGN(pgLast - pgFirst, PAGE_SIZE);
3244
3245 pHandler->GCPhysFirst = pgFirst;
3246 pHandler->GCPhysLast = pHandler->GCPhysFirst + (regionSize - 1);
3247
3248 LogFunc(("\tRegistering region '%s': 0x%x - 0x%x (region size: %zu)\n",
3249 szDesc, pHandler->GCPhysFirst, pHandler->GCPhysLast, regionSize));
3250 LogFunc(("\tBDLE @ 0x%x - 0x%x (%RU32)\n",
3251 pHandler->BDLEAddr, pHandler->BDLEAddr + pHandler->BDLESize, pHandler->BDLESize));
3252
3253 rc2 = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
3254 pHandler->GCPhysFirst, pHandler->GCPhysLast,
3255 pHandler->hAccessHandlerType, pHandler, NIL_RTR0PTR, NIL_RTRCPTR,
3256 szDesc);
3257 AssertRCBreak(rc2);
3258
3259 pHandler->fRegistered = true;
3260 }
3261
3262 LogFunc(("Registration ended with rc=%Rrc\n", rc));
3263
3264 return RT_SUCCESS(rc);
3265}
3266
3267/**
3268 * Unregisters access handlers of a stream's BDLEs.
3269 *
3270 * @param pThis HDA state.
3271 * @param pStream HDA stream to unregister BDLE access handlers for.
3272 */
3273static void hdaStreamUnregisterDMAHandlers(PHDASTATE pThis, PHDASTREAM pStream)
3274{
3275 LogFunc(("\n"));
3276
3277 PHDADMAACCESSHANDLER pHandler, pHandlerNext;
3278 RTListForEachSafe(&pStream->State.lstDMAHandlers, pHandler, pHandlerNext, HDADMAACCESSHANDLER, Node)
3279 {
3280 if (!pHandler->fRegistered) /* Handler not registered? Skip. */
3281 continue;
3282
3283 LogFunc(("Unregistering 0x%x - 0x%x (%zu)\n",
3284 pHandler->GCPhysFirst, pHandler->GCPhysLast, pHandler->GCPhysLast - pHandler->GCPhysFirst));
3285
3286 int rc2 = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3),
3287 pHandler->GCPhysFirst);
3288 AssertRC(rc2);
3289
3290 RTListNodeRemove(&pHandler->Node);
3291
3292 RTMemFree(pHandler);
3293 pHandler = NULL;
3294 }
3295
3296 Assert(RTListIsEmpty(&pStream->State.lstDMAHandlers));
3297}
3298# endif /* HDA_USE_DMA_ACCESS_HANDLER */
3299
3300#ifdef LOG_ENABLED
3301static void hdaBDLEDumpAll(PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
3302{
3303 LogFlowFunc(("BDLEs @ 0x%x (%RU16):\n", u64BDLBase, cBDLE));
3304 if (!u64BDLBase)
3305 return;
3306
3307 uint32_t cbBDLE = 0;
3308 for (uint16_t i = 0; i < cBDLE; i++)
3309 {
3310 HDABDLEDESC bd;
3311 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
3312
3313 LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
3314 i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC));
3315
3316 cbBDLE += bd.u32BufSize;
3317 }
3318
3319 LogFlowFunc(("Total: %RU32 bytes\n", cbBDLE));
3320
3321 if (!pThis->u64DPBase) /* No DMA base given? Bail out. */
3322 return;
3323
3324 LogFlowFunc(("DMA counters:\n"));
3325
3326 for (int i = 0; i < cBDLE; i++)
3327 {
3328 uint32_t uDMACnt;
3329 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
3330 &uDMACnt, sizeof(uDMACnt));
3331
3332 LogFlowFunc(("\t#%03d DMA @ 0x%x\n", i , uDMACnt));
3333 }
3334}
3335#endif
3336
3337/**
3338 * Fetches a Bundle Descriptor List Entry (BDLE) from the DMA engine.
3339 *
3340 * @param pThis Pointer to HDA state.
3341 * @param pBDLE Where to store the fetched result.
3342 * @param u64BaseDMA Address base of DMA engine to use.
3343 * @param u16Entry BDLE entry to fetch.
3344 */
3345static int hdaBDLEFetch(PHDASTATE pThis, PHDABDLE pBDLE, uint64_t u64BaseDMA, uint16_t u16Entry)
3346{
3347 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3348 AssertPtrReturn(pBDLE, VERR_INVALID_POINTER);
3349 AssertReturn(u64BaseDMA, VERR_INVALID_PARAMETER);
3350
3351 if (!u64BaseDMA)
3352 {
3353 LogRel2(("HDA: Unable to fetch BDLE #%RU16 - no base DMA address set (yet)\n", u16Entry));
3354 return VERR_NOT_FOUND;
3355 }
3356 /** @todo Compare u16Entry with LVI. */
3357
3358 int rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + u16Entry * sizeof(HDABDLEDESC),
3359 &pBDLE->Desc, sizeof(pBDLE->Desc));
3360 if (RT_FAILURE(rc))
3361 return rc;
3362
3363 /* Set internal state. */
3364 pBDLE->State.u32BufOff = 0;
3365 pBDLE->State.u32BDLIndex = u16Entry;
3366
3367 return VINF_SUCCESS;
3368}
3369
3370/**
3371 * Returns the number of outstanding stream data bytes which need to be processed
3372 * by the DMA engine assigned to this stream.
3373 *
3374 * @return Number of bytes for the DMA engine to process.
3375 */
3376DECLINLINE(uint32_t) hdaStreamGetTransferSize(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbMax)
3377{
3378 AssertPtrReturn(pThis, 0);
3379 AssertPtrReturn(pStream, 0);
3380 AssertReturn (cbMax, 0);
3381
3382 PHDABDLE pBDLE = &pStream->State.BDLE;
3383
3384 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
3385 Assert(u32LPIB <= pStream->u32CBL);
3386
3387 /* Do we have space left in the CBL at all? */
3388 uint32_t cbData = pStream->u32CBL - u32LPIB;
3389
3390 /* Limit to the available free space of the current BDLE. */
3391 cbData = RT_MIN(cbData, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
3392
3393 /* Make sure we only transfer as many bytes as requested. */
3394 cbData = RT_MIN(cbData, cbMax);
3395
3396 if (pBDLE->State.cbBelowFIFOW)
3397 {
3398 /* Are we not going to reach (or exceed) the FIFO watermark yet with the data to copy?
3399 * No need to read data from DMA then. */
3400 if (cbData > pBDLE->State.cbBelowFIFOW)
3401 {
3402 /* Subtract the amount of bytes that still would fit in the stream's FIFO
3403 * and therefore do not need to be processed by DMA. */
3404 cbData -= pBDLE->State.cbBelowFIFOW;
3405 }
3406 }
3407
3408 AssertMsg((cbData % 2 == 0), ("Transfer size invalid: %RU32\n", cbData));
3409
3410 Log3Func(("[SD%RU8]: CBL=%RU32, LPIB=%RU32, FIFOS=%RU16, cbData=%RU32, %R[bdle]\n", pStream->u8SD,
3411 pStream->u32CBL, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), pStream->u16FIFOS,
3412 cbData, pBDLE));
3413
3414 return cbData;
3415}
3416
3417DECLINLINE(void) hdaBDLEUpdate(PHDABDLE pBDLE, uint32_t cbData, uint32_t cbProcessed)
3418{
3419 AssertPtrReturnVoid(pBDLE);
3420
3421 if (!cbData || !cbProcessed)
3422 return;
3423
3424 Assert(pBDLE->Desc.u32BufSize >= cbProcessed);
3425
3426 /* Fewer than cbBelowFIFOW bytes were copied.
3427 * Probably we need to move the buffer, but it is rather hard to imagine a situation
3428 * where it might happen. */
3429 AssertMsg((cbProcessed == pBDLE->State.cbBelowFIFOW + cbData), /* we assume that we write the entire buffer including unreported bytes */
3430 ("cbProcessed=%RU32 != pBDLE->State.cbBelowFIFOW=%RU32 + cbData=%RU32\n",
3431 cbProcessed, pBDLE->State.cbBelowFIFOW, cbData));
3432
3433#if 0
3434 if ( pBDLE->State.cbBelowFIFOW
3435 && pBDLE->State.cbBelowFIFOW <= cbWritten)
3436 {
3437 LogFlowFunc(("BDLE(cbUnderFifoW:%RU32, off:%RU32, size:%RU32)\n",
3438 pBDLE->State.cbBelowFIFOW, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize));
3439 }
3440#endif
3441
3442 pBDLE->State.cbBelowFIFOW -= RT_MIN(pBDLE->State.cbBelowFIFOW, cbProcessed);
3443 Assert(pBDLE->State.cbBelowFIFOW == 0);
3444
3445 /* We always increment the position of DMA buffer counter because we're always reading
3446 * into an intermediate buffer. */
3447 Assert(pBDLE->Desc.u32BufSize >= (pBDLE->State.u32BufOff + cbProcessed));
3448 pBDLE->State.u32BufOff += cbProcessed;
3449
3450 LogFlowFunc(("cbData=%RU32, cbProcessed=%RU32, %R[bdle]\n", cbData, cbProcessed, pBDLE));
3451}
3452
3453#ifdef IN_RING3
3454/**
3455 * Initializes a stream mapping structure according to the given stream configuration.
3456 *
3457 * @return IPRT status code.
3458 * @param pMapping Pointer to mapping to initialize.
3459 * @param pCfg Pointer to stream configuration to use.
3460 */
3461static int hdaStreamMapInit(PHDASTREAMMAPPING pMapping, PPDMAUDIOSTREAMCFG pCfg)
3462{
3463 AssertPtrReturn(pMapping, VERR_INVALID_POINTER);
3464 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3465
3466 AssertReturn(pCfg->Props.cChannels, VERR_INVALID_PARAMETER);
3467
3468 hdaStreamMapReset(pMapping);
3469
3470 pMapping->paChannels = (PPDMAUDIOSTREAMCHANNEL)RTMemAlloc(sizeof(PDMAUDIOSTREAMCHANNEL) * pCfg->Props.cChannels);
3471 if (!pMapping->paChannels)
3472 return VERR_NO_MEMORY;
3473
3474 if (!DrvAudioHlpStreamCfgIsValid(pCfg))
3475 return VERR_INVALID_PARAMETER;
3476
3477 int rc = VINF_SUCCESS;
3478
3479 Assert(RT_IS_POWER_OF_TWO(pCfg->Props.cBits));
3480
3481 /** @todo We assume all channels in a stream have the same format. */
3482 PPDMAUDIOSTREAMCHANNEL pChan = pMapping->paChannels;
3483 for (uint8_t i = 0; i < pCfg->Props.cChannels; i++)
3484 {
3485 pChan->uChannel = i;
3486 pChan->cbStep = (pCfg->Props.cBits / 2);
3487 pChan->cbFrame = pChan->cbStep * pCfg->Props.cChannels;
3488 pChan->cbFirst = i * pChan->cbStep;
3489 pChan->cbOff = pChan->cbFirst;
3490
3491 int rc2 = hdaStreamChannelDataInit(&pChan->Data, PDMAUDIOSTREAMCHANNELDATA_FLAG_NONE);
3492 if (RT_SUCCESS(rc))
3493 rc = rc2;
3494
3495 if (RT_FAILURE(rc))
3496 break;
3497
3498 pChan++;
3499 }
3500
3501 if ( RT_SUCCESS(rc)
3502 /* Create circular buffer if not created yet. */
3503 && !pMapping->pCircBuf)
3504 {
3505 rc = RTCircBufCreate(&pMapping->pCircBuf, _4K); /** @todo Make size configurable? */
3506 }
3507
3508 if (RT_SUCCESS(rc))
3509 {
3510 pMapping->cChannels = pCfg->Props.cChannels;
3511#ifdef VBOX_WITH_HDA_AUDIO_INTERLEAVING_STREAMS_SUPPORT
3512 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
3513#else
3514 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
3515#endif
3516 }
3517
3518 return rc;
3519}
3520
3521/**
3522 * Destroys a given stream mapping.
3523 *
3524 * @param pMapping Pointer to mapping to destroy.
3525 */
3526static void hdaStreamMapDestroy(PHDASTREAMMAPPING pMapping)
3527{
3528 hdaStreamMapReset(pMapping);
3529
3530 if (pMapping->pCircBuf)
3531 {
3532 RTCircBufDestroy(pMapping->pCircBuf);
3533 pMapping->pCircBuf = NULL;
3534 }
3535}
3536
3537/**
3538 * Resets a given stream mapping.
3539 *
3540 * @param pMapping Pointer to mapping to reset.
3541 */
3542static void hdaStreamMapReset(PHDASTREAMMAPPING pMapping)
3543{
3544 AssertPtrReturnVoid(pMapping);
3545
3546 pMapping->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN;
3547
3548 if (pMapping->cChannels)
3549 {
3550 for (uint8_t i = 0; i < pMapping->cChannels; i++)
3551 hdaStreamChannelDataDestroy(&pMapping->paChannels[i].Data);
3552
3553 AssertPtr(pMapping->paChannels);
3554 RTMemFree(pMapping->paChannels);
3555 pMapping->paChannels = NULL;
3556
3557 pMapping->cChannels = 0;
3558 }
3559}
3560#endif /* IN_RING3 */
3561
3562DECLINLINE(bool) hdaStreamNeedsNextBDLE(PHDASTATE pThis, PHDASTREAM pStream)
3563{
3564 AssertPtrReturn(pThis, false);
3565 AssertPtrReturn(pStream, false);
3566
3567 PHDABDLE pBDLE = &pStream->State.BDLE;
3568 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD);
3569
3570 /* Did we reach the CBL (Cyclic Buffer List) limit? */
3571 bool fCBLLimitReached = u32LPIB >= pStream->u32CBL;
3572
3573 /* Do we need to use the next BDLE entry? Either because we reached
3574 * the CBL limit or our internal DMA buffer is full. */
3575 bool fNeedsNextBDLE = ( fCBLLimitReached
3576 || (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize));
3577
3578 Assert(u32LPIB <= pStream->u32CBL);
3579 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
3580
3581 LogFlowFunc(("[SD%RU8]: LPIB=%RU32, CBL=%RU32, fCBLLimitReached=%RTbool, fNeedsNextBDLE=%RTbool, %R[bdle]\n",
3582 pStream->u8SD, u32LPIB, pStream->u32CBL, fCBLLimitReached, fNeedsNextBDLE, pBDLE));
3583
3584 return fNeedsNextBDLE;
3585}
3586
3587DECLINLINE(void) hdaStreamTransferUpdate(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbInc)
3588{
3589 AssertPtrReturnVoid(pThis);
3590 AssertPtrReturnVoid(pStream);
3591
3592 if (!cbInc) /* Nothing to do? Bail out early. */
3593 return;
3594
3595 /*
3596 * If we're below the FIFO watermark (SDFIFOW), it's expected that HDA
3597 * doesn't fetch anything via DMA, so just update LPIB.
3598 * (ICH6 datasheet 18.2.38).
3599 */
3600 PHDABDLE pBDLE = &pStream->State.BDLE;
3601 if (pBDLE->State.cbBelowFIFOW == 0) /* Did we hit (or exceed) the watermark? */
3602 {
3603 uint32_t u32LPIB = HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) + cbInc;
3604
3605 Log3Func(("[SD%RU8]: LPIB: %RU32 -> %RU32, CBL=%RU32\n",
3606 pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), u32LPIB, pStream->u32CBL));
3607
3608 hdaStreamUpdateLPIB(pThis, pStream, u32LPIB);
3609 }
3610}
3611
3612static bool hdaBDLEIsComplete(PHDABDLE pBDLE, bool *pfInterrupt)
3613{
3614 AssertPtrReturn(pBDLE, true);
3615
3616 bool fInterrupt = false;
3617 bool fIsComplete = false;
3618
3619 /* Check if the current BDLE entry is complete (full). */
3620 if (pBDLE->State.u32BufOff >= pBDLE->Desc.u32BufSize)
3621 {
3622 Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
3623
3624 if (/* IOC (Interrupt On Completion) bit set? */
3625 pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC
3626 /* All data put into the DMA FIFO? */
3627 && pBDLE->State.cbBelowFIFOW == 0
3628 )
3629 {
3630 fInterrupt = true;
3631 }
3632
3633 fIsComplete = true;
3634 }
3635
3636 if (pfInterrupt)
3637 *pfInterrupt = fInterrupt;
3638
3639 LogFlowFunc(("%R[bdle] fIsComplete=%RTbool, fInterrupt=%RTbool\n", pBDLE, fIsComplete, fInterrupt));
3640
3641 return fIsComplete;
3642}
3643
3644/**
3645 * Retrieves a corresponding sink for a given mixer control.
3646 * Returns NULL if no sink is found.
3647 *
3648 * @return PHDAMIXERSINK
3649 * @param pThis HDA state.
3650 * @param enmMixerCtl Mixer control to get the corresponding sink for.
3651 */
3652static PHDAMIXERSINK hdaMixerControlToSink(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
3653{
3654 PHDAMIXERSINK pSink;
3655
3656 switch (enmMixerCtl)
3657 {
3658 case PDMAUDIOMIXERCTL_VOLUME_MASTER:
3659 /* Fall through is intentional. */
3660 case PDMAUDIOMIXERCTL_FRONT:
3661 pSink = &pThis->SinkFront;
3662 break;
3663#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3664 case PDMAUDIOMIXERCTL_CENTER_LFE:
3665 pSink = &pThis->SinkCenterLFE;
3666 break;
3667 case PDMAUDIOMIXERCTL_REAR:
3668 pSink = &pThis->SinkRear;
3669 break;
3670#endif
3671 case PDMAUDIOMIXERCTL_LINE_IN:
3672 pSink = &pThis->SinkLineIn;
3673 break;
3674#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3675 case PDMAUDIOMIXERCTL_MIC_IN:
3676 pSink = &pThis->SinkMicIn;
3677 break;
3678#endif
3679 default:
3680 pSink = NULL;
3681 AssertMsgFailed(("Unhandled mixer control\n"));
3682 break;
3683 }
3684
3685 return pSink;
3686}
3687
3688static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PHDAMIXERSINK pSink, PPDMAUDIOSTREAMCFG pCfg)
3689{
3690 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3691 AssertPtrReturn(pSink, VERR_INVALID_POINTER);
3692 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3693
3694 LogFunc(("Sink=%s, Stream=%s\n", pSink->pMixSink->pszName, pCfg->szName));
3695
3696 if (!DrvAudioHlpStreamCfgIsValid(pCfg))
3697 return VERR_INVALID_PARAMETER;
3698
3699 int rc = AudioMixerSinkSetFormat(pSink->pMixSink, &pCfg->Props);
3700 if (RT_FAILURE(rc))
3701 return rc;
3702
3703 PHDADRIVER pDrv;
3704 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3705 {
3706 int rc2 = VINF_SUCCESS;
3707 PHDADRIVERSTREAM pDrvStream = NULL;
3708
3709 PPDMAUDIOSTREAMCFG pStreamCfg = DrvAudioHlpStreamCfgDup(pCfg);
3710 if (!pStreamCfg)
3711 {
3712 rc = VERR_NO_MEMORY;
3713 break;
3714 }
3715
3716 /* Include the driver's LUN in the stream name for easier identification. */
3717 RTStrPrintf(pStreamCfg->szName, RT_ELEMENTS(pStreamCfg->szName), "[LUN#%RU8] %s", pDrv->uLUN, pCfg->szName);
3718
3719 if (pStreamCfg->enmDir == PDMAUDIODIR_IN)
3720 {
3721 LogFunc(("enmRecSource=%d\n", pStreamCfg->DestSource.Source));
3722
3723 switch (pStreamCfg->DestSource.Source)
3724 {
3725 case PDMAUDIORECSOURCE_LINE:
3726 pDrvStream = &pDrv->LineIn;
3727 break;
3728#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3729 case PDMAUDIORECSOURCE_MIC:
3730 pDrvStream = &pDrv->MicIn;
3731 break;
3732#endif
3733 default:
3734 rc2 = VERR_NOT_SUPPORTED;
3735 break;
3736 }
3737 }
3738 else if (pStreamCfg->enmDir == PDMAUDIODIR_OUT)
3739 {
3740 LogFunc(("enmPlaybackDest=%d\n", pStreamCfg->DestSource.Dest));
3741
3742 switch (pStreamCfg->DestSource.Dest)
3743 {
3744 case PDMAUDIOPLAYBACKDEST_FRONT:
3745 pDrvStream = &pDrv->Front;
3746 break;
3747#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3748 case PDMAUDIOPLAYBACKDEST_CENTER_LFE:
3749 pDrvStream = &pDrv->CenterLFE;
3750 break;
3751 case PDMAUDIOPLAYBACKDEST_REAR:
3752 pDrvStream = &pDrv->Rear;
3753 break;
3754#endif
3755 default:
3756 rc2 = VERR_NOT_SUPPORTED;
3757 break;
3758 }
3759 }
3760 else
3761 rc2 = VERR_NOT_SUPPORTED;
3762
3763 if (RT_SUCCESS(rc2))
3764 {
3765 AssertPtr(pDrvStream);
3766
3767 AudioMixerSinkRemoveStream(pSink->pMixSink, pDrvStream->pMixStrm);
3768
3769 AudioMixerStreamDestroy(pDrvStream->pMixStrm);
3770 pDrvStream->pMixStrm = NULL;
3771
3772 PAUDMIXSTREAM pMixStrm;
3773 rc2 = AudioMixerSinkCreateStream(pSink->pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, &pMixStrm);
3774 if (RT_SUCCESS(rc2))
3775 {
3776 rc2 = AudioMixerSinkAddStream(pSink->pMixSink, pMixStrm);
3777 LogFlowFunc(("LUN#%RU8: Added \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName , rc2));
3778 }
3779
3780 if (RT_SUCCESS(rc2))
3781 pDrvStream->pMixStrm = pMixStrm;
3782
3783 /* If creating a stream fails, be forgiving and continue -- don't pass rc2 to rc here. */
3784 }
3785
3786 if (pStreamCfg)
3787 {
3788 RTMemFree(pStreamCfg);
3789 pStreamCfg = NULL;
3790 }
3791 }
3792
3793 LogFlowFuncLeaveRC(rc);
3794 return rc;
3795}
3796
3797/**
3798 * Adds a new audio stream to a specific mixer control.
3799 * Depending on the mixer control the stream then gets assigned to one of the internal
3800 * mixer sinks, which in turn then handle the mixing of all connected streams to that sink.
3801 *
3802 * @return IPRT status code.
3803 * @param pThis HDA state.
3804 * @param enmMixerCtl Mixer control to assign new stream to.
3805 * @param pCfg Stream configuration for the new stream.
3806 */
3807static DECLCALLBACK(int) hdaMixerAddStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOSTREAMCFG pCfg)
3808{
3809 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3810 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
3811
3812 int rc;
3813
3814 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3815 if (pSink)
3816 {
3817 rc = hdaMixerAddStream(pThis, pSink, pCfg);
3818
3819 AssertPtr(pSink->pMixSink);
3820 LogFlowFunc(("Sink=%s, enmMixerCtl=%d\n", pSink->pMixSink->pszName, enmMixerCtl));
3821 }
3822 else
3823 rc = VERR_NOT_FOUND;
3824
3825 LogFlowFuncLeaveRC(rc);
3826 return rc;
3827}
3828
3829/**
3830 * Removes a specified mixer control from the HDA's mixer.
3831 *
3832 * @return IPRT status code.
3833 * @param pThis HDA state.
3834 * @param enmMixerCtl Mixer control to remove.
3835 *
3836 * @remarks Can be called as a callback by the HDA codec.
3837 */
3838static DECLCALLBACK(int) hdaMixerRemoveStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl)
3839{
3840 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
3841
3842 int rc;
3843
3844 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3845 if (pSink)
3846 {
3847 PHDADRIVER pDrv;
3848 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
3849 {
3850 PAUDMIXSTREAM pMixStream = NULL;
3851 switch (enmMixerCtl)
3852 {
3853 /*
3854 * Input.
3855 */
3856 case PDMAUDIOMIXERCTL_LINE_IN:
3857 pMixStream = pDrv->LineIn.pMixStrm;
3858 pDrv->LineIn.pMixStrm = NULL;
3859 break;
3860#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
3861 case PDMAUDIOMIXERCTL_MIC_IN:
3862 pMixStream = pDrv->MicIn.pMixStrm;
3863 pDrv->MicIn.pMixStrm = NULL;
3864 break;
3865#endif
3866 /*
3867 * Output.
3868 */
3869 case PDMAUDIOMIXERCTL_FRONT:
3870 pMixStream = pDrv->Front.pMixStrm;
3871 pDrv->Front.pMixStrm = NULL;
3872 break;
3873#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
3874 case PDMAUDIOMIXERCTL_CENTER_LFE:
3875 pMixStream = pDrv->CenterLFE.pMixStrm;
3876 pDrv->CenterLFE.pMixStrm = NULL;
3877 break;
3878 case PDMAUDIOMIXERCTL_REAR:
3879 pMixStream = pDrv->Rear.pMixStrm;
3880 pDrv->Rear.pMixStrm = NULL;
3881 break;
3882#endif
3883 default:
3884 AssertMsgFailed(("Mixer control %d not implemented\n", enmMixerCtl));
3885 break;
3886 }
3887
3888 if (pMixStream)
3889 {
3890 AudioMixerSinkRemoveStream(pSink->pMixSink, pMixStream);
3891 AudioMixerStreamDestroy(pMixStream);
3892
3893 pMixStream = NULL;
3894 }
3895 }
3896
3897 AudioMixerSinkRemoveAllStreams(pSink->pMixSink);
3898 rc = VINF_SUCCESS;
3899 }
3900 else
3901 rc = VERR_NOT_FOUND;
3902
3903 LogFlowFunc(("enmMixerCtl=%d, rc=%Rrc\n", enmMixerCtl, rc));
3904 return rc;
3905}
3906
3907/**
3908 * Sets a SDn stream number and channel to a particular mixer control.
3909 *
3910 * @returns IPRT status code.
3911 * @param pThis HDA State.
3912 * @param enmMixerCtl Mixer control to set SD stream number and channel for.
3913 * @param uSD SD stream number (number + 1) to set. Set to 0 for unassign.
3914 * @param uChannel Channel to set. Only valid if a valid SD stream number is specified.
3915 *
3916 * @remarks Can be called as a callback by the HDA codec.
3917 */
3918static DECLCALLBACK(int) hdaMixerSetStream(PHDASTATE pThis, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel)
3919{
3920 LogFlowFunc(("enmMixerCtl=%RU32, uSD=%RU8, uChannel=%RU8\n", enmMixerCtl, uSD, uChannel));
3921
3922 if (uSD == 0) /* Stream number 0 is reserved. */
3923 {
3924 LogFlowFunc(("Invalid SDn (%RU8) number for mixer control %d, ignoring\n", uSD, enmMixerCtl));
3925 return VINF_SUCCESS;
3926 }
3927 /* uChannel is optional. */
3928
3929 /* SDn0 starts as 1. */
3930 Assert(uSD);
3931 uSD--;
3932
3933 int rc;
3934
3935 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3936 if (pSink)
3937 {
3938 if ( (uSD < HDA_MAX_SDI)
3939 && AudioMixerSinkGetDir(pSink->pMixSink) == AUDMIXSINKDIR_OUTPUT)
3940 {
3941 uSD += HDA_MAX_SDI;
3942 }
3943
3944 LogFlowFunc(("%s: Setting to stream ID=%RU8, channel=%RU8, enmMixerCtl=%RU32\n",
3945 pSink->pMixSink->pszName, uSD, uChannel, enmMixerCtl));
3946
3947 Assert(uSD < HDA_MAX_STREAMS);
3948
3949 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, uSD);
3950 if (pStream)
3951 {
3952 hdaStreamLock(pStream);
3953
3954 pSink->uSD = uSD;
3955 pSink->uChannel = uChannel;
3956 pStream->pMixSink = pSink;
3957
3958 hdaStreamUnlock(pStream);
3959
3960 rc = VINF_SUCCESS;
3961 }
3962 else
3963 {
3964 LogRel(("HDA: Guest wanted to assign invalid stream ID=%RU8 (channel %RU8) to mixer control %RU32, skipping\n",
3965 uSD, uChannel, enmMixerCtl));
3966 rc = VERR_INVALID_PARAMETER;
3967 }
3968 }
3969 else
3970 rc = VERR_NOT_FOUND;
3971
3972 LogFlowFuncLeaveRC(rc);
3973 return rc;
3974}
3975
3976/**
3977 * Sets the volume of a specified mixer control.
3978 *
3979 * @return IPRT status code.
3980 * @param pThis HDA State.
3981 * @param enmMixerCtl Mixer control to set volume for.
3982 * @param pVol Pointer to volume data to set.
3983 *
3984 * @remarks Can be called as a callback by the HDA codec.
3985 */
3986static DECLCALLBACK(int) hdaMixerSetVolume(PHDASTATE pThis,
3987 PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol)
3988{
3989 int rc;
3990
3991 PHDAMIXERSINK pSink = hdaMixerControlToSink(pThis, enmMixerCtl);
3992 if (pSink)
3993 {
3994 /* Set the volume.
3995 * We assume that the codec already converted it to the correct range. */
3996 rc = AudioMixerSinkSetVolume(pSink->pMixSink, pVol);
3997 }
3998 else
3999 rc = VERR_NOT_FOUND;
4000
4001 LogFlowFuncLeaveRC(rc);
4002 return rc;
4003}
4004
4005#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
4006/**
4007 * Starts the internal audio device timer (if not started yet).
4008 *
4009 * @param pThis HDA state.
4010 */
4011static void hdaTimerMaybeStart(PHDASTATE pThis)
4012{
4013 LogFlowFuncEnter();
4014
4015 if (!pThis->pTimer)
4016 return;
4017
4018 pThis->cStreamsActive++;
4019
4020 /* Only start the timer at the first active stream. */
4021 if (pThis->cStreamsActive == 1)
4022 {
4023 LogRel2(("HDA: Starting transfers\n"));
4024
4025 /* Set timer flag. */
4026 ASMAtomicXchgBool(&pThis->fTimerActive, true);
4027
4028 /* Update current time timestamp. */
4029 pThis->uTimerTS = TMTimerGet(pThis->pTimer);
4030
4031 /* Start transfers. */
4032 hdaTimerMain(pThis);
4033 }
4034}
4035
4036/**
4037 * Stops the internal audio device timer.
4038 *
4039 * @param pThis HDA state.
4040 */
4041static void hdaTimerStop(PHDASTATE pThis)
4042{
4043 LogFlowFuncEnter();
4044
4045 /* Set timer flag. */
4046 ASMAtomicXchgBool(&pThis->fTimerActive, false);
4047}
4048
4049/**
4050 * Decreases the active HDA streams count by one and
4051 * then checks if the internal audio device timer can be
4052 * stopped.
4053 *
4054 * @param pThis HDA state.
4055 */
4056static void hdaTimerMaybeStop(PHDASTATE pThis)
4057{
4058 LogFlowFuncEnter();
4059
4060 if (!pThis->pTimer)
4061 return;
4062
4063 if (pThis->cStreamsActive) /* Disable can be called mupltiple times. */
4064 {
4065 pThis->cStreamsActive--;
4066
4067 if (pThis->cStreamsActive == 0)
4068 hdaTimerStop(pThis);
4069 }
4070}
4071
4072/**
4073 * Main routine for the device timer.
4074 *
4075 * @returns IPRT status code.
4076 * @param pThis HDA state.
4077 */
4078static void hdaTimerMain(PHDASTATE pThis)
4079{
4080 AssertPtrReturnVoid(pThis);
4081
4082 STAM_PROFILE_START(&pThis->StatTimer, a);
4083
4084 uint64_t cTicksNow = TMTimerGet(pThis->pTimer);
4085
4086 /* Update current time timestamp. */
4087 pThis->uTimerTS = cTicksNow;
4088
4089 /* Flag indicating whether to kick the timer again for a
4090 * new data processing round. */
4091 bool fKickTimer = false;
4092
4093 hdaDoTransfers(pThis);
4094
4095 /* Do we need to kick the timer again? */
4096 if ( AudioMixerSinkIsActive(pThis->SinkFront.pMixSink)
4097#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4098 || AudioMixerSinkIsActive(pThis->SinkCenterLFE.pMixSink)
4099 || AudioMixerSinkIsActive(pThis->SinkRear.pMixSink)
4100#endif
4101 || AudioMixerSinkIsActive(pThis->SinkLineIn.pMixSink)
4102#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4103 || AudioMixerSinkIsActive(pThis->SinkMicIn.pMixSink)
4104#endif
4105 )
4106 {
4107 fKickTimer = true;
4108 }
4109
4110 pThis->uTimerMS = RTTimeMilliTS();
4111
4112 if ( ASMAtomicReadBool(&pThis->fTimerActive)
4113 || fKickTimer)
4114 {
4115 /* Kick the timer again. */
4116 uint64_t cTicks = pThis->cTimerTicks;
4117 /** @todo adjust cTicks down by now much cbOutMin represents. */
4118 TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
4119 }
4120 else
4121 LogRel2(("HDA: Stopping transfers\n"));
4122
4123 STAM_PROFILE_STOP(&pThis->StatTimer, a);
4124}
4125
4126#ifdef HDA_USE_DMA_ACCESS_HANDLER
4127/**
4128 * HC access handler for the FIFO.
4129 *
4130 * @returns VINF_SUCCESS if the handler have carried out the operation.
4131 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
4132 * @param pVM VM Handle.
4133 * @param pVCpu The cross context CPU structure for the calling EMT.
4134 * @param GCPhys The physical address the guest is writing to.
4135 * @param pvPhys The HC mapping of that address.
4136 * @param pvBuf What the guest is reading/writing.
4137 * @param cbBuf How much it's reading/writing.
4138 * @param enmAccessType The access type.
4139 * @param enmOrigin Who is making the access.
4140 * @param pvUser User argument.
4141 */
4142static DECLCALLBACK(VBOXSTRICTRC) hdaDMAAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys,
4143 void *pvBuf, size_t cbBuf,
4144 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
4145{
4146 RT_NOREF(pVM, pVCpu, pvPhys, pvBuf, enmOrigin);
4147
4148 PHDADMAACCESSHANDLER pHandler = (PHDADMAACCESSHANDLER)pvUser;
4149 AssertPtr(pHandler);
4150
4151 PHDASTREAM pStream = pHandler->pStream;
4152 AssertPtr(pStream);
4153
4154 Assert(GCPhys >= pHandler->GCPhysFirst);
4155 Assert(GCPhys <= pHandler->GCPhysLast);
4156 Assert(enmAccessType == PGMACCESSTYPE_WRITE);
4157
4158 /* Not within BDLE range? Bail out. */
4159 if ( (GCPhys < pHandler->BDLEAddr)
4160 || (GCPhys + cbBuf > pHandler->BDLEAddr + pHandler->BDLESize))
4161 {
4162 return VINF_PGM_HANDLER_DO_DEFAULT;
4163 }
4164
4165 switch(enmAccessType)
4166 {
4167 case PGMACCESSTYPE_WRITE:
4168 {
4169# ifdef DEBUG
4170 PHDASTREAMDBGINFO pStreamDbg = &pStream->Dbg;
4171
4172 const uint64_t tsNowNs = RTTimeNanoTS();
4173 const uint32_t tsElapsedMs = (tsNowNs - pStreamDbg->tsWriteSlotBegin) / 1000 / 1000;
4174
4175 uint64_t cWritesHz = ASMAtomicReadU64(&pStreamDbg->cWritesHz);
4176 uint64_t cbWrittenHz = ASMAtomicReadU64(&pStreamDbg->cbWrittenHz);
4177
4178 if (tsElapsedMs >= (1000 / HDA_TIMER_HZ))
4179 {
4180 LogFunc(("[SD%RU8] %RU32ms elapsed, cbWritten=%RU64, cWritten=%RU64 -- %RU32 bytes on average per time slot (%zums)\n",
4181 pStream->u8SD, tsElapsedMs, cbWrittenHz, cWritesHz,
4182 ASMDivU64ByU32RetU32(cbWrittenHz, cWritesHz ? cWritesHz : 1), 1000 / HDA_TIMER_HZ));
4183
4184 pStreamDbg->tsWriteSlotBegin = tsNowNs;
4185
4186 cWritesHz = 0;
4187 cbWrittenHz = 0;
4188 }
4189
4190 cWritesHz += 1;
4191 cbWrittenHz += cbBuf;
4192
4193 ASMAtomicIncU64(&pStreamDbg->cWritesTotal);
4194 ASMAtomicAddU64(&pStreamDbg->cbWrittenTotal, cbBuf);
4195
4196 ASMAtomicWriteU64(&pStreamDbg->cWritesHz, cWritesHz);
4197 ASMAtomicWriteU64(&pStreamDbg->cbWrittenHz, cbWrittenHz);
4198
4199 LogFunc(("[SD%RU8] Writing %3zu @ 0x%x (off %zu)\n",
4200 pStream->u8SD, cbBuf, GCPhys, GCPhys - pHandler->BDLEAddr));
4201
4202 LogFunc(("[SD%RU8] cWrites=%RU64, cbWritten=%RU64 -> %RU32 bytes on average\n",
4203 pStream->u8SD, pStreamDbg->cWritesTotal, pStreamDbg->cbWrittenTotal,
4204 ASMDivU64ByU32RetU32(pStreamDbg->cbWrittenTotal, pStreamDbg->cWritesTotal)));
4205# endif
4206
4207# ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4208 RTFILE fh;
4209 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAAccessWrite.pcm",
4210 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4211 RTFileWrite(fh, pvBuf, cbBuf, NULL);
4212 RTFileClose(fh);
4213# endif
4214
4215# ifdef HDA_USE_DMA_ACCESS_HANDLER_WRITING
4216 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4217 AssertPtr(pCircBuf);
4218
4219 uint8_t *pbBuf = (uint8_t *)pvBuf;
4220 while (cbBuf)
4221 {
4222 /* Make sure we only copy as much as the stream's FIFO can hold (SDFIFOS, 18.2.39). */
4223 void *pvChunk;
4224 size_t cbChunk;
4225 RTCircBufAcquireWriteBlock(pCircBuf, cbBuf, &pvChunk, &cbChunk);
4226
4227 if (cbChunk)
4228 {
4229 memcpy(pvChunk, pbBuf, cbChunk);
4230
4231 pbBuf += cbChunk;
4232 Assert(cbBuf >= cbChunk);
4233 cbBuf -= cbChunk;
4234 }
4235 else
4236 {
4237 //AssertMsg(RTCircBufFree(pCircBuf), ("No more space but still %zu bytes to write\n", cbBuf));
4238 break;
4239 }
4240
4241 LogFunc(("[SD%RU8] cbChunk=%zu\n", pStream->u8SD, cbChunk));
4242
4243 RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
4244 }
4245# endif /* HDA_USE_DMA_ACCESS_HANDLER_WRITING */
4246 break;
4247 }
4248
4249 default:
4250 AssertMsgFailed(("Access type not implemented\n"));
4251 break;
4252 }
4253
4254 return VINF_PGM_HANDLER_DO_DEFAULT;
4255}
4256#endif /* HDA_USE_DMA_ACCESS_HANDLER */
4257
4258/**
4259 * Timer callback which handles the audio data transfers on a periodic basis.
4260 *
4261 * @param pDevIns Device instance.
4262 * @param pTimer Timer which was used when calling this.
4263 * @param pvUser User argument as PHDASTATE.
4264 */
4265static DECLCALLBACK(void) hdaTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
4266{
4267 RT_NOREF(pDevIns, pTimer);
4268
4269 PHDASTATE pThis = (PHDASTATE)pvUser;
4270 Assert(pThis == PDMINS_2_DATA(pDevIns, PHDASTATE));
4271 AssertPtr(pThis);
4272
4273 hdaTimerMain(pThis);
4274}
4275
4276#else /* VBOX_WITH_AUDIO_HDA_CALLBACKS */
4277
4278static DECLCALLBACK(int) hdaCallbackInput(PDMAUDIOCBTYPE enmType, void *pvCtx, size_t cbCtx, void *pvUser, size_t cbUser)
4279{
4280 Assert(enmType == PDMAUDIOCALLBACKTYPE_INPUT);
4281 AssertPtrReturn(pvCtx, VERR_INVALID_POINTER);
4282 AssertReturn(cbCtx, VERR_INVALID_PARAMETER);
4283 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
4284 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
4285
4286 PHDACALLBACKCTX pCtx = (PHDACALLBACKCTX)pvCtx;
4287 AssertReturn(cbCtx == sizeof(HDACALLBACKCTX), VERR_INVALID_PARAMETER);
4288
4289 PPDMAUDIOCBDATA_DATA_INPUT pData = (PPDMAUDIOCBDATA_DATA_INPUT)pvUser;
4290 AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_INPUT), VERR_INVALID_PARAMETER);
4291
4292 return hdaStreamDoDMA(pCtx->pThis, PI_INDEX, UINT32_MAX, &pData->cbOutRead);
4293}
4294
4295static DECLCALLBACK(int) hdaCallbackOutput(PDMAUDIOCBTYPE enmType, void *pvCtx, size_t cbCtx, void *pvUser, size_t cbUser)
4296{
4297 Assert(enmType == PDMAUDIOCALLBACKTYPE_OUTPUT);
4298 AssertPtrReturn(pvCtx, VERR_INVALID_POINTER);
4299 AssertReturn(cbCtx, VERR_INVALID_PARAMETER);
4300 AssertPtrReturn(pvUser, VERR_INVALID_POINTER);
4301 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
4302
4303 PHDACALLBACKCTX pCtx = (PHDACALLBACKCTX)pvCtx;
4304 AssertReturn(cbCtx == sizeof(HDACALLBACKCTX), VERR_INVALID_PARAMETER);
4305
4306 PPDMAUDIOCBDATA_DATA_OUTPUT pData = (PPDMAUDIOCBDATA_DATA_OUTPUT)pvUser;
4307 AssertReturn(cbUser == sizeof(PDMAUDIOCBDATA_DATA_OUTPUT), VERR_INVALID_PARAMETER);
4308
4309 PHDASTATE pThis = pCtx->pThis;
4310
4311 int rc = hdaStreamDoDMA(pCtx->pThis, PO_INDEX, UINT32_MAX, &pData->cbOutWritten);
4312 if ( RT_SUCCESS(rc)
4313 && pData->cbOutWritten)
4314 {
4315 PHDADRIVER pDrv;
4316 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
4317 {
4318 uint32_t cSamplesPlayed;
4319 int rc2 = pDrv->pConnector->pfnPlay(pDrv->pConnector, &cSamplesPlayed);
4320 LogFlowFunc(("LUN#%RU8: cSamplesPlayed=%RU32, rc=%Rrc\n", pDrv->uLUN, cSamplesPlayed, rc2));
4321 }
4322 }
4323}
4324#endif /* VBOX_WITH_AUDIO_HDA_CALLBACKS */
4325
4326/**
4327 * Main routine to perform the actual audio data transfers from the HDA streams
4328 * to the backend(s) and vice versa.
4329 *
4330 * @param pThis HDA state.
4331 */
4332static void hdaDoTransfers(PHDASTATE pThis)
4333{
4334 PHDASTREAM pStreamLineIn = hdaSinkGetStream(pThis, &pThis->SinkLineIn);
4335#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4336 PHDASTREAM pStreamMicIn = hdaSinkGetStream(pThis, &pThis->SinkMicIn);
4337#endif
4338 PHDASTREAM pStreamFront = hdaSinkGetStream(pThis, &pThis->SinkFront);
4339#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4340 /** @todo See note below. */
4341#endif
4342
4343 hdaStreamUpdate(pThis, pStreamLineIn);
4344#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
4345 hdaStreamUpdate(pThis, pStreamMicIn);
4346#endif
4347 hdaStreamUpdate(pThis, pStreamFront);
4348
4349
4350#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
4351 int rc2 = AudioMixerSinkUpdate(pThis->SinkCenterLFE.pMixSink);
4352 AssertRC(rc2);
4353
4354 rc2 = AudioMixerSinkUpdate(pThis->SinkRear.pMixSink);
4355 AssertRC(rc2);
4356 /** @todo Check for stream interleaving and only call hdaStreamDoDMA() if required! */
4357
4358 /*
4359 * Only call hdaTransfer if CenterLFE and/or Rear are on different SDs,
4360 * otherwise we have to use the interleaved streams support for getting the data
4361 * out of the Front sink (depending on the mapping layout).
4362 */
4363#endif
4364}
4365
4366#ifdef DEBUG_andy
4367# define HDA_DEBUG_DMA
4368#endif
4369
4370/**
4371 * Does a single DMA transfer for a specific HDA stream (SDI/SDO).
4372 * This either can be a read or write operation, depending on the HDA stream.
4373 *
4374 * @returns IPRT status code.
4375 * @param pThis HDA state.
4376 * @param pStream HDA stream to do the DMA transfer for.
4377 * @param pvBuf Pointer to buffer data to write data to / read data from.
4378 * @param cbBuf Size of buffer (in bytes).
4379 * @param cbToProcess Size (in bytes) to transfer (read/write).
4380 * @param pcbProcessed Size (in bytes) transferred (read/written). Optional.
4381 */
4382static int hdaStreamDoDMA(PHDASTATE pThis, PHDASTREAM pStream, void *pvBuf, uint32_t cbBuf,
4383 uint32_t cbToProcess, uint32_t *pcbProcessed)
4384{
4385 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
4386 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4387 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
4388 AssertReturn(cbBuf >= cbToProcess, VERR_INVALID_PARAMETER);
4389 /* pcbProcessed is optional. */
4390
4391 if (ASMAtomicReadBool(&pThis->fInReset)) /* HDA controller in reset mode? Bail out. */
4392 {
4393 if (pcbProcessed)
4394 *pcbProcessed = 0;
4395 return VINF_SUCCESS;
4396 }
4397
4398 bool fProceed = true;
4399
4400 Log3Func(("[SD%RU8] %R[sdsts] cbToProcess=%RU32\n",
4401 pStream->u8SD, HDA_STREAM_REG(pThis, STS, pStream->u8SD), cbToProcess));
4402
4403 /* Is the stream not in a running state currently? */
4404 if (!(HDA_STREAM_REG(pThis, CTL, pStream->u8SD) & HDA_SDCTL_RUN))
4405 fProceed = false;
4406 /* Is the BCIS (Buffer Completion Interrupt Status) flag set? Then we have to wait and skip. */
4407 else if ((HDA_STREAM_REG(pThis, STS, pStream->u8SD) & HDA_SDSTS_BCIS))
4408 fProceed = false;
4409
4410 if (!fProceed)
4411 {
4412#ifdef HDA_DEBUG_DMA
4413 Log3Func(("[SD%RU8] DMA: Skip\n", pStream->u8SD));
4414#endif
4415 if (pcbProcessed)
4416 *pcbProcessed = 0;
4417 return VINF_SUCCESS;
4418 }
4419
4420 int rc = VINF_SUCCESS;
4421
4422#ifdef HDA_DEBUG_DMA
4423 Log3Func(("[SD%RU8] DMA: Start\n", pStream->u8SD));
4424#endif
4425
4426 /* Sanity checks. */
4427 Assert(pStream->u8SD <= HDA_MAX_STREAMS);
4428 Assert(pStream->u64BDLBase);
4429 Assert(pStream->u32CBL);
4430
4431 /* State sanity checks. */
4432 Assert(pStream->State.fInReset == false);
4433 Assert(HDA_STREAM_REG(pThis, LPIB, pStream->u8SD) <= pStream->u32CBL);
4434
4435 bool fSendInterrupt = false;
4436
4437 /* Only do one FIFO size at a time. */
4438 uint32_t cbLeft = RT_MIN(pStream->u16FIFOS, RT_MIN(cbToProcess, cbBuf));
4439 uint32_t cbTotal = 0;
4440 uint32_t cbChunk = 0;
4441 uint32_t cbChunkProcessed = 0;
4442
4443#ifdef HDA_DEBUG_DMA
4444 LogFunc(("[SD%RU8] DMA: cbToProcess=%RU32, cbLeft=%RU32\n", pStream->u8SD, cbToProcess, cbLeft));
4445#endif
4446
4447 /* Get the maximum number of BDL entries. */
4448 uint16_t cBDLE = pStream->u16LVI + 1;
4449
4450 while ( cbLeft
4451 && cBDLE--)
4452 {
4453 cbChunk = hdaStreamGetTransferSize(pThis, pStream, cbLeft);
4454 cbChunkProcessed = 0;
4455
4456 PHDABDLE pBDLE = &pStream->State.BDLE;
4457
4458 if (cbChunk)
4459 {
4460 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
4461 {
4462 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns),
4463 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,
4464 (uint8_t *)pvBuf + cbTotal, cbChunk);
4465 }
4466 else /* Input (SDI). */
4467 {
4468 PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns),
4469 pBDLE->Desc.u64BufAdr + pBDLE->State.u32BufOff,
4470 (uint8_t *)pvBuf + cbTotal, cbChunk);
4471 }
4472
4473#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4474 RTFILE fh;
4475 RTFileOpen(&fh,
4476 hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT
4477 ? VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm" : VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm",
4478 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4479 RTFileWrite(fh, (uint8_t *)pvBuf + cbTotal, cbChunk, NULL);
4480 RTFileClose(fh);
4481#endif
4482 }
4483
4484 cbChunkProcessed = cbChunk;
4485
4486 hdaBDLEUpdate(pBDLE, cbChunkProcessed, cbChunkProcessed);
4487
4488 LogFunc(("[SD%RU8] DMA: Entry %RU32 Pos %RU32/%RU32 Chunk %RU32\n",
4489 pStream->u8SD, pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->Desc.u32BufSize, cbChunk));
4490
4491 Assert(cbLeft >= cbChunkProcessed);
4492 cbLeft -= cbChunkProcessed;
4493 cbTotal += cbChunkProcessed;
4494 Assert(cbTotal <= cbToProcess);
4495
4496 hdaStreamTransferUpdate(pThis, pStream, cbChunkProcessed);
4497
4498#ifdef HDA_DEBUG_DMA
4499 LogFunc(("[SD%RU8] DMA: LPIB %RU32 Pos %RU32 Left %RU32\n",
4500 pStream->u8SD, HDA_STREAM_REG(pThis, LPIB, pStream->u8SD), cbTotal, cbLeft));
4501#endif
4502 bool fNeedsInterrupt = false;
4503 bool fBDLEIsComplete = hdaBDLEIsComplete(pBDLE, &fNeedsInterrupt);
4504
4505 if (fNeedsInterrupt)
4506 fSendInterrupt = true;
4507
4508 if (fBDLEIsComplete)
4509 {
4510 /* Do we need to fetch the next Buffer Descriptor Entry (BDLE)? */
4511 if (hdaStreamNeedsNextBDLE(pThis, pStream))
4512 {
4513 bool fWrapAround;
4514 rc = hdaStreamGetNextBDLE(pThis, pStream, &fWrapAround);
4515 if ( RT_SUCCESS(rc)
4516 && fWrapAround)
4517 {
4518 hdaStreamUpdateLPIB(pThis, pStream, 0);
4519 }
4520 }
4521 }
4522
4523 if (RT_FAILURE(rc))
4524 break;
4525 }
4526
4527 Log3Func(("[SD%RU8]: cbLeft=%RU32, rc=%Rrc\n", pStream->u8SD, cbLeft, rc));
4528
4529 if (fSendInterrupt)
4530 {
4531#ifdef HDA_DEBUG_DMA
4532 Log3Func(("[SD%RU8] DMA: Interrupt\n", pStream->u8SD));
4533#endif
4534 /**
4535 * Set the BCIS (Buffer Completion Interrupt Status) flag as the
4536 * last byte of data for the current descriptor has been fetched
4537 * from memory and put into the DMA FIFO.
4538 *
4539 * Speech synthesis works fine on Mac Guest if this bit isn't set
4540 * but in general sound quality gets worse.
4541 *
4542 * This must be set in *any* case.
4543 */
4544 HDA_STREAM_REG(pThis, STS, pStream->u8SD) |= HDA_SDSTS_BCIS;
4545 Log3Func(("[SD%RU8]: BCIS set\n", pStream->u8SD));
4546
4547 hdaUpdateInterrupt(pThis);
4548 }
4549
4550 if (RT_SUCCESS(rc))
4551 {
4552 if (pcbProcessed)
4553 *pcbProcessed = cbTotal;
4554 }
4555
4556#ifdef HDA_DEBUG_DMA
4557 Log3Func(("[SD%RU8] DMA: End\n", pStream->u8SD));
4558#endif
4559
4560 return rc;
4561}
4562
4563/**
4564 * Writes audio data from a mixer sink into an HDA stream's DMA buffer.
4565 *
4566 * @returns IPRT status code.
4567 * @param pThis HDA state.
4568 * @param pStream HDA stream to write to.
4569 * @param cbToWrite Number of bytes to write.
4570 * @param pcbWritten Number of bytes written. Optional.
4571 */
4572static int hdaStreamWrite(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToWrite, uint32_t *pcbWritten)
4573{
4574 RT_NOREF(pThis);
4575 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4576 AssertReturn(cbToWrite, VERR_INVALID_PARAMETER);
4577 /* pcbWritten is optional. */
4578
4579 PHDAMIXERSINK pSink = pStream->pMixSink;
4580 if (!pSink)
4581 {
4582 AssertMsgFailed(("[SD%RU8]: Can't write to a stream with no sink attached\n", pStream->u8SD));
4583
4584 if (pcbWritten)
4585 *pcbWritten = 0;
4586 return VINF_SUCCESS;
4587 }
4588
4589 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4590 AssertPtr(pCircBuf);
4591
4592 void *pvDst;
4593 size_t cbDst;
4594
4595 uint32_t cbWritten = 0;
4596
4597 RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite, &pvDst, &cbDst);
4598
4599 if (cbDst)
4600 {
4601 int rc2 = AudioMixerSinkRead(pSink->pMixSink, AUDMIXOP_COPY, pvDst, (uint32_t)cbDst, &cbWritten);
4602 AssertRC(rc2);
4603
4604 Assert(cbDst >= cbWritten);
4605 Log2Func(("[SD%RU8]: %zu/%zu bytes written\n", pStream->u8SD, cbWritten, cbDst));
4606
4607#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4608 RTFILE fh;
4609 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm",
4610 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4611 RTFileWrite(fh, pvDst, cbWritten, NULL);
4612 RTFileClose(fh);
4613#endif
4614 }
4615
4616 RTCircBufReleaseWriteBlock(pCircBuf, cbWritten);
4617
4618 if (pcbWritten)
4619 *pcbWritten = cbWritten;
4620
4621 return VINF_SUCCESS;
4622}
4623
4624/**
4625 * Reads audio data from an HDA stream's DMA buffer and writes into a specified mixer sink.
4626 *
4627 * @returns IPRT status code.
4628 * @param pThis HDA state.
4629 * @param pStream HDA stream to read audio data from.
4630 * @param cbToRead Number of bytes to read.
4631 * @param pcbRead Number of bytes read. Optional.
4632 */
4633static int hdaStreamRead(PHDASTATE pThis, PHDASTREAM pStream, uint32_t cbToRead, uint32_t *pcbRead)
4634{
4635 RT_NOREF(pThis);
4636 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4637 AssertReturn(cbToRead, VERR_INVALID_PARAMETER);
4638 /* pcbWritten is optional. */
4639
4640 PHDAMIXERSINK pSink = pStream->pMixSink;
4641 if (!pSink)
4642 {
4643 AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));
4644
4645 if (pcbRead)
4646 *pcbRead = 0;
4647 return VINF_SUCCESS;
4648 }
4649
4650 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4651 AssertPtr(pCircBuf);
4652
4653 void *pvSrc;
4654 size_t cbSrc;
4655
4656 uint32_t cbRead = 0;
4657
4658 RTCircBufAcquireReadBlock(pCircBuf, cbToRead, &pvSrc, &cbSrc);
4659
4660 if (cbSrc)
4661 {
4662 Log2Func(("[SD%RU8]: Reading %zu bytes ...\n", pStream->u8SD, cbSrc));
4663
4664#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
4665 RTFILE fh;
4666 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm",
4667 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
4668 RTFileWrite(fh, pvSrc, cbSrc, NULL);
4669 RTFileClose(fh);
4670#endif
4671 int rc2 = AudioMixerSinkWrite(pSink->pMixSink, AUDMIXOP_COPY, pvSrc, (uint32_t)cbSrc, &cbRead);
4672 AssertRC(rc2);
4673
4674 Assert(cbSrc >= cbRead);
4675 Log2Func(("[SD%RU8]: %zu/%zu bytes read\n", pStream->u8SD, cbRead, cbSrc));
4676 }
4677
4678 RTCircBufReleaseReadBlock(pCircBuf, cbRead);
4679
4680 if (pcbRead)
4681 *pcbRead = cbRead;
4682
4683 return VINF_SUCCESS;
4684}
4685
4686#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
4687/**
4688 * Asynchronous I/O thread for a HDA stream.
4689 * This will do the heavy lifting work for us as soon as it's getting notified by another thread.
4690 *
4691 * @returns IPRT status code.
4692 * @param hThreadSelf Thread handle.
4693 * @param pvUser User argument. Must be of type PHDASTREAMTHREADCTX.
4694 */
4695static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
4696{
4697 PHDASTREAMTHREADCTX pCtx = (PHDASTREAMTHREADCTX)pvUser;
4698 AssertPtr(pCtx);
4699
4700 PHDASTATE pThis = pCtx->pThis;
4701 AssertPtr(pThis);
4702
4703 PHDASTREAM pStream = pCtx->pStream;
4704 AssertPtr(pStream);
4705
4706 PHDASTREAMSTATEAIO pAIO = &pCtx->pStream->State.AIO;
4707
4708 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4709 AssertPtr(pCircBuf);
4710
4711 ASMAtomicXchgBool(&pAIO->fStarted, true);
4712
4713 RTThreadUserSignal(hThreadSelf);
4714
4715 LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));
4716
4717 for (;;)
4718 {
4719 int rc2 = RTSemEventWait(pAIO->Event, RT_INDEFINITE_WAIT);
4720 if (RT_FAILURE(rc2))
4721 break;
4722
4723 if (ASMAtomicReadBool(&pAIO->fShutdown))
4724 break;
4725
4726 PHDAMIXERSINK pSink = pStream->pMixSink;
4727
4728 rc2 = RTCritSectEnter(&pAIO->CritSect);
4729 if (RT_SUCCESS(rc2))
4730 {
4731 if (!pAIO->fEnabled)
4732 {
4733 RTCritSectLeave(&pAIO->CritSect);
4734 continue;
4735 }
4736
4737 uint32_t cbToProcess;
4738 uint32_t cbProcessed = 0;
4739
4740 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
4741 {
4742 cbToProcess = (uint32_t)RTCircBufUsed(pCircBuf);
4743 if (cbToProcess)
4744 rc2 = hdaStreamRead(pThis, pStream, cbToProcess, &cbProcessed);
4745 }
4746 else /* Input (SDI). */
4747 {
4748 cbToProcess = (uint32_t)RTCircBufFree(pCircBuf);
4749 if (cbToProcess)
4750 rc2 = hdaStreamWrite(pThis, pStream, cbToProcess, &cbProcessed);
4751 }
4752
4753 if ( pSink
4754 && RT_SUCCESS(rc2))
4755 {
4756 rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
4757 }
4758
4759 int rc3 = RTCritSectLeave(&pAIO->CritSect);
4760 AssertRC(rc3);
4761 }
4762
4763 AssertRC(rc2);
4764 }
4765
4766 LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));
4767
4768 ASMAtomicXchgBool(&pAIO->fStarted, false);
4769
4770 return VINF_SUCCESS;
4771}
4772
4773/**
4774 * Creates the async I/O thread for a specific HDA audio stream.
4775 *
4776 * @returns IPRT status code.
4777 * @param pThis HDA state.
4778 * @param pStream HDA audio stream to create the async I/O thread for.
4779 */
4780static int hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream)
4781{
4782 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4783
4784 int rc;
4785
4786 if (!ASMAtomicReadBool(&pAIO->fStarted))
4787 {
4788 pAIO->fShutdown = false;
4789
4790 rc = RTSemEventCreate(&pAIO->Event);
4791 if (RT_SUCCESS(rc))
4792 {
4793 rc = RTCritSectInit(&pAIO->CritSect);
4794 if (RT_SUCCESS(rc))
4795 {
4796 HDASTREAMTHREADCTX Ctx = { pThis, pStream };
4797
4798 char szThreadName[64];
4799 RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
4800
4801 rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,
4802 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
4803 if (RT_SUCCESS(rc))
4804 rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
4805 }
4806 }
4807 }
4808 else
4809 rc = VINF_SUCCESS;
4810
4811 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
4812 return rc;
4813}
4814
4815/**
4816 * Destroys the async I/O thread of a specific HDA audio stream.
4817 *
4818 * @returns IPRT status code.
4819 * @param pThis HDA state.
4820 * @param pStream HDA audio stream to destroy the async I/O thread for.
4821 */
4822static int hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream)
4823{
4824 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4825
4826 if (!ASMAtomicReadBool(&pAIO->fStarted))
4827 return VINF_SUCCESS;
4828
4829 ASMAtomicWriteBool(&pAIO->fShutdown, true);
4830
4831 int rc = hdaStreamAsyncIONotify(pThis, pStream);
4832 AssertRC(rc);
4833
4834 int rcThread;
4835 rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
4836 LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
4837
4838 if (RT_SUCCESS(rc))
4839 {
4840 rc = RTCritSectDelete(&pAIO->CritSect);
4841 AssertRC(rc);
4842
4843 rc = RTSemEventDestroy(pAIO->Event);
4844 AssertRC(rc);
4845
4846 pAIO->fStarted = false;
4847 pAIO->fShutdown = false;
4848 pAIO->fEnabled = false;
4849 }
4850
4851 LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
4852 return rc;
4853}
4854
4855/**
4856 * Lets the stream's async I/O thread know that there is some data to process.
4857 *
4858 * @returns IPRT status code.
4859 * @param pThis HDA state.
4860 * @param pStream HDA stream to notify async I/O thread for.
4861 */
4862static int hdaStreamAsyncIONotify(PHDASTATE pThis, PHDASTREAM pStream)
4863{
4864 RT_NOREF(pThis);
4865 return RTSemEventSignal(pStream->State.AIO.Event);
4866}
4867
4868/**
4869 * Locks the async I/O thread of a specific HDA audio stream.
4870 *
4871 * @param pStream HDA stream to lock async I/O thread for.
4872 */
4873static void hdaStreamAsyncIOLock(PHDASTREAM pStream)
4874{
4875 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4876
4877 if (!ASMAtomicReadBool(&pAIO->fStarted))
4878 return;
4879
4880 int rc2 = RTCritSectEnter(&pAIO->CritSect);
4881 AssertRC(rc2);
4882}
4883
4884/**
4885 * Unlocks the async I/O thread of a specific HDA audio stream.
4886 *
4887 * @param pStream HDA stream to unlock async I/O thread for.
4888 */
4889static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream)
4890{
4891 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4892
4893 if (!ASMAtomicReadBool(&pAIO->fStarted))
4894 return;
4895
4896 int rc2 = RTCritSectLeave(&pAIO->CritSect);
4897 AssertRC(rc2);
4898}
4899
4900/**
4901 * Enables (resumes) or disables (pauses) the async I/O thread.
4902 *
4903 * @param pStream HDA stream to enable/disable async I/O thread for.
4904 * @param fEnable Whether to enable or disable the I/O thread.
4905 *
4906 * @remarks Does not do locking.
4907 */
4908static void hdaStreamAsyncIOEnable(PHDASTREAM pStream, bool fEnable)
4909{
4910 PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
4911 ASMAtomicXchgBool(&pAIO->fEnabled, fEnable);
4912}
4913#endif /* VBOX_WITH_AUDIO_HDA_ASYNC_IO */
4914
4915/**
4916 * Updates a HDA stream according to its usage (input / output).
4917 *
4918 * For an SDO (output) stream this means reading DMA data from the device to
4919 * the connected audio sink(s).
4920 *
4921 * For an SDI (input) stream this is reading audio data from the connected
4922 * audio sink(s) and writing it as DMA data to the device.
4923 *
4924 * @returns IPRT status code.
4925 * @param pThis HDA state.
4926 * @param pStream HDA stream to update.
4927 */
4928static int hdaStreamUpdate(PHDASTATE pThis, PHDASTREAM pStream)
4929{
4930 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
4931 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
4932
4933 hdaStreamLock(pStream);
4934
4935 PHDAMIXERSINK pSink = pStream->pMixSink;
4936 AssertPtr(pSink);
4937
4938 PRTCIRCBUF pCircBuf = pStream->State.pCircBuf;
4939 AssertPtr(pCircBuf);
4940
4941 if (!AudioMixerSinkIsActive(pSink->pMixSink))
4942 {
4943 hdaStreamUnlock(pStream);
4944 return VINF_SUCCESS;
4945 }
4946
4947 Log2Func(("[SD%RU8]\n", pStream->u8SD));
4948
4949 bool fDone = false;
4950 uint8_t cTransfers = 0;
4951
4952 while (!fDone)
4953 {
4954 int rc2;
4955 uint32_t cbDMA = 0;
4956
4957 if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_OUT) /* Output (SDO). */
4958 {
4959 STAM_PROFILE_START(&pThis->StatOut, a);
4960
4961 /*
4962 * Read from DMA.
4963 */
4964
4965 uint8_t abFIFO[HDA_FIFO_MAX + 1];
4966 size_t offFIFO = 0;
4967
4968 /* Do one DMA transfer with FIFOS size at a time. */
4969 rc2 = hdaStreamDoDMA(pThis, pStream, abFIFO, sizeof(abFIFO), (uint32_t)pStream->u16FIFOS /* cbToProcess */, &cbDMA);
4970 AssertRC(rc2);
4971
4972 uint32_t cbDMALeft = cbDMA;
4973
4974 while ( cbDMALeft
4975 && RTCircBufFree(pCircBuf))
4976 {
4977 void *pvDst;
4978 size_t cbDst;
4979
4980 RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvDst, &cbDst);
4981
4982 if (cbDst)
4983 {
4984 memcpy(pvDst, abFIFO + offFIFO, cbDst);
4985
4986 offFIFO += cbDst;
4987 Assert(offFIFO <= sizeof(abFIFO));
4988 }
4989
4990 RTCircBufReleaseWriteBlock(pCircBuf, cbDst);
4991
4992 Assert(cbDst <= cbDMALeft);
4993 cbDMALeft -= (uint32_t)cbDst;
4994 }
4995
4996 AssertMsg(cbDMALeft == 0, ("%RU32 bytes of DMA data left, CircBuf=%zu/%zu\n",
4997 cbDMALeft, RTCircBufUsed(pCircBuf), RTCircBufSize(pCircBuf)));
4998
4999 /*
5000 * Process backends.
5001 */
5002
5003 uint32_t cbUsed = (uint32_t)RTCircBufUsed(pCircBuf);
5004 if (cbUsed)
5005 {
5006#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5007 /* Let the asynchronous thread know that there is some new data to process. */
5008 hdaStreamAsyncIONotify(pThis, pStream);
5009#else
5010 /* Read audio data from the HDA stream and write to the backends. */
5011 rc2 = hdaStreamRead(pThis, pStream, cbUsed, NULL /* pcbRead */);
5012 AssertRC(rc2);
5013#endif
5014 }
5015
5016 /* All DMA transfers done for now? */
5017 if ( !cbDMA
5018#ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5019 /* All data read *and* processed for now? */
5020 && RTCircBufUsed(pCircBuf) == 0
5021#endif
5022 )
5023 {
5024 fDone = true;
5025 }
5026
5027#ifndef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5028 rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
5029 AssertRC(rc2);
5030#endif
5031 STAM_PROFILE_STOP(&pThis->StatOut, a);
5032 }
5033 else if (hdaGetDirFromSD(pStream->u8SD) == PDMAUDIODIR_IN) /* Input (SDI). */
5034 {
5035 STAM_PROFILE_START(&pThis->StatIn, a);
5036
5037 /*
5038 * Process backends.
5039 */
5040
5041#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
5042 /* Let the asynchronous thread know that there is some new data to process. */
5043 hdaStreamAsyncIONotify(pThis, pStream);
5044#else
5045 rc2 = AudioMixerSinkUpdate(pSink->pMixSink);
5046 AssertRC(rc2);
5047
5048 /* Write read data from the backend to the HDA stream. */
5049 rc2 = hdaStreamWrite(pThis, pStream, pStream->u16FIFOS, NULL /* pcbWritten */);
5050 AssertRC(rc2);
5051#endif
5052 /*
5053 * Write to DMA.
5054 */
5055
5056 void *pvSrc;
5057 size_t cbSrc;
5058
5059 RTCircBufAcquireReadBlock(pCircBuf, pStream->u16FIFOS, &pvSrc, &cbSrc);
5060
5061 if (cbSrc)
5062 {
5063 /* Do one DMA transfer with FIFOS size at a time. */
5064 rc2 = hdaStreamDoDMA(pThis, pStream, pvSrc, (uint32_t)cbSrc, (uint32_t)cbSrc /* cbToProcess */, &cbDMA);
5065 AssertRC(rc2);
5066 }
5067
5068 RTCircBufReleaseReadBlock(pCircBuf, cbDMA);
5069
5070 /* All DMA transfers done for now? */
5071 if (!cbDMA)
5072 fDone = true;
5073
5074 STAM_PROFILE_STOP(&pThis->StatIn, a);
5075 }
5076 else
5077 AssertFailed();
5078
5079 if (++cTransfers == UINT8_MAX) /* Failsafe counter. */
5080 fDone = true;
5081
5082 } /* while !fDone */
5083
5084#ifdef VBOX_STRICT
5085 AssertMsg(cTransfers < UINT8_MAX, ("HDA: Update for SD#%RU8 ran for too long\n", pStream->u8SD));
5086#endif
5087
5088 Log2Func(("[SD%RU8] End\n", pStream->u8SD));
5089
5090 hdaStreamUnlock(pStream);
5091
5092 return VINF_SUCCESS;
5093}
5094#endif /* IN_RING3 */
5095
5096/* MMIO callbacks */
5097
5098/**
5099 * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
5100 *
5101 * @note During implementation, we discovered so-called "forgotten" or "hole"
5102 * registers whose description is not listed in the RPM, datasheet, or
5103 * spec.
5104 */
5105PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
5106{
5107 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5108 int rc;
5109 RT_NOREF_PV(pvUser);
5110
5111 /*
5112 * Look up and log.
5113 */
5114 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
5115 int idxRegDsc = hdaRegLookup(offReg); /* Register descriptor index. */
5116#ifdef LOG_ENABLED
5117 unsigned const cbLog = cb;
5118 uint32_t offRegLog = offReg;
5119#endif
5120
5121 Log3Func(("offReg=%#x cb=%#x\n", offReg, cb));
5122 Assert(cb == 4); Assert((offReg & 3) == 0);
5123
5124 if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
5125 LogFunc(("Access to registers except GCTL is blocked while reset\n"));
5126
5127 if (idxRegDsc == -1)
5128 LogRel(("HDA: Invalid read access @0x%x (bytes=%u)\n", offReg, cb));
5129
5130 if (idxRegDsc != -1)
5131 {
5132 /* ASSUMES gapless DWORD at end of map. */
5133 if (g_aHdaRegMap[idxRegDsc].size == 4)
5134 {
5135 /*
5136 * Straight forward DWORD access.
5137 */
5138 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, (uint32_t *)pv);
5139 Log3Func(("\tRead %s => %x (%Rrc)\n", g_aHdaRegMap[idxRegDsc].abbrev, *(uint32_t *)pv, rc));
5140 }
5141 else
5142 {
5143 /*
5144 * Multi register read (unless there are trailing gaps).
5145 * ASSUMES that only DWORD reads have sideeffects.
5146 */
5147 uint32_t u32Value = 0;
5148 unsigned cbLeft = 4;
5149 do
5150 {
5151 uint32_t const cbReg = g_aHdaRegMap[idxRegDsc].size;
5152 uint32_t u32Tmp = 0;
5153
5154 rc = g_aHdaRegMap[idxRegDsc].pfnRead(pThis, idxRegDsc, &u32Tmp);
5155 Log3Func(("\tRead %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxRegDsc].abbrev, cbReg, u32Tmp, rc));
5156 if (rc != VINF_SUCCESS)
5157 break;
5158 u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
5159
5160 cbLeft -= cbReg;
5161 offReg += cbReg;
5162 idxRegDsc++;
5163 } while (cbLeft > 0 && g_aHdaRegMap[idxRegDsc].offset == offReg);
5164
5165 if (rc == VINF_SUCCESS)
5166 *(uint32_t *)pv = u32Value;
5167 else
5168 Assert(!IOM_SUCCESS(rc));
5169 }
5170 }
5171 else
5172 {
5173 rc = VINF_IOM_MMIO_UNUSED_FF;
5174 Log3Func(("\tHole at %x is accessed for read\n", offReg));
5175 }
5176
5177 /*
5178 * Log the outcome.
5179 */
5180#ifdef LOG_ENABLED
5181 if (cbLog == 4)
5182 Log3Func(("\tReturning @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
5183 else if (cbLog == 2)
5184 Log3Func(("\tReturning @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
5185 else if (cbLog == 1)
5186 Log3Func(("\tReturning @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
5187#endif
5188 return rc;
5189}
5190
5191
5192DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxRegDsc, uint32_t u32Value, char const *pszLog)
5193{
5194 if (pThis->fInReset && idxRegDsc != HDA_REG_GCTL)
5195 {
5196 Log(("hdaWriteReg: Warning: Access to %s is blocked while controller is in reset mode\n", g_aHdaRegMap[idxRegDsc].abbrev));
5197 LogRel2(("HDA: Warning: Access to register %s is blocked while controller is in reset mode\n",
5198 g_aHdaRegMap[idxRegDsc].abbrev));
5199 return VINF_SUCCESS;
5200 }
5201
5202 /*
5203 * Handle RD (register description) flags.
5204 */
5205
5206 /* For SDI / SDO: Check if writes to those registers are allowed while SDCTL's RUN bit is set. */
5207 if (idxRegDsc >= HDA_NUM_GENERAL_REGS)
5208 {
5209 const uint32_t uSDCTL = HDA_STREAM_REG(pThis, CTL, HDA_SD_NUM_FROM_REG(pThis, CTL, idxRegDsc));
5210
5211 /*
5212 * Some OSes (like Win 10 AU) violate the spec by writing stuff to registers which are not supposed to be be touched
5213 * while SDCTL's RUN bit is set. So just ignore those values.
5214 */
5215
5216 /* Is the RUN bit currently set? */
5217 if ( RT_BOOL(uSDCTL & HDA_SDCTL_RUN)
5218 /* Are writes to the register denied if RUN bit is set? */
5219 && !(g_aHdaRegMap[idxRegDsc].fFlags & HDA_RD_FLAG_SD_WRITE_RUN))
5220 {
5221 Log(("hdaWriteReg: Warning: Access to %s is blocked! %R[sdctl]\n", g_aHdaRegMap[idxRegDsc].abbrev, uSDCTL));
5222 LogRel2(("HDA: Warning: Access to register %s is blocked while the stream's RUN bit is set\n",
5223 g_aHdaRegMap[idxRegDsc].abbrev));
5224 return VINF_SUCCESS;
5225 }
5226 }
5227
5228#ifdef LOG_ENABLED
5229 uint32_t const idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5230 uint32_t const u32OldValue = pThis->au32Regs[idxRegMem];
5231#endif
5232 int rc = g_aHdaRegMap[idxRegDsc].pfnWrite(pThis, idxRegDsc, u32Value);
5233 Log3Func(("Written value %#x to %s[%d byte]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxRegDsc].abbrev,
5234 g_aHdaRegMap[idxRegDsc].size, u32OldValue, pThis->au32Regs[idxRegMem], pszLog));
5235 RT_NOREF(pszLog);
5236 return rc;
5237}
5238
5239
5240/**
5241 * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
5242 */
5243PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
5244{
5245 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5246 int rc;
5247 RT_NOREF_PV(pvUser);
5248
5249 /*
5250 * The behavior of accesses that aren't aligned on natural boundraries is
5251 * undefined. Just reject them outright.
5252 */
5253 /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
5254 Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
5255 if (GCPhysAddr & (cb - 1))
5256 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
5257
5258 /*
5259 * Look up and log the access.
5260 */
5261 uint32_t offReg = GCPhysAddr - pThis->MMIOBaseAddr;
5262 int idxRegDsc = hdaRegLookup(offReg);
5263 uint32_t idxRegMem = idxRegDsc != -1 ? g_aHdaRegMap[idxRegDsc].mem_idx : UINT32_MAX;
5264 uint64_t u64Value;
5265 if (cb == 4) u64Value = *(uint32_t const *)pv;
5266 else if (cb == 2) u64Value = *(uint16_t const *)pv;
5267 else if (cb == 1) u64Value = *(uint8_t const *)pv;
5268 else if (cb == 8) u64Value = *(uint64_t const *)pv;
5269 else
5270 {
5271 u64Value = 0; /* shut up gcc. */
5272 AssertReleaseMsgFailed(("%u\n", cb));
5273 }
5274
5275#ifdef LOG_ENABLED
5276 uint32_t const u32LogOldValue = idxRegDsc >= 0 ? pThis->au32Regs[idxRegMem] : UINT32_MAX;
5277 if (idxRegDsc == -1)
5278 Log3Func(("@%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
5279 else if (cb == 4)
5280 Log3Func(("@%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5281 else if (cb == 2)
5282 Log3Func(("@%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5283 else if (cb == 1)
5284 Log3Func(("@%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxRegDsc].abbrev));
5285
5286 if (idxRegDsc >= 0 && g_aHdaRegMap[idxRegDsc].size != cb)
5287 Log3Func(("\tsize=%RU32 != cb=%u!!\n", g_aHdaRegMap[idxRegDsc].size, cb));
5288#endif
5289
5290 /*
5291 * Try for a direct hit first.
5292 */
5293 if (idxRegDsc != -1 && g_aHdaRegMap[idxRegDsc].size == cb)
5294 {
5295 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "");
5296 Log3Func(("\t%#x -> %#x\n", u32LogOldValue, idxRegMem != UINT32_MAX ? pThis->au32Regs[idxRegMem] : UINT32_MAX));
5297 }
5298 /*
5299 * Partial or multiple register access, loop thru the requested memory.
5300 */
5301 else
5302 {
5303 /*
5304 * If it's an access beyond the start of the register, shift the input
5305 * value and fill in missing bits. Natural alignment rules means we
5306 * will only see 1 or 2 byte accesses of this kind, so no risk of
5307 * shifting out input values.
5308 */
5309 if (idxRegDsc == -1 && (idxRegDsc = hdaRegLookupWithin(offReg)) != -1)
5310 {
5311 uint32_t const cbBefore = offReg - g_aHdaRegMap[idxRegDsc].offset; Assert(cbBefore > 0 && cbBefore < 4);
5312 offReg -= cbBefore;
5313 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5314 u64Value <<= cbBefore * 8;
5315 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbBefore];
5316 Log3Func(("\tWithin register, supplied %u leading bits: %#llx -> %#llx ...\n",
5317 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
5318 }
5319
5320 /* Loop thru the write area, it may cover multiple registers. */
5321 rc = VINF_SUCCESS;
5322 for (;;)
5323 {
5324 uint32_t cbReg;
5325 if (idxRegDsc != -1)
5326 {
5327 idxRegMem = g_aHdaRegMap[idxRegDsc].mem_idx;
5328 cbReg = g_aHdaRegMap[idxRegDsc].size;
5329 if (cb < cbReg)
5330 {
5331 u64Value |= pThis->au32Regs[idxRegMem] & g_afMasks[cbReg] & ~g_afMasks[cb];
5332 Log3Func(("\tSupplying missing bits (%#x): %#llx -> %#llx ...\n",
5333 g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
5334 }
5335#ifdef LOG_ENABLED
5336 uint32_t uLogOldVal = pThis->au32Regs[idxRegMem];
5337#endif
5338 rc = hdaWriteReg(pThis, idxRegDsc, u64Value, "*");
5339 Log3Func(("\t%#x -> %#x\n", uLogOldVal, pThis->au32Regs[idxRegMem]));
5340 }
5341 else
5342 {
5343 LogRel(("HDA: Invalid write access @0x%x\n", offReg));
5344 cbReg = 1;
5345 }
5346 if (rc != VINF_SUCCESS)
5347 break;
5348 if (cbReg >= cb)
5349 break;
5350
5351 /* Advance. */
5352 offReg += cbReg;
5353 cb -= cbReg;
5354 u64Value >>= cbReg * 8;
5355 if (idxRegDsc == -1)
5356 idxRegDsc = hdaRegLookup(offReg);
5357 else
5358 {
5359 idxRegDsc++;
5360 if ( (unsigned)idxRegDsc >= RT_ELEMENTS(g_aHdaRegMap)
5361 || g_aHdaRegMap[idxRegDsc].offset != offReg)
5362 {
5363 idxRegDsc = -1;
5364 }
5365 }
5366 }
5367 }
5368
5369 return rc;
5370}
5371
5372
5373/* PCI callback. */
5374
5375#ifdef IN_RING3
5376/**
5377 * @callback_method_impl{FNPCIIOREGIONMAP}
5378 */
5379static DECLCALLBACK(int) hdaPciIoRegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
5380 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
5381{
5382 RT_NOREF(iRegion, enmType);
5383 PHDASTATE pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
5384
5385 /*
5386 * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
5387 *
5388 * Let IOM talk DWORDs when reading, saves a lot of complications. On
5389 * writing though, we have to do it all ourselves because of sideeffects.
5390 */
5391 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
5392 int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
5393 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_PASSTHRU,
5394 hdaMMIOWrite, hdaMMIORead, "HDA");
5395 if (RT_FAILURE(rc))
5396 return rc;
5397
5398 if (pThis->fR0Enabled)
5399 {
5400 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
5401 "hdaMMIOWrite", "hdaMMIORead");
5402 if (RT_FAILURE(rc))
5403 return rc;
5404 }
5405
5406 if (pThis->fRCEnabled)
5407 {
5408 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
5409 "hdaMMIOWrite", "hdaMMIORead");
5410 if (RT_FAILURE(rc))
5411 return rc;
5412 }
5413
5414 pThis->MMIOBaseAddr = GCPhysAddress;
5415 return VINF_SUCCESS;
5416}
5417
5418
5419/* Saved state callbacks. */
5420
5421static int hdaSaveStream(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PHDASTREAM pStrm)
5422{
5423 RT_NOREF(pDevIns);
5424#ifdef DEBUG
5425 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5426#endif
5427 LogFlowFunc(("[SD%RU8]\n", pStrm->u8SD));
5428
5429 /* Save stream ID. */
5430 int rc = SSMR3PutU8(pSSM, pStrm->u8SD);
5431 AssertRCReturn(rc, rc);
5432 Assert(pStrm->u8SD <= HDA_MAX_STREAMS);
5433
5434 rc = SSMR3PutStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE), 0 /*fFlags*/, g_aSSMStreamStateFields6, NULL);
5435 AssertRCReturn(rc, rc);
5436
5437#ifdef DEBUG /* Sanity checks. */
5438 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStrm->u8SD),
5439 HDA_STREAM_REG(pThis, BDPU, pStrm->u8SD));
5440 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, pStrm->u8SD);
5441 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, pStrm->u8SD);
5442
5443 hdaBDLEDumpAll(pThis, u64BaseDMA, u16LVI + 1);
5444
5445 Assert(u64BaseDMA == pStrm->u64BDLBase);
5446 Assert(u16LVI == pStrm->u16LVI);
5447 Assert(u32CBL == pStrm->u32CBL);
5448#endif
5449
5450 rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
5451 0 /*fFlags*/, g_aSSMBDLEDescFields7, NULL);
5452 AssertRCReturn(rc, rc);
5453
5454 rc = SSMR3PutStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
5455 0 /*fFlags*/, g_aSSMBDLEStateFields7, NULL);
5456 AssertRCReturn(rc, rc);
5457
5458#ifdef DEBUG /* Sanity checks. */
5459 PHDABDLE pBDLE = &pStrm->State.BDLE;
5460 if (u64BaseDMA)
5461 {
5462 Assert(pStrm->State.uCurBDLE <= u16LVI + 1);
5463
5464 HDABDLE curBDLE;
5465 rc = hdaBDLEFetch(pThis, &curBDLE, u64BaseDMA, pStrm->State.uCurBDLE);
5466 AssertRC(rc);
5467
5468 Assert(curBDLE.Desc.u32BufSize == pBDLE->Desc.u32BufSize);
5469 Assert(curBDLE.Desc.u64BufAdr == pBDLE->Desc.u64BufAdr);
5470 Assert(curBDLE.Desc.fFlags == pBDLE->Desc.fFlags);
5471 }
5472 else
5473 {
5474 Assert(pBDLE->Desc.u64BufAdr == 0);
5475 Assert(pBDLE->Desc.u32BufSize == 0);
5476 }
5477#endif
5478 return rc;
5479}
5480
5481/**
5482 * @callback_method_impl{FNSSMDEVSAVEEXEC}
5483 */
5484static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
5485{
5486 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5487
5488 /* Save Codec nodes states. */
5489 hdaCodecSaveState(pThis->pCodec, pSSM);
5490
5491 /* Save MMIO registers. */
5492 SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
5493 SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
5494
5495 /* Save number of streams. */
5496 SSMR3PutU32(pSSM, HDA_MAX_STREAMS);
5497
5498 /* Save stream states. */
5499 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
5500 {
5501 int rc = hdaSaveStream(pDevIns, pSSM, &pThis->aStreams[i]);
5502 AssertRCReturn(rc, rc);
5503 }
5504
5505 return VINF_SUCCESS;
5506}
5507
5508/**
5509 * Does required post processing when loading a saved state.
5510 *
5511 * @param pThis Pointer to HDA state.
5512 */
5513static int hdaLoadExecPost(PHDASTATE pThis)
5514{
5515 int rc = VINF_SUCCESS;
5516
5517 bool fStartTimer = false; /* Whether to resume the device timer. */
5518
5519 /*
5520 * Enable all previously active streams.
5521 */
5522 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
5523 {
5524 PHDASTREAM pStream = hdaStreamGetFromSD(pThis, i);
5525 if (pStream)
5526 {
5527 hdaStreamEnable(pThis, pStream, false /* fEnable */);
5528
5529 bool fActive = RT_BOOL(HDA_STREAM_REG(pThis, CTL, i) & HDA_SDCTL_RUN);
5530 if (fActive)
5531 {
5532 int rc2 = hdaStreamEnable(pThis, pStream, true /* fEnable */);
5533 AssertRC(rc2);
5534
5535#ifdef HDA_USE_DMA_ACCESS_HANDLER
5536 hdaStreamRegisterDMAHandlers(pThis, pStream);
5537#endif
5538 fStartTimer = true;
5539 }
5540 }
5541 }
5542
5543#ifndef VBOX_WITH_AUDIO_CALLBACKS
5544 if ( fStartTimer
5545 && pThis->pTimer
5546 && !TMTimerIsActive(pThis->pTimer))
5547 {
5548 pThis->tsTimerExpire = TMTimerGet(pThis->pTimer) + pThis->cTimerTicks;
5549
5550 /* Resume timer. */
5551 int rc2 = TMTimerSet(pThis->pTimer, pThis->tsTimerExpire);
5552 AssertRC(rc2);
5553 }
5554#endif
5555
5556 LogFlowFuncLeaveRC(rc);
5557 return rc;
5558}
5559
5560
5561/**
5562 * Handles loading of all saved state versions older than the current one.
5563 *
5564 * @param pThis Pointer to HDA state.
5565 * @param pSSM Pointer to SSM handle.
5566 * @param uVersion Saved state version to load.
5567 * @param uPass Loading stage to handle.
5568 */
5569static int hdaLoadExecLegacy(PHDASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5570{
5571 RT_NOREF(uPass);
5572
5573 int rc = VINF_SUCCESS;
5574
5575 /*
5576 * Load MMIO registers.
5577 */
5578 uint32_t cRegs;
5579 switch (uVersion)
5580 {
5581 case HDA_SSM_VERSION_1:
5582 /* Starting with r71199, we would save 112 instead of 113
5583 registers due to some code cleanups. This only affected trunk
5584 builds in the 4.1 development period. */
5585 cRegs = 113;
5586 if (SSMR3HandleRevision(pSSM) >= 71199)
5587 {
5588 uint32_t uVer = SSMR3HandleVersion(pSSM);
5589 if ( VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
5590 && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
5591 && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
5592 cRegs = 112;
5593 }
5594 break;
5595
5596 case HDA_SSM_VERSION_2:
5597 case HDA_SSM_VERSION_3:
5598 cRegs = 112;
5599 AssertCompile(RT_ELEMENTS(pThis->au32Regs) >= 112);
5600 break;
5601
5602 /* Since version 4 we store the register count to stay flexible. */
5603 case HDA_SSM_VERSION_4:
5604 case HDA_SSM_VERSION_5:
5605 case HDA_SSM_VERSION_6:
5606 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
5607 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
5608 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
5609 break;
5610
5611 default:
5612 LogRel(("HDA: Unsupported / too new saved state version (%RU32)\n", uVersion));
5613 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
5614 }
5615
5616 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
5617 {
5618 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
5619 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
5620 }
5621 else
5622 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
5623
5624 /* Make sure to update the base addresses first before initializing any streams down below. */
5625 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
5626 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
5627 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
5628
5629 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
5630 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
5631
5632 /*
5633 * Note: Saved states < v5 store LVI (u32BdleMaxCvi) for
5634 * *every* BDLE state, whereas it only needs to be stored
5635 * *once* for every stream. Most of the BDLE state we can
5636 * get out of the registers anyway, so just ignore those values.
5637 *
5638 * Also, only the current BDLE was saved, regardless whether
5639 * there were more than one (and there are at least two entries,
5640 * according to the spec).
5641 */
5642#define HDA_SSM_LOAD_BDLE_STATE_PRE_V5(v, x) \
5643 { \
5644 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */ \
5645 AssertRCReturn(rc, rc); \
5646 rc = SSMR3GetU64(pSSM, &x.Desc.u64BufAdr); /* u64BdleCviAddr */ \
5647 AssertRCReturn(rc, rc); \
5648 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* u32BdleMaxCvi */ \
5649 AssertRCReturn(rc, rc); \
5650 rc = SSMR3GetU32(pSSM, &x.State.u32BDLIndex); /* u32BdleCvi */ \
5651 AssertRCReturn(rc, rc); \
5652 rc = SSMR3GetU32(pSSM, &x.Desc.u32BufSize); /* u32BdleCviLen */ \
5653 AssertRCReturn(rc, rc); \
5654 rc = SSMR3GetU32(pSSM, &x.State.u32BufOff); /* u32BdleCviPos */ \
5655 AssertRCReturn(rc, rc); \
5656 bool fIOC; \
5657 rc = SSMR3GetBool(pSSM, &fIOC); /* fBdleCviIoc */ \
5658 AssertRCReturn(rc, rc); \
5659 x.Desc.fFlags = fIOC ? HDA_BDLE_FLAG_IOC : 0; \
5660 rc = SSMR3GetU32(pSSM, &x.State.cbBelowFIFOW); /* cbUnderFifoW */ \
5661 AssertRCReturn(rc, rc); \
5662 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO */ \
5663 AssertRCReturn(rc, rc); \
5664 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */ \
5665 AssertRCReturn(rc, rc); \
5666 }
5667
5668 /*
5669 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
5670 */
5671 switch (uVersion)
5672 {
5673 case HDA_SSM_VERSION_1:
5674 case HDA_SSM_VERSION_2:
5675 case HDA_SSM_VERSION_3:
5676 case HDA_SSM_VERSION_4:
5677 {
5678 /* Only load the internal states.
5679 * The rest will be initialized from the saved registers later. */
5680
5681 /* Note 1: Only the *current* BDLE for a stream was saved! */
5682 /* Note 2: The stream's saving order is/was fixed, so don't touch! */
5683
5684 /* Output */
5685 PHDASTREAM pStream = &pThis->aStreams[4];
5686 rc = hdaStreamInit(pThis, pStream, 4 /* Stream descriptor, hardcoded */);
5687 if (RT_FAILURE(rc))
5688 break;
5689 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
5690 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
5691
5692 /* Microphone-In */
5693 pStream = &pThis->aStreams[2];
5694 rc = hdaStreamInit(pThis, pStream, 2 /* Stream descriptor, hardcoded */);
5695 if (RT_FAILURE(rc))
5696 break;
5697 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
5698 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
5699
5700 /* Line-In */
5701 pStream = &pThis->aStreams[0];
5702 rc = hdaStreamInit(pThis, pStream, 0 /* Stream descriptor, hardcoded */);
5703 if (RT_FAILURE(rc))
5704 break;
5705 HDA_SSM_LOAD_BDLE_STATE_PRE_V5(uVersion, pStream->State.BDLE);
5706 pStream->State.uCurBDLE = pStream->State.BDLE.State.u32BDLIndex;
5707 break;
5708 }
5709
5710#undef HDA_SSM_LOAD_BDLE_STATE_PRE_V5
5711
5712 default: /* Since v5 we support flexible stream and BDLE counts. */
5713 {
5714 uint32_t cStreams;
5715 rc = SSMR3GetU32(pSSM, &cStreams);
5716 if (RT_FAILURE(rc))
5717 break;
5718
5719 LogRel2(("hdaLoadExec: cStreams=%RU32\n", cStreams));
5720
5721 /* Load stream states. */
5722 for (uint32_t i = 0; i < cStreams; i++)
5723 {
5724 uint8_t uStreamID;
5725 rc = SSMR3GetU8(pSSM, &uStreamID);
5726 if (RT_FAILURE(rc))
5727 break;
5728
5729 PHDASTREAM pStrm = hdaStreamGetFromSD(pThis, uStreamID);
5730 HDASTREAM StreamDummy;
5731
5732 if (!pStrm)
5733 {
5734 pStrm = &StreamDummy;
5735 LogRel2(("HDA: Warning: Stream ID=%RU32 not supported, skipping to load ...\n", uStreamID));
5736 }
5737
5738 rc = hdaStreamInit(pThis, pStrm, uStreamID);
5739 if (RT_FAILURE(rc))
5740 {
5741 LogRel(("HDA: Stream #%RU32: Initialization of stream %RU8 failed, rc=%Rrc\n", i, uStreamID, rc));
5742 break;
5743 }
5744
5745 /*
5746 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
5747 */
5748
5749 if (uVersion == HDA_SSM_VERSION_5)
5750 {
5751 /* Get the current BDLE entry and skip the rest. */
5752 uint16_t cBDLE;
5753
5754 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
5755 AssertRC(rc);
5756 rc = SSMR3GetU16(pSSM, &cBDLE); /* cBDLE */
5757 AssertRC(rc);
5758 rc = SSMR3GetU16(pSSM, &pStrm->State.uCurBDLE); /* uCurBDLE */
5759 AssertRC(rc);
5760 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
5761 AssertRC(rc);
5762
5763 uint32_t u32BDLEIndex;
5764 for (uint16_t a = 0; a < cBDLE; a++)
5765 {
5766 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* Begin marker */
5767 AssertRC(rc);
5768 rc = SSMR3GetU32(pSSM, &u32BDLEIndex); /* u32BDLIndex */
5769 AssertRC(rc);
5770
5771 /* Does the current BDLE index match the current BDLE to process? */
5772 if (u32BDLEIndex == pStrm->State.uCurBDLE)
5773 {
5774 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.cbBelowFIFOW); /* cbBelowFIFOW */
5775 AssertRC(rc);
5776 rc = SSMR3Skip(pSSM, sizeof(uint8_t) * 256); /* FIFO, deprecated */
5777 AssertRC(rc);
5778 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.State.u32BufOff); /* u32BufOff */
5779 AssertRC(rc);
5780 rc = SSMR3Skip(pSSM, sizeof(uint32_t)); /* End marker */
5781 AssertRC(rc);
5782 }
5783 else /* Skip not current BDLEs. */
5784 {
5785 rc = SSMR3Skip(pSSM, sizeof(uint32_t) /* cbBelowFIFOW */
5786 + sizeof(uint8_t) * 256 /* au8FIFO */
5787 + sizeof(uint32_t) /* u32BufOff */
5788 + sizeof(uint32_t)); /* End marker */
5789 AssertRC(rc);
5790 }
5791 }
5792 }
5793 else
5794 {
5795 rc = SSMR3GetStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE),
5796 0 /* fFlags */, g_aSSMStreamStateFields6, NULL);
5797 if (RT_FAILURE(rc))
5798 break;
5799
5800 /* Get HDABDLEDESC. */
5801 uint32_t uMarker;
5802 rc = SSMR3GetU32(pSSM, &uMarker); /* Begin marker. */
5803 AssertRC(rc);
5804 Assert(uMarker == UINT32_C(0x19200102) /* SSMR3STRUCT_BEGIN */);
5805 rc = SSMR3GetU64(pSSM, &pStrm->State.BDLE.Desc.u64BufAdr);
5806 AssertRC(rc);
5807 rc = SSMR3GetU32(pSSM, &pStrm->State.BDLE.Desc.u32BufSize);
5808 AssertRC(rc);
5809 bool fFlags = false;
5810 rc = SSMR3GetBool(pSSM, &fFlags); /* Saved states < v7 only stored the IOC as boolean flag. */
5811 AssertRC(rc);
5812 pStrm->State.BDLE.Desc.fFlags = fFlags ? HDA_BDLE_FLAG_IOC : 0;
5813 rc = SSMR3GetU32(pSSM, &uMarker); /* End marker. */
5814 AssertRC(rc);
5815 Assert(uMarker == UINT32_C(0x19920406) /* SSMR3STRUCT_END */);
5816
5817 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
5818 0 /* fFlags */, g_aSSMBDLEStateFields6, NULL);
5819 if (RT_FAILURE(rc))
5820 break;
5821
5822 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
5823 uStreamID,
5824 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
5825#ifdef LOG_ENABLED
5826 hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
5827#endif
5828 }
5829
5830 rc = hdaSDFMTToStrmCfg(HDA_STREAM_REG(pThis, FMT, uStreamID), &pStrm->State.strmCfg);
5831 if (RT_FAILURE(rc))
5832 {
5833 LogRel(("HDA: Stream #%RU8: Loading format failed, rc=%Rrc\n", uStreamID, rc));
5834 /* Continue. */
5835 }
5836
5837 } /* for cStreams */
5838 break;
5839 } /* default */
5840 }
5841
5842 return rc;
5843}
5844
5845/**
5846 * @callback_method_impl{FNSSMDEVLOADEXEC}
5847 */
5848static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5849{
5850 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
5851
5852 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
5853
5854 LogRel2(("hdaLoadExec: uVersion=%RU32, uPass=0x%x\n", uVersion, uPass));
5855
5856 /*
5857 * Load Codec nodes states.
5858 */
5859 int rc = hdaCodecLoadState(pThis->pCodec, pSSM, uVersion);
5860 if (RT_FAILURE(rc))
5861 {
5862 LogRel(("HDA: Failed loading codec state (version %RU32, pass 0x%x), rc=%Rrc\n", uVersion, uPass, rc));
5863 return rc;
5864 }
5865
5866 if (uVersion < HDA_SSM_VERSION) /* Handle older saved states? */
5867 {
5868 rc = hdaLoadExecLegacy(pThis, pSSM, uVersion, uPass);
5869 if (RT_SUCCESS(rc))
5870 rc = hdaLoadExecPost(pThis);
5871
5872 return rc;
5873 }
5874
5875 /*
5876 * Load MMIO registers.
5877 */
5878 uint32_t cRegs;
5879 rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
5880 if (cRegs != RT_ELEMENTS(pThis->au32Regs))
5881 LogRel(("HDA: SSM version cRegs is %RU32, expected %RU32\n", cRegs, RT_ELEMENTS(pThis->au32Regs)));
5882
5883 if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
5884 {
5885 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
5886 SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
5887 }
5888 else
5889 SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
5890
5891 /* Make sure to update the base addresses first before initializing any streams down below. */
5892 pThis->u64CORBBase = RT_MAKE_U64(HDA_REG(pThis, CORBLBASE), HDA_REG(pThis, CORBUBASE));
5893 pThis->u64RIRBBase = RT_MAKE_U64(HDA_REG(pThis, RIRBLBASE), HDA_REG(pThis, RIRBUBASE));
5894 pThis->u64DPBase = RT_MAKE_U64(HDA_REG(pThis, DPLBASE) & DPBASE_ADDR_MASK, HDA_REG(pThis, DPUBASE));
5895
5896 /* Also make sure to update the DMA position bit if this was enabled when saving the state. */
5897 pThis->fDMAPosition = RT_BOOL(HDA_REG(pThis, DPLBASE) & RT_BIT_32(0));
5898
5899 /*
5900 * Load controller-specifc internals.
5901 */
5902 rc = SSMR3GetU64(pSSM, &pThis->u64BaseTS);
5903 AssertRC(rc);
5904
5905 /*
5906 * Load streams.
5907 */
5908 uint32_t cStreams;
5909 rc = SSMR3GetU32(pSSM, &cStreams);
5910 AssertRC(rc);
5911
5912 Log2Func(("cStreams=%RU32\n", cStreams));
5913
5914 /* Load stream states. */
5915 for (uint32_t i = 0; i < cStreams; i++)
5916 {
5917 uint8_t uStreamID;
5918 rc = SSMR3GetU8(pSSM, &uStreamID);
5919 AssertRC(rc);
5920
5921 PHDASTREAM pStrm = hdaStreamGetFromSD(pThis, uStreamID);
5922 HDASTREAM StreamDummy;
5923
5924 if (!pStrm)
5925 {
5926 pStrm = &StreamDummy;
5927 LogRel2(("HDA: Warning: Loading of stream #%RU8 not supported, skipping to load ...\n", uStreamID));
5928 }
5929
5930 rc = hdaStreamInit(pThis, pStrm, uStreamID);
5931 if (RT_FAILURE(rc))
5932 {
5933 LogRel(("HDA: Stream #%RU8: Loading initialization failed, rc=%Rrc\n", uStreamID, rc));
5934 /* Continue. */
5935 }
5936
5937 /*
5938 * Load BDLEs (Buffer Descriptor List Entries) and DMA counters.
5939 */
5940 rc = SSMR3GetStructEx(pSSM, &pStrm->State, sizeof(HDASTREAMSTATE),
5941 0 /* fFlags */, g_aSSMStreamStateFields7,
5942 NULL);
5943 AssertRC(rc);
5944
5945 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.Desc, sizeof(HDABDLEDESC),
5946 0 /* fFlags */, g_aSSMBDLEDescFields7, NULL);
5947 AssertRC(rc);
5948
5949 rc = SSMR3GetStructEx(pSSM, &pStrm->State.BDLE.State, sizeof(HDABDLESTATE),
5950 0 /* fFlags */, g_aSSMBDLEStateFields7, NULL);
5951 AssertRC(rc);
5952
5953 Log2Func(("[SD%RU8] %R[bdle]\n", pStrm->u8SD, &pStrm->State.BDLE));
5954
5955 /*
5956 * Load internal (FIFO) buffer.
5957 */
5958
5959 uint32_t cbCircBufSize = 0;
5960 rc = SSMR3GetU32(pSSM, &cbCircBufSize); /* cbCircBuf */
5961 AssertRC(rc);
5962
5963 uint32_t cbCircBufUsed = 0;
5964 rc = SSMR3GetU32(pSSM, &cbCircBufUsed); /* cbCircBuf */
5965 AssertRC(rc);
5966
5967 if (cbCircBufSize) /* If 0, skip the buffer. */
5968 {
5969 /* Paranoia. */
5970 AssertReleaseMsg(cbCircBufSize <= _1M,
5971 ("HDA: Saved state contains bogus DMA buffer size (%RU32) for stream #%RU8",
5972 cbCircBufSize, uStreamID));
5973 AssertReleaseMsg(cbCircBufUsed <= cbCircBufSize,
5974 ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
5975 cbCircBufUsed, cbCircBufSize, uStreamID));
5976 AssertPtr(pStrm->State.pCircBuf);
5977
5978 /* Do we need to cre-create the circular buffer do fit the data size? */
5979 if (cbCircBufSize != (uint32_t)RTCircBufSize(pStrm->State.pCircBuf))
5980 {
5981 RTCircBufDestroy(pStrm->State.pCircBuf);
5982 pStrm->State.pCircBuf = NULL;
5983
5984 rc = RTCircBufCreate(&pStrm->State.pCircBuf, cbCircBufSize);
5985 AssertRC(rc);
5986 }
5987
5988 if ( RT_SUCCESS(rc)
5989 && cbCircBufUsed)
5990 {
5991 void *pvBuf;
5992 size_t cbBuf;
5993
5994 RTCircBufAcquireWriteBlock(pStrm->State.pCircBuf, cbCircBufUsed, &pvBuf, &cbBuf);
5995
5996 if (cbBuf)
5997 {
5998 rc = SSMR3GetMem(pSSM, pvBuf, cbBuf);
5999 AssertRC(rc);
6000 }
6001
6002 RTCircBufReleaseWriteBlock(pStrm->State.pCircBuf, cbBuf);
6003
6004 Assert(cbBuf == cbCircBufUsed);
6005 }
6006 }
6007
6008 Log2Func(("[SD%RU8] LPIB=%RU32, CBL=%RU32, LVI=%RU32\n",
6009 uStreamID,
6010 HDA_STREAM_REG(pThis, LPIB, uStreamID), HDA_STREAM_REG(pThis, CBL, uStreamID), HDA_STREAM_REG(pThis, LVI, uStreamID)));
6011#ifdef LOG_ENABLED
6012 hdaBDLEDumpAll(pThis, pStrm->u64BDLBase, pStrm->u16LVI + 1);
6013#endif
6014 /** @todo (Re-)initialize active periods? */
6015
6016 } /* for cStreams */
6017
6018 rc = hdaLoadExecPost(pThis);
6019 AssertRC(rc);
6020
6021 LogFlowFuncLeaveRC(rc);
6022 return rc;
6023}
6024
6025/* Debug and log type formatters. */
6026
6027/**
6028 * @callback_method_impl{FNRTSTRFORMATTYPE}
6029 */
6030static DECLCALLBACK(size_t) hdaDbgFmtBDLE(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6031 const char *pszType, void const *pvValue,
6032 int cchWidth, int cchPrecision, unsigned fFlags,
6033 void *pvUser)
6034{
6035 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6036 PHDABDLE pBDLE = (PHDABDLE)pvValue;
6037 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6038 "BDLE(idx:%RU32, off:%RU32, fifow:%RU32, IOC:%RTbool, DMA[%RU32 bytes @ 0x%x])",
6039 pBDLE->State.u32BDLIndex, pBDLE->State.u32BufOff, pBDLE->State.cbBelowFIFOW,
6040 pBDLE->Desc.fFlags & HDA_BDLE_FLAG_IOC, pBDLE->Desc.u32BufSize, pBDLE->Desc.u64BufAdr);
6041}
6042
6043/**
6044 * @callback_method_impl{FNRTSTRFORMATTYPE}
6045 */
6046static DECLCALLBACK(size_t) hdaDbgFmtSDCTL(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6047 const char *pszType, void const *pvValue,
6048 int cchWidth, int cchPrecision, unsigned fFlags,
6049 void *pvUser)
6050{
6051 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6052 uint32_t uSDCTL = (uint32_t)(uintptr_t)pvValue;
6053 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6054 "SDCTL(raw:%#x, DIR:%s, TP:%RTbool, STRIPE:%x, DEIE:%RTbool, FEIE:%RTbool, IOCE:%RTbool, RUN:%RTbool, RESET:%RTbool)",
6055 uSDCTL,
6056 uSDCTL & HDA_SDCTL_DIR ? "OUT" : "IN",
6057 RT_BOOL(uSDCTL & HDA_SDCTL_TP),
6058 (uSDCTL & HDA_SDCTL_STRIPE_MASK) >> HDA_SDCTL_STRIPE_SHIFT,
6059 RT_BOOL(uSDCTL & HDA_SDCTL_DEIE),
6060 RT_BOOL(uSDCTL & HDA_SDCTL_FEIE),
6061 RT_BOOL(uSDCTL & HDA_SDCTL_IOCE),
6062 RT_BOOL(uSDCTL & HDA_SDCTL_RUN),
6063 RT_BOOL(uSDCTL & HDA_SDCTL_SRST));
6064}
6065
6066/**
6067 * @callback_method_impl{FNRTSTRFORMATTYPE}
6068 */
6069static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6070 const char *pszType, void const *pvValue,
6071 int cchWidth, int cchPrecision, unsigned fFlags,
6072 void *pvUser)
6073{
6074 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6075 uint32_t uSDFIFOS = (uint32_t)(uintptr_t)pvValue;
6076 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw:%#x, sdfifos:%RU8 B)", uSDFIFOS, uSDFIFOS ? uSDFIFOS + 1 : 0);
6077}
6078
6079/**
6080 * @callback_method_impl{FNRTSTRFORMATTYPE}
6081 */
6082static DECLCALLBACK(size_t) hdaDbgFmtSDFIFOW(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6083 const char *pszType, void const *pvValue,
6084 int cchWidth, int cchPrecision, unsigned fFlags,
6085 void *pvUser)
6086{
6087 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6088 uint32_t uSDFIFOW = (uint32_t)(uintptr_t)pvValue;
6089 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSDFIFOW, hdaSDFIFOWToBytes(uSDFIFOW));
6090}
6091
6092/**
6093 * @callback_method_impl{FNRTSTRFORMATTYPE}
6094 */
6095static DECLCALLBACK(size_t) hdaDbgFmtSDSTS(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6096 const char *pszType, void const *pvValue,
6097 int cchWidth, int cchPrecision, unsigned fFlags,
6098 void *pvUser)
6099{
6100 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6101 uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
6102 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
6103 "SDSTS(raw:%#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
6104 uSdSts,
6105 RT_BOOL(uSdSts & HDA_SDSTS_FIFORDY),
6106 RT_BOOL(uSdSts & HDA_SDSTS_DESE),
6107 RT_BOOL(uSdSts & HDA_SDSTS_FIFOE),
6108 RT_BOOL(uSdSts & HDA_SDSTS_BCIS));
6109}
6110
6111static int hdaDbgLookupRegByName(const char *pszArgs)
6112{
6113 int iReg = 0;
6114 for (; iReg < HDA_NUM_REGS; ++iReg)
6115 if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
6116 return iReg;
6117 return -1;
6118}
6119
6120
6121static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
6122{
6123 Assert( pThis
6124 && iHdaIndex >= 0
6125 && iHdaIndex < HDA_NUM_REGS);
6126 pHlp->pfnPrintf(pHlp, "%s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[g_aHdaRegMap[iHdaIndex].mem_idx]);
6127}
6128
6129/**
6130 * @callback_method_impl{FNDBGFHANDLERDEV}
6131 */
6132static DECLCALLBACK(void) hdaDbgInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6133{
6134 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6135 int iHdaRegisterIndex = hdaDbgLookupRegByName(pszArgs);
6136 if (iHdaRegisterIndex != -1)
6137 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
6138 else
6139 {
6140 for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NUM_REGS; ++iHdaRegisterIndex)
6141 hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
6142 }
6143}
6144
6145static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
6146{
6147 Assert( pThis
6148 && iIdx >= 0
6149 && iIdx < HDA_MAX_STREAMS);
6150
6151 const PHDASTREAM pStrm = &pThis->aStreams[iIdx];
6152
6153 pHlp->pfnPrintf(pHlp, "Stream #%d:\n", iIdx);
6154 pHlp->pfnPrintf(pHlp, "\tSD%dCTL : %R[sdctl]\n", iIdx, HDA_STREAM_REG(pThis, CTL, iIdx));
6155 pHlp->pfnPrintf(pHlp, "\tSD%dCTS : %R[sdsts]\n", iIdx, HDA_STREAM_REG(pThis, STS, iIdx));
6156 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOS: %R[sdfifos]\n", iIdx, HDA_STREAM_REG(pThis, FIFOS, iIdx));
6157 pHlp->pfnPrintf(pHlp, "\tSD%dFIFOW: %R[sdfifow]\n", iIdx, HDA_STREAM_REG(pThis, FIFOW, iIdx));
6158 pHlp->pfnPrintf(pHlp, "\tBDLE : %R[bdle]\n", &pStrm->State.BDLE);
6159}
6160
6161static void hdaDbgPrintBDLE(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iIdx)
6162{
6163 Assert( pThis
6164 && iIdx >= 0
6165 && iIdx < HDA_MAX_STREAMS);
6166
6167 const PHDASTREAM pStrm = &pThis->aStreams[iIdx];
6168 const PHDABDLE pBDLE = &pStrm->State.BDLE;
6169
6170 pHlp->pfnPrintf(pHlp, "Stream #%d BDLE:\n", iIdx);
6171
6172 uint64_t u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, iIdx),
6173 HDA_STREAM_REG(pThis, BDPU, iIdx));
6174 uint16_t u16LVI = HDA_STREAM_REG(pThis, LVI, iIdx);
6175 uint32_t u32CBL = HDA_STREAM_REG(pThis, CBL, iIdx);
6176
6177 if (!u64BaseDMA)
6178 return;
6179
6180 pHlp->pfnPrintf(pHlp, "\tCurrent: %R[bdle]\n\n", pBDLE);
6181
6182 pHlp->pfnPrintf(pHlp, "\tMemory:\n");
6183
6184 uint32_t cbBDLE = 0;
6185 for (uint16_t i = 0; i < u16LVI + 1; i++)
6186 {
6187 HDABDLEDESC bd;
6188 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), u64BaseDMA + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
6189
6190 pHlp->pfnPrintf(pHlp, "\t\t%s #%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
6191 pBDLE->State.u32BDLIndex == i ? "*" : " ", i, bd.u64BufAdr, bd.u32BufSize, bd.fFlags & HDA_BDLE_FLAG_IOC);
6192
6193 cbBDLE += bd.u32BufSize;
6194 }
6195
6196 pHlp->pfnPrintf(pHlp, "Total: %RU32 bytes\n", cbBDLE);
6197
6198 if (cbBDLE != u32CBL)
6199 pHlp->pfnPrintf(pHlp, "Warning: %RU32 bytes does not match CBL (%RU32)!\n", cbBDLE, u32CBL);
6200
6201 pHlp->pfnPrintf(pHlp, "DMA counters (base @ 0x%llx):\n", u64BaseDMA);
6202 if (!u64BaseDMA) /* No DMA base given? Bail out. */
6203 {
6204 pHlp->pfnPrintf(pHlp, "\tNo counters found\n");
6205 return;
6206 }
6207
6208 for (int i = 0; i < u16LVI + 1; i++)
6209 {
6210 uint32_t uDMACnt;
6211 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
6212 &uDMACnt, sizeof(uDMACnt));
6213
6214 pHlp->pfnPrintf(pHlp, "\t#%03d DMA @ 0x%x\n", i , uDMACnt);
6215 }
6216}
6217
6218static int hdaDbgLookupStrmIdx(PHDASTATE pThis, const char *pszArgs)
6219{
6220 RT_NOREF(pThis, pszArgs);
6221 /** @todo Add args parsing. */
6222 return -1;
6223}
6224
6225/**
6226 * @callback_method_impl{FNDBGFHANDLERDEV}
6227 */
6228static DECLCALLBACK(void) hdaDbgInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6229{
6230 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6231 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
6232 if (iHdaStreamdex != -1)
6233 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
6234 else
6235 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
6236 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
6237}
6238
6239/**
6240 * @callback_method_impl{FNDBGFHANDLERDEV}
6241 */
6242static DECLCALLBACK(void) hdaDbgInfoBDLE(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6243{
6244 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6245 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
6246 if (iHdaStreamdex != -1)
6247 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
6248 else
6249 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
6250 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
6251}
6252
6253/**
6254 * @callback_method_impl{FNDBGFHANDLERDEV}
6255 */
6256static DECLCALLBACK(void) hdaDbgInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6257{
6258 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6259
6260 if (pThis->pCodec->pfnDbgListNodes)
6261 pThis->pCodec->pfnDbgListNodes(pThis->pCodec, pHlp, pszArgs);
6262 else
6263 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
6264}
6265
6266/**
6267 * @callback_method_impl{FNDBGFHANDLERDEV}
6268 */
6269static DECLCALLBACK(void) hdaDbgInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6270{
6271 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6272
6273 if (pThis->pCodec->pfnDbgSelector)
6274 pThis->pCodec->pfnDbgSelector(pThis->pCodec, pHlp, pszArgs);
6275 else
6276 pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback\n");
6277}
6278
6279/**
6280 * @callback_method_impl{FNDBGFHANDLERDEV}
6281 */
6282static DECLCALLBACK(void) hdaDbgInfoMixer(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6283{
6284 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6285
6286 if (pThis->pMixer)
6287 AudioMixerDebug(pThis->pMixer, pHlp, pszArgs);
6288 else
6289 pHlp->pfnPrintf(pHlp, "Mixer not available\n");
6290}
6291
6292
6293/* PDMIBASE */
6294
6295/**
6296 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6297 */
6298static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
6299{
6300 PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
6301 Assert(&pThis->IBase == pInterface);
6302
6303 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
6304 return NULL;
6305}
6306
6307
6308/* PDMDEVREG */
6309
6310/**
6311 * Reset notification.
6312 *
6313 * @returns VBox status code.
6314 * @param pDevIns The device instance data.
6315 *
6316 * @remark The original sources didn't install a reset handler, but it seems to
6317 * make sense to me so we'll do it.
6318 */
6319static DECLCALLBACK(void) hdaReset(PPDMDEVINS pDevIns)
6320{
6321 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6322
6323 LogFlowFuncEnter();
6324
6325# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
6326 /*
6327 * Stop the timer, if any.
6328 */
6329 hdaTimerStop(pThis);
6330
6331 pThis->cStreamsActive = 0;
6332# endif
6333
6334 /* See 6.2.1. */
6335 HDA_REG(pThis, GCAP) = HDA_MAKE_GCAP(HDA_MAX_SDO /* Ouput streams */,
6336 HDA_MAX_SDI /* Input streams */,
6337 0 /* Bidirectional output streams */,
6338 0 /* Serial data out signals */,
6339 1 /* 64-bit */);
6340 HDA_REG(pThis, VMIN) = 0x00; /* see 6.2.2 */
6341 HDA_REG(pThis, VMAJ) = 0x01; /* see 6.2.3 */
6342 /* Announce the full 60 words output payload. */
6343 HDA_REG(pThis, OUTPAY) = 0x003C; /* see 6.2.4 */
6344 /* Announce the full 29 words input payload. */
6345 HDA_REG(pThis, INPAY) = 0x001D; /* see 6.2.5 */
6346 HDA_REG(pThis, CORBSIZE) = 0x42; /* see 6.2.1 */
6347 HDA_REG(pThis, RIRBSIZE) = 0x42; /* see 6.2.1 */
6348 HDA_REG(pThis, CORBRP) = 0x0;
6349 HDA_REG(pThis, RIRBWP) = 0x0;
6350
6351 /*
6352 * Stop any audio currently playing and/or recording.
6353 */
6354 if (pThis->SinkFront.pMixSink)
6355 AudioMixerSinkReset(pThis->SinkFront.pMixSink);
6356# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6357 if (pThis->SinkMicIn.pMixSink)
6358 AudioMixerSinkReset(pThis->SinkMicIn.pMixSink);
6359# endif
6360 if (pThis->SinkLineIn.pMixSink)
6361 AudioMixerSinkReset(pThis->SinkLineIn.pMixSink);
6362# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
6363 if (pThis->SinkCenterLFE.pMixSink)
6364 AudioMixerSinkReset(pThis->SinkCenterLFE.pMixSink);
6365 if (pThis->SinkRear.pMixSink)
6366 AudioMixerSinkReset(pThis->SinkRear.pMixSink);
6367# endif
6368
6369 /*
6370 * Reset the codec.
6371 */
6372 if ( pThis->pCodec
6373 && pThis->pCodec->pfnReset)
6374 {
6375 pThis->pCodec->pfnReset(pThis->pCodec);
6376 }
6377
6378 /*
6379 * Set some sensible defaults for which HDA sinks
6380 * are connected to which stream number.
6381 *
6382 * We use SD0 for input and SD4 for output by default.
6383 * These stream numbers can be changed by the guest dynamically lateron.
6384 */
6385#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6386 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_MIC_IN , 1 /* SD0 */, 0 /* Channel */);
6387#endif
6388 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_LINE_IN , 1 /* SD0 */, 0 /* Channel */);
6389
6390 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_FRONT , 5 /* SD4 */, 0 /* Channel */);
6391#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
6392 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_CENTER_LFE, 5 /* SD4 */, 0 /* Channel */);
6393 hdaMixerSetStream(pThis, PDMAUDIOMIXERCTL_REAR , 5 /* SD4 */, 0 /* Channel */);
6394#endif
6395
6396 pThis->cbCorbBuf = 256 * sizeof(uint32_t); /** @todo Use a define here. */
6397
6398 if (pThis->pu32CorbBuf)
6399 RT_BZERO(pThis->pu32CorbBuf, pThis->cbCorbBuf);
6400 else
6401 pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
6402
6403 pThis->cbRirbBuf = 256 * sizeof(uint64_t); /** @todo Use a define here. */
6404 if (pThis->pu64RirbBuf)
6405 RT_BZERO(pThis->pu64RirbBuf, pThis->cbRirbBuf);
6406 else
6407 pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
6408
6409 pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
6410
6411 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
6412 {
6413 /* Remove the RUN bit from SDnCTL in case the stream was in a running state before. */
6414 HDA_STREAM_REG(pThis, CTL, i) &= ~HDA_SDCTL_RUN;
6415 hdaStreamReset(pThis, &pThis->aStreams[i]);
6416 }
6417
6418 /* Clear stream tags <-> objects mapping table. */
6419 RT_ZERO(pThis->aTags);
6420
6421 /* Emulation of codec "wake up" (HDA spec 5.5.1 and 6.5). */
6422 HDA_REG(pThis, STATESTS) = 0x1;
6423
6424 LogFlowFuncLeave();
6425 LogRel(("HDA: Reset\n"));
6426}
6427
6428/**
6429 * @interface_method_impl{PDMDEVREG,pfnDestruct}
6430 */
6431static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
6432{
6433 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6434
6435 PHDADRIVER pDrv;
6436 while (!RTListIsEmpty(&pThis->lstDrv))
6437 {
6438 pDrv = RTListGetFirst(&pThis->lstDrv, HDADRIVER, Node);
6439
6440 RTListNodeRemove(&pDrv->Node);
6441 RTMemFree(pDrv);
6442 }
6443
6444 if (pThis->pCodec)
6445 {
6446 hdaCodecDestruct(pThis->pCodec);
6447
6448 RTMemFree(pThis->pCodec);
6449 pThis->pCodec = NULL;
6450 }
6451
6452 RTMemFree(pThis->pu32CorbBuf);
6453 pThis->pu32CorbBuf = NULL;
6454
6455 RTMemFree(pThis->pu64RirbBuf);
6456 pThis->pu64RirbBuf = NULL;
6457
6458 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
6459 hdaStreamDestroy(pThis, &pThis->aStreams[i]);
6460
6461 return VINF_SUCCESS;
6462}
6463
6464
6465/**
6466 * Attach command, internal version.
6467 *
6468 * This is called to let the device attach to a driver for a specified LUN
6469 * during runtime. This is not called during VM construction, the device
6470 * constructor has to attach to all the available drivers.
6471 *
6472 * @returns VBox status code.
6473 * @param pDevIns The device instance.
6474 * @param pDrv Driver to (re-)use for (re-)attaching to.
6475 * If NULL is specified, a new driver will be created and appended
6476 * to the driver list.
6477 * @param uLUN The logical unit which is being detached.
6478 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6479 */
6480static int hdaAttachInternal(PPDMDEVINS pDevIns, PHDADRIVER pDrv, unsigned uLUN, uint32_t fFlags)
6481{
6482 RT_NOREF(fFlags);
6483 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6484
6485 /*
6486 * Attach driver.
6487 */
6488 char *pszDesc = NULL;
6489 if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
6490 AssertReleaseMsgReturn(pszDesc,
6491 ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
6492 VERR_NO_MEMORY);
6493
6494 PPDMIBASE pDrvBase;
6495 int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
6496 &pThis->IBase, &pDrvBase, pszDesc);
6497 if (RT_SUCCESS(rc))
6498 {
6499 if (pDrv == NULL)
6500 pDrv = (PHDADRIVER)RTMemAllocZ(sizeof(HDADRIVER));
6501 if (pDrv)
6502 {
6503 pDrv->pDrvBase = pDrvBase;
6504 pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
6505 AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
6506 pDrv->pHDAState = pThis;
6507 pDrv->uLUN = uLUN;
6508
6509 /*
6510 * For now we always set the driver at LUN 0 as our primary
6511 * host backend. This might change in the future.
6512 */
6513 if (pDrv->uLUN == 0)
6514 pDrv->fFlags |= PDMAUDIODRVFLAGS_PRIMARY;
6515
6516 LogFunc(("LUN#%u: pCon=%p, drvFlags=0x%x\n", uLUN, pDrv->pConnector, pDrv->fFlags));
6517
6518 /* Attach to driver list if not attached yet. */
6519 if (!pDrv->fAttached)
6520 {
6521 RTListAppend(&pThis->lstDrv, &pDrv->Node);
6522 pDrv->fAttached = true;
6523 }
6524 }
6525 else
6526 rc = VERR_NO_MEMORY;
6527 }
6528 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
6529 LogFunc(("No attached driver for LUN #%u\n", uLUN));
6530
6531 if (RT_FAILURE(rc))
6532 {
6533 /* Only free this string on failure;
6534 * must remain valid for the live of the driver instance. */
6535 RTStrFree(pszDesc);
6536 }
6537
6538 LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
6539 return rc;
6540}
6541
6542/**
6543 * Attach command.
6544 *
6545 * This is called to let the device attach to a driver for a specified LUN
6546 * during runtime. This is not called during VM construction, the device
6547 * constructor has to attach to all the available drivers.
6548 *
6549 * @returns VBox status code.
6550 * @param pDevIns The device instance.
6551 * @param uLUN The logical unit which is being detached.
6552 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6553 */
6554static DECLCALLBACK(int) hdaAttach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
6555{
6556 return hdaAttachInternal(pDevIns, NULL /* pDrv */, uLUN, fFlags);
6557}
6558
6559static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
6560{
6561 RT_NOREF(pDevIns, uLUN, fFlags);
6562 LogFunc(("iLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
6563}
6564
6565/**
6566 * Powers off the device.
6567 *
6568 * @param pDevIns Device instance to power off.
6569 */
6570static DECLCALLBACK(void) hdaPowerOff(PPDMDEVINS pDevIns)
6571{
6572 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6573
6574 LogRel2(("HDA: Powering off ...\n"));
6575
6576 /* Ditto goes for the codec, which in turn uses the mixer. */
6577 hdaCodecPowerOff(pThis->pCodec);
6578
6579 /**
6580 * Note: Destroy the mixer while powering off and *not* in hdaDestruct,
6581 * giving the mixer the chance to release any references held to
6582 * PDM audio streams it maintains.
6583 */
6584 if (pThis->pMixer)
6585 {
6586 AudioMixerDestroy(pThis->pMixer);
6587 pThis->pMixer = NULL;
6588 }
6589}
6590
6591/**
6592 * Re-attaches a new driver to the device's driver chain.
6593 *
6594 * @returns VBox status code.
6595 * @param pThis Device instance to re-attach driver to.
6596 * @param pDrv Driver instance used for attaching to.
6597 * If NULL is specified, a new driver will be created and appended
6598 * to the driver list.
6599 * @param uLUN The logical unit which is being re-detached.
6600 * @param pszDriver Driver name.
6601 */
6602static int hdaReattach(PHDASTATE pThis, PHDADRIVER pDrv, uint8_t uLUN, const char *pszDriver)
6603{
6604 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
6605 AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
6606
6607 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
6608 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
6609 PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/hda/0/");
6610
6611 /* Remove LUN branch. */
6612 CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN));
6613
6614 if (pDrv)
6615 {
6616 /* Re-use a driver instance => detach the driver before. */
6617 int rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
6618 if (RT_FAILURE(rc))
6619 return rc;
6620 }
6621
6622#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
6623
6624 int rc = VINF_SUCCESS;
6625 do
6626 {
6627 PCFGMNODE pLunL0;
6628 rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", uLUN); RC_CHECK();
6629 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
6630 rc = CFGMR3InsertNode(pLunL0, "Config/", NULL); RC_CHECK();
6631
6632 PCFGMNODE pLunL1, pLunL2;
6633 rc = CFGMR3InsertNode (pLunL0, "AttachedDriver/", &pLunL1); RC_CHECK();
6634 rc = CFGMR3InsertNode (pLunL1, "Config/", &pLunL2); RC_CHECK();
6635 rc = CFGMR3InsertString(pLunL1, "Driver", pszDriver); RC_CHECK();
6636
6637 rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver); RC_CHECK();
6638
6639 } while (0);
6640
6641 if (RT_SUCCESS(rc))
6642 rc = hdaAttachInternal(pThis->pDevInsR3, pDrv, uLUN, 0 /* fFlags */);
6643
6644 LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, uLUN, pszDriver, rc));
6645
6646#undef RC_CHECK
6647
6648 return rc;
6649}
6650
6651/**
6652 * @interface_method_impl{PDMDEVREG,pfnConstruct}
6653 */
6654static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
6655{
6656 RT_NOREF(iInstance);
6657 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
6658 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
6659 Assert(iInstance == 0);
6660
6661 /*
6662 * Validations.
6663 */
6664 if (!CFGMR3AreValuesValid(pCfg, "R0Enabled\0"
6665 "RCEnabled\0"
6666 "TimerHz\0"))
6667 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
6668 N_ ("Invalid configuration for the Intel HDA device"));
6669
6670 int rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &pThis->fRCEnabled, false);
6671 if (RT_FAILURE(rc))
6672 return PDMDEV_SET_ERROR(pDevIns, rc,
6673 N_("HDA configuration error: failed to read RCEnabled as boolean"));
6674 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, false);
6675 if (RT_FAILURE(rc))
6676 return PDMDEV_SET_ERROR(pDevIns, rc,
6677 N_("HDA configuration error: failed to read R0Enabled as boolean"));
6678#ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
6679 uint16_t uTimerHz;
6680 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, HDA_TIMER_HZ /* Default value, if not set. */);
6681 if (RT_FAILURE(rc))
6682 return PDMDEV_SET_ERROR(pDevIns, rc,
6683 N_("HDA configuration error: failed to read Hertz (Hz) rate as unsigned integer"));
6684#endif
6685
6686 /*
6687 * Initialize data (most of it anyway).
6688 */
6689 pThis->pDevInsR3 = pDevIns;
6690 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
6691 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
6692 /* IBase */
6693 pThis->IBase.pfnQueryInterface = hdaQueryInterface;
6694
6695 /* PCI Device */
6696 PCIDevSetVendorId (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
6697 PCIDevSetDeviceId (&pThis->PciDev, HDA_PCI_DEVICE_ID); /* HDA */
6698
6699 PCIDevSetCommand (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
6700 PCIDevSetStatus (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
6701 PCIDevSetRevisionId (&pThis->PciDev, 0x01); /* 08 ro - rid. */
6702 PCIDevSetClassProg (&pThis->PciDev, 0x00); /* 09 ro - pi. */
6703 PCIDevSetClassSub (&pThis->PciDev, 0x03); /* 0a ro - scc; 03 == HDA. */
6704 PCIDevSetClassBase (&pThis->PciDev, 0x04); /* 0b ro - bcc; 04 == multimedia. */
6705 PCIDevSetHeaderType (&pThis->PciDev, 0x00); /* 0e ro - headtyp. */
6706 PCIDevSetBaseAddress (&pThis->PciDev, 0, /* 10 rw - MMIO */
6707 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
6708 PCIDevSetInterruptLine (&pThis->PciDev, 0x00); /* 3c rw. */
6709 PCIDevSetInterruptPin (&pThis->PciDev, 0x01); /* 3d ro - INTA#. */
6710
6711#if defined(HDA_AS_PCI_EXPRESS)
6712 PCIDevSetCapabilityList (&pThis->PciDev, 0x80);
6713#elif defined(VBOX_WITH_MSI_DEVICES)
6714 PCIDevSetCapabilityList (&pThis->PciDev, 0x60);
6715#else
6716 PCIDevSetCapabilityList (&pThis->PciDev, 0x50); /* ICH6 datasheet 18.1.16 */
6717#endif
6718
6719 /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
6720 /// of these values needs to be properly documented!
6721 /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
6722 PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
6723
6724 /* Power Management */
6725 PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
6726 PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
6727 PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
6728
6729#ifdef HDA_AS_PCI_EXPRESS
6730 /* PCI Express */
6731 PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
6732 PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
6733 /* Device flags */
6734 PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
6735 /* version */ 0x1 |
6736 /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
6737 /* MSI */ (100) << 9 );
6738 /* Device capabilities */
6739 PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
6740 /* Device control */
6741 PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
6742 /* Device status */
6743 PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
6744 /* Link caps */
6745 PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
6746 /* Link control */
6747 PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
6748 /* Link status */
6749 PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
6750 /* Slot capabilities */
6751 PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
6752 /* Slot control */
6753 PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
6754 /* Slot status */
6755 PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
6756 /* Root control */
6757 PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
6758 /* Root capabilities */
6759 PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
6760 /* Root status */
6761 PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
6762 /* Device capabilities 2 */
6763 PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
6764 /* Device control 2 */
6765 PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
6766 /* Link control 2 */
6767 PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
6768 /* Slot control 2 */
6769 PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
6770#endif
6771
6772 /*
6773 * Register the PCI device.
6774 */
6775 rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
6776 if (RT_FAILURE(rc))
6777 return rc;
6778
6779 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
6780 if (RT_FAILURE(rc))
6781 return rc;
6782
6783#ifdef VBOX_WITH_MSI_DEVICES
6784 PDMMSIREG MsiReg;
6785 RT_ZERO(MsiReg);
6786 MsiReg.cMsiVectors = 1;
6787 MsiReg.iMsiCapOffset = 0x60;
6788 MsiReg.iMsiNextOffset = 0x50;
6789 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
6790 if (RT_FAILURE(rc))
6791 {
6792 /* That's OK, we can work without MSI */
6793 PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
6794 }
6795#endif
6796
6797 rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
6798 if (RT_FAILURE(rc))
6799 return rc;
6800
6801 RTListInit(&pThis->lstDrv);
6802
6803#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
6804 LogRel(("HDA: Asynchronous I/O enabled\n"));
6805#endif
6806
6807 uint8_t uLUN;
6808 for (uLUN = 0; uLUN < UINT8_MAX; ++uLUN)
6809 {
6810 LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
6811 rc = hdaAttachInternal(pDevIns, NULL /* pDrv */, uLUN, 0 /* fFlags */);
6812 if (RT_FAILURE(rc))
6813 {
6814 if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
6815 rc = VINF_SUCCESS;
6816 else if (rc == VERR_AUDIO_BACKEND_INIT_FAILED)
6817 {
6818 hdaReattach(pThis, NULL /* pDrv */, uLUN, "NullAudio");
6819 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
6820 N_("Host audio backend initialization has failed. Selecting the NULL audio backend "
6821 "with the consequence that no sound is audible"));
6822 /* Attaching to the NULL audio backend will never fail. */
6823 rc = VINF_SUCCESS;
6824 }
6825 break;
6826 }
6827 }
6828
6829 LogFunc(("cLUNs=%RU8, rc=%Rrc\n", uLUN, rc));
6830
6831 if (RT_SUCCESS(rc))
6832 {
6833 rc = AudioMixerCreate("HDA Mixer", 0 /* uFlags */, &pThis->pMixer);
6834 if (RT_SUCCESS(rc))
6835 {
6836 /*
6837 * Add mixer output sinks.
6838 */
6839#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
6840 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Front",
6841 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
6842 AssertRC(rc);
6843 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Center / Subwoofer",
6844 AUDMIXSINKDIR_OUTPUT, &pThis->SinkCenterLFE.pMixSink);
6845 AssertRC(rc);
6846 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] Rear",
6847 AUDMIXSINKDIR_OUTPUT, &pThis->SinkRear.pMixSink);
6848 AssertRC(rc);
6849#else
6850 rc = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output",
6851 AUDMIXSINKDIR_OUTPUT, &pThis->SinkFront.pMixSink);
6852 AssertRC(rc);
6853#endif
6854 /*
6855 * Add mixer input sinks.
6856 */
6857 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Line In",
6858 AUDMIXSINKDIR_INPUT, &pThis->SinkLineIn.pMixSink);
6859 AssertRC(rc);
6860#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6861 rc = AudioMixerCreateSink(pThis->pMixer, "[Recording] Microphone In",
6862 AUDMIXSINKDIR_INPUT, &pThis->SinkMicIn.pMixSink);
6863 AssertRC(rc);
6864#endif
6865 /* There is no master volume control. Set the master to max. */
6866 PDMAUDIOVOLUME vol = { false, 255, 255 };
6867 rc = AudioMixerSetMasterVolume(pThis->pMixer, &vol);
6868 AssertRC(rc);
6869 }
6870 }
6871
6872 if (RT_SUCCESS(rc))
6873 {
6874 /* Construct codec. */
6875 pThis->pCodec = (PHDACODEC)RTMemAllocZ(sizeof(HDACODEC));
6876 if (!pThis->pCodec)
6877 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Out of memory allocating HDA codec state"));
6878
6879 /* Set codec callbacks to this controller. */
6880 pThis->pCodec->pfnCbMixerAddStream = hdaMixerAddStream;
6881 pThis->pCodec->pfnCbMixerRemoveStream = hdaMixerRemoveStream;
6882 pThis->pCodec->pfnCbMixerSetStream = hdaMixerSetStream;
6883 pThis->pCodec->pfnCbMixerSetVolume = hdaMixerSetVolume;
6884
6885 pThis->pCodec->pHDAState = pThis; /* Assign HDA controller state to codec. */
6886
6887 /* Construct the codec. */
6888 rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg);
6889 if (RT_FAILURE(rc))
6890 AssertRCReturn(rc, rc);
6891
6892 /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
6893 verb F20 should provide device/codec recognition. */
6894 Assert(pThis->pCodec->u16VendorId);
6895 Assert(pThis->pCodec->u16DeviceId);
6896 PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->pCodec->u16VendorId); /* 2c ro - intel.) */
6897 PCIDevSetSubSystemId( &pThis->PciDev, pThis->pCodec->u16DeviceId); /* 2e ro. */
6898 }
6899
6900 if (RT_SUCCESS(rc))
6901 {
6902 /*
6903 * Create all hardware streams.
6904 */
6905 for (uint8_t i = 0; i < HDA_MAX_STREAMS; i++)
6906 {
6907 rc = hdaStreamCreate(pThis, &pThis->aStreams[i], i /* uSD */);
6908 AssertRC(rc);
6909 }
6910
6911#ifdef VBOX_WITH_AUDIO_HDA_ONETIME_INIT
6912 /*
6913 * Initialize the driver chain.
6914 */
6915 PHDADRIVER pDrv;
6916 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
6917 {
6918 /*
6919 * Only primary drivers are critical for the VM to run. Everything else
6920 * might not worth showing an own error message box in the GUI.
6921 */
6922 if (!(pDrv->fFlags & PDMAUDIODRVFLAGS_PRIMARY))
6923 continue;
6924
6925 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
6926 AssertPtr(pCon);
6927
6928 bool fValidLineIn = AudioMixerStreamIsValid(pDrv->LineIn.pMixStrm);
6929# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6930 bool fValidMicIn = AudioMixerStreamIsValid(pDrv->MicIn.pMixStrm);
6931# endif
6932 bool fValidOut = AudioMixerStreamIsValid(pDrv->Front.pMixStrm);
6933# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
6934 /** @todo Anything to do here? */
6935# endif
6936
6937 if ( !fValidLineIn
6938# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6939 && !fValidMicIn
6940# endif
6941 && !fValidOut)
6942 {
6943 LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
6944
6945 hdaReset(pDevIns);
6946 hdaReattach(pThis, pDrv, pDrv->uLUN, "NullAudio");
6947
6948 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
6949 N_("No audio devices could be opened. Selecting the NULL audio backend "
6950 "with the consequence that no sound is audible"));
6951 }
6952 else
6953 {
6954 bool fWarn = false;
6955
6956 PDMAUDIOBACKENDCFG backendCfg;
6957 int rc2 = pCon->pfnGetConfig(pCon, &backendCfg);
6958 if (RT_SUCCESS(rc2))
6959 {
6960 if (backendCfg.cMaxStreamsIn)
6961 {
6962# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
6963 /* If the audio backend supports two or more input streams at once,
6964 * warn if one of our two inputs (microphone-in and line-in) failed to initialize. */
6965 if (backendCfg.cMaxStreamsIn >= 2)
6966 fWarn = !fValidLineIn || !fValidMicIn;
6967 /* If the audio backend only supports one input stream at once (e.g. pure ALSA, and
6968 * *not* ALSA via PulseAudio plugin!), only warn if both of our inputs failed to initialize.
6969 * One of the two simply is not in use then. */
6970 else if (backendCfg.cMaxStreamsIn == 1)
6971 fWarn = !fValidLineIn && !fValidMicIn;
6972 /* Don't warn if our backend is not able of supporting any input streams at all. */
6973# else /* !VBOX_WITH_AUDIO_HDA_MIC_IN */
6974 /* We only have line-in as input source. */
6975 fWarn = !fValidLineIn;
6976# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
6977 }
6978
6979 if ( !fWarn
6980 && backendCfg.cMaxStreamsOut)
6981 {
6982 fWarn = !fValidOut;
6983 }
6984 }
6985 else
6986 {
6987 LogRel(("HDA: Unable to retrieve audio backend configuration for LUN #%RU8, rc=%Rrc\n", pDrv->uLUN, rc2));
6988 fWarn = true;
6989 }
6990
6991 if (fWarn)
6992 {
6993 char szMissingStreams[255];
6994 size_t len = 0;
6995 if (!fValidLineIn)
6996 {
6997 LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU8!\n", pDrv->uLUN));
6998 len = RTStrPrintf(szMissingStreams, sizeof(szMissingStreams), "PCM Input");
6999 }
7000# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
7001 if (!fValidMicIn)
7002 {
7003 LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU8!\n", pDrv->uLUN));
7004 len += RTStrPrintf(szMissingStreams + len,
7005 sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
7006 }
7007# endif /* VBOX_WITH_AUDIO_HDA_MIC_IN */
7008 if (!fValidOut)
7009 {
7010 LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU8!\n", pDrv->uLUN));
7011 len += RTStrPrintf(szMissingStreams + len,
7012 sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
7013 }
7014
7015 PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
7016 N_("Some HDA audio streams (%s) could not be opened. Guest applications generating audio "
7017 "output or depending on audio input may hang. Make sure your host audio device "
7018 "is working properly. Check the logfile for error messages of the audio "
7019 "subsystem"), szMissingStreams);
7020 }
7021 }
7022 }
7023#endif /* VBOX_WITH_AUDIO_HDA_ONETIME_INIT */
7024 }
7025
7026 if (RT_SUCCESS(rc))
7027 {
7028 hdaReset(pDevIns);
7029
7030 /*
7031 * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
7032 * hdaReset shouldn't affects these registers.
7033 */
7034 HDA_REG(pThis, WAKEEN) = 0x0;
7035 HDA_REG(pThis, STATESTS) = 0x0;
7036
7037 /*
7038 * Debug and string formatter types.
7039 */
7040 PDMDevHlpDBGFInfoRegister(pDevIns, "hda", "HDA info. (hda [register case-insensitive])", hdaDbgInfo);
7041 PDMDevHlpDBGFInfoRegister(pDevIns, "hdabdle", "HDA stream BDLE info. (hdabdle [stream number])", hdaDbgInfoBDLE);
7042 PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm", "HDA stream info. (hdastrm [stream number])", hdaDbgInfoStream);
7043 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes", "HDA codec nodes.", hdaDbgInfoCodecNodes);
7044 PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].", hdaDbgInfoCodecSelector);
7045 PDMDevHlpDBGFInfoRegister(pDevIns, "hdamixer", "HDA mixer state.", hdaDbgInfoMixer);
7046
7047 rc = RTStrFormatTypeRegister("bdle", hdaDbgFmtBDLE, NULL);
7048 AssertRC(rc);
7049 rc = RTStrFormatTypeRegister("sdctl", hdaDbgFmtSDCTL, NULL);
7050 AssertRC(rc);
7051 rc = RTStrFormatTypeRegister("sdsts", hdaDbgFmtSDSTS, NULL);
7052 AssertRC(rc);
7053 rc = RTStrFormatTypeRegister("sdfifos", hdaDbgFmtSDFIFOS, NULL);
7054 AssertRC(rc);
7055 rc = RTStrFormatTypeRegister("sdfifow", hdaDbgFmtSDFIFOW, NULL);
7056 AssertRC(rc);
7057
7058 /*
7059 * Some debug assertions.
7060 */
7061 for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
7062 {
7063 struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
7064 struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
7065
7066 /* binary search order. */
7067 AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
7068 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7069 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
7070
7071 /* alignment. */
7072 AssertReleaseMsg( pReg->size == 1
7073 || (pReg->size == 2 && (pReg->offset & 1) == 0)
7074 || (pReg->size == 3 && (pReg->offset & 3) == 0)
7075 || (pReg->size == 4 && (pReg->offset & 3) == 0),
7076 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7077
7078 /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
7079 AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
7080 if (pReg->offset & 3)
7081 {
7082 struct HDAREGDESC const *pPrevReg = i > 0 ? &g_aHdaRegMap[i - 1] : NULL;
7083 AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7084 if (pPrevReg)
7085 AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
7086 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7087 i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
7088 }
7089#if 0
7090 if ((pReg->offset + pReg->size) & 3)
7091 {
7092 AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7093 if (pNextReg)
7094 AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
7095 ("[%#x] = {%#x LB %#x} vs. [%#x] = {%#x LB %#x}\n",
7096 i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
7097 }
7098#endif
7099 /* The final entry is a full DWORD, no gaps! Allows shortcuts. */
7100 AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
7101 ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
7102 }
7103 }
7104
7105# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
7106 if (RT_SUCCESS(rc))
7107 {
7108 /* Create the emulation timer. */
7109 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, hdaTimer, pThis,
7110 TMTIMER_FLAGS_NO_CRIT_SECT, "DevHDA", &pThis->pTimer);
7111 AssertRCReturn(rc, rc);
7112
7113 if (RT_SUCCESS(rc))
7114 {
7115 pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
7116 pThis->uTimerTS = TMTimerGet(pThis->pTimer);
7117 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
7118 }
7119 }
7120# else
7121 if (RT_SUCCESS(rc))
7122 {
7123 PHDADRIVER pDrv;
7124 RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
7125 {
7126 /* Only register primary driver.
7127 * The device emulation does the output multiplexing then. */
7128 if (pDrv->fFlags != PDMAUDIODRVFLAGS_PRIMARY)
7129 continue;
7130
7131 PDMAUDIOCALLBACK AudioCallbacks[2];
7132
7133 HDACALLBACKCTX Ctx = { pThis, pDrv };
7134
7135 AudioCallbacks[0].enmType = PDMAUDIOCALLBACKTYPE_INPUT;
7136 AudioCallbacks[0].pfnCallback = hdaCallbackInput;
7137 AudioCallbacks[0].pvCtx = &Ctx;
7138 AudioCallbacks[0].cbCtx = sizeof(HDACALLBACKCTX);
7139
7140 AudioCallbacks[1].enmType = PDMAUDIOCALLBACKTYPE_OUTPUT;
7141 AudioCallbacks[1].pfnCallback = hdaCallbackOutput;
7142 AudioCallbacks[1].pvCtx = &Ctx;
7143 AudioCallbacks[1].cbCtx = sizeof(HDACALLBACKCTX);
7144
7145 rc = pDrv->pConnector->pfnRegisterCallbacks(pDrv->pConnector, AudioCallbacks, RT_ELEMENTS(AudioCallbacks));
7146 if (RT_FAILURE(rc))
7147 break;
7148 }
7149 }
7150# endif
7151
7152# ifdef VBOX_WITH_STATISTICS
7153 if (RT_SUCCESS(rc))
7154 {
7155 /*
7156 * Register statistics.
7157 */
7158# ifndef VBOX_WITH_AUDIO_HDA_CALLBACKS
7159 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTimer, STAMTYPE_PROFILE, "/Devices/HDA/Timer", STAMUNIT_TICKS_PER_CALL, "Profiling hdaTimer.");
7160# endif
7161 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIn, STAMTYPE_PROFILE, "/Devices/HDA/Input", STAMUNIT_TICKS_PER_CALL, "Profiling input.");
7162 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatOut, STAMTYPE_PROFILE, "/Devices/HDA/Output", STAMUNIT_TICKS_PER_CALL, "Profiling output.");
7163 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, "/Devices/HDA/BytesRead" , STAMUNIT_BYTES, "Bytes read from HDA emulation.");
7164 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, "/Devices/HDA/BytesWritten", STAMUNIT_BYTES, "Bytes written to HDA emulation.");
7165 }
7166# endif
7167
7168#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
7169 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMARead.pcm");
7170 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaDMAWrite.pcm");
7171 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamRead.pcm");
7172 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "hdaStreamWrite.pcm");
7173#endif
7174
7175 LogFlowFuncLeaveRC(rc);
7176 return rc;
7177}
7178
7179/**
7180 * The device registration structure.
7181 */
7182const PDMDEVREG g_DeviceHDA =
7183{
7184 /* u32Version */
7185 PDM_DEVREG_VERSION,
7186 /* szName */
7187 "hda",
7188 /* szRCMod */
7189 "VBoxDDRC.rc",
7190 /* szR0Mod */
7191 "VBoxDDR0.r0",
7192 /* pszDescription */
7193 "Intel HD Audio Controller",
7194 /* fFlags */
7195 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
7196 /* fClass */
7197 PDM_DEVREG_CLASS_AUDIO,
7198 /* cMaxInstances */
7199 1,
7200 /* cbInstance */
7201 sizeof(HDASTATE),
7202 /* pfnConstruct */
7203 hdaConstruct,
7204 /* pfnDestruct */
7205 hdaDestruct,
7206 /* pfnRelocate */
7207 NULL,
7208 /* pfnMemSetup */
7209 NULL,
7210 /* pfnPowerOn */
7211 NULL,
7212 /* pfnReset */
7213 hdaReset,
7214 /* pfnSuspend */
7215 NULL,
7216 /* pfnResume */
7217 NULL,
7218 /* pfnAttach */
7219 hdaAttach,
7220 /* pfnDetach */
7221 hdaDetach,
7222 /* pfnQueryInterface. */
7223 NULL,
7224 /* pfnInitComplete */
7225 NULL,
7226 /* pfnPowerOff */
7227 hdaPowerOff,
7228 /* pfnSoftReset */
7229 NULL,
7230 /* u32VersionEnd */
7231 PDM_DEVREG_VERSION
7232};
7233
7234#endif /* IN_RING3 */
7235#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
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