summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Audio
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2021-06-24 12:30:53 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2021-06-24 12:30:53 +0000
commit0705eb11f4ae371f6a36deb7ffd5a4e07d338c67 (patch)
tree81decaf6bc5f0a4a8c178f1d38d19948d863c979 /src/VBox/Devices/Audio
parent891b234764b207fd6124500ed04501522c9e5083 (diff)
downloadVirtualBox-svn-0705eb11f4ae371f6a36deb7ffd5a4e07d338c67.tar.gz
DevHda: Merged DevHdaCommon.h into DevHda.h and mostly likewise with the corresponding code. bugref:9890
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@89887 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src/VBox/Devices/Audio')
-rw-r--r--src/VBox/Devices/Audio/DevHda.cpp135
-rw-r--r--src/VBox/Devices/Audio/DevHda.h530
-rw-r--r--src/VBox/Devices/Audio/DevHdaCodec.cpp2
-rw-r--r--src/VBox/Devices/Audio/DevHdaCommon.cpp373
-rw-r--r--src/VBox/Devices/Audio/DevHdaCommon.h591
-rw-r--r--src/VBox/Devices/Audio/DevHdaStream.cpp159
-rw-r--r--src/VBox/Devices/Audio/DevHdaStream.h8
7 files changed, 822 insertions, 976 deletions
diff --git a/src/VBox/Devices/Audio/DevHda.cpp b/src/VBox/Devices/Audio/DevHda.cpp
index b3c975fce60..2f1c4deaf5c 100644
--- a/src/VBox/Devices/Audio/DevHda.cpp
+++ b/src/VBox/Devices/Audio/DevHda.cpp
@@ -400,7 +400,17 @@ const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS] =
HDA_REG_MAP_DEF_STREAM(7, SD7)
};
-const HDAREGALIAS g_aHdaRegAliases[] =
+/**
+ * HDA register aliases (HDA spec 3.3.45).
+ * @remarks Sorted by offReg.
+ */
+static struct HDAREGALIAS
+{
+ /** The alias register offset. */
+ uint32_t offReg;
+ /** The register index. */
+ int idxAlias;
+} const g_aHdaRegAliases[] =
{
{ 0x2030, HDA_REG_WALCLK },
{ 0x2084, HDA_REG_SD0LPIB },
@@ -498,6 +508,94 @@ static uint32_t const g_afMasks[5] =
};
+
+/**
+ * Returns a new INTSTS value based on the current device state.
+ *
+ * @returns Determined INTSTS register value.
+ * @param pThis The shared HDA device state.
+ *
+ * @remarks This function does *not* set INTSTS!
+ */
+static uint32_t hdaGetINTSTS(PHDASTATE pThis)
+{
+ uint32_t intSts = 0;
+
+ /* Check controller interrupts (RIRB, STATEST). */
+ if (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
+ {
+ intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
+ }
+
+ /* Check SDIN State Change Status Flags. */
+ if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
+ {
+ intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */
+ }
+
+ /* For each stream, check if any interrupt status bit is set and enabled. */
+ for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)
+ {
+ if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE | HDA_SDCTL_IOCE))
+ {
+ Log3Func(("[SD%d] interrupt status set\n", iStrm));
+ intSts |= RT_BIT(iStrm);
+ }
+ }
+
+ if (intSts)
+ intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
+
+ Log3Func(("-> 0x%x\n", intSts));
+
+ return intSts;
+}
+
+
+/**
+ * Processes (asserts/deasserts) the HDA interrupt according to the current state.
+ *
+ * @param pDevIns The device instance.
+ * @param pThis The shared HDA device state.
+ * @param pszSource Caller information.
+ */
+#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
+void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource)
+#else
+void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis)
+#endif
+{
+ uint32_t uIntSts = hdaGetINTSTS(pThis);
+
+ HDA_REG(pThis, INTSTS) = uIntSts;
+
+ /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
+ * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
+ */
+ /* Global Interrupt Enable (GIE) set? */
+ if ( (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
+ && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))
+ {
+ Log3Func(("Asserted (%s)\n", pszSource));
+
+ PDMDevHlpPCISetIrq(pDevIns, 0, 1 /* Assert */);
+ pThis->u8IRQL = 1;
+
+#ifdef DEBUG
+ pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
+ pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
+#endif
+ }
+ else
+ {
+ Log3Func(("Deasserted (%s)\n", pszSource));
+
+ PDMDevHlpPCISetIrq(pDevIns, 0, 0 /* Deassert */);
+ pThis->u8IRQL = 0;
+ }
+}
+
+
/**
* Looks up a register at the exact offset given by @a offReg.
*
@@ -1551,6 +1649,29 @@ static VBOXSTRICTRC hdaRegWriteSDLVI(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32
return hdaRegWriteU16(pDevIns, pThis, iReg, u32Value);
}
+/**
+ * Calculates the number of bytes of a FIFOW register.
+ *
+ * @return Number of bytes of a given FIFOW register.
+ * @param u16RegFIFOW FIFOW register to convert.
+ */
+uint8_t hdaSDFIFOWToBytes(uint16_t u16RegFIFOW)
+{
+ uint32_t cb;
+ switch (u16RegFIFOW)
+ {
+ case HDA_SDFIFOW_8B: cb = 8; break;
+ case HDA_SDFIFOW_16B: cb = 16; break;
+ case HDA_SDFIFOW_32B: cb = 32; break;
+ default:
+ AssertFailedStmt(cb = 32); /* Paranoia. */
+ break;
+ }
+
+ Assert(RT_IS_POWER_OF_TWO(cb));
+ return cb;
+}
+
static VBOXSTRICTRC hdaRegWriteSDFIFOW(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
{
size_t const idxStream = HDA_SD_NUM_FROM_REG(pThis, FIFOW, iReg);
@@ -2158,7 +2279,7 @@ static int hdaR3MixerAddDrv(PPDMDEVINS pDevIns, PHDASTATER3 pThisCC, PHDADRIVER
{
int rc = VINF_SUCCESS;
- PHDASTREAM pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkLineIn);
+ PHDASTREAM pStream = pThisCC->SinkLineIn.pStreamShared;
if ( pStream
&& AudioHlpStreamCfgIsValid(&pStream->State.Cfg))
{
@@ -2168,7 +2289,7 @@ static int hdaR3MixerAddDrv(PPDMDEVINS pDevIns, PHDASTATER3 pThisCC, PHDADRIVER
}
# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
- pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkMicIn);
+ pStream = pThisCC->SinkMicIn.pStreamShared;
if ( pStream
&& AudioHlpStreamCfgIsValid(&pStream->State.Cfg))
{
@@ -2178,7 +2299,7 @@ static int hdaR3MixerAddDrv(PPDMDEVINS pDevIns, PHDASTATER3 pThisCC, PHDADRIVER
}
# endif
- pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkFront);
+ pStream = pThisCC->SinkFront.pStreamShared;
if ( pStream
&& AudioHlpStreamCfgIsValid(&pStream->State.Cfg))
{
@@ -2188,7 +2309,7 @@ static int hdaR3MixerAddDrv(PPDMDEVINS pDevIns, PHDASTATER3 pThisCC, PHDADRIVER
}
# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
- pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkCenterLFE);
+ pStream = pThisCC->SinkCenterLFE.pStreamShared;
if ( pStream
&& AudioHlpStreamCfgIsValid(&pStream->State.Cfg))
{
@@ -2197,7 +2318,7 @@ static int hdaR3MixerAddDrv(PPDMDEVINS pDevIns, PHDASTATER3 pThisCC, PHDADRIVER
rc = rc2;
}
- pStream = hdaR3GetSharedStreamFromSink(&pThisCC->SinkRear);
+ pStream = pThisCC->SinkRear.pStreamShared;
if ( pStream
&& AudioHlpStreamCfgIsValid(&pStream->State.Cfg))
{
@@ -4856,7 +4977,7 @@ static DECLCALLBACK(int) hdaR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGM
for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
{
struct HDAREGDESC const *pReg = &g_aHdaRegMap[i];
- struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
+ struct HDAREGDESC const *pNextReg = i + 1 < RT_ELEMENTS(g_aHdaRegMap) ? &g_aHdaRegMap[i + 1] : NULL;
/* binary search order. */
AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
diff --git a/src/VBox/Devices/Audio/DevHda.h b/src/VBox/Devices/Audio/DevHda.h
index 08339d943b1..54a4938fd11 100644
--- a/src/VBox/Devices/Audio/DevHda.h
+++ b/src/VBox/Devices/Audio/DevHda.h
@@ -68,16 +68,506 @@ typedef struct HDASTREAMR3 *PHDASTREAMR3;
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 "DevHdaCommon.h"
#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);
+
+
+/** Number of general registers. */
+#define HDA_NUM_GENERAL_REGS 34
+/** Number of total registers in the HDA's register map. */
+#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
+/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
+#define HDA_MAX_TAGS 16
+
+
+/** Read callback. */
+typedef VBOXSTRICTRC FNHDAREGREAD(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+/** Write callback. */
+typedef VBOXSTRICTRC FNHDAREGWRITE(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+
+/**
+ * HDA register descriptor.
+ */
+typedef struct HDAREGDESC
+{
+ /** Register offset in the register space. */
+ uint32_t offset;
+ /** Size in bytes. Registers of size > 4 are in fact tables. */
+ uint32_t size;
+ /** Readable bits. */
+ uint32_t readable;
+ /** Writable bits. */
+ uint32_t writable;
+ /** Register descriptor (RD) flags of type HDA_RD_F_XXX. These are used to
+ * specify the handling (read/write) policy of the register. */
+ uint32_t fFlags;
+ /** Read callback. */
+ FNHDAREGREAD *pfnRead;
+ /** Write callback. */
+ FNHDAREGWRITE *pfnWrite;
+ /** Index into the register storage array.
+ * @todo r=bird: Bad structure layout. Move up before pfnRead. */
+ uint32_t mem_idx;
+ /** Abbreviated name. */
+ const char *abbrev;
+ /** Descripton. */
+ const char *desc;
+} HDAREGDESC;
+
+extern const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS];
+
+
+/**
+ * ICH6 datasheet defines limits for FIFOS registers (18.2.39).
+ * Formula: size - 1
+ * Other values not listed are not supported.
+ */
+
+/** Offset of the SD0 register map. */
+#define HDA_REG_DESC_SD0_BASE 0x80
+
+/** Turn a short global register name into an memory index and a stringized name. */
+#define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
+
+/** Turns a short stream register name into an memory index and a stringized name. */
+#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
+
+/** Same as above for a register *not* stored in memory. */
+#define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev
+
+/*
+ * NB: Register values stored in memory (au32Regs[]) are indexed through
+ * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
+ * register descriptors in g_aHdaRegMap[] are indexed through the
+ * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
+ *
+ * The au32Regs[] layout is kept unchanged for saved state
+ * compatibility.
+ */
+
+/* Registers */
+#define HDA_REG_IND_NAME(x) HDA_REG_##x
+#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
+#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
+#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
+
+
+#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_OUTSTRMPAY 9 /* 0x18 */
+#define HDA_RMX_OUTSTRMPAY 112
+
+#define HDA_REG_INSTRMPAY 10 /* 0x1a */
+#define HDA_RMX_INSTRMPAY 113
+
+#define HDA_REG_INTCTL 11 /* 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 12 /* 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 13 /* 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.
+ */
+#define HDA_REG_SSYNC 14 /* 0x34 */
+#define HDA_RMX_SSYNC 12
+
+#define HDA_REG_CORBLBASE 15 /* 0x40 */
+#define HDA_RMX_CORBLBASE 13
+
+#define HDA_REG_CORBUBASE 16 /* 0x44 */
+#define HDA_RMX_CORBUBASE 14
+
+#define HDA_REG_CORBWP 17 /* 0x48 */
+#define HDA_RMX_CORBWP 15
+
+#define HDA_REG_CORBRP 18 /* 0x4A */
+#define HDA_RMX_CORBRP 16
+#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
+
+#define HDA_REG_CORBCTL 19 /* 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 20 /* 0x4D */
+#define HDA_RMX_CORBSTS 18
+
+#define HDA_REG_CORBSIZE 21 /* 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 22 /* 0x50 */
+#define HDA_RMX_RIRBLBASE 20
+
+#define HDA_REG_RIRBUBASE 23 /* 0x54 */
+#define HDA_RMX_RIRBUBASE 21
+
+#define HDA_REG_RIRBWP 24 /* 0x58 */
+#define HDA_RMX_RIRBWP 22
+#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
+
+#define HDA_REG_RINTCNT 25 /* 0x5A */
+#define HDA_RMX_RINTCNT 23
+
+/** Maximum number of Response Interrupts. */
+#define HDA_MAX_RINTCNT 256
+
+#define HDA_REG_RIRBCTL 26 /* 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 27 /* 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 28 /* 0x5E */
+#define HDA_RMX_RIRBSIZE 26
+
+#define HDA_REG_IC 29 /* 0x60 */
+#define HDA_RMX_IC 27
+
+#define HDA_REG_IR 30 /* 0x64 */
+#define HDA_RMX_IR 28
+
+#define HDA_REG_IRS 31 /* 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 32 /* 0x70 */
+#define HDA_RMX_DPLBASE 30
+
+#define HDA_REG_DPUBASE 33 /* 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]. */
+#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
+
+#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 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 35 /* 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 36 /* 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 37 /* 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 38 /* 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 39 /* 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 40 /* 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)
+
+#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 41 /* 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 42 /* 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 43 /* 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))
+
+/** Interrupt on completion (IOC) flag. */
+#define HDA_BDLE_F_IOC RT_BIT(0)
+
+
+/**
+ * BDL description structure.
+ * Do not touch this, as this must match to the HDA specs.
+ */
+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;
+ /** Bit 0: Interrupt on completion; the controller will generate
+ * an interrupt when the last byte of the buffer has been
+ * fetched by the DMA engine.
+ *
+ * Rest is 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. */
+
+
+
/**
* HDA mixer sink definition (ring-3).
*
@@ -97,8 +587,6 @@ typedef struct HDAMIXERSINK
/** Pointer to the actual audio mixer sink. */
R3PTRTYPE(PAUDMIXSINK) pMixSink;
} HDAMIXERSINK;
-/** Pointer to an HDA mixer sink definition (ring-3). */
-typedef HDAMIXERSINK *PHDAMIXERSINK;
/**
* Mapping a stream tag to an HDA stream (ring-3).
@@ -302,5 +790,41 @@ typedef struct HDASTATER3
/** 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);
+
#endif /* !VBOX_INCLUDED_SRC_Audio_DevHda_h */
diff --git a/src/VBox/Devices/Audio/DevHdaCodec.cpp b/src/VBox/Devices/Audio/DevHdaCodec.cpp
index cc0cba69f61..ef015f10cbe 100644
--- a/src/VBox/Devices/Audio/DevHdaCodec.cpp
+++ b/src/VBox/Devices/Audio/DevHdaCodec.cpp
@@ -40,8 +40,6 @@
#include "VBoxDD.h"
#include "AudioMixer.h"
#include "DevHda.h"
-#include "DevHdaCodec.h"
-#include "DevHdaCommon.h"
/*********************************************************************************************************************************
diff --git a/src/VBox/Devices/Audio/DevHdaCommon.cpp b/src/VBox/Devices/Audio/DevHdaCommon.cpp
deleted file mode 100644
index 241d56bea14..00000000000
--- a/src/VBox/Devices/Audio/DevHdaCommon.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/* $Id$ */
-/** @file
- * Intel HD Audio Controller Emulation - Common stuff.
- *
- * @todo r=bird: Shared with whom exactly?
- */
-
-/*
- * Copyright (C) 2017-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-
-/*********************************************************************************************************************************
-* Header Files *
-*********************************************************************************************************************************/
-#define LOG_GROUP LOG_GROUP_DEV_HDA
-#include <iprt/assert.h>
-#include <iprt/errcore.h>
-#include <iprt/time.h>
-
-#include <VBox/AssertGuest.h>
-#include <VBox/vmm/pdmaudioinline.h>
-
-#include <VBox/log.h>
-
-#include "DevHda.h"
-#include "DevHdaCommon.h"
-
-
-
-/**
- * Processes (de/asserts) the interrupt according to the HDA's current state.
- *
- * @param pDevIns The device instance.
- * @param pThis The shared HDA device state.
- * @param pszSource Caller information.
- */
-#if defined(LOG_ENABLED) || defined(DOXYGEN_RUNNING)
-void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis, const char *pszSource)
-#else
-void hdaProcessInterrupt(PPDMDEVINS pDevIns, PHDASTATE pThis)
-#endif
-{
- uint32_t uIntSts = hdaGetINTSTS(pThis);
-
- HDA_REG(pThis, INTSTS) = uIntSts;
-
- /* NB: It is possible to have GIS set even when CIE/SIEn are all zero; the GIS bit does
- * not control the interrupt signal. See Figure 4 on page 54 of the HDA 1.0a spec.
- */
- /* Global Interrupt Enable (GIE) set? */
- if ( (HDA_REG(pThis, INTCTL) & HDA_INTCTL_GIE)
- && (HDA_REG(pThis, INTSTS) & HDA_REG(pThis, INTCTL) & (HDA_INTCTL_CIE | HDA_STRMINT_MASK)))
- {
- Log3Func(("Asserted (%s)\n", pszSource));
-
- PDMDevHlpPCISetIrq(pDevIns, 0, 1 /* Assert */);
- pThis->u8IRQL = 1;
-
-#ifdef DEBUG
- pThis->Dbg.IRQ.tsAssertedNs = RTTimeNanoTS();
- pThis->Dbg.IRQ.tsProcessedLastNs = pThis->Dbg.IRQ.tsAssertedNs;
-#endif
- }
- else
- {
- Log3Func(("Deasserted (%s)\n", pszSource));
-
- PDMDevHlpPCISetIrq(pDevIns, 0, 0 /* Deassert */);
- pThis->u8IRQL = 0;
- }
-}
-
-/**
- * Retrieves the number of bytes of a FIFOW register.
- *
- * @return Number of bytes of a given FIFOW register.
- * @param u16RegFIFOW FIFOW register to convert.
- */
-uint8_t hdaSDFIFOWToBytes(uint16_t u16RegFIFOW)
-{
- uint32_t cb;
- switch (u16RegFIFOW)
- {
- case HDA_SDFIFOW_8B: cb = 8; break;
- case HDA_SDFIFOW_16B: cb = 16; break;
- case HDA_SDFIFOW_32B: cb = 32; break;
- default:
- AssertFailedStmt(cb = 32); /* Paranoia. */
- break;
- }
-
- Assert(RT_IS_POWER_OF_TWO(cb));
- return cb;
-}
-
-#ifdef IN_RING3
-/**
- * Returns the default (mixer) sink from a given SD#.
- * Returns NULL if no sink is found.
- *
- * @return PHDAMIXERSINK
- * @param pThisCC The ring-3 HDA device state.
- * @param uSD SD# to return mixer sink for.
- * NULL if not found / handled.
- */
-PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATER3 pThisCC, uint8_t uSD)
-{
- if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
- {
- const uint8_t uFirstSDI = 0;
-
- if (uSD == uFirstSDI) /* First SDI. */
- return &pThisCC->SinkLineIn;
-# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
- if (uSD == uFirstSDI + 1)
- return &pThisCC->SinkMicIn;
-# else
- /* If we don't have a dedicated Mic-In sink, use the always present Line-In sink. */
- return &pThisCC->SinkLineIn;
-# endif
- }
- else
- {
- const uint8_t uFirstSDO = HDA_MAX_SDI;
-
- if (uSD == uFirstSDO)
- return &pThisCC->SinkFront;
-# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
- if (uSD == uFirstSDO + 1)
- return &pThisCC->SinkCenterLFE;
- if (uSD == uFirstSDO + 2)
- return &pThisCC->SinkRear;
-# endif
- }
-
- return NULL;
-}
-#endif /* IN_RING3 */
-
-/**
- * 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.
- */
-PDMAUDIODIR hdaGetDirFromSD(uint8_t uSD)
-{
- AssertReturn(uSD < HDA_MAX_STREAMS, PDMAUDIODIR_UNKNOWN);
-
- if (uSD < HDA_MAX_SDI)
- return PDMAUDIODIR_IN;
-
- return PDMAUDIODIR_OUT;
-}
-
-/**
- * Returns the HDA stream of specified stream descriptor number.
- *
- * @return Pointer to HDA stream, or NULL if none found.
- */
-PHDASTREAM hdaGetStreamFromSD(PHDASTATE pThis, uint8_t uSD)
-{
- AssertPtr(pThis);
- ASSERT_GUEST_MSG_RETURN(uSD < HDA_MAX_STREAMS, ("uSD=%u (%#x)\n", uSD, uSD), NULL);
- return &pThis->aStreams[uSD];
-}
-
-#ifdef IN_RING3
-
-/**
- * Returns the HDA stream of specified HDA sink.
- *
- * @return Pointer to HDA stream, or NULL if none found.
- */
-PHDASTREAMR3 hdaR3GetR3StreamFromSink(PHDAMIXERSINK pSink)
-{
- AssertPtrReturn(pSink, NULL);
-
- /** @todo Do something with the channel mapping here? */
- return pSink->pStreamR3;
-}
-
-
-/**
- * Returns the HDA stream of specified HDA sink.
- *
- * @return Pointer to HDA stream, or NULL if none found.
- */
-PHDASTREAM hdaR3GetSharedStreamFromSink(PHDAMIXERSINK pSink)
-{
- AssertPtrReturn(pSink, NULL);
-
- /** @todo Do something with the channel mapping here? */
- return pSink->pStreamShared;
-}
-
-#endif /* IN_RING3 */
-
-/**
- * Returns a new INTSTS value based on the current device state.
- *
- * @returns Determined INTSTS register value.
- * @param pThis The shared HDA device state.
- *
- * @remark This function does *not* set INTSTS!
- */
-uint32_t hdaGetINTSTS(PHDASTATE pThis)
-{
- uint32_t intSts = 0;
-
- /* Check controller interrupts (RIRB, STATEST). */
- if (HDA_REG(pThis, RIRBSTS) & HDA_REG(pThis, RIRBCTL) & (HDA_RIRBCTL_ROIC | HDA_RIRBCTL_RINTCTL))
- {
- intSts |= HDA_INTSTS_CIS; /* Set the Controller Interrupt Status (CIS). */
- }
-
- /* Check SDIN State Change Status Flags. */
- if (HDA_REG(pThis, STATESTS) & HDA_REG(pThis, WAKEEN))
- {
- intSts |= HDA_INTSTS_CIS; /* Touch Controller Interrupt Status (CIS). */
- }
-
- /* For each stream, check if any interrupt status bit is set and enabled. */
- for (uint8_t iStrm = 0; iStrm < HDA_MAX_STREAMS; ++iStrm)
- {
- if (HDA_STREAM_REG(pThis, STS, iStrm) & HDA_STREAM_REG(pThis, CTL, iStrm) & (HDA_SDCTL_DEIE | HDA_SDCTL_FEIE | HDA_SDCTL_IOCE))
- {
- Log3Func(("[SD%d] interrupt status set\n", iStrm));
- intSts |= RT_BIT(iStrm);
- }
- }
-
- if (intSts)
- intSts |= HDA_INTSTS_GIS; /* Set the Global Interrupt Status (GIS). */
-
- Log3Func(("-> 0x%x\n", intSts));
-
- return intSts;
-}
-
-#ifdef IN_RING3
-
-/**
- * Converts an HDA stream's SDFMT register into a given PCM properties structure.
- *
- * @returns VBox status code.
- * @param u16SDFMT The HDA stream's SDFMT value to convert.
- * @param pProps PCM properties structure to hold converted result on success.
- */
-int hdaR3SDFMTToPCMProps(uint16_t u16SDFMT, PPDMAUDIOPCMPROPS pProps)
-{
- AssertPtrReturn(pProps, VERR_INVALID_POINTER);
-
-# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
-
- int rc = VINF_SUCCESS;
-
- uint32_t u32Hz = EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
- ? 44100 : 48000;
- uint32_t u32HzMult = 1;
- uint32_t u32HzDiv = 1;
-
- switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
- {
- case 0: u32HzMult = 1; break;
- case 1: u32HzMult = 2; break;
- case 2: u32HzMult = 3; break;
- case 3: u32HzMult = 4; break;
- default:
- LogFunc(("Unsupported multiplier %x\n",
- EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
- rc = VERR_NOT_SUPPORTED;
- break;
- }
- switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
- {
- case 0: u32HzDiv = 1; break;
- case 1: u32HzDiv = 2; break;
- case 2: u32HzDiv = 3; break;
- case 3: u32HzDiv = 4; break;
- case 4: u32HzDiv = 5; break;
- case 5: u32HzDiv = 6; break;
- case 6: u32HzDiv = 7; break;
- case 7: u32HzDiv = 8; break;
- default:
- LogFunc(("Unsupported divisor %x\n",
- EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
- rc = VERR_NOT_SUPPORTED;
- break;
- }
-
- uint8_t cbSample = 0;
- switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
- {
- case 0:
- cbSample = 1;
- break;
- case 1:
- cbSample = 2;
- break;
- case 4:
- cbSample = 4;
- break;
- default:
- AssertMsgFailed(("Unsupported bits per sample %x\n",
- EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
- rc = VERR_NOT_SUPPORTED;
- break;
- }
-
- if (RT_SUCCESS(rc))
- {
- PDMAudioPropsInit(pProps, cbSample, true /*fSigned*/, (u16SDFMT & 0xf) + 1 /*cChannels*/, u32Hz * u32HzMult / u32HzDiv);
- /** @todo is there anything we need to / can do about channel assignments? */
- }
-
-# undef EXTRACT_VALUE
- return rc;
-}
-
-# ifdef LOG_ENABLED
-void hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
-{
- LogFlowFunc(("BDLEs @ 0x%x (%RU16):\n", u64BDLBase, cBDLE));
- if (!u64BDLBase)
- return;
-
- uint32_t cbBDLE = 0;
- for (uint16_t i = 0; i < cBDLE; i++)
- {
- HDABDLEDESC bd;
- PDMDevHlpPhysRead(pDevIns, u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
-
- LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
- i, bd.u64BufAddr, bd.u32BufSize, bd.fFlags & HDA_BDLE_F_IOC));
-
- cbBDLE += bd.u32BufSize;
- }
-
- LogFlowFunc(("Total: %RU32 bytes\n", cbBDLE));
-
- if (!pThis->u64DPBase) /* No DMA base given? Bail out. */
- return;
-
- LogFlowFunc(("DMA counters:\n"));
-
- for (int i = 0; i < cBDLE; i++)
- {
- uint32_t uDMACnt;
- PDMDevHlpPhysRead(pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
- &uDMACnt, sizeof(uDMACnt));
-
- LogFlowFunc(("\t#%03d DMA @ 0x%x\n", i , uDMACnt));
- }
-}
-# endif /* LOG_ENABLED */
-
-#endif /* IN_RING3 */
diff --git a/src/VBox/Devices/Audio/DevHdaCommon.h b/src/VBox/Devices/Audio/DevHdaCommon.h
deleted file mode 100644
index 6b6c5d6aada..00000000000
--- a/src/VBox/Devices/Audio/DevHdaCommon.h
+++ /dev/null
@@ -1,591 +0,0 @@
-/* $Id$ */
-/** @file
- * Intel HD Audio Controller Emulation - Common stuff.
- *
- * @todo r=bird: Wtf is this? Do we have some other HDA implementations
- * that I'm not aware of that shares this code?
- */
-
-/*
- * Copyright (C) 2016-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef VBOX_INCLUDED_SRC_Audio_DevHdaCommon_h
-#define VBOX_INCLUDED_SRC_Audio_DevHdaCommon_h
-#ifndef RT_WITHOUT_PRAGMA_ONCE
-# pragma once
-#endif
-
-#ifndef VBOX_INCLUDED_SRC_Audio_DevHda_h
-# error "Only include DevHda.h!"
-#endif
-
-#include "AudioMixer.h"
-#include <VBox/log.h> /* LOG_ENABLED */
-
-
-/** Read callback. */
-typedef VBOXSTRICTRC FNHDAREGREAD(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-/** Write callback. */
-typedef VBOXSTRICTRC FNHDAREGWRITE(PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-
-/**
- * HDA register descriptor.
- *
- * See 302349 p 6.2.
- */
-typedef struct HDAREGDESC
-{
- /** Register offset in the register space. */
- uint32_t offset;
- /** Size in bytes. Registers of size > 4 are in fact tables. */
- uint32_t size;
- /** Readable bits. */
- uint32_t readable;
- /** Writable bits. */
- uint32_t writable;
- /** Register descriptor (RD) flags of type HDA_RD_F_XXX. These are used to
- * specify the handling (read/write) policy of the register. */
- uint32_t fFlags;
- /** Read callback. */
- FNHDAREGREAD *pfnRead;
- /** Write callback. */
- FNHDAREGWRITE *pfnWrite;
- /** Index into the register storage array. */
- uint32_t mem_idx;
- /** Abbreviated name. */
- const char *abbrev;
- /** Descripton. */
- const char *desc;
-} HDAREGDESC;
-/** Pointer to a a const HDA register descriptor. */
-typedef HDAREGDESC const *PCHDAREGDESC;
-
-/**
- * HDA register aliases (HDA spec 3.3.45).
- * @remarks Sorted by offReg.
- */
-typedef struct HDAREGALIAS
-{
- /** The alias register offset. */
- uint32_t offReg;
- /** The register index. */
- int idxAlias;
-} HDAREGALIAS;
-
-/**
- * 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);
-
-/** Number of general registers. */
-#define HDA_NUM_GENERAL_REGS 34
-/** Number of total registers in the HDA's register map. */
-#define HDA_NUM_REGS (HDA_NUM_GENERAL_REGS + (HDA_MAX_STREAMS * 10 /* Each stream descriptor has 10 registers */))
-/** Total number of stream tags (channels). Index 0 is reserved / invalid. */
-#define HDA_MAX_TAGS 16
-
-/**
- * ICH6 datasheet defines limits for FIFOS registers (18.2.39).
- * Formula: size - 1
- * Other values not listed are not supported.
- */
-
-/** Offset of the SD0 register map. */
-#define HDA_REG_DESC_SD0_BASE 0x80
-
-/** Turn a short global register name into an memory index and a stringized name. */
-#define HDA_REG_IDX(abbrev) HDA_MEM_IND_NAME(abbrev), #abbrev
-
-/** Turns a short stream register name into an memory index and a stringized name. */
-#define HDA_REG_IDX_STRM(reg, suff) HDA_MEM_IND_NAME(reg ## suff), #reg #suff
-
-/** Same as above for a register *not* stored in memory. */
-#define HDA_REG_IDX_NOMEM(abbrev) 0, #abbrev
-
-extern const HDAREGDESC g_aHdaRegMap[HDA_NUM_REGS];
-
-/**
- * NB: Register values stored in memory (au32Regs[]) are indexed through
- * the HDA_RMX_xxx macros (also HDA_MEM_IND_NAME()). On the other hand, the
- * register descriptors in g_aHdaRegMap[] are indexed through the
- * HDA_REG_xxx macros (also HDA_REG_IND_NAME()).
- *
- * The au32Regs[] layout is kept unchanged for saved state
- * compatibility.
- */
-
-/* Registers */
-#define HDA_REG_IND_NAME(x) HDA_REG_##x
-#define HDA_MEM_IND_NAME(x) HDA_RMX_##x
-#define HDA_REG_IND(pThis, x) ((pThis)->au32Regs[g_aHdaRegMap[x].mem_idx])
-#define HDA_REG(pThis, x) (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
-
-
-#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_OUTSTRMPAY 9 /* 0x18 */
-#define HDA_RMX_OUTSTRMPAY 112
-
-#define HDA_REG_INSTRMPAY 10 /* 0x1a */
-#define HDA_RMX_INSTRMPAY 113
-
-#define HDA_REG_INTCTL 11 /* 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 12 /* 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 13 /* 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.
- */
-#define HDA_REG_SSYNC 14 /* 0x34 */
-#define HDA_RMX_SSYNC 12
-
-#define HDA_REG_CORBLBASE 15 /* 0x40 */
-#define HDA_RMX_CORBLBASE 13
-
-#define HDA_REG_CORBUBASE 16 /* 0x44 */
-#define HDA_RMX_CORBUBASE 14
-
-#define HDA_REG_CORBWP 17 /* 0x48 */
-#define HDA_RMX_CORBWP 15
-
-#define HDA_REG_CORBRP 18 /* 0x4A */
-#define HDA_RMX_CORBRP 16
-#define HDA_CORBRP_RST RT_BIT(15) /* CORB Read Pointer Reset */
-
-#define HDA_REG_CORBCTL 19 /* 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 20 /* 0x4D */
-#define HDA_RMX_CORBSTS 18
-
-#define HDA_REG_CORBSIZE 21 /* 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 22 /* 0x50 */
-#define HDA_RMX_RIRBLBASE 20
-
-#define HDA_REG_RIRBUBASE 23 /* 0x54 */
-#define HDA_RMX_RIRBUBASE 21
-
-#define HDA_REG_RIRBWP 24 /* 0x58 */
-#define HDA_RMX_RIRBWP 22
-#define HDA_RIRBWP_RST RT_BIT(15) /* RIRB Write Pointer Reset */
-
-#define HDA_REG_RINTCNT 25 /* 0x5A */
-#define HDA_RMX_RINTCNT 23
-
-/** Maximum number of Response Interrupts. */
-#define HDA_MAX_RINTCNT 256
-
-#define HDA_REG_RIRBCTL 26 /* 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 27 /* 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 28 /* 0x5E */
-#define HDA_RMX_RIRBSIZE 26
-
-#define HDA_REG_IC 29 /* 0x60 */
-#define HDA_RMX_IC 27
-
-#define HDA_REG_IR 30 /* 0x64 */
-#define HDA_RMX_IR 28
-
-#define HDA_REG_IRS 31 /* 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 32 /* 0x70 */
-#define HDA_RMX_DPLBASE 30
-
-#define HDA_REG_DPUBASE 33 /* 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]. */
-#define HDA_STREAM_REG(pThis, name, sdnum) (HDA_REG_IND((pThis), HDA_REG_SD0##name + (sdnum) * 10))
-
-#define HDA_SD_NUM_FROM_REG(pThis, func, reg) ((reg - HDA_STREAM_REG_DEF(func, 0)) / 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 35 /* 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 36 /* 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 37 /* 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 38 /* 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 39 /* 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 40 /* 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)
-
-#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 41 /* 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 42 /* 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 43 /* 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))
-
-/** Interrupt on completion (IOC) flag. */
-#define HDA_BDLE_F_IOC RT_BIT(0)
-
-
-
-/** Pointer to a shared HDA state. */
-typedef struct HDASTATE *PHDASTATE;
-/** Pointer to a HDA stream state. */
-typedef struct HDASTREAM *PHDASTREAM;
-/** Pointer to a mixer sink. */
-typedef struct HDAMIXERSINK *PHDAMIXERSINK;
-
-
-/**
- * BDL description structure.
- * Do not touch this, as this must match to the HDA specs.
- */
-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;
- /** Bit 0: Interrupt on completion; the controller will generate
- * an interrupt when the last byte of the buffer has been
- * fetched by the DMA engine.
- *
- * Rest is 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. */
-
-
-/** @name Object lookup functions.
- * @{
- */
-#ifdef IN_RING3
-PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATER3 pThisCC, uint8_t uSD);
-#endif
-PDMAUDIODIR hdaGetDirFromSD(uint8_t uSD);
-//PHDASTREAM hdaGetStreamFromSD(PHDASTATER3 pThisCC, uint8_t uSD);
-#ifdef IN_RING3
-PHDASTREAMR3 hdaR3GetR3StreamFromSink(PHDAMIXERSINK pSink);
-PHDASTREAM hdaR3GetSharedStreamFromSink(PHDAMIXERSINK pSink);
-#endif
-/** @} */
-
-/** @name Interrupt functions.
- * @{
- */
-#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
-/** @} */
-
-/** @name Register utility functions.
- * @{ */
-uint8_t hdaSDFIFOWToBytes(uint16_t u16RegFIFOW);
-/** @} */
-
-/** @name Register functions.
- * @{
- */
-uint32_t hdaGetINTSTS(PHDASTATE pThis);
-#ifdef IN_RING3
-int hdaR3SDFMTToPCMProps(uint16_t u16SDFMT, PPDMAUDIOPCMPROPS pProps);
-#endif /* IN_RING3 */
-/** @} */
-
-/** @name BDLE (Buffer Descriptor List Entry) functions.
- * @{
- */
-#ifdef IN_RING3
-# ifdef LOG_ENABLED
-void hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE);
-# endif
-#endif /* IN_RING3 */
-/** @} */
-
-#endif /* !VBOX_INCLUDED_SRC_Audio_DevHdaCommon_h */
-
diff --git a/src/VBox/Devices/Audio/DevHdaStream.cpp b/src/VBox/Devices/Audio/DevHdaStream.cpp
index 763564cf5b7..c5799fe59ed 100644
--- a/src/VBox/Devices/Audio/DevHdaStream.cpp
+++ b/src/VBox/Devices/Audio/DevHdaStream.cpp
@@ -208,6 +208,122 @@ void hdaR3StreamDestroy(PHDASTREAMR3 pStreamR3)
/**
+ * Converts an HDA stream's SDFMT register into a given PCM properties structure.
+ *
+ * @returns VBox status code.
+ * @param u16SDFMT The HDA stream's SDFMT value to convert.
+ * @param pProps PCM properties structure to hold converted result on success.
+ */
+int hdaR3SDFMTToPCMProps(uint16_t u16SDFMT, PPDMAUDIOPCMPROPS pProps)
+{
+ AssertPtrReturn(pProps, VERR_INVALID_POINTER);
+
+# define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
+
+ int rc = VINF_SUCCESS;
+
+ uint32_t u32Hz = EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BASE_RATE_MASK, HDA_SDFMT_BASE_RATE_SHIFT)
+ ? 44100 : 48000;
+ uint32_t u32HzMult = 1;
+ uint32_t u32HzDiv = 1;
+
+ switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT))
+ {
+ case 0: u32HzMult = 1; break;
+ case 1: u32HzMult = 2; break;
+ case 2: u32HzMult = 3; break;
+ case 3: u32HzMult = 4; break;
+ default:
+ LogFunc(("Unsupported multiplier %x\n",
+ EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_MULT_MASK, HDA_SDFMT_MULT_SHIFT)));
+ rc = VERR_NOT_SUPPORTED;
+ break;
+ }
+ switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT))
+ {
+ case 0: u32HzDiv = 1; break;
+ case 1: u32HzDiv = 2; break;
+ case 2: u32HzDiv = 3; break;
+ case 3: u32HzDiv = 4; break;
+ case 4: u32HzDiv = 5; break;
+ case 5: u32HzDiv = 6; break;
+ case 6: u32HzDiv = 7; break;
+ case 7: u32HzDiv = 8; break;
+ default:
+ LogFunc(("Unsupported divisor %x\n",
+ EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_DIV_MASK, HDA_SDFMT_DIV_SHIFT)));
+ rc = VERR_NOT_SUPPORTED;
+ break;
+ }
+
+ uint8_t cbSample = 0;
+ switch (EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT))
+ {
+ case 0:
+ cbSample = 1;
+ break;
+ case 1:
+ cbSample = 2;
+ break;
+ case 4:
+ cbSample = 4;
+ break;
+ default:
+ AssertMsgFailed(("Unsupported bits per sample %x\n",
+ EXTRACT_VALUE(u16SDFMT, HDA_SDFMT_BITS_MASK, HDA_SDFMT_BITS_SHIFT)));
+ rc = VERR_NOT_SUPPORTED;
+ break;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ PDMAudioPropsInit(pProps, cbSample, true /*fSigned*/, (u16SDFMT & 0xf) + 1 /*cChannels*/, u32Hz * u32HzMult / u32HzDiv);
+ /** @todo is there anything we need to / can do about channel assignments? */
+ }
+
+# undef EXTRACT_VALUE
+ return rc;
+}
+
+# ifdef LOG_ENABLED
+void hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE)
+{
+ LogFlowFunc(("BDLEs @ 0x%x (%RU16):\n", u64BDLBase, cBDLE));
+ if (!u64BDLBase)
+ return;
+
+ uint32_t cbBDLE = 0;
+ for (uint16_t i = 0; i < cBDLE; i++)
+ {
+ HDABDLEDESC bd;
+ PDMDevHlpPhysRead(pDevIns, u64BDLBase + i * sizeof(HDABDLEDESC), &bd, sizeof(bd));
+
+ LogFunc(("\t#%03d BDLE(adr:0x%llx, size:%RU32, ioc:%RTbool)\n",
+ i, bd.u64BufAddr, bd.u32BufSize, bd.fFlags & HDA_BDLE_F_IOC));
+
+ cbBDLE += bd.u32BufSize;
+ }
+
+ LogFlowFunc(("Total: %RU32 bytes\n", cbBDLE));
+
+ if (!pThis->u64DPBase) /* No DMA base given? Bail out. */
+ return;
+
+ LogFlowFunc(("DMA counters:\n"));
+
+ for (int i = 0; i < cBDLE; i++)
+ {
+ uint32_t uDMACnt;
+ PDMDevHlpPhysRead(pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + (i * 2 * sizeof(uint32_t)),
+ &uDMACnt, sizeof(uDMACnt));
+
+ LogFlowFunc(("\t#%03d DMA @ 0x%x\n", i , uDMACnt));
+ }
+}
+# endif /* LOG_ENABLED */
+
+
+/**
* Appends a item to the scheduler.
*
* @returns VBox status code.
@@ -793,6 +909,49 @@ int hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShar
return rc;
}
+
+/**
+ * Worker for hdaR3StreamReset().
+ *
+ * @returns The default mixer sink, NULL if none found.
+ * @param pThisCC The ring-3 HDA device state.
+ * @param uSD SD# to return mixer sink for.
+ * NULL if not found / handled.
+ */
+static PHDAMIXERSINK hdaR3GetDefaultSink(PHDASTATER3 pThisCC, uint8_t uSD)
+{
+ if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_IN)
+ {
+ const uint8_t uFirstSDI = 0;
+
+ if (uSD == uFirstSDI) /* First SDI. */
+ return &pThisCC->SinkLineIn;
+# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
+ if (uSD == uFirstSDI + 1)
+ return &pThisCC->SinkMicIn;
+# else
+ /* If we don't have a dedicated Mic-In sink, use the always present Line-In sink. */
+ return &pThisCC->SinkLineIn;
+# endif
+ }
+ else
+ {
+ const uint8_t uFirstSDO = HDA_MAX_SDI;
+
+ if (uSD == uFirstSDO)
+ return &pThisCC->SinkFront;
+# ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
+ if (uSD == uFirstSDO + 1)
+ return &pThisCC->SinkCenterLFE;
+ if (uSD == uFirstSDO + 2)
+ return &pThisCC->SinkRear;
+# endif
+ }
+
+ return NULL;
+}
+
+
/**
* Resets an HDA stream.
*
diff --git a/src/VBox/Devices/Audio/DevHdaStream.h b/src/VBox/Devices/Audio/DevHdaStream.h
index ff6f9338c12..d1b46037ca6 100644
--- a/src/VBox/Devices/Audio/DevHdaStream.h
+++ b/src/VBox/Devices/Audio/DevHdaStream.h
@@ -336,6 +336,14 @@ uint64_t hdaR3StreamTimerMain(PPDMDEVINS pDevIns, PHDASTATE pThis, PH
DECLCALLBACK(void) hdaR3StreamUpdateAsyncIoJob(PPDMDEVINS pDevIns, PAUDMIXSINK pSink, void *pvUser);
/** @} */
+/** @name Helper functions associated with the stream code.
+ * @{ */
+int hdaR3SDFMTToPCMProps(uint16_t u16SDFMT, PPDMAUDIOPCMPROPS pProps);
+# ifdef LOG_ENABLED
+void hdaR3BDLEDumpAll(PPDMDEVINS pDevIns, PHDASTATE pThis, uint64_t u64BDLBase, uint16_t cBDLE);
+# endif
+/** @} */
+
#endif /* IN_RING3 */
#endif /* !VBOX_INCLUDED_SRC_Audio_DevHdaStream_h */