summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Audio/DevHda.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/Audio/DevHda.h')
-rw-r--r--src/VBox/Devices/Audio/DevHda.h918
1 files changed, 918 insertions, 0 deletions
diff --git a/src/VBox/Devices/Audio/DevHda.h b/src/VBox/Devices/Audio/DevHda.h
new file mode 100644
index 00000000..b8fe851f
--- /dev/null
+++ b/src/VBox/Devices/Audio/DevHda.h
@@ -0,0 +1,918 @@
+/* $Id: DevHda.h $ */
+/** @file
+ * Intel HD Audio Controller Emulation - Structures.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h
+#define VBOX_INCLUDED_SRC_Audio_DevHda_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/path.h>
+#include <VBox/vmm/pdmdev.h>
+#include "AudioMixer.h"
+
+/*
+ * Compile time feature configuration.
+ */
+
+/** @def VBOX_HDA_WITH_ON_REG_ACCESS_DMA
+ * Enables doing DMA work on certain register accesses (LPIB, WALCLK) in
+ * addition to the DMA timer. All but the last frame can be done during
+ * register accesses (as we don't wish to leave the DMA timer w/o work to
+ * do in case that upsets it). */
+#if defined(DOXYGEN_RUNNING) || 0
+# define VBOX_HDA_WITH_ON_REG_ACCESS_DMA
+#endif
+
+#ifdef DEBUG_andy
+/** Enables strict mode, which checks for stuff which isn't supposed to happen.
+ * Be prepared for assertions coming in! */
+//# define HDA_STRICT
+#endif
+
+/** @def HDA_AS_PCI_EXPRESS
+ * Enables PCI express hardware. */
+#if defined(DOXYGEN_RUNNING) || 0
+# define HDA_AS_PCI_EXPRESS
+#endif
+
+/** @def HDA_DEBUG_SILENCE
+ * To debug silence coming from the guest in form of audio gaps.
+ * Very crude implementation for now.
+ * @todo probably borked atm */
+#if defined(DOXYGEN_RUNNING) || 0
+# define HDA_DEBUG_SILENCE
+#endif
+
+
+/*
+ * Common pointer types.
+ */
+/** Pointer to an HDA stream (SDI / SDO). */
+typedef struct HDASTREAMR3 *PHDASTREAMR3;
+/** Pointer to a shared HDA device state. */
+typedef struct HDASTATE *PHDASTATE;
+/** Pointer to a ring-3 HDA device state. */
+typedef struct HDASTATER3 *PHDASTATER3;
+/** Pointer to an HDA mixer sink definition (ring-3). */
+typedef struct HDAMIXERSINK *PHDAMIXERSINK;
+
+
+/*
+ * The rest of the headers.
+ */
+#include "DevHdaStream.h"
+#include "DevHdaCodec.h"
+
+
+
+/** @name Stream counts.
+ *
+ * At the moment we support 4 input + 4 output streams max, which is 8 in total.
+ * Bidirectional streams are currently *not* supported.
+ *
+ * @note When changing any of those values, be prepared for some saved state
+ * fixups / trouble!
+ * @{
+ */
+#define HDA_MAX_SDI 4
+#define HDA_MAX_SDO 4
+#define HDA_MAX_STREAMS (HDA_MAX_SDI + HDA_MAX_SDO)
+/** @} */
+AssertCompile(HDA_MAX_SDI <= HDA_MAX_SDO);
+
+
+/** @defgroup grp_hda_regs HDA Register Definitions
+ *
+ * There are two variants for most register defines:
+ * - HDA_REG_XXX: Index into g_aHdaRegMap
+ * - HDA_RMX_XXX: Index into HDASTATE::au32Regs
+ *
+ * Use the HDA_REG and HDA_STREAM_REG macros to access registers where possible.
+ *
+ * @note The au32Regs[] layout is kept unchanged for saved state compatibility,
+ * thus the HDA_RMX_XXX assignments are for all purposes set in stone.
+ *
+ * @{ */
+
+/** Number of general registers. */
+#define HDA_NUM_GENERAL_REGS 36
+/** Number of stream registers (10 registers per stream). */
+#define HDA_NUM_STREAM_REGS (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */)
+/** Number of register after the stream registers. */
+#define HDA_NUM_POST_STREAM_REGS (2 + HDA_MAX_STREAMS * 2)
+/** Number of total registers in the HDA's register map. */
+#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + HDA_NUM_STREAM_REGS + HDA_NUM_POST_STREAM_REGS)
+/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
+#define HDA_MAX_TAGS 16
+
+
+/** Offset of the SD0 register map. */
+#define HDA_REG_DESC_SD0_BASE 0x80
+
+/* Registers */
+#define HDA_REG_IND_NAME(x) HDA_REG_##x
+#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
+
+/** Direct register access by HDASTATE::au32Reg index. */
+#define HDA_REG_BY_IDX(a_pThis, a_idxReg) ((a_pThis)->au32Regs[(a_idxReg)])
+
+/** Accesses register @a ShortRegNm. */
+#if defined(VBOX_STRICT) && defined(VBOX_HDA_CAN_ACCESS_REG_MAP)
+# define HDA_REG(a_pThis, a_ShortRegNm) (*hdaStrictRegAccessor(a_pThis, HDA_REG_IND_NAME(a_ShortRegNm), HDA_MEM_IND_NAME(a_ShortRegNm)))
+#else
+# define HDA_REG(a_pThis, a_ShortRegNm) HDA_REG_BY_IDX(a_pThis, HDA_MEM_IND_NAME(a_ShortRegNm))
+#endif
+
+/** Indirect register access via g_aHdaRegMap[].idxReg. */
+#define HDA_REG_IND(a_pThis, a_idxMap) HDA_REG_BY_IDX(a_pThis, g_aHdaRegMap[(a_idxMap)].idxReg)
+
+
+#define HDA_REG_GCAP 0 /* Range 0x00 - 0x01 */
+#define HDA_RMX_GCAP 0
+/**
+ * GCAP HDASpec 3.3.2 This macro encodes the following information about HDA in a compact manner:
+ *
+ * oss (15:12) - Number of output streams supported.
+ * iss (11:8) - Number of input streams supported.
+ * bss (7:3) - Number of bidirectional streams supported.
+ * bds (2:1) - Number of serial data out (SDO) signals supported.
+ * b64sup (0) - 64 bit addressing supported.
+ */
+#define HDA_MAKE_GCAP(oss, iss, bss, bds, b64sup) \
+ ( (((oss) & 0xF) << 12) \
+ | (((iss) & 0xF) << 8) \
+ | (((bss) & 0x1F) << 3) \
+ | (((bds) & 0x3) << 2) \
+ | ((b64sup) & 1))
+
+#define HDA_REG_VMIN 1 /* 0x02 */
+#define HDA_RMX_VMIN 1
+
+#define HDA_REG_VMAJ 2 /* 0x03 */
+#define HDA_RMX_VMAJ 2
+
+#define HDA_REG_OUTPAY 3 /* 0x04-0x05 */
+#define HDA_RMX_OUTPAY 3
+
+#define HDA_REG_INPAY 4 /* 0x06-0x07 */
+#define HDA_RMX_INPAY 4
+
+#define HDA_REG_GCTL 5 /* 0x08-0x0B */
+#define HDA_RMX_GCTL 5
+#define HDA_GCTL_UNSOL RT_BIT(8) /* Accept Unsolicited Response Enable */
+#define HDA_GCTL_FCNTRL RT_BIT(1) /* Flush Control */
+#define HDA_GCTL_CRST RT_BIT(0) /* Controller Reset */
+
+#define HDA_REG_WAKEEN 6 /* 0x0C */
+#define HDA_RMX_WAKEEN 6
+
+#define HDA_REG_STATESTS 7 /* 0x0E */
+#define HDA_RMX_STATESTS 7
+#define HDA_STATESTS_SCSF_MASK 0x7 /* State Change Status Flags (6.2.8). */
+
+#define HDA_REG_GSTS 8 /* 0x10-0x11*/
+#define HDA_RMX_GSTS 8
+#define HDA_GSTS_FSTS RT_BIT(1) /* Flush Status */
+
+#define HDA_REG_LLCH 9 /* 0x14 */
+#define HDA_RMX_LLCH 114
+
+#define HDA_REG_OUTSTRMPAY 10 /* 0x18 */
+#define HDA_RMX_OUTSTRMPAY 112
+
+#define HDA_REG_INSTRMPAY 11 /* 0x1a */
+#define HDA_RMX_INSTRMPAY 113
+
+#define HDA_REG_INTCTL 12 /* 0x20 */
+#define HDA_RMX_INTCTL 9
+#define HDA_INTCTL_GIE RT_BIT(31) /* Global Interrupt Enable */
+#define HDA_INTCTL_CIE RT_BIT(30) /* Controller Interrupt Enable */
+/** Bits 0-29 correspond to streams 0-29. */
+#define HDA_STRMINT_MASK 0xFF /* Streams 0-7 implemented. Applies to INTCTL and INTSTS. */
+
+#define HDA_REG_INTSTS 13 /* 0x24 */
+#define HDA_RMX_INTSTS 10
+#define HDA_INTSTS_GIS RT_BIT(31) /* Global Interrupt Status */
+#define HDA_INTSTS_CIS RT_BIT(30) /* Controller Interrupt Status */
+
+#define HDA_REG_WALCLK 14 /* 0x30 */
+/* NB: HDA_RMX_WALCLK is not defined because the register is not stored in memory. */
+
+/**
+ * @note The HDA specification defines a SSYNC register at offset 0x38. The ICH6/ICH9
+ * datahseet defines SSYNC at offset 0x34. The Linux HDA driver matches the datasheet.
+ * See also https://mailman.alsa-project.org/pipermail/alsa-devel/2011-March/037819.html
+ */
+#define HDA_REG_SSYNC 15 /* 0x34 */
+#define HDA_RMX_SSYNC 12
+
+#define HDA_REG_NEW_SSYNC 16 /* 0x38 */
+#define HDA_RMX_NEW_SSYNC HDA_RMX_SSYNC
+
+#define HDA_REG_CORBLBASE 17 /* 0x40 */
+#define HDA_RMX_CORBLBASE 13
+
+#define HDA_REG_CORBUBASE 18 /* 0x44 */
+#define HDA_RMX_CORBUBASE 14
+
+#define HDA_REG_CORBWP 19 /* 0x48 */
+#define HDA_RMX_CORBWP 15
+
+#define HDA_REG_CORBRP 20 /* 0x4A */
+#define HDA_RMX_CORBRP 16
+#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
+
+#define HDA_REG_CORBCTL 21 /* 0x4C */
+#define HDA_RMX_CORBCTL 17
+#define HDA_CORBCTL_DMA RT_BIT(1) /* Enable CORB DMA Engine */
+#define HDA_CORBCTL_CMEIE RT_BIT(0) /* CORB Memory Error Interrupt Enable */
+
+#define HDA_REG_CORBSTS 22 /* 0x4D */
+#define HDA_RMX_CORBSTS 18
+
+#define HDA_REG_CORBSIZE 23 /* 0x4E */
+#define HDA_RMX_CORBSIZE 19
+#define HDA_CORBSIZE_SZ_CAP 0xF0
+#define HDA_CORBSIZE_SZ 0x3
+
+/** Number of CORB buffer entries. */
+#define HDA_CORB_SIZE 256
+/** CORB element size (in bytes). */
+#define HDA_CORB_ELEMENT_SIZE 4
+/** Number of RIRB buffer entries. */
+#define HDA_RIRB_SIZE 256
+/** RIRB element size (in bytes). */
+#define HDA_RIRB_ELEMENT_SIZE 8
+
+#define HDA_REG_RIRBLBASE 24 /* 0x50 */
+#define HDA_RMX_RIRBLBASE 20
+
+#define HDA_REG_RIRBUBASE 25 /* 0x54 */
+#define HDA_RMX_RIRBUBASE 21
+
+#define HDA_REG_RIRBWP 26 /* 0x58 */
+#define HDA_RMX_RIRBWP 22
+#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
+
+#define HDA_REG_RINTCNT 27 /* 0x5A */
+#define HDA_RMX_RINTCNT 23
+
+/** Maximum number of Response Interrupts. */
+#define HDA_MAX_RINTCNT 256
+
+#define HDA_REG_RIRBCTL 28 /* 0x5C */
+#define HDA_RMX_RIRBCTL 24
+#define HDA_RIRBCTL_ROIC RT_BIT(2) /* Response Overrun Interrupt Control */
+#define HDA_RIRBCTL_RDMAEN RT_BIT(1) /* RIRB DMA Enable */
+#define HDA_RIRBCTL_RINTCTL RT_BIT(0) /* Response Interrupt Control */
+
+#define HDA_REG_RIRBSTS 29 /* 0x5D */
+#define HDA_RMX_RIRBSTS 25
+#define HDA_RIRBSTS_RIRBOIS RT_BIT(2) /* Response Overrun Interrupt Status */
+#define HDA_RIRBSTS_RINTFL RT_BIT(0) /* Response Interrupt Flag */
+
+#define HDA_REG_RIRBSIZE 30 /* 0x5E */
+#define HDA_RMX_RIRBSIZE 26
+
+#define HDA_REG_IC 31 /* 0x60 */
+#define HDA_RMX_IC 27
+
+#define HDA_REG_IR 32 /* 0x64 */
+#define HDA_RMX_IR 28
+
+#define HDA_REG_IRS 33 /* 0x68 */
+#define HDA_RMX_IRS 29
+#define HDA_IRS_IRV RT_BIT(1) /* Immediate Result Valid */
+#define HDA_IRS_ICB RT_BIT(0) /* Immediate Command Busy */
+
+#define HDA_REG_DPLBASE 34 /* 0x70 */
+#define HDA_RMX_DPLBASE 30
+
+#define HDA_REG_DPUBASE 35 /* 0x74 */
+#define HDA_RMX_DPUBASE 31
+
+#define DPBASE_ADDR_MASK (~(uint64_t)0x7f)
+
+#define HDA_STREAM_REG_DEF(name, num) (HDA_REG_SD##num##name)
+#define HDA_STREAM_RMX_DEF(name, num) (HDA_RMX_SD##num##name)
+/** @note sdnum here _MUST_ be stream reg number [0,7]. */
+#if defined(VBOX_STRICT) && defined(VBOX_HDA_CAN_ACCESS_REG_MAP)
+# define HDA_STREAM_REG(pThis, name, sdnum) (*hdaStrictStreamRegAccessor((pThis), HDA_REG_SD0##name, HDA_RMX_SD0##name, (sdnum)))
+#else
+# define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_BY_IDX((pThis), HDA_RMX_SD0##name + (sdnum) * 10))
+#endif
+
+#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 10)
+#define HDA_SD_TO_REG(a_Name, uSD) (HDA_STREAM_REG_DEF(a_Name, 0) + (uSD) * 10)
+
+/** @todo Condense marcos! */
+
+#define HDA_REG_SD0CTL HDA_NUM_GENERAL_REGS /* 0x80; other streams offset by 0x20 */
+#define HDA_RMX_SD0CTL 32
+#define HDA_RMX_SD1CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 10)
+#define HDA_RMX_SD2CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 20)
+#define HDA_RMX_SD3CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 30)
+#define HDA_RMX_SD4CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 40)
+#define HDA_RMX_SD5CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 50)
+#define HDA_RMX_SD6CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 60)
+#define HDA_RMX_SD7CTL (HDA_STREAM_RMX_DEF(CTL, 0) + 70)
+
+#define HDA_SDCTL_NUM_MASK 0xF
+#define HDA_SDCTL_NUM_SHIFT 20
+#define HDA_SDCTL_DIR RT_BIT(19) /* Direction (Bidirectional streams only!) */
+#define HDA_SDCTL_TP RT_BIT(18) /* Traffic Priority (PCI Express) */
+#define HDA_SDCTL_STRIPE_MASK 0x3
+#define HDA_SDCTL_STRIPE_SHIFT 16
+#define HDA_SDCTL_DEIE RT_BIT(4) /* Descriptor Error Interrupt Enable */
+#define HDA_SDCTL_FEIE RT_BIT(3) /* FIFO Error Interrupt Enable */
+#define HDA_SDCTL_IOCE RT_BIT(2) /* Interrupt On Completion Enable */
+#define HDA_SDCTL_RUN RT_BIT(1) /* Stream Run */
+#define HDA_SDCTL_SRST RT_BIT(0) /* Stream Reset */
+
+#define HDA_REG_SD0STS (HDA_NUM_GENERAL_REGS + 1) /* 0x83; other streams offset by 0x20 */
+#define HDA_RMX_SD0STS 33
+#define HDA_RMX_SD1STS (HDA_STREAM_RMX_DEF(STS, 0) + 10)
+#define HDA_RMX_SD2STS (HDA_STREAM_RMX_DEF(STS, 0) + 20)
+#define HDA_RMX_SD3STS (HDA_STREAM_RMX_DEF(STS, 0) + 30)
+#define HDA_RMX_SD4STS (HDA_STREAM_RMX_DEF(STS, 0) + 40)
+#define HDA_RMX_SD5STS (HDA_STREAM_RMX_DEF(STS, 0) + 50)
+#define HDA_RMX_SD6STS (HDA_STREAM_RMX_DEF(STS, 0) + 60)
+#define HDA_RMX_SD7STS (HDA_STREAM_RMX_DEF(STS, 0) + 70)
+
+#define HDA_SDSTS_FIFORDY RT_BIT(5) /* FIFO Ready */
+#define HDA_SDSTS_DESE RT_BIT(4) /* Descriptor Error */
+#define HDA_SDSTS_FIFOE RT_BIT(3) /* FIFO Error */
+#define HDA_SDSTS_BCIS RT_BIT(2) /* Buffer Completion Interrupt Status */
+
+#define HDA_REG_SD0LPIB (HDA_NUM_GENERAL_REGS + 2) /* 0x84; other streams offset by 0x20 */
+#define HDA_REG_SD1LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
+#define HDA_REG_SD2LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
+#define HDA_REG_SD3LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
+#define HDA_REG_SD4LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
+#define HDA_REG_SD5LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
+#define HDA_REG_SD6LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
+#define HDA_REG_SD7LPIB (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
+#define HDA_RMX_SD0LPIB 34
+#define HDA_RMX_SD1LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 10)
+#define HDA_RMX_SD2LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 20)
+#define HDA_RMX_SD3LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 30)
+#define HDA_RMX_SD4LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 40)
+#define HDA_RMX_SD5LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 50)
+#define HDA_RMX_SD6LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 60)
+#define HDA_RMX_SD7LPIB (HDA_STREAM_RMX_DEF(LPIB, 0) + 70)
+
+#define HDA_REG_SD0CBL (HDA_NUM_GENERAL_REGS + 3) /* 0x88; other streams offset by 0x20 */
+#define HDA_RMX_SD0CBL 35
+#define HDA_RMX_SD1CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 10)
+#define HDA_RMX_SD2CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 20)
+#define HDA_RMX_SD3CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 30)
+#define HDA_RMX_SD4CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 40)
+#define HDA_RMX_SD5CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 50)
+#define HDA_RMX_SD6CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 60)
+#define HDA_RMX_SD7CBL (HDA_STREAM_RMX_DEF(CBL, 0) + 70)
+
+#define HDA_REG_SD0LVI (HDA_NUM_GENERAL_REGS + 4) /* 0x8C; other streams offset by 0x20 */
+#define HDA_RMX_SD0LVI 36
+#define HDA_RMX_SD1LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 10)
+#define HDA_RMX_SD2LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 20)
+#define HDA_RMX_SD3LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 30)
+#define HDA_RMX_SD4LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 40)
+#define HDA_RMX_SD5LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 50)
+#define HDA_RMX_SD6LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 60)
+#define HDA_RMX_SD7LVI (HDA_STREAM_RMX_DEF(LVI, 0) + 70)
+
+#define HDA_REG_SD0FIFOW (HDA_NUM_GENERAL_REGS + 5) /* 0x8E; other streams offset by 0x20 */
+#define HDA_RMX_SD0FIFOW 37
+#define HDA_RMX_SD1FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 10)
+#define HDA_RMX_SD2FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 20)
+#define HDA_RMX_SD3FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 30)
+#define HDA_RMX_SD4FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 40)
+#define HDA_RMX_SD5FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 50)
+#define HDA_RMX_SD6FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 60)
+#define HDA_RMX_SD7FIFOW (HDA_STREAM_RMX_DEF(FIFOW, 0) + 70)
+
+/*
+ * ICH6 datasheet defined limits for FIFOW values (18.2.38).
+ */
+#define HDA_SDFIFOW_8B 0x2
+#define HDA_SDFIFOW_16B 0x3
+#define HDA_SDFIFOW_32B 0x4
+
+#define HDA_REG_SD0FIFOS (HDA_NUM_GENERAL_REGS + 6) /* 0x90; other streams offset by 0x20 */
+#define HDA_RMX_SD0FIFOS 38
+#define HDA_RMX_SD1FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 10)
+#define HDA_RMX_SD2FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 20)
+#define HDA_RMX_SD3FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 30)
+#define HDA_RMX_SD4FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 40)
+#define HDA_RMX_SD5FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 50)
+#define HDA_RMX_SD6FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 60)
+#define HDA_RMX_SD7FIFOS (HDA_STREAM_RMX_DEF(FIFOS, 0) + 70)
+
+/* The ICH6 datasheet defines limits for FIFOS registers (18.2.39).
+ Formula: size - 1
+ Other values not listed are not supported. */
+
+#define HDA_SDIFIFO_120B 0x77 /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
+#define HDA_SDIFIFO_160B 0x9F /* 20-, 24-bit Input Streams Streams */
+
+#define HDA_SDOFIFO_16B 0x0F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDOFIFO_32B 0x1F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDOFIFO_64B 0x3F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDOFIFO_128B 0x7F /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDOFIFO_192B 0xBF /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDOFIFO_256B 0xFF /* 20-, 24-bit Output Streams */
+
+#define HDA_REG_SD0FMT (HDA_NUM_GENERAL_REGS + 7) /* 0x92; other streams offset by 0x20 */
+#define HDA_RMX_SD0FMT 39
+#define HDA_RMX_SD1FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 10)
+#define HDA_RMX_SD2FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 20)
+#define HDA_RMX_SD3FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 30)
+#define HDA_RMX_SD4FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 40)
+#define HDA_RMX_SD5FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 50)
+#define HDA_RMX_SD6FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 60)
+#define HDA_RMX_SD7FMT (HDA_STREAM_RMX_DEF(FMT, 0) + 70)
+
+#define HDA_REG_SD0BDPL (HDA_NUM_GENERAL_REGS + 8) /* 0x98; other streams offset by 0x20 */
+#define HDA_RMX_SD0BDPL 40
+#define HDA_RMX_SD1BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 10)
+#define HDA_RMX_SD2BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 20)
+#define HDA_RMX_SD3BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 30)
+#define HDA_RMX_SD4BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 40)
+#define HDA_RMX_SD5BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 50)
+#define HDA_RMX_SD6BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 60)
+#define HDA_RMX_SD7BDPL (HDA_STREAM_RMX_DEF(BDPL, 0) + 70)
+
+#define HDA_REG_SD0BDPU (HDA_NUM_GENERAL_REGS + 9) /* 0x9C; other streams offset by 0x20 */
+#define HDA_RMX_SD0BDPU 41
+#define HDA_RMX_SD1BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 10)
+#define HDA_RMX_SD2BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 20)
+#define HDA_RMX_SD3BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 30)
+#define HDA_RMX_SD4BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 40)
+#define HDA_RMX_SD5BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 50)
+#define HDA_RMX_SD6BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 60)
+#define HDA_RMX_SD7BDPU (HDA_STREAM_RMX_DEF(BDPU, 0) + 70)
+
+#define HDA_CODEC_CAD_SHIFT 28
+/** Encodes the (required) LUN into a codec command. */
+#define HDA_CODEC_CMD(cmd, lun) ((cmd) | (lun << HDA_CODEC_CAD_SHIFT))
+
+#define HDA_SDFMT_NON_PCM_SHIFT 15
+#define HDA_SDFMT_NON_PCM_MASK 0x1
+#define HDA_SDFMT_BASE_RATE_SHIFT 14
+#define HDA_SDFMT_BASE_RATE_MASK 0x1
+#define HDA_SDFMT_MULT_SHIFT 11
+#define HDA_SDFMT_MULT_MASK 0x7
+#define HDA_SDFMT_DIV_SHIFT 8
+#define HDA_SDFMT_DIV_MASK 0x7
+#define HDA_SDFMT_BITS_SHIFT 4
+#define HDA_SDFMT_BITS_MASK 0x7
+#define HDA_SDFMT_CHANNELS_MASK 0xF
+
+#define HDA_SDFMT_TYPE RT_BIT(15)
+#define HDA_SDFMT_TYPE_PCM (0)
+#define HDA_SDFMT_TYPE_NON_PCM (1)
+
+#define HDA_SDFMT_BASE RT_BIT(14)
+#define HDA_SDFMT_BASE_48KHZ (0)
+#define HDA_SDFMT_BASE_44KHZ (1)
+
+#define HDA_SDFMT_MULT_1X (0)
+#define HDA_SDFMT_MULT_2X (1)
+#define HDA_SDFMT_MULT_3X (2)
+#define HDA_SDFMT_MULT_4X (3)
+
+#define HDA_SDFMT_DIV_1X (0)
+#define HDA_SDFMT_DIV_2X (1)
+#define HDA_SDFMT_DIV_3X (2)
+#define HDA_SDFMT_DIV_4X (3)
+#define HDA_SDFMT_DIV_5X (4)
+#define HDA_SDFMT_DIV_6X (5)
+#define HDA_SDFMT_DIV_7X (6)
+#define HDA_SDFMT_DIV_8X (7)
+
+#define HDA_SDFMT_8_BIT (0)
+#define HDA_SDFMT_16_BIT (1)
+#define HDA_SDFMT_20_BIT (2)
+#define HDA_SDFMT_24_BIT (3)
+#define HDA_SDFMT_32_BIT (4)
+
+#define HDA_SDFMT_CHAN_MONO (0)
+#define HDA_SDFMT_CHAN_STEREO (1)
+
+/** Emits a SDnFMT register format.
+ * Also being used in the codec's converter format. */
+#define HDA_SDFMT_MAKE(_afNonPCM, _aBaseRate, _aMult, _aDiv, _aBits, _aChan) \
+ ( (((_afNonPCM) & HDA_SDFMT_NON_PCM_MASK) << HDA_SDFMT_NON_PCM_SHIFT) \
+ | (((_aBaseRate) & HDA_SDFMT_BASE_RATE_MASK) << HDA_SDFMT_BASE_RATE_SHIFT) \
+ | (((_aMult) & HDA_SDFMT_MULT_MASK) << HDA_SDFMT_MULT_SHIFT) \
+ | (((_aDiv) & HDA_SDFMT_DIV_MASK) << HDA_SDFMT_DIV_SHIFT) \
+ | (((_aBits) & HDA_SDFMT_BITS_MASK) << HDA_SDFMT_BITS_SHIFT) \
+ | ( (_aChan) & HDA_SDFMT_CHANNELS_MASK))
+
+
+/* Post stream registers: */
+#define HDA_REG_MLCH (HDA_NUM_GENERAL_REGS + HDA_NUM_STREAM_REGS) /* 0xc00 */
+#define HDA_RMX_MLCH 115
+#define HDA_REG_MLCD (HDA_REG_MLCH + 1) /* 0xc04 */
+#define HDA_RMX_MLCD 116
+
+/* Registers added/specific-to skylake/broxton: */
+#define HDA_SD_NUM_FROM_SKYLAKE_REG(a_Name, a_iMap) (((a_iMap) - HDA_STREAM_REG_DEF(a_Name, 0)) / 2)
+
+#define HDA_REG_SD0DPIB (HDA_REG_MLCD + 1) /* 0x1084 */
+#define HDA_REG_SD1DPIB (HDA_REG_SD0DPIB + 1*2)
+#define HDA_REG_SD2DPIB (HDA_REG_SD0DPIB + 2*2)
+#define HDA_REG_SD3DPIB (HDA_REG_SD0DPIB + 3*2)
+#define HDA_REG_SD4DPIB (HDA_REG_SD0DPIB + 4*2)
+#define HDA_REG_SD5DPIB (HDA_REG_SD0DPIB + 5*2)
+#define HDA_REG_SD6DPIB (HDA_REG_SD0DPIB + 6*2)
+#define HDA_REG_SD7DPIB (HDA_REG_SD0DPIB + 7*2)
+
+#define HDA_RMX_SD0DPIB HDA_RMX_SD0LPIB
+#define HDA_RMX_SD1DPIB HDA_RMX_SD1LPIB
+#define HDA_RMX_SD2DPIB HDA_RMX_SD2LPIB
+#define HDA_RMX_SD3DPIB HDA_RMX_SD3LPIB
+#define HDA_RMX_SD4DPIB HDA_RMX_SD4LPIB
+#define HDA_RMX_SD5DPIB HDA_RMX_SD5LPIB
+#define HDA_RMX_SD6DPIB HDA_RMX_SD6LPIB
+#define HDA_RMX_SD7DPIB HDA_RMX_SD7LPIB
+
+#define HDA_REG_SD0EFIFOS (HDA_REG_SD0DPIB + 1) /* 0x1094 */
+#define HDA_REG_SD1EFIFOS (HDA_REG_SD0EFIFOS + 1*2)
+#define HDA_REG_SD2EFIFOS (HDA_REG_SD0EFIFOS + 2*2)
+#define HDA_REG_SD3EFIFOS (HDA_REG_SD0EFIFOS + 3*2)
+#define HDA_REG_SD4EFIFOS (HDA_REG_SD0EFIFOS + 4*2)
+#define HDA_REG_SD5EFIFOS (HDA_REG_SD0EFIFOS + 5*2)
+#define HDA_REG_SD6EFIFOS (HDA_REG_SD0EFIFOS + 6*2)
+#define HDA_REG_SD7EFIFOS (HDA_REG_SD0EFIFOS + 7*2)
+
+#define HDA_RMX_SD0EFIFOS 117
+#define HDA_RMX_SD1EFIFOS (HDA_RMX_SD0EFIFOS + 1)
+#define HDA_RMX_SD2EFIFOS (HDA_RMX_SD0EFIFOS + 2)
+#define HDA_RMX_SD3EFIFOS (HDA_RMX_SD0EFIFOS + 3)
+#define HDA_RMX_SD4EFIFOS (HDA_RMX_SD0EFIFOS + 4)
+#define HDA_RMX_SD5EFIFOS (HDA_RMX_SD0EFIFOS + 5)
+#define HDA_RMX_SD6EFIFOS (HDA_RMX_SD0EFIFOS + 6)
+#define HDA_RMX_SD7EFIFOS (HDA_RMX_SD0EFIFOS + 7)
+
+/** @} */ /* grp_hda_regs */
+
+
+/**
+ * Buffer descriptor list entry (BDLE).
+ *
+ * See 3.6.3 in HDA specs rev 1.0a (2010-06-17).
+ */
+typedef struct HDABDLEDESC
+{
+ /** Starting address of the actual buffer. Must be 128-bit aligned. */
+ uint64_t u64BufAddr;
+ /** Size of the actual buffer (in bytes). */
+ uint32_t u32BufSize;
+ /** HDA_BDLE_F_XXX.
+ *
+ * Bit 0: IOC - Interrupt on completion / HDA_BDLE_F_IOC.
+ * The controller will generate an interrupt when the last byte of the buffer
+ * has been fetched by the DMA engine.
+ *
+ * Bits 31:1 are reserved for further use and must be 0. */
+ uint32_t fFlags;
+} HDABDLEDESC, *PHDABDLEDESC;
+AssertCompileSize(HDABDLEDESC, 16); /* Always 16 byte. Also must be aligned on 128-byte boundary. */
+
+/** Interrupt on completion (IOC) flag. */
+#define HDA_BDLE_F_IOC RT_BIT(0)
+
+
+/**
+ * HDA mixer sink definition (ring-3).
+ *
+ * Its purpose is to know which audio mixer sink is bound to which SDn
+ * (SDI/SDO) device stream.
+ *
+ * This is needed in order to handle interleaved streams (that is, multiple
+ * channels in one stream) or non-interleaved streams (each channel has a
+ * dedicated stream).
+ *
+ * This is only known to the actual device emulation level.
+ */
+typedef struct HDAMIXERSINK
+{
+ R3PTRTYPE(PHDASTREAM) pStreamShared;
+ R3PTRTYPE(PHDASTREAMR3) pStreamR3;
+ /** Pointer to the actual audio mixer sink. */
+ R3PTRTYPE(PAUDMIXSINK) pMixSink;
+} HDAMIXERSINK;
+
+/**
+ * Mapping a stream tag to an HDA stream (ring-3).
+ */
+typedef struct HDATAG
+{
+ /** Own stream tag. */
+ uint8_t uTag;
+ uint8_t Padding[7];
+ /** Pointer to associated stream. */
+ R3PTRTYPE(PHDASTREAMR3) pStreamR3;
+} HDATAG;
+/** Pointer to a HDA stream tag mapping. */
+typedef HDATAG *PHDATAG;
+
+/**
+ * Shared ICH Intel HD audio controller state.
+ */
+typedef struct HDASTATE
+{
+ /** Critical section protecting the HDA state. */
+ PDMCRITSECT CritSect;
+ /** Internal stream states (aligned on 64 byte boundrary). */
+ HDASTREAM aStreams[HDA_MAX_STREAMS];
+ /** The HDA's register set. */
+ uint32_t au32Regs[HDA_NUM_REGS];
+ /** CORB buffer base address. */
+ uint64_t u64CORBBase;
+ /** RIRB buffer base address. */
+ uint64_t u64RIRBBase;
+ /** DMA base address.
+ * Made out of DPLBASE + DPUBASE (3.3.32 + 3.3.33). */
+ uint64_t u64DPBase;
+ /** Size in bytes of CORB buffer (#au32CorbBuf). */
+ uint32_t cbCorbBuf;
+ /** Size in bytes of RIRB buffer (#au64RirbBuf). */
+ uint32_t cbRirbBuf;
+ /** Response Interrupt Count (RINTCNT). */
+ uint16_t u16RespIntCnt;
+ /** DMA position buffer enable bit. */
+ bool fDMAPosition;
+ /** Current IRQ level. */
+ uint8_t u8IRQL;
+ /** Config: Internal input DMA buffer size override, specified in milliseconds.
+ * Zero means default size according to buffer and stream config.
+ * @sa BufSizeInMs config value. */
+ uint16_t cMsCircBufIn;
+ /** Config: Internal output DMA buffer size override, specified in milliseconds.
+ * Zero means default size according to buffer and stream config.
+ * @sa BufSizeOutMs config value. */
+ uint16_t cMsCircBufOut;
+ /** The start time of the wall clock (WALCLK), measured on the virtual sync clock. */
+ uint64_t tsWalClkStart;
+ /** CORB DMA task handle.
+ * We use this when there is stuff we cannot handle in ring-0. */
+ PDMTASKHANDLE hCorbDmaTask;
+ /** The CORB buffer. */
+ uint32_t au32CorbBuf[HDA_CORB_SIZE];
+ /** Pointer to RIRB buffer. */
+ uint64_t au64RirbBuf[HDA_RIRB_SIZE];
+
+ /** PCI Region \#0: 16KB of MMIO stuff. */
+ IOMMMIOHANDLE hMmio;
+
+#ifdef VBOX_HDA_WITH_ON_REG_ACCESS_DMA
+ STAMCOUNTER StatAccessDmaOutput;
+ STAMCOUNTER StatAccessDmaOutputToR3;
+#endif
+#ifdef VBOX_WITH_STATISTICS
+ STAMPROFILE StatIn;
+ STAMPROFILE StatOut;
+ STAMCOUNTER StatBytesRead;
+ STAMCOUNTER StatBytesWritten;
+
+ /** @name Register statistics.
+ * The array members run parallel to g_aHdaRegMap.
+ * @{ */
+ STAMCOUNTER aStatRegReads[HDA_NUM_REGS];
+ STAMCOUNTER aStatRegReadsToR3[HDA_NUM_REGS];
+ STAMCOUNTER aStatRegWrites[HDA_NUM_REGS];
+ STAMCOUNTER aStatRegWritesToR3[HDA_NUM_REGS];
+ STAMCOUNTER StatRegMultiReadsRZ;
+ STAMCOUNTER StatRegMultiReadsR3;
+ STAMCOUNTER StatRegMultiWritesRZ;
+ STAMCOUNTER StatRegMultiWritesR3;
+ STAMCOUNTER StatRegSubWriteRZ;
+ STAMCOUNTER StatRegSubWriteR3;
+ STAMCOUNTER StatRegUnknownReads;
+ STAMCOUNTER StatRegUnknownWrites;
+ STAMCOUNTER StatRegWritesBlockedByReset;
+ STAMCOUNTER StatRegWritesBlockedByRun;
+ /** @} */
+#endif
+
+#ifdef DEBUG
+ /** Debug stuff.
+ * @todo Make STAM values out some of this? */
+ struct
+ {
+# if 0 /* unused */
+ /** Timestamp (in ns) of the last timer callback (hdaTimer).
+ * Used to calculate the time actually elapsed between two timer callbacks. */
+ uint64_t tsTimerLastCalledNs;
+# endif
+ /** IRQ debugging information. */
+ struct
+ {
+ /** Timestamp (in ns) of last processed (asserted / deasserted) IRQ. */
+ uint64_t tsProcessedLastNs;
+ /** Timestamp (in ns) of last asserted IRQ. */
+ uint64_t tsAssertedNs;
+# if 0 /* unused */
+ /** How many IRQs have been asserted already. */
+ uint64_t cAsserted;
+ /** Accumulated elapsed time (in ns) of all IRQ being asserted. */
+ uint64_t tsAssertedTotalNs;
+ /** Timestamp (in ns) of last deasserted IRQ. */
+ uint64_t tsDeassertedNs;
+ /** How many IRQs have been deasserted already. */
+ uint64_t cDeasserted;
+ /** Accumulated elapsed time (in ns) of all IRQ being deasserted. */
+ uint64_t tsDeassertedTotalNs;
+# endif
+ } IRQ;
+ } Dbg;
+#endif
+ /** This is for checking that the build was correctly configured in all contexts.
+ * This is set to HDASTATE_ALIGNMENT_CHECK_MAGIC. */
+ uint64_t uAlignmentCheckMagic;
+} HDASTATE;
+AssertCompileMemberAlignment(HDASTATE, aStreams, 64);
+/** Pointer to a shared HDA device state. */
+typedef HDASTATE *PHDASTATE;
+
+/** Value for HDASTATE:uAlignmentCheckMagic. */
+#define HDASTATE_ALIGNMENT_CHECK_MAGIC UINT64_C(0x1298afb75893e059)
+
+/**
+ * Ring-0 ICH Intel HD audio controller state.
+ */
+typedef struct HDASTATER0
+{
+# if 0 /* Codec is not yet kosher enough for ring-0. @bugref{9890c64} */
+ /** Pointer to HDA codec to use. */
+ HDACODECR0 Codec;
+# else
+ uint32_t u32Dummy;
+# endif
+} HDASTATER0;
+/** Pointer to a ring-0 HDA device state. */
+typedef HDASTATER0 *PHDASTATER0;
+
+/**
+ * Ring-3 ICH Intel HD audio controller state.
+ */
+typedef struct HDASTATER3
+{
+ /** Internal stream states. */
+ HDASTREAMR3 aStreams[HDA_MAX_STREAMS];
+ /** Mapping table between stream tags and stream states. */
+ HDATAG aTags[HDA_MAX_TAGS];
+ /** R3 Pointer to the device instance. */
+ PPDMDEVINSR3 pDevIns;
+ /** The base interface for LUN\#0. */
+ PDMIBASE IBase;
+ /** List of associated LUN drivers (HDADRIVER). */
+ RTLISTANCHORR3 lstDrv;
+ /** The device' software mixer. */
+ R3PTRTYPE(PAUDIOMIXER) pMixer;
+ /** HDA sink for (front) output. */
+ HDAMIXERSINK SinkFront;
+#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
+ /** HDA sink for center / LFE output. */
+ HDAMIXERSINK SinkCenterLFE;
+ /** HDA sink for rear output. */
+ HDAMIXERSINK SinkRear;
+#endif
+ /** HDA mixer sink for line input. */
+ HDAMIXERSINK SinkLineIn;
+#ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+ /** Audio mixer sink for microphone input. */
+ HDAMIXERSINK SinkMicIn;
+#endif
+ /** Debug stuff. */
+ struct
+ {
+ /** Whether debugging is enabled or not. */
+ bool fEnabled;
+ /** Path where to dump the debug output to.
+ * Can be NULL, in which the system's temporary directory will be used then. */
+ R3PTRTYPE(char *) pszOutPath;
+ } Dbg;
+ /** Align the codec state on a cache line. */
+ uint64_t au64Padding[3];
+ /** The HDA codec state. */
+ HDACODECR3 Codec;
+} HDASTATER3;
+AssertCompileMemberAlignment(HDASTATER3, Codec, 64);
+
+
+/** Pointer to the context specific HDA state (HDASTATER3 or HDASTATER0). */
+typedef CTX_SUFF(PHDASTATE) PHDASTATECC;
+
+
+/** @def HDA_PROCESS_INTERRUPT
+ * Wrapper around hdaProcessInterrupt that supplies the source function name
+ * string in logging builds. */
+#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
+void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource);
+# define HDA_PROCESS_INTERRUPT(a_pDevIns, a_pThis) hdaProcessInterrupt((a_pDevIns), (a_pThis), __FUNCTION__)
+#else
+void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis);
+# define HDA_PROCESS_INTERRUPT(a_pDevIns, a_pThis) hdaProcessInterrupt((a_pDevIns), (a_pThis))
+#endif
+
+/**
+ * Returns the audio direction of a specified stream descriptor.
+ *
+ * The register layout specifies that input streams (SDI) come first,
+ * followed by the output streams (SDO). So every stream ID below HDA_MAX_SDI
+ * is an input stream, whereas everything >= HDA_MAX_SDI is an output stream.
+ *
+ * @note SDnFMT register does not provide that information, so we have to judge
+ * for ourselves.
+ *
+ * @return Audio direction.
+ * @param uSD The stream number.
+ */
+DECLINLINE(PDMAUDIODIR) hdaGetDirFromSD(uint8_t uSD)
+{
+ if (uSD < HDA_MAX_SDI)
+ return PDMAUDIODIR_IN;
+ AssertReturn(uSD < HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
+ return PDMAUDIODIR_OUT;
+}
+
+/* Used by hdaR3StreamSetUp: */
+uint8_t hdaSDFIFOWToBytes(uint16_t u16RegFIFOW);
+
+#if defined(VBOX_STRICT) && defined(VBOX_HDA_CAN_ACCESS_REG_MAP)
+/* Only in DevHda.cpp: */
+DECLINLINE(uint32_t *) hdaStrictRegAccessor(PHDASTATE pThis, uint32_t idxMap, uint32_t idxReg);
+DECLINLINE(uint32_t *) hdaStrictStreamRegAccessor(PHDASTATE pThis, uint32_t idxMap0, uint32_t idxReg0, size_t idxStream);
+#endif /* VBOX_STRICT && VBOX_HDA_CAN_ACCESS_REG_MAP */
+
+
+/** @name HDA device functions used by the codec.
+ * @{ */
+DECLHIDDEN(int) hdaR3MixerAddStream(PHDACODECR3 pCodec, PDMAUDIOMIXERCTL enmMixerCtl, PCPDMAUDIOSTREAMCFG pCfg);
+DECLHIDDEN(int) hdaR3MixerRemoveStream(PHDACODECR3 pCodec, PDMAUDIOMIXERCTL enmMixerCtl, bool fImmediate);
+DECLHIDDEN(int) hdaR3MixerControl(PHDACODECR3 pCodec, PDMAUDIOMIXERCTL enmMixerCtl, uint8_t uSD, uint8_t uChannel);
+DECLHIDDEN(int) hdaR3MixerSetVolume(PHDACODECR3 pCodec, PDMAUDIOMIXERCTL enmMixerCtl, PPDMAUDIOVOLUME pVol);
+/** @} */
+
+
+/** @name Saved state versions for the HDA device
+ * @{ */
+/** The current staved state version.
+ * @note Only for the registration call. Never used for tests. */
+#define HDA_SAVED_STATE_VERSION HDA_SAVED_STATE_WITHOUT_PERIOD
+
+/** Removed period and redefined wall clock. */
+#define HDA_SAVED_STATE_WITHOUT_PERIOD 8
+/** Added (Controller): Current wall clock value (this independent from WALCLK register value).
+ * Added (Controller): Current IRQ level.
+ * Added (Per stream): Ring buffer. This is optional and can be skipped if (not) needed.
+ * Added (Per stream): Struct g_aSSMStreamStateFields7.
+ * Added (Per stream): Struct g_aSSMStreamPeriodFields7.
+ * Added (Current BDLE per stream): Struct g_aSSMBDLEDescFields7.
+ * Added (Current BDLE per stream): Struct g_aSSMBDLEStateFields7. */
+#define HDA_SAVED_STATE_VERSION_7 7
+/** Saves the current BDLE state.
+ * @since 5.0.14 (r104839) */
+#define HDA_SAVED_STATE_VERSION_6 6
+/** Introduced dynamic number of streams + stream identifiers for serialization.
+ * Bug: Did not save the BDLE states correctly.
+ * Those will be skipped on load then.
+ * @since 5.0.12 (r104520) */
+#define HDA_SAVED_STATE_VERSION_5 5
+/** Since this version the number of MMIO registers can be flexible. */
+#define HDA_SAVED_STATE_VERSION_4 4
+#define HDA_SAVED_STATE_VERSION_3 3
+#define HDA_SAVED_STATE_VERSION_2 2
+#define HDA_SAVED_STATE_VERSION_1 1
+/** @} */
+
+#endif /* !VBOX_INCLUDED_SRC_Audio_DevHda_h */
+