Index: trunk/src/VBox/Devices/Audio/DevCodec.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevCodec.cpp	(revision 44668)
+++ 	(revision )
@@ -1,2444 +1,0 @@
-/* $Id$ */
-/** @file
- * DevCodec - VBox ICH Intel HD Audio Codec.
- *
- * Implemented against "Intel I/O Controller Hub 6 (ICH6) High Definition
- * Audio / AC '97 - Programmer's Reference Manual (PRM)", document number
- * 302349-003.
- */
-
-/*
- * Copyright (C) 2006-2013 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_AUDIO
-#include <VBox/vmm/pdmdev.h>
-#include <iprt/assert.h>
-#include <iprt/uuid.h>
-#include <iprt/string.h>
-#include <iprt/mem.h>
-#include <iprt/asm.h>
-#include <iprt/cpp/utils.h>
-
-#include "VBoxDD.h"
-extern "C" {
-#include "audio.h"
-}
-#include "DevCodec.h"
-
-
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
-/* PRM 5.3.1 */
-#define CODEC_CAD_MASK              0xF0000000
-#define CODEC_CAD_SHIFT             28
-#define CODEC_DIRECT_MASK           RT_BIT(27)
-#define CODEC_NID_MASK              0x07F00000
-#define CODEC_NID_SHIFT             20
-#define CODEC_VERBDATA_MASK         0x000FFFFF
-#define CODEC_VERB_4BIT_CMD         0x000FFFF0
-#define CODEC_VERB_4BIT_DATA        0x0000000F
-#define CODEC_VERB_8BIT_CMD         0x000FFF00
-#define CODEC_VERB_8BIT_DATA        0x000000FF
-#define CODEC_VERB_16BIT_CMD        0x000F0000
-#define CODEC_VERB_16BIT_DATA       0x0000FFFF
-
-#define CODEC_CAD(cmd) ((cmd) & CODEC_CAD_MASK)
-#define CODEC_DIRECT(cmd) ((cmd) & CODEC_DIRECT_MASK)
-#define CODEC_NID(cmd) ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
-#define CODEC_VERBDATA(cmd) ((cmd) & CODEC_VERBDATA_MASK)
-#define CODEC_VERB_CMD(cmd, mask, x) (((cmd) & (mask)) >> (x))
-#define CODEC_VERB_CMD4(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
-#define CODEC_VERB_CMD8(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
-#define CODEC_VERB_CMD16(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
-#define CODEC_VERB_PAYLOAD4(cmd) ((cmd) & CODEC_VERB_4BIT_DATA)
-#define CODEC_VERB_PAYLOAD8(cmd) ((cmd) & CODEC_VERB_8BIT_DATA)
-#define CODEC_VERB_PAYLOAD16(cmd) ((cmd) & CODEC_VERB_16BIT_DATA)
-
-#define CODEC_VERB_GET_AMP_DIRECTION  RT_BIT(15)
-#define CODEC_VERB_GET_AMP_SIDE       RT_BIT(13)
-#define CODEC_VERB_GET_AMP_INDEX      0x7
-
-/* HDA spec 7.3.3.7 NoteA */
-#define CODEC_GET_AMP_DIRECTION(cmd)  (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
-#define CODEC_GET_AMP_SIDE(cmd)       (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
-#define CODEC_GET_AMP_INDEX(cmd)      (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
-
-/* HDA spec 7.3.3.7 NoteC */
-#define CODEC_VERB_SET_AMP_OUT_DIRECTION  RT_BIT(15)
-#define CODEC_VERB_SET_AMP_IN_DIRECTION   RT_BIT(14)
-#define CODEC_VERB_SET_AMP_LEFT_SIDE      RT_BIT(13)
-#define CODEC_VERB_SET_AMP_RIGHT_SIDE     RT_BIT(12)
-#define CODEC_VERB_SET_AMP_INDEX          (0x7 << 8)
-
-#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd)  (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
-#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd)   (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
-#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd)      (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
-#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd)     (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
-#define CODEC_SET_AMP_INDEX(cmd)             (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
-
-/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
-/* VendorID (7.3.4.1) */
-#define CODEC_MAKE_F00_00(vendorID, deviceID) (((vendorID) << 16) | (deviceID))
-#define CODEC_F00_00_VENDORID(f00_00) (((f00_00) >> 16) & 0xFFFF)
-#define CODEC_F00_00_DEVICEID(f00_00) ((f00_00) & 0xFFFF)
-/* RevisionID (7.3.4.2)*/
-#define CODEC_MAKE_F00_02(MajRev, MinRev, RevisionID, SteppingID) (((MajRev) << 20)|((MinRev) << 16)|((RevisionID) << 8)|(SteppingID))
-/* Subordinate node count (7.3.4.3)*/
-#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
-#define CODEC_F00_04_TO_START_NODE_NUMBER(f00_04) (((f00_04) >> 16) & 0xFF)
-#define CODEC_F00_04_TO_NODE_COUNT(f00_04) ((f00_04) & 0xFF)
-/*
- * Function Group Type  (7.3.4.4)
- * 0 & [0x3-0x7f] are reserved types
- * [0x80 - 0xff] are vendor defined function groups
- */
-#define CODEC_MAKE_F00_05(UnSol, NodeType) (((UnSol) << 8)|(NodeType))
-#define CODEC_F00_05_UNSOL  RT_BIT(8)
-#define CODEC_F00_05_AFG    (0x1)
-#define CODEC_F00_05_MFG    (0x2)
-#define CODEC_F00_05_IS_UNSOL(f00_05) RT_BOOL((f00_05) & RT_BIT(8))
-#define CODEC_F00_05_GROUP(f00_05) ((f00_05) & 0xff)
-/*  Audio Function Group capabilities (7.3.4.5) */
-#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
-#define CODEC_F00_08_BEEP_GEN(f00_08) ((f00_08) & RT_BIT(16)
-
-/* Widget Capabilities (7.3.4.6) */
-#define CODEC_MAKE_F00_09(type, delay, chanel_count) \
-    ( (((type) & 0xF) << 20)            \
-    | (((delay) & 0xF) << 16)           \
-    | (((chanel_count) & 0xF) << 13))
-/* note: types 0x8-0xe are reserved */
-#define CODEC_F00_09_TYPE_AUDIO_OUTPUT      (0x0)
-#define CODEC_F00_09_TYPE_AUDIO_INPUT       (0x1)
-#define CODEC_F00_09_TYPE_AUDIO_MIXER       (0x2)
-#define CODEC_F00_09_TYPE_AUDIO_SELECTOR    (0x3)
-#define CODEC_F00_09_TYPE_PIN_COMPLEX       (0x4)
-#define CODEC_F00_09_TYPE_POWER_WIDGET      (0x5)
-#define CODEC_F00_09_TYPE_VOLUME_KNOB       (0x6)
-#define CODEC_F00_09_TYPE_BEEP_GEN          (0x7)
-#define CODEC_F00_09_TYPE_VENDOR_DEFINED    (0xF)
-
-#define CODEC_F00_09_CAP_CP                 RT_BIT(12)
-#define CODEC_F00_09_CAP_L_R_SWAP           RT_BIT(11)
-#define CODEC_F00_09_CAP_POWER_CTRL         RT_BIT(10)
-#define CODEC_F00_09_CAP_DIGITAL            RT_BIT(9)
-#define CODEC_F00_09_CAP_CONNECTION_LIST    RT_BIT(8)
-#define CODEC_F00_09_CAP_UNSOL              RT_BIT(7)
-#define CODEC_F00_09_CAP_PROC_WIDGET        RT_BIT(6)
-#define CODEC_F00_09_CAP_STRIPE             RT_BIT(5)
-#define CODEC_F00_09_CAP_FMT_OVERRIDE       RT_BIT(4)
-#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE   RT_BIT(3)
-#define CODEC_F00_09_CAP_OUT_AMP_PRESENT    RT_BIT(2)
-#define CODEC_F00_09_CAP_IN_AMP_PRESENT     RT_BIT(1)
-#define CODEC_F00_09_CAP_LSB                RT_BIT(0)
-
-#define CODEC_F00_09_TYPE(f00_09) (((f00_09) >> 20) & 0xF)
-
-#define CODEC_F00_09_IS_CAP_CP(f00_09)              RT_BOOL((f00_09) & RT_BIT(12))
-#define CODEC_F00_09_IS_CAP_L_R_SWAP(f00_09)        RT_BOOL((f00_09) & RT_BIT(11))
-#define CODEC_F00_09_IS_CAP_POWER_CTRL(f00_09)      RT_BOOL((f00_09) & RT_BIT(10))
-#define CODEC_F00_09_IS_CAP_DIGITAL(f00_09)         RT_BOOL((f00_09) & RT_BIT(9))
-#define CODEC_F00_09_IS_CAP_CONNECTION_LIST(f00_09) RT_BOOL((f00_09) & RT_BIT(8))
-#define CODEC_F00_09_IS_CAP_UNSOL(f00_09)           RT_BOOL((f00_09) & RT_BIT(7))
-#define CODEC_F00_09_IS_CAP_PROC_WIDGET(f00_09)     RT_BOOL((f00_09) & RT_BIT(6))
-#define CODEC_F00_09_IS_CAP_STRIPE(f00_09)          RT_BOOL((f00_09) & RT_BIT(5))
-#define CODEC_F00_09_IS_CAP_FMT_OVERRIDE(f00_09)    RT_BOOL((f00_09) & RT_BIT(4))
-#define CODEC_F00_09_IS_CAP_AMP_OVERRIDE(f00_09)    RT_BOOL((f00_09) & RT_BIT(3))
-#define CODEC_F00_09_IS_CAP_OUT_AMP_PRESENT(f00_09) RT_BOOL((f00_09) & RT_BIT(2))
-#define CODEC_F00_09_IS_CAP_IN_AMP_PRESENT(f00_09)  RT_BOOL((f00_09) & RT_BIT(1))
-#define CODEC_F00_09_IS_CAP_LSB(f00_09)             RT_BOOL((f00_09) & RT_BIT(0))
-
-/* Supported PCM size, rates (7.3.4.7) */
-#define CODEC_F00_0A_32_BIT             RT_BIT(19)
-#define CODEC_F00_0A_24_BIT             RT_BIT(18)
-#define CODEC_F00_0A_16_BIT             RT_BIT(17)
-#define CODEC_F00_0A_8_BIT              RT_BIT(16)
-
-#define CODEC_F00_0A_48KHZ_MULT_8X      RT_BIT(11)
-#define CODEC_F00_0A_48KHZ_MULT_4X      RT_BIT(10)
-#define CODEC_F00_0A_44_1KHZ_MULT_4X    RT_BIT(9)
-#define CODEC_F00_0A_48KHZ_MULT_2X      RT_BIT(8)
-#define CODEC_F00_0A_44_1KHZ_MULT_2X    RT_BIT(7)
-#define CODEC_F00_0A_48KHZ              RT_BIT(6)
-#define CODEC_F00_0A_44_1KHZ            RT_BIT(5)
-/* 2/3 * 48kHz */
-#define CODEC_F00_0A_48KHZ_2_3X         RT_BIT(4)
-/* 1/2 * 44.1kHz */
-#define CODEC_F00_0A_44_1KHZ_1_2X       RT_BIT(3)
-/* 1/3 * 48kHz */
-#define CODEC_F00_0A_48KHZ_1_3X         RT_BIT(2)
-/* 1/4 * 44.1kHz */
-#define CODEC_F00_0A_44_1KHZ_1_4X       RT_BIT(1)
-/* 1/6 * 48kHz */
-#define CODEC_F00_0A_48KHZ_1_6X         RT_BIT(0)
-
-/* Supported streams formats (7.3.4.8) */
-#define CODEC_F00_0B_AC3                RT_BIT(2)
-#define CODEC_F00_0B_FLOAT32            RT_BIT(1)
-#define CODEC_F00_0B_PCM                RT_BIT(0)
-
-/* Pin Capabilities (7.3.4.9)*/
-#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
-#define CODEC_F00_0C_CAP_HBR                    RT_BIT(27)
-#define CODEC_F00_0C_CAP_DP                     RT_BIT(24)
-#define CODEC_F00_0C_CAP_EAPD                   RT_BIT(16)
-#define CODEC_F00_0C_CAP_HDMI                   RT_BIT(7)
-#define CODEC_F00_0C_CAP_BALANCED_IO            RT_BIT(6)
-#define CODEC_F00_0C_CAP_INPUT                  RT_BIT(5)
-#define CODEC_F00_0C_CAP_OUTPUT                 RT_BIT(4)
-#define CODEC_F00_0C_CAP_HP                     RT_BIT(3)
-#define CODEC_F00_0C_CAP_PRESENSE_DETECT        RT_BIT(2)
-#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED       RT_BIT(1)
-#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE       RT_BIT(0)
-
-#define CODEC_F00_0C_IS_CAP_HBR(f00_0c)                    ((f00_0c) & RT_BIT(27))
-#define CODEC_F00_0C_IS_CAP_DP(f00_0c)                     ((f00_0c) & RT_BIT(24))
-#define CODEC_F00_0C_IS_CAP_EAPD(f00_0c)                   ((f00_0c) & RT_BIT(16))
-#define CODEC_F00_0C_IS_CAP_HDMI(f00_0c)                   ((f00_0c) & RT_BIT(7))
-#define CODEC_F00_0C_IS_CAP_BALANCED_IO(f00_0c)            ((f00_0c) & RT_BIT(6))
-#define CODEC_F00_0C_IS_CAP_INPUT(f00_0c)                  ((f00_0c) & RT_BIT(5))
-#define CODEC_F00_0C_IS_CAP_OUTPUT(f00_0c)                 ((f00_0c) & RT_BIT(4))
-#define CODEC_F00_0C_IS_CAP_HP(f00_0c)                     ((f00_0c) & RT_BIT(3))
-#define CODEC_F00_0C_IS_CAP_PRESENSE_DETECT(f00_0c)        ((f00_0c) & RT_BIT(2))
-#define CODEC_F00_0C_IS_CAP_TRIGGER_REQUIRED(f00_0c)       ((f00_0c) & RT_BIT(1))
-#define CODEC_F00_0C_IS_CAP_IMPENDANCE_SENSE(f00_0c)       ((f00_0c) & RT_BIT(0))
-
-/* Input Amplifier capabilities (7.3.4.10) */
-#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
-        (  (((mute_cap) & 0x1) << 31)                             \
-         | (((step_size) & 0xFF) << 16)                           \
-         | (((num_steps) & 0xFF) << 8)                            \
-         | ((offset) & 0xFF))
-
-/* Output Amplifier capabilities (7.3.4.10) */
-#define CODEC_MAKE_F00_12 CODEC_MAKE_F00_0D
-
-/* Connection list lenght (7.3.4.11) */
-#define CODEC_MAKE_F00_0E(long_form, length)    \
-    (  (((long_form) & 0x1) << 7)               \
-     | ((length) & 0x7F))
-#define CODEC_F00_0E_IS_LONG(f00_0e) RT_BOOL((f00_0e) & RT_BIT(7))
-#define CODEC_F00_0E_COUNT(f00_0e) ((f00_0e) & 0x7F)
-/* Supported Power States (7.3.4.12) */
-#define CODEC_F00_0F_EPSS       RT_BIT(31)
-#define CODEC_F00_0F_CLKSTOP    RT_BIT(30)
-#define CODEC_F00_0F_S3D3       RT_BIT(29)
-#define CODEC_F00_0F_D3COLD     RT_BIT(4)
-#define CODEC_F00_0F_D3         RT_BIT(3)
-#define CODEC_F00_0F_D2         RT_BIT(2)
-#define CODEC_F00_0F_D1         RT_BIT(1)
-#define CODEC_F00_0F_D0         RT_BIT(0)
-
-/* Processing capabilities 7.3.4.13 */
-#define CODEC_MAKE_F00_10(num, benign) ((((num) & 0xFF) << 8) | ((benign) & 0x1))
-#define CODEC_F00_10_NUM(f00_10) (((f00_10) & (0xFF << 8)) >> 8)
-#define CODEC_F00_10_BENING(f00_10) ((f00_10) & 0x1)
-
-/* CP/IO Count (7.3.4.14) */
-#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
-    (  (((wake) & 0x1) << 31)                                   \
-     | (((unsol) & 0x1) << 30)                                  \
-     | (((numgpi) & 0xFF) << 16)                                \
-     | (((numgpo) & 0xFF) << 8)                                 \
-     | ((numgpio) & 0xFF))
-
-/* Processing States (7.3.3.4) */
-#define CODEC_F03_OFF    (0)
-#define CODEC_F03_ON     RT_BIT(0)
-#define CODEC_F03_BENING RT_BIT(1)
-/* Power States (7.3.3.10) */
-#define CODEC_MAKE_F05(reset, stopok, error, act, set)          \
-    (   (((reset) & 0x1) << 10)                                 \
-      | (((stopok) & 0x1) << 9)                                 \
-      | (((error) & 0x1) << 8)                                  \
-      | (((act) & 0x7) << 4)                                    \
-      | ((set) & 0x7))
-#define CODEC_F05_D3COLD    (4)
-#define CODEC_F05_D3        (3)
-#define CODEC_F05_D2        (2)
-#define CODEC_F05_D1        (1)
-#define CODEC_F05_D0        (0)
-
-#define CODEC_F05_IS_RESET(value)   (((value) & RT_BIT(10)) != 0)
-#define CODEC_F05_IS_STOPOK(value)  (((value) & RT_BIT(9)) != 0)
-#define CODEC_F05_IS_ERROR(value)   (((value) & RT_BIT(8)) != 0)
-#define CODEC_F05_ACT(value)        (((value) & 0x7) >> 4)
-#define CODEC_F05_SET(value)        (((value) & 0x7))
-
-#define CODEC_F05_GE(p0, p1) ((p0) <= (p1))
-#define CODEC_F05_LE(p0, p1) ((p0) >= (p1))
-
-/* Pin Widged Control (7.3.3.13) */
-#define CODEC_F07_VREF_HIZ      (0)
-#define CODEC_F07_VREF_50       (0x1)
-#define CODEC_F07_VREF_GROUND   (0x2)
-#define CODEC_F07_VREF_80       (0x4)
-#define CODEC_F07_VREF_100      (0x5)
-#define CODEC_F07_IN_ENABLE     RT_BIT(5)
-#define CODEC_F07_OUT_ENABLE    RT_BIT(6)
-#define CODEC_F07_OUT_H_ENABLE  RT_BIT(7)
-
-/* Unsolicited enabled (7.3.3.14) */
-#define CODEC_MAKE_F08(enable, tag) ((((enable) & 1) << 7) | ((tag) & 0x3F))
-
-/* Converter formats (7.3.3.8) and (3.7.1) */
-#define CODEC_MAKE_A(fNonPCM, f44_1BaseRate, mult, div, bits, chan) \
-    (  (((fNonPCM) & 0x1) << 15)                                    \
-     | (((f44_1BaseRate) & 0x1) << 14)                              \
-     | (((mult) & 0x7) << 11)                                       \
-     | (((div) & 0x7) << 8)                                         \
-     | (((bits) & 0x7) << 4)                                        \
-     | ((chan) & 0xF))
-
-#define CODEC_A_MULT_1X     (0)
-#define CODEC_A_MULT_2X     (1)
-#define CODEC_A_MULT_3X     (2)
-#define CODEC_A_MULT_4X     (3)
-
-#define CODEC_A_DIV_1X      (0)
-#define CODEC_A_DIV_2X      (1)
-#define CODEC_A_DIV_3X      (2)
-#define CODEC_A_DIV_4X      (3)
-#define CODEC_A_DIV_5X      (4)
-#define CODEC_A_DIV_6X      (5)
-#define CODEC_A_DIV_7X      (6)
-#define CODEC_A_DIV_8X      (7)
-
-#define CODEC_A_8_BIT       (0)
-#define CODEC_A_16_BIT      (1)
-#define CODEC_A_20_BIT      (2)
-#define CODEC_A_24_BIT      (3)
-#define CODEC_A_32_BIT      (4)
-
-/* Pin Sense (7.3.3.15) */
-#define CODEC_MAKE_F09_ANALOG(fPresent, impedance)  \
-(  (((fPresent) & 0x1) << 31)                       \
- | (((impedance) & 0x7FFFFFFF)))
-#define CODEC_F09_ANALOG_NA    0x7FFFFFFF
-#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
-(   (((fPresent) & 0x1) << 31)                      \
-  | (((fELDValid) & 0x1) << 30))
-
-#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
-#define CODEC_FOC_IS_LRSWAP(f0c)    RT_BOOL((f0c) & RT_BIT(2))
-#define CODEC_FOC_IS_EAPD(f0c)      RT_BOOL((f0c) & RT_BIT(1))
-#define CODEC_FOC_IS_BTL(f0c)       RT_BOOL((f0c) & RT_BIT(0))
-/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
-/* Configuration's port connection */
-#define CODEC_F1C_PORT_MASK    (0x3)
-#define CODEC_F1C_PORT_SHIFT   (30)
-
-#define CODEC_F1C_PORT_COMPLEX (0x0)
-#define CODEC_F1C_PORT_NO_PHYS (0x1)
-#define CODEC_F1C_PORT_FIXED   (0x2)
-#define CODEC_F1C_BOTH         (0x3)
-
-/* Configuration's location */
-#define CODEC_F1C_LOCATION_MASK  (0x3F)
-#define CODEC_F1C_LOCATION_SHIFT (24)
-/* [4:5] bits of location region means chassis attachment */
-#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS     (0)
-#define CODEC_F1C_LOCATION_INTERNAL            RT_BIT(4)
-#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS  RT_BIT(5)
-#define CODEC_F1C_LOCATION_OTHER               (RT_BIT(5))
-
-/* [0:3] bits of location region means geometry location attachment */
-#define CODEC_F1C_LOCATION_NA                  (0)
-#define CODEC_F1C_LOCATION_REAR                (0x1)
-#define CODEC_F1C_LOCATION_FRONT               (0x2)
-#define CODEC_F1C_LOCATION_LEFT                (0x3)
-#define CODEC_F1C_LOCATION_RIGTH               (0x4)
-#define CODEC_F1C_LOCATION_TOP                 (0x5)
-#define CODEC_F1C_LOCATION_BOTTOM              (0x6)
-#define CODEC_F1C_LOCATION_SPECIAL_0           (0x7)
-#define CODEC_F1C_LOCATION_SPECIAL_1           (0x8)
-#define CODEC_F1C_LOCATION_SPECIAL_2           (0x9)
-
-/* Configuration's devices */
-#define CODEC_F1C_DEVICE_MASK                  (0xF)
-#define CODEC_F1C_DEVICE_SHIFT                 (20)
-#define CODEC_F1C_DEVICE_LINE_OUT              (0)
-#define CODEC_F1C_DEVICE_SPEAKER               (0x1)
-#define CODEC_F1C_DEVICE_HP                    (0x2)
-#define CODEC_F1C_DEVICE_CD                    (0x3)
-#define CODEC_F1C_DEVICE_SPDIF_OUT             (0x4)
-#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT     (0x5)
-#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE       (0x6)
-#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE    (0x7)
-#define CODEC_F1C_DEVICE_LINE_IN               (0x8)
-#define CODEC_F1C_DEVICE_AUX                   (0x9)
-#define CODEC_F1C_DEVICE_MIC                   (0xA)
-#define CODEC_F1C_DEVICE_PHONE                 (0xB)
-#define CODEC_F1C_DEVICE_SPDIF_IN              (0xC)
-#define CODEC_F1C_DEVICE_RESERVED              (0xE)
-#define CODEC_F1C_DEVICE_OTHER                 (0xF)
-
-/* Configuration's Connection type */
-#define CODEC_F1C_CONNECTION_TYPE_MASK         (0xF)
-#define CODEC_F1C_CONNECTION_TYPE_SHIFT        (16)
-
-#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN               (0)
-#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES             (0x1)
-#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES             (0x2)
-#define CODEC_F1C_CONNECTION_TYPE_ATAPI                 (0x3)
-#define CODEC_F1C_CONNECTION_TYPE_RCA                   (0x4)
-#define CODEC_F1C_CONNECTION_TYPE_OPTICAL               (0x5)
-#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL         (0x6)
-#define CODEC_F1C_CONNECTION_TYPE_ANALOG                (0x7)
-#define CODEC_F1C_CONNECTION_TYPE_DIN                   (0x8)
-#define CODEC_F1C_CONNECTION_TYPE_XLR                   (0x9)
-#define CODEC_F1C_CONNECTION_TYPE_RJ_11                 (0xA)
-#define CODEC_F1C_CONNECTION_TYPE_COMBO                 (0xB)
-#define CODEC_F1C_CONNECTION_TYPE_OTHER                 (0xF)
-
-/* Configuration's color */
-#define CODEC_F1C_COLOR_MASK                  (0xF)
-#define CODEC_F1C_COLOR_SHIFT                 (12)
-#define CODEC_F1C_COLOR_UNKNOWN               (0)
-#define CODEC_F1C_COLOR_BLACK                 (0x1)
-#define CODEC_F1C_COLOR_GREY                  (0x2)
-#define CODEC_F1C_COLOR_BLUE                  (0x3)
-#define CODEC_F1C_COLOR_GREEN                 (0x4)
-#define CODEC_F1C_COLOR_RED                   (0x5)
-#define CODEC_F1C_COLOR_ORANGE                (0x6)
-#define CODEC_F1C_COLOR_YELLOW                (0x7)
-#define CODEC_F1C_COLOR_PURPLE                (0x8)
-#define CODEC_F1C_COLOR_PINK                  (0x9)
-#define CODEC_F1C_COLOR_RESERVED_0            (0xA)
-#define CODEC_F1C_COLOR_RESERVED_1            (0xB)
-#define CODEC_F1C_COLOR_RESERVED_2            (0xC)
-#define CODEC_F1C_COLOR_RESERVED_3            (0xD)
-#define CODEC_F1C_COLOR_WHITE                 (0xE)
-#define CODEC_F1C_COLOR_OTHER                 (0xF)
-
-/* Configuration's misc */
-#define CODEC_F1C_MISC_MASK                  (0xF)
-#define CODEC_F1C_MISC_SHIFT                 (8)
-#define CODEC_F1C_MISC_JACK_DETECT           (0)
-#define CODEC_F1C_MISC_RESERVED_0            (1)
-#define CODEC_F1C_MISC_RESERVED_1            (2)
-#define CODEC_F1C_MISC_RESERVED_2            (3)
-
-/* Configuration's association */
-#define CODEC_F1C_ASSOCIATION_MASK                  (0xF)
-#define CODEC_F1C_ASSOCIATION_SHIFT                 (4)
-/* Connection's sequence */
-#define CODEC_F1C_SEQ_MASK                  (0xF)
-#define CODEC_F1C_SEQ_SHIFT                 (0)
-
-/* Implementation identification (7.3.3.30) */
-#define CODEC_MAKE_F20(bmid, bsku, aid)     \
-    (  (((bmid) & 0xFFFF) << 16)            \
-     | (((bsku) & 0xFF) << 8)               \
-     | (((aid) & 0xFF))                     \
-    )
-
-/* macro definition helping in filling the configuration registers. */
-#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence)    \
-    (  ((port_connectivity) << CODEC_F1C_PORT_SHIFT)          \
-     | ((location) << CODEC_F1C_LOCATION_SHIFT)               \
-     | ((device) << CODEC_F1C_DEVICE_SHIFT)                   \
-     | ((connection_type) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
-     | ((color) << CODEC_F1C_COLOR_SHIFT)                     \
-     | ((misc) << CODEC_F1C_MISC_SHIFT)                       \
-     | ((association) << CODEC_F1C_ASSOCIATION_SHIFT)         \
-     | ((sequence)))
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-/** The F00 parameter length (in dwords). */
-#define CODECNODE_F00_PARAM_LENGTH  20
-/** The F02 parameter length (in dwords). */
-#define CODECNODE_F02_PARAM_LENGTH  16
-
-/**
- * Common (or core) codec node structure.
- */
-typedef struct CODECCOMMONNODE
-{
-    /** Node id - 7 bit format */
-    uint8_t         id;
-    /** The node name. */
-    char const     *pszName;
-    /* PRM 5.3.6 */
-    uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH];
-    uint32_t au32F02_param[CODECNODE_F02_PARAM_LENGTH];
-} CODECCOMMONNODE;
-typedef CODECCOMMONNODE *PCODECCOMMONNODE;
-AssertCompile(CODECNODE_F00_PARAM_LENGTH == 20);  /* saved state */
-AssertCompile(CODECNODE_F02_PARAM_LENGTH == 16); /* saved state */
-
-/**
- * Compile time assertion on the expected node size.
- */
-#define AssertNodeSize(a_Node, a_cParams) \
-    AssertCompile((a_cParams) <= (60 + 6)); /* the max size - saved state */ \
-    AssertCompile(   sizeof(a_Node) - sizeof(CODECCOMMONNODE)  \
-                  == (((a_cParams) * sizeof(uint32_t) + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) )
-
-typedef struct ROOTCODECNODE
-{
-    CODECCOMMONNODE node;
-} ROOTCODECNODE, *PROOTCODECNODE;
-AssertNodeSize(ROOTCODECNODE, 0);
-
-#define AMPLIFIER_SIZE 60
-typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
-#define AMPLIFIER_IN    0
-#define AMPLIFIER_OUT   1
-#define AMPLIFIER_LEFT  1
-#define AMPLIFIER_RIGHT 0
-#define AMPLIFIER_REGISTER(amp, inout, side, index) ((amp)[30*(inout) + 15*(side) + (index)])
-typedef struct DACNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F0d_param;
-    uint32_t    u32F04_param;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F0c_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER B_params;
-
-} DACNODE, *PDACNODE;
-AssertNodeSize(DACNODE, 6 + 60);
-
-typedef struct ADCNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F03_param;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-
-    uint32_t    u32A_param;
-    uint32_t    u32F01_param;
-    AMPLIFIER   B_params;
-} ADCNODE, *PADCNODE;
-AssertNodeSize(DACNODE, 6 + 60);
-
-typedef struct SPDIFOUTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-    uint32_t    u32F0d_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} SPDIFOUTNODE, *PSPDIFOUTNODE;
-AssertNodeSize(SPDIFOUTNODE, 5 + 60);
-
-typedef struct SPDIFINNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F09_param;
-    uint32_t    u32F0d_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} SPDIFINNODE, *PSPDIFINNODE;
-AssertNodeSize(SPDIFINNODE, 5 + 60);
-
-typedef struct AFGCODECNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t  u32F05_param;
-    uint32_t  u32F08_param;
-    uint32_t  u32F20_param;
-    uint32_t  u32F17_param;
-} AFGCODECNODE, *PAFGCODECNODE;
-AssertNodeSize(AFGCODECNODE, 4);
-
-typedef struct PORTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F07_param;
-    uint32_t u32F08_param;
-    uint32_t u32F09_param;
-    uint32_t u32F01_param;
-    uint32_t u32F1c_param;
-    AMPLIFIER   B_params;
-} PORTNODE, *PPORTNODE;
-AssertNodeSize(PORTNODE, 5 + 60);
-
-typedef struct DIGOUTNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F01_param;
-    uint32_t u32F08_param;
-    uint32_t u32F07_param;
-    uint32_t u32F09_param;
-    uint32_t u32F1c_param;
-} DIGOUTNODE, *PDIGOUTNODE;
-AssertNodeSize(DIGOUTNODE, 5);
-
-typedef struct DIGINNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F05_param;
-    uint32_t u32F07_param;
-    uint32_t u32F08_param;
-    uint32_t u32F09_param;
-    uint32_t u32F0c_param;
-    uint32_t u32F1c_param;
-    uint32_t u32F1e_param;
-} DIGINNODE, *PDIGINNODE;
-AssertNodeSize(DIGINNODE, 7);
-
-typedef struct ADCMUXNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F01_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-} ADCMUXNODE, *PADCMUXNODE;
-AssertNodeSize(ADCMUXNODE, 2 + 60);
-
-typedef struct PCBEEPNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F07_param;
-    uint32_t    u32F0a_param;
-
-    uint32_t    u32A_param;
-    AMPLIFIER   B_params;
-    uint32_t    u32F1c_param;
-} PCBEEPNODE, *PPCBEEPNODE;
-AssertNodeSize(PCBEEPNODE, 3 + 60 + 1);
-
-typedef struct CDNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t u32F07_param;
-    uint32_t u32F1c_param;
-} CDNODE, *PCDNODE;
-AssertNodeSize(CDNODE, 2);
-
-typedef struct VOLUMEKNOBNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F08_param;
-    uint32_t    u32F0f_param;
-} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
-AssertNodeSize(VOLUMEKNOBNODE, 2);
-
-typedef struct ADCVOLNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F0c_param;
-    uint32_t    u32F01_param;
-    uint32_t    u32A_params;
-    AMPLIFIER   B_params;
-} ADCVOLNODE, *PADCVOLNODE;
-AssertNodeSize(ADCVOLNODE, 3 + 60);
-
-typedef struct RESNODE
-{
-    CODECCOMMONNODE node;
-    uint32_t    u32F05_param;
-    uint32_t    u32F06_param;
-    uint32_t    u32F07_param;
-    uint32_t    u32F1c_param;
-} RESNODE, *PRESNODE;
-AssertNodeSize(RESNODE, 4);
-
-/**
- * Used for the saved state.
- */
-typedef struct CODECSAVEDSTATENODE
-{
-    CODECCOMMONNODE Core;
-    uint32_t        au32Params[60 + 6];
-} CODECSAVEDSTATENODE;
-AssertNodeSize(CODECSAVEDSTATENODE, 60 + 6);
-
-typedef union CODECNODE
-{
-    CODECCOMMONNODE node;
-    ROOTCODECNODE   root;
-    AFGCODECNODE    afg;
-    DACNODE         dac;
-    ADCNODE         adc;
-    SPDIFOUTNODE    spdifout;
-    SPDIFINNODE     spdifin;
-    PORTNODE        port;
-    DIGOUTNODE      digout;
-    DIGINNODE       digin;
-    ADCMUXNODE      adcmux;
-    PCBEEPNODE      pcbeep;
-    CDNODE          cdnode;
-    VOLUMEKNOBNODE  volumeKnob;
-    ADCVOLNODE      adcvol;
-    RESNODE         reserved;
-    CODECSAVEDSTATENODE SavedState;
-} CODECNODE, *PCODECNODE;
-AssertNodeSize(CODECNODE, 60 + 6);
-
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
-/* STAC9220 - Referenced thru STAC9220WIDGET in the constructor below. */
-static uint8_t const g_abStac9220Ports[]      = { 0x0A, 0xB, 0xC, 0xD, 0xE, 0xF, 0};
-static uint8_t const g_abStac9220Dacs[]       = { 0x02, 0x3, 0x4, 0x5, 0};
-static uint8_t const g_abStac9220Adcs[]       = { 0x06, 0x7, 0};
-static uint8_t const g_abStac9220SpdifOuts[]  = { 0x08, 0 };
-static uint8_t const g_abStac9220SpdifIns[]   = { 0x09, 0 };
-static uint8_t const g_abStac9220DigOutPins[] = { 0x10, 0 };
-static uint8_t const g_abStac9220DigInPins[]  = { 0x11, 0 };
-static uint8_t const g_abStac9220AdcVols[]    = { 0x17, 0x18, 0};
-static uint8_t const g_abStac9220AdcMuxs[]    = { 0x12, 0x13, 0};
-static uint8_t const g_abStac9220Pcbeeps[]    = { 0x14, 0 };
-static uint8_t const g_abStac9220Cds[]        = { 0x15, 0 };
-static uint8_t const g_abStac9220VolKnobs[]   = { 0x16, 0 };
-static uint8_t const g_abStac9220Reserveds[]  = { 0x09, 0x19, 0x1a, 0x1b, 0 };
-
-
-/** SSM description of a CODECNODE. */
-static SSMFIELD const g_aCodecNodeFields[] =
-{
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
-    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F00_param),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F02_param),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, au32Params),
-    SSMFIELD_ENTRY_TERM()
-};
-
-/** Backward compatibility with v1 of the CODECNODE. */
-static SSMFIELD const g_aCodecNodeFieldsV1[] =
-{
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
-    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 7),
-    SSMFIELD_ENTRY_OLD_HCPTR(Core.name),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F00_param),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F02_param),
-    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, au32Params),
-    SSMFIELD_ENTRY_TERM()
-};
-
-
-
-
-static int stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCODECNODE pNode)
-{
-    pNode->node.id = nodenum;
-    pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
-    switch (nodenum)
-    {
-        /* Root Node*/
-        case 0:
-            pNode->node.au32F00_param[0x02] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
-            break;
-        case 1:
-            pNode->node.au32F00_param[0x08] = CODEC_MAKE_F00_08(1, 0xd, 0xd);
-            pNode->node.au32F00_param[0x0C] = CODEC_MAKE_F00_0C(0x17)
-                                            | CODEC_F00_0C_CAP_BALANCED_IO
-                                            | CODEC_F00_0C_CAP_INPUT
-                                            | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                            | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                            | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
-            pNode->node.au32F00_param[0x0B] = CODEC_F00_0B_PCM;
-            pNode->node.au32F00_param[0x0D] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
-            pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
-            pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
-            pNode->node.au32F00_param[0x0F] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
-            pNode->afg.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D2, CODEC_F05_D2);//0x2 << 4| 0x2; /* PS-Act: D3, PS->Set D3  */
-            pNode->afg.u32F08_param = 0;
-            pNode->afg.u32F17_param = 0;
-            break;
-        case 2:
-        case 3:
-        case 4:
-        case 5:
-            memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
-            pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
-
-            AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
-            AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
-
-            pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
-                                             | CODEC_F00_09_CAP_L_R_SWAP
-                                             | CODEC_F00_09_CAP_POWER_CTRL
-                                             | CODEC_F00_09_CAP_OUT_AMP_PRESENT
-                                             | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) |  RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
-            pNode->dac.u32F0c_param = 0;
-            pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3  */
-            break;
-        case 6:
-            pNode->node.au32F02_param[0] = 0x17;
-            goto adc_init;
-        case 7:
-            pNode->node.au32F02_param[0] = 0x18;
-        adc_init:
-            pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
-            pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
-            pNode->adc.u32F03_param = RT_BIT(0);
-            pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
-            pNode->adc.u32F06_param = 0;
-            pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
-                                             | CODEC_F00_09_CAP_POWER_CTRL
-                                             | CODEC_F00_09_CAP_CONNECTION_LIST
-                                             | CODEC_F00_09_CAP_PROC_WIDGET
-                                             | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) |  RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
-            break;
-        case 8:
-            pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
-            pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
-                                                  | CODEC_F00_09_CAP_DIGITAL
-                                                  | CODEC_F00_09_CAP_FMT_OVERRIDE
-                                                  | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
-            pNode->node.au32F00_param[0xa] = pThis->paNodes[1].node.au32F00_param[0xA];
-            pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
-            pNode->spdifout.u32F06_param = 0;
-            pNode->spdifout.u32F0d_param = 0;
-            break;
-        case 9:
-            pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(0x1<<4) | 0x1;
-            pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
-                                                 | CODEC_F00_09_CAP_DIGITAL
-                                                 | CODEC_F00_09_CAP_CONNECTION_LIST
-                                                 | CODEC_F00_09_CAP_FMT_OVERRIDE
-                                                 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
-            pNode->node.au32F00_param[0xA] = pThis->paNodes[1].node.au32F00_param[0xA];
-            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
-            pNode->node.au32F02_param[0] = 0x11;
-            pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
-            pNode->spdifin.u32F06_param = 0;
-            pNode->spdifin.u32F0d_param = 0;
-            break;
-        case 0xA:
-            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
-                                           | CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_HP
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
-            pNode->node.au32F02_param[0] = 0x2;
-            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE
-                                     | CODEC_F07_OUT_ENABLE;
-            pNode->port.u32F08_param = 0;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_FRONT,
-                                                          CODEC_F1C_DEVICE_HP,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_GREEN,
-                                                          CODEC_F1C_MISC_JACK_DETECT,
-                                                          0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
-            goto port_init;
-        case 0xB:
-            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
-                                           | CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
-            pNode->node.au32F02_param[0] = 0x4;
-            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
-                                                          CODEC_F1C_DEVICE_SPEAKER,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_BLACK,
-                                                          CODEC_F1C_MISC_JACK_DETECT,
-                                                          0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
-            goto port_init;
-        case 0xC:
-            pNode->node.au32F02_param[0] = 0x3;
-            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
-                                           | CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
-            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_REAR,
-                                                          CODEC_F1C_DEVICE_SPEAKER,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_GREEN,
-                                                          0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
-            goto port_init;
-        case 0xD:
-            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
-                                           | CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
-            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
-            pNode->node.au32F02_param[0] = 0x2;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_FRONT,
-                                                          CODEC_F1C_DEVICE_MIC,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_PINK,
-                                                          0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
-        port_init:
-            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
-            pNode->port.u32F08_param = 0;
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
-                                         | CODEC_F00_09_CAP_CONNECTION_LIST
-                                         | CODEC_F00_09_CAP_UNSOL
-                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
-            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
-            break;
-        case 0xE:
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
-                                         | CODEC_F00_09_CAP_UNSOL
-                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
-            pNode->port.u32F08_param = 0;
-            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
-            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
-            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_REAR,
-                                                          CODEC_F1C_DEVICE_LINE_OUT,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_BLUE,
-                                                          0x0, 0x4, 0x0);//0x01013040;  /* Line Out */
-            break;
-        case 0xF:
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
-                                         | CODEC_F00_09_CAP_CONNECTION_LIST
-                                         | CODEC_F00_09_CAP_UNSOL
-                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT
-                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
-            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_OUTPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
-                                           /* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
-                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
-            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
-            pNode->port.u32F08_param = 0;
-            pNode->port.u32F07_param = CODEC_F07_OUT_ENABLE
-                                     | CODEC_F07_IN_ENABLE;
-            if (!pThis->fInReset)
-                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                          CODEC_F1C_LOCATION_INTERNAL,
-                                                          CODEC_F1C_DEVICE_SPEAKER,
-                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
-                                                          CODEC_F1C_COLOR_ORANGE,
-                                                          0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
-            pNode->node.au32F02_param[0] = 0x5;
-            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
-            break;
-        case 0x10:
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
-                                         | CODEC_F00_09_CAP_DIGITAL
-                                         | CODEC_F00_09_CAP_CONNECTION_LIST
-                                         | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
-            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
-            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
-            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
-            if (!pThis->fInReset)
-                pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                            CODEC_F1C_LOCATION_REAR,
-                                                            CODEC_F1C_DEVICE_SPDIF_OUT,
-                                                            CODEC_F1C_CONNECTION_TYPE_DIN,
-                                                            CODEC_F1C_COLOR_BLACK,
-                                                            0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
-            break;
-        case 0x11:
-            pNode->node.au32F00_param[9] = (4 << 20) | (3 << 16) | RT_BIT(10) | RT_BIT(9) | RT_BIT(7) | RT_BIT(0);
-            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
-                                           | CODEC_F00_0C_CAP_INPUT
-                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
-            pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
-            pNode->digin.u32F07_param = 0;
-            pNode->digin.u32F08_param = 0;
-            pNode->digin.u32F09_param = 0;
-            pNode->digin.u32F0c_param = 0;
-            if (!pThis->fInReset)
-                pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
-                                                           CODEC_F1C_LOCATION_REAR,
-                                                           CODEC_F1C_DEVICE_SPDIF_IN,
-                                                           CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
-                                                           CODEC_F1C_COLOR_BLACK,
-                                                           0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
-            break;
-        case 0x12:
-            pNode->adcmux.u32F01_param = 0;
-            goto adcmux_init;
-        case 0x13:
-            pNode->adcmux.u32F01_param = 1;
-            adcmux_init:
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
-                                         | CODEC_F00_09_CAP_CONNECTION_LIST
-                                         | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
-                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT
-                                         | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
-            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
-            pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
-            /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
-            memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
-            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
-            pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
-            break;
-        case 0x14:
-            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
-                                         | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
-                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
-            pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
-            pNode->pcbeep.u32F0a_param = 0;
-            memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
-            break;
-        case 0x15:
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
-                                           | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
-            pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
-            if (!pThis->fInReset)
-                pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
-                                                            CODEC_F1C_LOCATION_INTERNAL,
-                                                            CODEC_F1C_DEVICE_CD,
-                                                            CODEC_F1C_CONNECTION_TYPE_ATAPI,
-                                                            CODEC_F1C_COLOR_UNKNOWN,
-                                                            0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
-            break;
-        case 0x16:
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
-            pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
-            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
-            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
-            pNode->volumeKnob.u32F08_param = 0;
-            pNode->volumeKnob.u32F0f_param = 0x7f;
-            break;
-        case 0x17:
-            pNode->node.au32F02_param[0] = 0x12;
-            goto adcvol_init;
-        case 0x18:
-            pNode->node.au32F02_param[0] = 0x13;
-        adcvol_init:
-            memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
-
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
-                                           | CODEC_F00_09_CAP_L_R_SWAP
-                                           | CODEC_F00_09_CAP_CONNECTION_LIST
-                                           | CODEC_F00_09_CAP_IN_AMP_PRESENT
-                                           | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
-            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
-            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
-            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
-            pNode->adcvol.u32F0c_param = 0;
-            break;
-        case 0x19:
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
-                                           | CODEC_F00_09_CAP_DIGITAL
-                                           | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
-            break;
-        case 0x1A:
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
-                                           | CODEC_F00_09_CAP_DIGITAL
-                                           | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
-            break;
-        case 0x1B:
-            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
-                                           | CODEC_F00_09_CAP_DIGITAL
-                                           | CODEC_F00_09_CAP_CONNECTION_LIST
-                                           | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
-            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
-            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
-            pNode->node.au32F02_param[0] = 0x1a;
-            pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
-                                                          CODEC_F1C_LOCATION_NA,
-                                                          CODEC_F1C_DEVICE_LINE_OUT,
-                                                          CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
-                                                          CODEC_F1C_COLOR_UNKNOWN,
-                                                          0x0, 0x0, 0xf);//0x4000000f;
-            break;
-        default:
-        break;
-    }
-    return VINF_SUCCESS;
-}
-
-
-static int stac9220Construct(PHDACODEC pThis)
-{
-    unconst(pThis->cTotalNodes) = 0x1C;
-    pThis->pfnCodecNodeReset = stac9220ResetNode;
-    pThis->u16VendorId = 0x8384;
-    pThis->u16DeviceId = 0x7680;
-    pThis->u8BSKU = 0x76;
-    pThis->u8AssemblyId = 0x80;
-    pThis->paNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pThis->cTotalNodes);
-    pThis->fInReset = false;
-#define STAC9220WIDGET(type) pThis->au8##type##s = g_abStac9220##type##s
-    STAC9220WIDGET(Port);
-    STAC9220WIDGET(Dac);
-    STAC9220WIDGET(Adc);
-    STAC9220WIDGET(AdcVol);
-    STAC9220WIDGET(AdcMux);
-    STAC9220WIDGET(Pcbeep);
-    STAC9220WIDGET(SpdifIn);
-    STAC9220WIDGET(SpdifOut);
-    STAC9220WIDGET(DigInPin);
-    STAC9220WIDGET(DigOutPin);
-    STAC9220WIDGET(Cd);
-    STAC9220WIDGET(VolKnob);
-    STAC9220WIDGET(Reserved);
-#undef STAC9220WIDGET
-    unconst(pThis->u8AdcVolsLineIn) = 0x17;
-    unconst(pThis->u8DacLineOut) = 0x2;
-
-    return VINF_SUCCESS;
-}
-
-
-/*
- * Some generic predicate functions.
- */
-
-#define DECLISNODEOFTYPE(type)                                                                  \
-    DECLINLINE(int) hdaCodecIs##type##Node(PHDACODEC pThis, uint8_t cNode)                     \
-    {                                                                                           \
-        Assert(pThis->au8##type##s);                                                           \
-        for (int i = 0; pThis->au8##type##s[i] != 0; ++i)                                      \
-            if (pThis->au8##type##s[i] == cNode)                                               \
-                return 1;                                                                       \
-        return 0;                                                                               \
-    }
-/* hdaCodecIsPortNode */
-DECLISNODEOFTYPE(Port)
-/* hdaCodecIsDacNode */
-DECLISNODEOFTYPE(Dac)
-/* hdaCodecIsAdcVolNode */
-DECLISNODEOFTYPE(AdcVol)
-/* hdaCodecIsAdcNode */
-DECLISNODEOFTYPE(Adc)
-/* hdaCodecIsAdcMuxNode */
-DECLISNODEOFTYPE(AdcMux)
-/* hdaCodecIsPcbeepNode */
-DECLISNODEOFTYPE(Pcbeep)
-/* hdaCodecIsSpdifOutNode */
-DECLISNODEOFTYPE(SpdifOut)
-/* hdaCodecIsSpdifInNode */
-DECLISNODEOFTYPE(SpdifIn)
-/* hdaCodecIsDigInPinNode */
-DECLISNODEOFTYPE(DigInPin)
-/* hdaCodecIsDigOutPinNode */
-DECLISNODEOFTYPE(DigOutPin)
-/* hdaCodecIsCdNode */
-DECLISNODEOFTYPE(Cd)
-/* hdaCodecIsVolKnobNode */
-DECLISNODEOFTYPE(VolKnob)
-/* hdaCodecIsReservedNode */
-DECLISNODEOFTYPE(Reserved)
-
-
-/*
- * Misc helpers.
- */
-
-static int hdaCodecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
-{
-    uint32_t dir = AMPLIFIER_OUT;
-    switch (mt)
-    {
-        case AUD_MIXER_VOLUME:
-        case AUD_MIXER_PCM:
-            dir = AMPLIFIER_OUT;
-            break;
-        case AUD_MIXER_LINE_IN:
-            dir = AMPLIFIER_IN;
-            break;
-    }
-    int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
-    mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
-    mute >>=7;
-    mute &= 0x1;
-    uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
-    uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
-    AUD_set_volume(mt, &mute, &lVol, &rVol);
-    return VINF_SUCCESS;
-}
-
-DECLINLINE(void) hdaCodecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
-{
-    Assert((pu32Reg && u8Offset < 32));
-    *pu32Reg &= ~(mask << u8Offset);
-    *pu32Reg |= (u32Cmd & mask) << u8Offset;
-}
-
-DECLINLINE(void) hdaCodecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
-{
-    hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
-}
-
-DECLINLINE(void) hdaCodecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
-{
-    hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
-}
-
-
-/*
- * Verb processor functions.
- */
-
-static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Log(("vrbProcUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
-        CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
-    *pResp = 0;
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcBreak(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    int rc;
-    rc = vrbProcUnimplemented(pThis, cmd, pResp);
-    *pResp |= CODEC_RESPONSE_UNSOLICITED;
-    return rc;
-}
-
-/* B-- */
-static DECLCALLBACK(int) vrbProcGetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    /* HDA spec 7.3.3.7 Note A */
-    /** @todo: if index out of range response should be 0 */
-    uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
-
-    PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
-                            CODEC_GET_AMP_DIRECTION(cmd),
-                            CODEC_GET_AMP_SIDE(cmd),
-                            u8Index);
-    else
-        AssertMsgFailedReturn(("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
-    return VINF_SUCCESS;
-}
-
-/* 3-- */
-static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    bool fIsLeft = false;
-    bool fIsRight = false;
-    bool fIsOut = false;
-    bool fIsIn = false;
-    uint8_t u8Index = 0;
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
-    AMPLIFIER *pAmplifier;
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->dac.B_params;
-    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->adcvol.B_params;
-    else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->adcmux.B_params;
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->pcbeep.B_params;
-    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->port.B_params;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pAmplifier = &pNode->adc.B_params;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-
-    fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
-    fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
-    fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
-    fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
-    u8Index = CODEC_SET_AMP_INDEX(cmd);
-    if (   (!fIsLeft && !fIsRight)
-        || (!fIsOut && !fIsIn))
-        return VINF_SUCCESS;
-    if (fIsIn)
-    {
-        if (fIsLeft)
-            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
-        if (fIsRight)
-            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
-    }
-    if (fIsOut)
-    {
-        if (fIsLeft)
-            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
-        if (fIsRight)
-            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
-    }
-    if (CODEC_NID(cmd) == pThis->u8DacLineOut)
-        hdaCodecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
-    if (CODEC_NID(cmd) == pThis->u8AdcVolsLineIn) /* Microphone */
-        hdaCodecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F00_PARAM_LENGTH);
-    if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F00_PARAM_LENGTH)
-    {
-        Log(("HdaCodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
-        return VINF_SUCCESS;
-    }
-    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
-    return VINF_SUCCESS;
-}
-
-/* F01 */
-static DECLCALLBACK(int) vrbProcGetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
-    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
-    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
-    return VINF_SUCCESS;
-}
-
-/* 701 */
-static DECLCALLBACK(int) vrbProcSetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
-    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
-    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F07 */
-static DECLCALLBACK(int) vrbProcGetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
-    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
-    else
-        AssertMsgFailed(("Unsupported"));
-    return VINF_SUCCESS;
-}
-
-/* 707 */
-static DECLCALLBACK(int) vrbProcSetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
-    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
-    else if (   hdaCodecIsReservedNode(pThis, CODEC_NID(cmd))
-             && CODEC_NID(cmd) == 0x1b)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F08 */
-static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
-    else if ((cmd) == 1 /* AFG */)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
-    else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
-    else
-        AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
-    return VINF_SUCCESS;
-}
-
-/* 708 */
-static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
-    else if (CODEC_NID(cmd) == 1 /* AFG */)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
-    else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
-    else
-        AssertMsgFailedReturn(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)), VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F09 */
-static DECLCALLBACK(int) vrbProcGetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
-    else
-        AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
-    return VINF_SUCCESS;
-}
-
-/* 709 */
-static DECLCALLBACK(int) vrbProcSetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    *pResp = 0;
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
-    if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
-    {
-        Log(("HdaCodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
-        return VINF_SUCCESS;
-    }
-    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
-    return VINF_SUCCESS;
-}
-
-/* F03 */
-static DECLCALLBACK(int) vrbProcGetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param;
-    return VINF_SUCCESS;
-}
-
-/* 703 */
-static DECLCALLBACK(int) vrbProcSetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F0D */
-static DECLCALLBACK(int) vrbProcGetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
-    return VINF_SUCCESS;
-}
-
-static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
-    return VINF_SUCCESS;
-}
-
-/* 70D */
-static DECLCALLBACK(int) vrbProcSetDigitalConverter1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    return codecSetDigitalConverter(pThis, cmd, 0, pResp);
-}
-
-/* 70E */
-static DECLCALLBACK(int) vrbProcSetDigitalConverter2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    return codecSetDigitalConverter(pThis, cmd, 8, pResp);
-}
-
-/* F20 */
-static DECLCALLBACK(int) vrbProcGetSubId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    if (CODEC_NID(cmd) == 1 /* AFG */)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
-    else
-        *pResp = 0;
-    return VINF_SUCCESS;
-}
-
-static int codecSetSubIdX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    uint32_t *pu32Reg;
-    if (CODEC_NID(cmd) == 0x1 /* AFG */)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
-    return VINF_SUCCESS;
-}
-
-/* 720 */
-static DECLCALLBACK(int) vrbProcSetSubId0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetSubIdX(pThis, cmd, 0);
-}
-
-/* 721 */
-static DECLCALLBACK(int) vrbProcSetSubId1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetSubIdX(pThis, cmd, 8);
-}
-
-/* 722 */
-static DECLCALLBACK(int) vrbProcSetSubId2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetSubIdX(pThis, cmd, 16);
-}
-
-/* 723 */
-static DECLCALLBACK(int) vrbProcSetSubId3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetSubIdX(pThis, cmd, 24);
-}
-
-static DECLCALLBACK(int) vrbProcReset(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) == 1 /* AFG */);
-    if (   CODEC_NID(cmd) == 1 /* AFG */
-        && pThis->pfnCodecNodeReset)
-    {
-        uint8_t i;
-        Log(("HdaCodec: enters reset\n"));
-        Assert(pThis->pfnCodecNodeReset);
-        for (i = 0; i < pThis->cTotalNodes; ++i)
-        {
-            pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
-        }
-        pThis->fInReset = false;
-        Log(("HdaCodec: exits reset\n"));
-    }
-    *pResp = 0;
-    return VINF_SUCCESS;
-}
-
-/* F05 */
-static DECLCALLBACK(int) vrbProcGetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (CODEC_NID(cmd) == 1 /* AFG */)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
-    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
-    return VINF_SUCCESS;
-}
-
-/* 705 */
-
-DECLINLINE(void) codecPropogatePowerState(uint32_t *pu32F05_param)
-{
-    Assert(pu32F05_param);
-    if (!pu32F05_param)
-        return;
-    bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
-    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
-    uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
-    *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
-}
-
-static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (CODEC_NID(cmd) == 1 /* AFG */)
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
-    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-
-    bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
-    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
-
-    if (CODEC_NID(cmd) != 1 /* AFG */)
-    {
-        /*
-         * We shouldn't propogate actual power state, which actual for AFG
-         */
-        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
-                                  CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param),
-                                  CODEC_F05_SET(cmd));
-    }
-
-    /* Propagate next power state only if AFG is on or verb modifies AFG power state */
-    if (   CODEC_NID(cmd) == 1 /* AFG */
-        || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param))
-    {
-        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
-        if (   CODEC_NID(cmd) == 1 /* AFG */
-            && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
-        {
-            /* now we're powered on AFG and may propogate power states on nodes */
-            const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0];
-            while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param);
-
-            pu8NodeIndex = &pThis->au8Adcs[0];
-            while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param);
-
-            pu8NodeIndex = &pThis->au8DigInPins[0];
-            while (*(++pu8NodeIndex))
-                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param);
-        }
-    }
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcGetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
-    else if (CODEC_NID(cmd) == 0x1A)
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    uint32_t *pu32addr;
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32addr, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param;
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param;
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param;
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param;
-    return VINF_SUCCESS;
-}
-
-static DECLCALLBACK(int) vrbProcSetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
-    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
-    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
-    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
-        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F0C */
-static DECLCALLBACK(int) vrbProcGetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
-    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
-    return VINF_SUCCESS;
-}
-
-/* 70C */
-static DECLCALLBACK(int) vrbProcSetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-
-    *pResp = 0;
-    uint32_t *pu32Reg;
-    if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
-    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
-    else
-        AssertFailedReturn(VINF_SUCCESS);
-    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-
-    return VINF_SUCCESS;
-}
-
-/* F0F */
-static DECLCALLBACK(int) vrbProcGetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
-    return VINF_SUCCESS;
-}
-
-/* 70F */
-static DECLCALLBACK(int) vrbProcSetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    uint32_t *pu32Reg = NULL;
-    *pResp = 0;
-    if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
-    Assert(pu32Reg);
-    if (pu32Reg)
-        hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F17 */
-static DECLCALLBACK(int) vrbProcGetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    /* note: this is true for ALC885 */
-    if (CODEC_NID(cmd) == 0x1 /* AFG */)
-        *pResp = pThis->paNodes[1].afg.u32F17_param;
-    return VINF_SUCCESS;
-}
-
-/* 717 */
-static DECLCALLBACK(int) vrbProcSetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    uint32_t *pu32Reg = NULL;
-    *pResp = 0;
-    if (CODEC_NID(cmd) == 1 /* AFG */)
-        pu32Reg = &pThis->paNodes[1].afg.u32F17_param;
-    Assert(pu32Reg);
-    if (pu32Reg)
-        hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
-    return VINF_SUCCESS;
-}
-
-/* F1C */
-static DECLCALLBACK(int) vrbProcGetConfig(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    *pResp = 0;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
-    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
-    return VINF_SUCCESS;
-}
-
-static int codecSetConfigX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
-    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
-        return VINF_SUCCESS;
-    }
-    uint32_t *pu32Reg = NULL;
-    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
-    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
-    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
-    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
-    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
-    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
-    Assert(pu32Reg);
-    if (pu32Reg)
-        hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
-    return VINF_SUCCESS;
-}
-
-/* 71C */
-static DECLCALLBACK(int) vrbProcSetConfig0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetConfigX(pThis, cmd, 0);
-}
-
-/* 71D */
-static DECLCALLBACK(int) vrbProcSetConfig1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetConfigX(pThis, cmd, 8);
-}
-
-/* 71E */
-static DECLCALLBACK(int) vrbProcSetConfig2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetConfigX(pThis, cmd, 16);
-}
-
-/* 71E */
-static DECLCALLBACK(int) vrbProcSetConfig3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
-{
-    *pResp = 0;
-    return codecSetConfigX(pThis, cmd, 24);
-}
-
-
-/**
- * HDA codec verb map.
- * @todo Any reason not to use binary search here?
- */
-static const CODECVERB g_aCodecVerbs[] =
-{
-/*     verb     | verb mask              | callback               */
-/*   -----------  --------------------   -----------------------  */
-    { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter           },
-    { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl       },
-    { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl       },
-    { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId            },
-    { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId            },
-    { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl             },
-    { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl             },
-    { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled  },
-    { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled  },
-    { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense            },
-    { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense            },
-    { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry },
-    { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState     },
-    { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState     },
-    { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter    },
-    { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1   },
-    { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2   },
-    { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId               },
-    { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0              },
-    { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1              },
-    { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2              },
-    { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3              },
-    { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset                  },
-    { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState          },
-    { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState          },
-    { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled     },
-    { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled     },
-    { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl      },
-    { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl      },
-    { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted      },
-    { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted      },
-    { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig              },
-    { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0             },
-    { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1             },
-    { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2             },
-    { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3             },
-    { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat     },
-    { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat     },
-    { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier           },
-    { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier           },
-};
-
-static int codecLookup(PHDACODEC pThis, uint32_t cmd, PPFNHDACODECVERBPROCESSOR pfn)
-{
-    Assert(CODEC_CAD(cmd) == pThis->id);
-    if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
-        Log(("HdaCodec: cmd %x was addressed to reserved node\n", cmd));
-
-    if (   CODEC_VERBDATA(cmd) == 0
-        || CODEC_NID(cmd) >= pThis->cTotalNodes)
-    {
-        *pfn = vrbProcUnimplemented;
-        /// @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
-        Log(("HdaCodec: cmd %x was ignored\n", cmd));
-        return VINF_SUCCESS;
-    }
-
-    for (int i = 0; i < pThis->cVerbs; ++i)
-    {
-        if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb)
-        {
-            *pfn = pThis->paVerbs[i].pfn;
-            return VINF_SUCCESS;
-        }
-    }
-
-    *pfn = vrbProcUnimplemented;
-    Log(("HdaCodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
-    return VINF_SUCCESS;
-}
-
-static void pi_callback(void *opaque, int avail)
-{
-    PHDACODEC pThis = (PHDACODEC)opaque;
-    pThis->pfnTransfer(pThis, PI_INDEX, avail);
-}
-
-static void po_callback(void *opaque, int avail)
-{
-    PHDACODEC pThis = (PHDACODEC)opaque;
-    pThis->pfnTransfer(pThis, PO_INDEX, avail);
-}
-
-
-
-/*
- * APIs exposed to DevHDA.
- */
-
-
-/**
- *
- * routines open one of the voices (IN, OUT) with corresponding parameters.
- * this routine could be called from HDA on setting/resseting sound format.
- *
- * @todo Probably passed settings should be verified (if AFG's declared proposed
- *       format) before enabling.
- */
-int hdaCodecOpenVoice(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings)
-{
-    int rc;
-    Assert(pThis && pAudioSettings);
-    if (   !pThis
-        || !pAudioSettings)
-        return -1;
-    switch (enmSoundSource)
-    {
-        case PI_INDEX:
-            pThis->SwVoiceIn = AUD_open_in(&pThis->card, pThis->SwVoiceIn, "hda.in", pThis, pi_callback, pAudioSettings);
-            rc = pThis->SwVoiceIn ? 0 : 1;
-            break;
-        case PO_INDEX:
-            pThis->SwVoiceOut = AUD_open_out(&pThis->card, pThis->SwVoiceOut, "hda.out", pThis, po_callback, pAudioSettings);
-            rc = pThis->SwVoiceOut ? 0 : 1;
-            break;
-        default:
-            return -1;
-    }
-    if (!rc)
-        LogRel(("HdaCodec: can't open %s fmt(freq: %d)\n", enmSoundSource == PI_INDEX? "in" : "out", pAudioSettings->freq));
-    return rc;
-}
-
-
-int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM)
-{
-    AssertLogRelMsgReturn(pThis->cTotalNodes == 0x1c, ("cTotalNodes=%#x, should be 0x1c", pThis->cTotalNodes),
-                          VERR_INTERNAL_ERROR);
-    SSMR3PutU32(pSSM, pThis->cTotalNodes);
-    for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
-        SSMR3PutStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
-                         0 /*fFlags*/, g_aCodecNodeFields, NULL /*pvUser*/);
-    return VINF_SUCCESS;
-}
-
-
-int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion)
-{
-    PCSSMFIELD pFields;
-    uint32_t   fFlags;
-    switch (uVersion)
-    {
-        case HDA_SSM_VERSION_1:
-            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
-            pFields = g_aCodecNodeFieldsV1;
-            fFlags  = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
-            break;
-
-        case HDA_SSM_VERSION_2:
-        case HDA_SSM_VERSION_3:
-            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
-            pFields = g_aCodecNodeFields;
-            fFlags  = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
-            break;
-
-        case HDA_SSM_VERSION:
-        {
-            uint32_t cNodes;
-            int rc2 = SSMR3GetU32(pSSM, &cNodes);
-            AssertRCReturn(rc2, rc2);
-            if (cNodes != 0x1c)
-                return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
-            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
-
-            pFields = g_aCodecNodeFields;
-            fFlags  = 0;
-            break;
-        }
-
-        default:
-            return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
-    }
-
-    for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
-    {
-        uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.id;
-        int rc = SSMR3GetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState,
-                                  sizeof(pThis->paNodes[idxNode].SavedState),
-                                  fFlags, pFields, NULL);
-        if (RT_FAILURE(rc))
-            return rc;
-        AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.id,
-                              ("loaded %#x, expected \n", pThis->paNodes[idxNode].SavedState.Core.id, idOld),
-                              VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
-    }
-
-    /*
-     * Update stuff after changing the state.
-     */
-    if (hdaCodecIsDacNode(pThis, pThis->u8DacLineOut))
-        hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
-    else if (hdaCodecIsSpdifOutNode(pThis, pThis->u8DacLineOut))
-        hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
-    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
-
-    return VINF_SUCCESS;
-}
-
-
-int hdaCodecDestruct(PHDACODEC pThis)
-{
-    RTMemFree(pThis->paNodes);
-    pThis->paNodes = NULL;
-    return VINF_SUCCESS;
-}
-
-
-int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PCFGMNODE pCfg)
-{
-    pThis->paVerbs   = &g_aCodecVerbs[0];
-    pThis->cVerbs    = RT_ELEMENTS(g_aCodecVerbs);
-    pThis->pfnLookup = codecLookup;
-    int rc = stac9220Construct(pThis);
-    AssertRC(rc);
-
-    /* common root node initializers */
-    pThis->paNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
-    pThis->paNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
-    /* common AFG node initializers */
-    pThis->paNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
-    pThis->paNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
-    pThis->paNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
-
-    /// @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
-    AUD_register_card ("ICH0", &pThis->card);
-
-    /* 44.1 kHz */
-    audsettings_t as;
-    as.freq = 44100;
-    as.nchannels = 2;
-    as.fmt = AUD_FMT_S16;
-    as.endianness = 0;
-
-    pThis->paNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
-    hdaCodecOpenVoice(pThis, PI_INDEX, &as);
-    hdaCodecOpenVoice(pThis, PO_INDEX, &as);
-    pThis->paNodes[1].node.au32F00_param[0xA] |= CODEC_F00_0A_44_1KHZ;
-
-    uint8_t i;
-    Assert(pThis->paNodes);
-    Assert(pThis->pfnCodecNodeReset);
-    for (i = 0; i < pThis->cTotalNodes; ++i)
-    {
-        pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
-    }
-
-    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
-    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
-
-    /* If no host voices were created, then fallback to nul audio. */
-    if (!AUD_is_host_voice_in_ok(pThis->SwVoiceIn))
-        LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
-    if (!AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
-        LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
-
-    if (   !AUD_is_host_voice_in_ok(pThis->SwVoiceIn)
-        && !AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
-    {
-        /* Was not able initialize *any* voice. Select the NULL audio driver instead */
-        AUD_close_in  (&pThis->card, pThis->SwVoiceIn);
-        AUD_close_out (&pThis->card, pThis->SwVoiceOut);
-        pThis->SwVoiceOut = NULL;
-        pThis->SwVoiceIn = NULL;
-        AUD_init_null ();
-
-        PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
-            N_ ("No audio devices could be opened. Selecting the NULL audio backend "
-                "with the consequence that no sound is audible"));
-    }
-    else if (   !AUD_is_host_voice_in_ok(pThis->SwVoiceIn)
-             || !AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
-    {
-        char   szMissingVoices[128];
-        size_t len = 0;
-        if (!AUD_is_host_voice_in_ok(pThis->SwVoiceIn))
-            len = RTStrPrintf (szMissingVoices, sizeof(szMissingVoices), "PCM_in");
-        if (!AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
-            len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
-
-        PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
-            N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
-                "output or depending on audio input may hang. Make sure your host audio device "
-                "is working properly. Check the logfile for error messages of the audio "
-                "subsystem"), szMissingVoices);
-    }
-
-    return VINF_SUCCESS;
-}
-
Index: trunk/src/VBox/Devices/Audio/DevCodec.h
===================================================================
--- trunk/src/VBox/Devices/Audio/DevCodec.h	(revision 44668)
+++ 	(revision )
@@ -1,137 +1,0 @@
-/* $Id$ */
-/** @file
- * DevCodec - VBox ICH Intel HD Audio Codec.
- */
-
-/*
- * Copyright (C) 2006-2013 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 DEV_CODEC_H
-#define DEV_CODEC_H
-
-/** The ICH HDA (Intel) codec state. */
-typedef struct HDACODEC HDACODEC;
-/** Pointer to the Intel ICH HDA codec state. */
-typedef HDACODEC *PHDACODEC;
-
-/**
- * Verb processor method.
- */
-typedef DECLCALLBACK(int) FNHDACODECVERBPROCESSOR(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp);
-typedef FNHDACODECVERBPROCESSOR *PFNHDACODECVERBPROCESSOR;
-typedef FNHDACODECVERBPROCESSOR **PPFNHDACODECVERBPROCESSOR;
-
-/* PRM 5.3.1 */
-#define CODEC_RESPONSE_UNSOLICITED RT_BIT_64(34)
-
-
-#ifndef VBOX_WITH_HDA_CODEC_EMU
-typedef struct CODECVERB
-{
-    uint32_t verb;
-    /* operation bitness mask */
-    uint32_t mask;
-    PFNHDACODECVERBPROCESSOR pfn;
-} CODECVERB;
-#endif
-
-#ifndef VBOX_WITH_HDA_CODEC_EMU
-# define TYPE union
-#else
-# define TYPE struct
-typedef struct CODECEMU CODECEMU;
-typedef CODECEMU *PCODECEMU;
-#endif
-TYPE CODECNODE;
-typedef TYPE CODECNODE CODECNODE;
-typedef TYPE CODECNODE *PCODECNODE;
-
-typedef enum
-{
-    PI_INDEX = 0,    /* PCM in */
-    PO_INDEX,        /* PCM out */
-    MC_INDEX,        /* Mic in */
-    LAST_INDEX
-} ENMSOUNDSOURCE;
-
-
-typedef struct HDACODEC
-{
-    uint16_t                id;
-    uint16_t                u16VendorId;
-    uint16_t                u16DeviceId;
-    uint8_t                 u8BSKU;
-    uint8_t                 u8AssemblyId;
-#ifndef VBOX_WITH_HDA_CODEC_EMU
-    CODECVERB const        *paVerbs;
-    int                     cVerbs;
-#else
-    PCODECEMU               pCodecBackend;
-#endif
-    PCODECNODE              paNodes;
-    QEMUSoundCard           card;
-    /** PCM in */
-    SWVoiceIn               *SwVoiceIn;
-    /** PCM out */
-    SWVoiceOut              *SwVoiceOut;
-    void                   *pvHDAState;
-    bool                    fInReset;
-#ifndef VBOX_WITH_HDA_CODEC_EMU
-    const uint8_t           cTotalNodes;
-    const uint8_t           *au8Ports;
-    const uint8_t           *au8Dacs;
-    const uint8_t           *au8AdcVols;
-    const uint8_t           *au8Adcs;
-    const uint8_t           *au8AdcMuxs;
-    const uint8_t           *au8Pcbeeps;
-    const uint8_t           *au8SpdifIns;
-    const uint8_t           *au8SpdifOuts;
-    const uint8_t           *au8DigInPins;
-    const uint8_t           *au8DigOutPins;
-    const uint8_t           *au8Cds;
-    const uint8_t           *au8VolKnobs;
-    const uint8_t           *au8Reserveds;
-    const uint8_t           u8AdcVolsLineIn;
-    const uint8_t           u8DacLineOut;
-#endif
-    DECLR3CALLBACKMEMBER(int, pfnProcess, (PHDACODEC pCodec));
-    DECLR3CALLBACKMEMBER(void, pfnTransfer, (PHDACODEC pCodec, ENMSOUNDSOURCE, int avail));
-    /* These callbacks are set by Codec implementation. */
-    DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t verb, PPFNHDACODECVERBPROCESSOR));
-    DECLR3CALLBACKMEMBER(int, pfnReset, (PHDACODEC pThis));
-    DECLR3CALLBACKMEMBER(int, pfnCodecNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE));
-    /* These callbacks are set by codec implementation to answer debugger requests. */
-    DECLR3CALLBACKMEMBER(void, pfnCodecDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
-    DECLR3CALLBACKMEMBER(void, pfnCodecDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
-} CODECState;
-
-int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PCFGMNODE pCfg);
-int hdaCodecDestruct(PHDACODEC pThis);
-int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM);
-int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion);
-int hdaCodecOpenVoice(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings);
-
-#define HDA_SSM_VERSION   4
-#define HDA_SSM_VERSION_1 1
-#define HDA_SSM_VERSION_2 2
-#define HDA_SSM_VERSION_3 3
-
-# ifdef VBOX_WITH_HDA_CODEC_EMU
-/* */
-struct CODECEMU
-{
-    DECLR3CALLBACKMEMBER(int, pfnCodecEmuConstruct,(PHDACODEC pThis));
-    DECLR3CALLBACKMEMBER(int, pfnCodecEmuDestruct,(PHDACODEC pThis));
-    DECLR3CALLBACKMEMBER(int, pfnCodecEmuReset,(PHDACODEC pThis, bool fInit));
-};
-# endif
-#endif
Index: trunk/src/VBox/Devices/Audio/DevIchHda.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevIchHda.cpp	(revision 44669)
+++ trunk/src/VBox/Devices/Audio/DevIchHda.cpp	(revision 44669)
@@ -0,0 +1,3086 @@
+/* $Id$ */
+/** @file
+ * DevIchHda - VBox ICH Intel HD Audio Controller.
+ *
+ * Implemented against the specifications found in "High Definition Audio
+ * Specification", Revision 1.0a June 17, 2010, and  "Intel I/O Controller
+ * HUB 6 (ICH6) Family, Datasheet", document number 301473-002.
+ */
+
+/*
+ * Copyright (C) 2006-2013 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_AUDIO
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/version.h>
+
+#include <iprt/assert.h>
+#include <iprt/uuid.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+
+#include "VBoxDD.h"
+
+extern "C" {
+#include "audio.h"
+}
+#include "DevIchHdaCodec.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+//#define HDA_AS_PCI_EXPRESS
+#define VBOX_WITH_INTEL_HDA
+
+#if defined(VBOX_WITH_HP_HDA)
+/* HP Pavilion dv4t-1300 */
+# define HDA_PCI_VENDOR_ID 0x103c
+# define HDA_PCI_DEICE_ID 0x30f7
+#elif defined(VBOX_WITH_INTEL_HDA)
+/* Intel HDA controller */
+# define HDA_PCI_VENDOR_ID 0x8086
+# define HDA_PCI_DEICE_ID 0x2668
+#elif defined(VBOX_WITH_NVIDIA_HDA)
+/* nVidia HDA controller */
+# define HDA_PCI_VENDOR_ID 0x10de
+# define HDA_PCI_DEICE_ID 0x0ac0
+#else
+# error "Please specify your HDA device vendor/device IDs"
+#endif
+
+/** @todo r=bird: Looking at what the linux driver (accidentally?) does when
+ * updating CORBWP, I belive that the ICH6 datahsheet is wrong and that CORBRP
+ * is read only except for bit 15 like the HDA spec states.
+ *
+ * Btw. the CORBRPRST implementation is incomplete according to both docs (sw
+ * writes 1, hw sets it to 1 (after completion), sw reads 1, sw writes 0). */
+#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
+
+#define HDA_NREGS 112
+/* Registers */
+#define HDA_REG_IND_NAME(x)                 ICH6_HDA_REG_##x
+#define HDA_REG_FIELD_NAME(reg, x)          ICH6_HDA_##reg##_##x
+#define HDA_REG_FIELD_MASK(reg, x)          ICH6_HDA_##reg##_##x##_MASK
+#define HDA_REG_FIELD_FLAG_MASK(reg, x)     RT_BIT(ICH6_HDA_##reg##_##x##_SHIFT)
+#define HDA_REG_FIELD_SHIFT(reg, x)         ICH6_HDA_##reg##_##x##_SHIFT
+#define HDA_REG_IND(pThis, x)               ((pThis)->au32Regs[(x)])
+#define HDA_REG(pThis, x)                   (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
+#define HDA_REG_VALUE(pThis, reg, val)      (HDA_REG((pThis),reg) & (((HDA_REG_FIELD_MASK(reg, val))) << (HDA_REG_FIELD_SHIFT(reg, val))))
+#define HDA_REG_FLAG_VALUE(pThis, reg, val) (HDA_REG((pThis),reg) & (((HDA_REG_FIELD_FLAG_MASK(reg, val)))))
+#define HDA_REG_SVALUE(pThis, reg, val)     (HDA_REG_VALUE(pThis, reg, val) >> (HDA_REG_FIELD_SHIFT(reg, val)))
+
+#define ICH6_HDA_REG_GCAP 0 /* range 0x00-0x01*/
+#define GCAP(pThis) (HDA_REG((pThis), GCAP))
+/* 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 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 ICH6_HDA_REG_VMIN           1 /* range 0x02 */
+#define VMIN(pThis)                 (HDA_REG((pThis), VMIN))
+
+#define ICH6_HDA_REG_VMAJ           2 /* range 0x03 */
+#define VMAJ(pThis)                 (HDA_REG((pThis), VMAJ))
+
+#define ICH6_HDA_REG_OUTPAY         3 /* range 0x04-0x05 */
+#define OUTPAY(pThis)               (HDA_REG((pThis), OUTPAY))
+
+#define ICH6_HDA_REG_INPAY          4 /* range 0x06-0x07 */
+#define INPAY(pThis)                (HDA_REG((pThis), INPAY))
+
+#define ICH6_HDA_REG_GCTL           (5)
+#define ICH6_HDA_GCTL_RST_SHIFT     (0)
+#define ICH6_HDA_GCTL_FSH_SHIFT     (1)
+#define ICH6_HDA_GCTL_UR_SHIFT      (8)
+#define GCTL(pThis)                 (HDA_REG((pThis), GCTL))
+
+#define ICH6_HDA_REG_WAKEEN         6 /* 0x0C */
+#define WAKEEN(pThis)               (HDA_REG((pThis), WAKEEN))
+
+#define ICH6_HDA_REG_STATESTS       7 /* range 0x0E */
+#define STATESTS(pThis)             (HDA_REG((pThis), STATESTS))
+#define ICH6_HDA_STATES_SCSF        0x7
+
+#define ICH6_HDA_REG_GSTS           8 /* range 0x10-0x11*/
+#define ICH6_HDA_GSTS_FSH_SHIFT     (1)
+#define GSTS(pThis)                 (HDA_REG(pThis, GSTS))
+
+#define ICH6_HDA_REG_INTCTL         9 /* 0x20 */
+#define ICH6_HDA_INTCTL_GIE_SHIFT   31
+#define ICH6_HDA_INTCTL_CIE_SHIFT   30
+#define ICH6_HDA_INTCTL_S0_SHIFT    (0)
+#define ICH6_HDA_INTCTL_S1_SHIFT    (1)
+#define ICH6_HDA_INTCTL_S2_SHIFT    (2)
+#define ICH6_HDA_INTCTL_S3_SHIFT    (3)
+#define ICH6_HDA_INTCTL_S4_SHIFT    (4)
+#define ICH6_HDA_INTCTL_S5_SHIFT    (5)
+#define ICH6_HDA_INTCTL_S6_SHIFT    (6)
+#define ICH6_HDA_INTCTL_S7_SHIFT    (7)
+#define INTCTL(pThis)               (HDA_REG((pThis), INTCTL))
+#define INTCTL_GIE(pThis)           (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
+#define INTCTL_CIE(pThis)           (HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE))
+#define INTCTL_SX(pThis, X)         (HDA_REG_FLAG_VALUE((pThis), INTCTL, S##X))
+#define INTCTL_SALL(pThis)          (INTCTL((pThis)) & 0xFF)
+
+/* 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 ICH6_HDA_REG_SSYNC          12 /* 0x34 */
+#define SSYNC(pThis)                (HDA_REG((pThis), SSYNC))
+
+#define ICH6_HDA_REG_INTSTS         10 /* 0x24 */
+#define ICH6_HDA_INTSTS_GIS_SHIFT   (31)
+#define ICH6_HDA_INTSTS_CIS_SHIFT   (30)
+#define ICH6_HDA_INTSTS_S0_SHIFT    (0)
+#define ICH6_HDA_INTSTS_S1_SHIFT    (1)
+#define ICH6_HDA_INTSTS_S2_SHIFT    (2)
+#define ICH6_HDA_INTSTS_S3_SHIFT    (3)
+#define ICH6_HDA_INTSTS_S4_SHIFT    (4)
+#define ICH6_HDA_INTSTS_S5_SHIFT    (5)
+#define ICH6_HDA_INTSTS_S6_SHIFT    (6)
+#define ICH6_HDA_INTSTS_S7_SHIFT    (7)
+#define ICH6_HDA_INTSTS_S_MASK(num) RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
+#define INTSTS(pThis)               (HDA_REG((pThis), INTSTS))
+#define INTSTS_GIS(pThis)           (HDA_REG_FLAG_VALUE((pThis), INTSTS, GIS)
+#define INTSTS_CIS(pThis)           (HDA_REG_FLAG_VALUE((pThis), INTSTS, CIS)
+#define INTSTS_SX(pThis, X)         (HDA_REG_FLAG_VALUE(pThis), INTSTS, S##X)
+#define INTSTS_SANY(pThis)          (INTSTS((pThis)) & 0xFF)
+
+#define ICH6_HDA_REG_CORBLBASE      13 /* 0x40 */
+#define CORBLBASE(pThis)            (HDA_REG((pThis), CORBLBASE))
+#define ICH6_HDA_REG_CORBUBASE      14 /* 0x44 */
+#define CORBUBASE(pThis)            (HDA_REG((pThis), CORBUBASE))
+#define ICH6_HDA_REG_CORBWP         15 /* 48 */
+#define ICH6_HDA_REG_CORBRP         16 /* 4A */
+#define ICH6_HDA_CORBRP_RST_SHIFT   15
+#define ICH6_HDA_CORBRP_WP_SHIFT    0
+#define ICH6_HDA_CORBRP_WP_MASK     0xFF
+
+#define CORBRP(pThis)               (HDA_REG(pThis, CORBRP))
+#define CORBWP(pThis)               (HDA_REG(pThis, CORBWP))
+
+#define ICH6_HDA_REG_CORBCTL        17 /* 0x4C */
+#define ICH6_HDA_CORBCTL_DMA_SHIFT  (1)
+#define ICH6_HDA_CORBCTL_CMEIE_SHIFT (0)
+
+#define CORBCTL(pThis)              (HDA_REG(pThis, CORBCTL))
+
+
+#define ICH6_HDA_REG_CORBSTS        18 /* 0x4D */
+#define CORBSTS(pThis)              (HDA_REG(pThis, CORBSTS))
+#define ICH6_HDA_CORBSTS_CMEI_SHIFT (0)
+
+#define ICH6_HDA_REG_CORBSIZE       19 /* 0x4E */
+#define ICH6_HDA_CORBSIZE_SZ_CAP    0xF0
+#define ICH6_HDA_CORBSIZE_SZ        0x3
+#define CORBSIZE_SZ(pThis)          (HDA_REG(pThis, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ)
+#define CORBSIZE_SZ_CAP(pThis)      (HDA_REG(pThis, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ_CAP)
+/* till ich 10 sizes of CORB and RIRB are hardcoded to 256 in real hw */
+
+#define ICH6_HDA_REG_RIRLBASE       20 /* 0x50 */
+#define RIRLBASE(pThis)             (HDA_REG((pThis), RIRLBASE))
+
+#define ICH6_HDA_REG_RIRUBASE       21 /* 0x54 */
+#define RIRUBASE(pThis)             (HDA_REG((pThis), RIRUBASE))
+
+#define ICH6_HDA_REG_RIRBWP         22 /* 0x58 */
+#define ICH6_HDA_RIRBWP_RST_SHIFT   (15)
+#define ICH6_HDA_RIRBWP_WP_MASK     0xFF
+#define RIRBWP(pThis)              (HDA_REG(pThis, RIRBWP))
+
+#define ICH6_HDA_REG_RINTCNT        23 /* 0x5A */
+#define RINTCNT(pThis)              (HDA_REG((pThis), RINTCNT))
+#define RINTCNT_N(pThis)            (RINTCNT((pThis)) & 0xff)
+
+#define ICH6_HDA_REG_RIRBCTL        24 /* 0x5C */
+#define ICH6_HDA_RIRBCTL_RIC_SHIFT  (0)
+#define ICH6_HDA_RIRBCTL_DMA_SHIFT  (1)
+#define ICH6_HDA_ROI_DMA_SHIFT      (2)
+#define RIRBCTL(pThis)              (HDA_REG((pThis), RIRBCTL))
+#define RIRBCTL_RIRB_RIC(pThis)     (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC))
+#define RIRBCTL_RIRB_DMA(pThis)     (HDA_REG_FLAG_VALUE((pThis), RIRBCTL, DMA)
+#define RIRBCTL_ROI(pThis)          (HDA_REG_FLAG_VALUE((pThis), RIRBCTL, ROI))
+
+#define ICH6_HDA_REG_RIRBSTS        25 /* 0x5D */
+#define ICH6_HDA_RIRBSTS_RINTFL_SHIFT (0)
+#define ICH6_HDA_RIRBSTS_RIRBOIS_SHIFT (2)
+#define RIRBSTS(pThis)              (HDA_REG(pThis, RIRBSTS))
+#define RIRBSTS_RINTFL(pThis)       (HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL))
+#define RIRBSTS_RIRBOIS(pThis)      (HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS))
+
+#define ICH6_HDA_REG_RIRBSIZE       26 /* 0x5E */
+#define ICH6_HDA_RIRBSIZE_SZ_CAP    0xF0
+#define ICH6_HDA_RIRBSIZE_SZ        0x3
+
+#define RIRBSIZE_SZ(pThis)          (HDA_REG(pThis, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ)
+#define RIRBSIZE_SZ_CAP(pThis)      (HDA_REG(pThis, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ_CAP)
+
+
+#define ICH6_HDA_REG_IC             27 /* 0x60 */
+#define IC(pThis)                   (HDA_REG(pThis, IC))
+#define ICH6_HDA_REG_IR             28 /* 0x64 */
+#define IR(pThis)                   (HDA_REG(pThis, IR))
+#define ICH6_HDA_REG_IRS            29 /* 0x68 */
+#define ICH6_HDA_IRS_ICB_SHIFT      (0)
+#define ICH6_HDA_IRS_IRV_SHIFT      (1)
+#define IRS(pThis)                  (HDA_REG(pThis, IRS))
+#define IRS_ICB(pThis)              (HDA_REG_FLAG_VALUE(pThis, IRS, ICB))
+#define IRS_IRV(pThis)              (HDA_REG_FLAG_VALUE(pThis, IRS, IRV))
+
+#define ICH6_HDA_REG_DPLBASE        30 /* 0x70 */
+#define DPLBASE(pThis)              (HDA_REG((pThis), DPLBASE))
+#define ICH6_HDA_REG_DPUBASE        31 /* 0x74 */
+#define DPUBASE(pThis)              (HDA_REG((pThis), DPUBASE))
+#define DPBASE_ENABLED              1
+#define DPBASE_ADDR_MASK            (~(uint64_t)0x7f)
+
+#define HDA_STREAM_REG_DEF(name, num)           (ICH6_HDA_REG_SD##num##name)
+#define HDA_STREAM_REG(pThis, name, num)        (HDA_REG((pThis), N_(HDA_STREAM_REG_DEF(name, num))))
+/* Note: sdnum here _MUST_ be stream reg number [0,7] */
+#define HDA_STREAM_REG2(pThis, name, sdnum)     (HDA_REG_IND((pThis), ICH6_HDA_REG_SD0##name + (sdnum) * 10))
+
+#define ICH6_HDA_REG_SD0CTL         32 /* 0x80 */
+#define ICH6_HDA_REG_SD1CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 10) /* 0xA0 */
+#define ICH6_HDA_REG_SD2CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 20) /* 0xC0 */
+#define ICH6_HDA_REG_SD3CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 30) /* 0xE0 */
+#define ICH6_HDA_REG_SD4CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 40) /* 0x100 */
+#define ICH6_HDA_REG_SD5CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 50) /* 0x120 */
+#define ICH6_HDA_REG_SD6CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 60) /* 0x140 */
+#define ICH6_HDA_REG_SD7CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 70) /* 0x160 */
+
+#define SD(func, num)               SD##num##func
+#define SDCTL(pThis, num)           HDA_REG((pThis), SD(CTL, num))
+#define SDCTL_NUM(pThis, num)       ((SDCTL((pThis), num) & HDA_REG_FIELD_MASK(SDCTL,NUM)) >> HDA_REG_FIELD_SHIFT(SDCTL, NUM))
+#define ICH6_HDA_SDCTL_NUM_MASK     (0xF)
+#define ICH6_HDA_SDCTL_NUM_SHIFT    (20)
+#define ICH6_HDA_SDCTL_DIR_SHIFT    (19)
+#define ICH6_HDA_SDCTL_TP_SHIFT     (18)
+#define ICH6_HDA_SDCTL_STRIPE_MASK  (0x3)
+#define ICH6_HDA_SDCTL_STRIPE_SHIFT (16)
+#define ICH6_HDA_SDCTL_DEIE_SHIFT   (4)
+#define ICH6_HDA_SDCTL_FEIE_SHIFT   (3)
+#define ICH6_HDA_SDCTL_ICE_SHIFT    (2)
+#define ICH6_HDA_SDCTL_RUN_SHIFT    (1)
+#define ICH6_HDA_SDCTL_SRST_SHIFT   (0)
+
+#define ICH6_HDA_REG_SD0STS         33 /* 0x83 */
+#define ICH6_HDA_REG_SD1STS         (HDA_STREAM_REG_DEF(STS, 0) + 10) /* 0xA3 */
+#define ICH6_HDA_REG_SD2STS         (HDA_STREAM_REG_DEF(STS, 0) + 20) /* 0xC3 */
+#define ICH6_HDA_REG_SD3STS         (HDA_STREAM_REG_DEF(STS, 0) + 30) /* 0xE3 */
+#define ICH6_HDA_REG_SD4STS         (HDA_STREAM_REG_DEF(STS, 0) + 40) /* 0x103 */
+#define ICH6_HDA_REG_SD5STS         (HDA_STREAM_REG_DEF(STS, 0) + 50) /* 0x123 */
+#define ICH6_HDA_REG_SD6STS         (HDA_STREAM_REG_DEF(STS, 0) + 60) /* 0x143 */
+#define ICH6_HDA_REG_SD7STS         (HDA_STREAM_REG_DEF(STS, 0) + 70) /* 0x163 */
+
+#define SDSTS(pThis, num)           HDA_REG((pThis), SD(STS, num))
+#define ICH6_HDA_SDSTS_FIFORDY_SHIFT (5)
+#define ICH6_HDA_SDSTS_DE_SHIFT     (4)
+#define ICH6_HDA_SDSTS_FE_SHIFT     (3)
+#define ICH6_HDA_SDSTS_BCIS_SHIFT   (2)
+
+#define ICH6_HDA_REG_SD0LPIB        34 /* 0x84 */
+#define ICH6_HDA_REG_SD1LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
+#define ICH6_HDA_REG_SD2LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
+#define ICH6_HDA_REG_SD3LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
+#define ICH6_HDA_REG_SD4LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
+#define ICH6_HDA_REG_SD5LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
+#define ICH6_HDA_REG_SD6LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
+#define ICH6_HDA_REG_SD7LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
+
+#define SDLPIB(pThis, num)          HDA_REG((pThis), SD(LPIB, num))
+
+#define ICH6_HDA_REG_SD0CBL         35 /* 0x88 */
+#define ICH6_HDA_REG_SD1CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 10) /* 0xA8 */
+#define ICH6_HDA_REG_SD2CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 20) /* 0xC8 */
+#define ICH6_HDA_REG_SD3CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 30) /* 0xE8 */
+#define ICH6_HDA_REG_SD4CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 40) /* 0x108 */
+#define ICH6_HDA_REG_SD5CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 50) /* 0x128 */
+#define ICH6_HDA_REG_SD6CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 60) /* 0x148 */
+#define ICH6_HDA_REG_SD7CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 70) /* 0x168 */
+
+#define SDLCBL(pThis, num)          HDA_REG((pThis), SD(CBL, num))
+
+#define ICH6_HDA_REG_SD0LVI         36 /* 0x8C */
+#define ICH6_HDA_REG_SD1LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 10) /* 0xAC */
+#define ICH6_HDA_REG_SD2LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 20) /* 0xCC */
+#define ICH6_HDA_REG_SD3LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 30) /* 0xEC */
+#define ICH6_HDA_REG_SD4LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 40) /* 0x10C */
+#define ICH6_HDA_REG_SD5LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 50) /* 0x12C */
+#define ICH6_HDA_REG_SD6LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 60) /* 0x14C */
+#define ICH6_HDA_REG_SD7LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 70) /* 0x16C */
+
+#define SDLVI(pThis, num)           HDA_REG((pThis), SD(LVI, num))
+
+#define ICH6_HDA_REG_SD0FIFOW       37 /* 0x8E */
+#define ICH6_HDA_REG_SD1FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 10) /* 0xAE */
+#define ICH6_HDA_REG_SD2FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 20) /* 0xCE */
+#define ICH6_HDA_REG_SD3FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 30) /* 0xEE */
+#define ICH6_HDA_REG_SD4FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 40) /* 0x10E */
+#define ICH6_HDA_REG_SD5FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 50) /* 0x12E */
+#define ICH6_HDA_REG_SD6FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 60) /* 0x14E */
+#define ICH6_HDA_REG_SD7FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 70) /* 0x16E */
+
+/*
+ * 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 SDFIFOW(pThis, num)         HDA_REG((pThis), SD(FIFOW, num))
+
+#define ICH6_HDA_REG_SD0FIFOS       38 /* 0x90 */
+#define ICH6_HDA_REG_SD1FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 10) /* 0xB0 */
+#define ICH6_HDA_REG_SD2FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 20) /* 0xD0 */
+#define ICH6_HDA_REG_SD3FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 30) /* 0xF0 */
+#define ICH6_HDA_REG_SD4FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 40) /* 0x110 */
+#define ICH6_HDA_REG_SD5FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 50) /* 0x130 */
+#define ICH6_HDA_REG_SD6FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 60) /* 0x150 */
+#define ICH6_HDA_REG_SD7FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 70) /* 0x170 */
+
+/*
+ * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
+ * formula: size - 1
+ * Other values not listed are not supported.
+ */
+#define HDA_SDONFIFO_16B            (0x0F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDONFIFO_32B            (0x1F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDONFIFO_64B            (0x3F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDONFIFO_128B           (0x7F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDONFIFO_192B           (0xBF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
+#define HDA_SDONFIFO_256B           (0xFF) /* 20-, 24-bit Output Streams */
+#define HDA_SDINFIFO_120B           (0x77) /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
+#define HDA_SDINFIFO_160B           (0x9F) /* 20-, 24-bit Input Streams Streams */
+#define SDFIFOS(pThis, num)         HDA_REG((pThis), SD(FIFOS, num))
+
+#define ICH6_HDA_REG_SD0FMT         39 /* 0x92 */
+#define ICH6_HDA_REG_SD1FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 10) /* 0xB2 */
+#define ICH6_HDA_REG_SD2FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 20) /* 0xD2 */
+#define ICH6_HDA_REG_SD3FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 30) /* 0xF2 */
+#define ICH6_HDA_REG_SD4FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 40) /* 0x112 */
+#define ICH6_HDA_REG_SD5FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 50) /* 0x132 */
+#define ICH6_HDA_REG_SD6FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 60) /* 0x152 */
+#define ICH6_HDA_REG_SD7FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 70) /* 0x172 */
+
+#define SDFMT(pThis, num)           (HDA_REG((pThis), SD(FMT, num)))
+#define ICH6_HDA_SDFMT_BASE_RATE_SHIFT (14)
+#define ICH6_HDA_SDFMT_MULT_SHIFT   (11)
+#define ICH6_HDA_SDFMT_MULT_MASK    (0x7)
+#define ICH6_HDA_SDFMT_DIV_SHIFT    (8)
+#define ICH6_HDA_SDFMT_DIV_MASK     (0x7)
+#define ICH6_HDA_SDFMT_BITS_SHIFT   (4)
+#define ICH6_HDA_SDFMT_BITS_MASK    (0x7)
+#define SDFMT_BASE_RATE(pThis, num) ((SDFMT(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDFMT, BASE_RATE)) >> HDA_REG_FIELD_SHIFT(SDFMT, BASE_RATE))
+#define SDFMT_MULT(pThis, num)      ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,MULT)) >> HDA_REG_FIELD_SHIFT(SDFMT, MULT))
+#define SDFMT_DIV(pThis, num)       ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,DIV)) >> HDA_REG_FIELD_SHIFT(SDFMT, DIV))
+
+#define ICH6_HDA_REG_SD0BDPL        40 /* 0x98 */
+#define ICH6_HDA_REG_SD1BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 10) /* 0xB8 */
+#define ICH6_HDA_REG_SD2BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 20) /* 0xD8 */
+#define ICH6_HDA_REG_SD3BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 30) /* 0xF8 */
+#define ICH6_HDA_REG_SD4BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 40) /* 0x118 */
+#define ICH6_HDA_REG_SD5BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 50) /* 0x138 */
+#define ICH6_HDA_REG_SD6BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 60) /* 0x158 */
+#define ICH6_HDA_REG_SD7BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 70) /* 0x178 */
+
+#define SDBDPL(pThis, num)          HDA_REG((pThis), SD(BDPL, num))
+
+#define ICH6_HDA_REG_SD0BDPU        41 /* 0x9C */
+#define ICH6_HDA_REG_SD1BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 10) /* 0xBC */
+#define ICH6_HDA_REG_SD2BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 20) /* 0xDC */
+#define ICH6_HDA_REG_SD3BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 30) /* 0xFC */
+#define ICH6_HDA_REG_SD4BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 40) /* 0x11C */
+#define ICH6_HDA_REG_SD5BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 50) /* 0x13C */
+#define ICH6_HDA_REG_SD6BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 60) /* 0x15C */
+#define ICH6_HDA_REG_SD7BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 70) /* 0x17C */
+
+#define SDBDPU(pThis, num)          HDA_REG((pThis), SD(BDPU, num))
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct HDABDLEDESC
+{
+    uint64_t    u64BdleCviAddr;
+    uint32_t    u32BdleMaxCvi;
+    uint32_t    u32BdleCvi;
+    uint32_t    u32BdleCviLen;
+    uint32_t    u32BdleCviPos;
+    bool        fBdleCviIoc;
+    uint32_t    cbUnderFifoW;
+    uint8_t     au8HdaBuffer[HDA_SDONFIFO_256B + 1];
+} HDABDLEDESC, *PHDABDLEDESC;
+
+typedef struct HDASTREAMTRANSFERDESC
+{
+    uint64_t u64BaseDMA;
+    uint32_t u32Ctl;
+    uint32_t *pu32Sts;
+    uint8_t  u8Strm;
+    uint32_t *pu32Lpib;
+    uint32_t u32Cbl;
+    uint32_t u32Fifos;
+} HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC;
+
+/**
+ * ICH Intel HD Audio Controller state.
+ */
+typedef struct HDASTATE
+{
+    /** The PCI device structure. */
+    PCIDevice               PciDev;
+    /** Pointer to the device instance. */
+    PPDMDEVINSR3            pDevIns;
+    /** Pointer to the connector of the attached audio driver. */
+    PPDMIAUDIOCONNECTOR     pDrv;
+    /** Pointer to the attached audio driver. */
+    PPDMIBASE               pDrvBase;
+    /** The base interface for LUN\#0. */
+    PDMIBASE                IBase;
+    RTGCPHYS                MMIOBaseAddr;
+    uint32_t                au32Regs[HDA_NREGS];
+    HDABDLEDESC             StInBdle;
+    HDABDLEDESC             StOutBdle;
+    HDABDLEDESC             StMicBdle;
+    /** Interrupt on completion */
+    bool                    fCviIoc;
+    uint64_t                u64CORBBase;
+    uint64_t                u64RIRBBase;
+    uint64_t                u64DPBase;
+    /** pointer to CORB buf */
+    uint32_t               *pu32CorbBuf;
+    /** size in bytes of CORB buf */
+    uint32_t                cbCorbBuf;
+    /** pointer on RIRB buf */
+    uint64_t               *pu64RirbBuf;
+    /** size in bytes of RIRB buf */
+    uint32_t                cbRirbBuf;
+    /** indicates if HDA in reset. */
+    bool                    fInReset;
+    /** The HDA codec state. */
+    HDACODEC                Codec;
+    /** 1.2.3.4.5.6.7. - someone please tell me what I'm counting! - .8.9.10... */
+    uint8_t                 u8Counter;
+    uint64_t                u64BaseTS;
+} HDASTATE;
+/** Pointer to the ICH Intel HD Audio Controller state. */
+typedef HDASTATE *PHDASTATE;
+
+#define ISD0FMT_TO_AUDIO_SELECTOR(pThis) \
+    ( AUDIO_FORMAT_SELECTOR(&(pThis)->Codec, In, SDFMT_BASE_RATE(pThis, 0), SDFMT_MULT(pThis, 0), SDFMT_DIV(pThis, 0)) )
+#define OSD0FMT_TO_AUDIO_SELECTOR(pThis) \
+    ( AUDIO_FORMAT_SELECTOR(&(pThis)->Codec, Out, SDFMT_BASE_RATE(pThis, 4), SDFMT_MULT(pThis, 4), SDFMT_DIV(pThis, 4)) )
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static FNPDMDEVRESET hdaReset;
+
+static int hdaRegReadUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadGCAP(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegReadSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+
+static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
+
+DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
+                                           PHDASTREAMTRANSFERDESC pStreamDesc);
+static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc);
+#ifdef LOG_ENABLED
+static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/* see 302349 p 6.2*/
+static const 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;
+    /** Read callback. */
+    int       (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
+    /** Write callback. */
+    int       (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
+    /** Abbreviated name. */
+    const char *abbrev;
+    /** Full name. */
+    const char *name;
+} g_aHdaRegMap[HDA_NREGS] =
+{
+    /* offset  size     read mask   write mask         read callback         write callback         abbrev      full name                     */
+    /*-------  -------  ----------  ----------  -----------------------  ------------------------ ----------    ------------------------------*/
+    { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, hdaRegReadGCAP         , hdaRegWriteUnimplemented, "GCAP"      , "Global Capabilities" },
+    { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "VMIN"      , "Minor Version" },
+    { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "VMAJ"      , "Major Version" },
+    { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimplemented, "OUTPAY"    , "Output Payload Capabilities" },
+    { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimplemented, "INPAY"     , "Input Payload Capabilities" },
+    { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadGCTL         , hdaRegWriteGCTL         , "GCTL"      , "Global Control" },
+    { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, hdaRegReadU16          , hdaRegWriteU16          , "WAKEEN"    , "Wake Enable" },
+    { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8           , hdaRegWriteSTATESTS     , "STATESTS"  , "State Change Status" },
+    { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimplemented, hdaRegWriteUnimplemented, "GSTS"      , "Global Status" },
+    { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32          , hdaRegWriteU32          , "INTCTL"    , "Interrupt Control" },
+    { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS       , hdaRegWriteUnimplemented, "INTSTS"    , "Interrupt Status" },
+    { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK       , hdaRegWriteUnimplemented, "WALCLK"    , "Wall Clock Counter" },
+    /// @todo r=michaln: Doesn't the SSYNC register need to actually stop the stream(s)?
+    { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32          , hdaRegWriteU32          , "SSYNC"     , "Stream Synchronization" },
+    { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteBase         , "CORBLBASE" , "CORB Lower Base Address" },
+    { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "CORBUBASE" , "CORB Upper Base Address" },
+    { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteCORBWP       , "CORBWP"    , "CORB Write Pointer" },
+#ifdef OLD_REGISTER_TABLE
+    { 0x0004A, 0x00002, 0x000000FF, 0x000080FF, hdaRegReadU8           , hdaRegWriteCORBRP       , "CORBRP"    , "CORB Read Pointer" },
+#else /** @todo 18.2.17 indicates that the 15th bit can be read as well as and written. hdaRegReadU8 is wrong, a special reader should be used. */
+    { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, hdaRegReadU16          , hdaRegWriteCORBRP       , "CORBRP"    , "CORB Read Pointer" },
+#endif
+    { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8           , hdaRegWriteCORBCTL      , "CORBCTL"   , "CORB Control" },
+    { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8           , hdaRegWriteCORBSTS      , "CORBSTS"   , "CORB Status" },
+    { 0x0004E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "CORBSIZE"  , "CORB Size" },
+    { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteBase         , "RIRBLBASE" , "RIRB Lower Base Address" },
+    { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "RIRBUBASE" , "RIRB Upper Base Address" },
+    { 0x00058, 0x00002, 0x000000FF, 0x00008000, hdaRegReadU8           , hdaRegWriteRIRBWP       , "RIRBWP"    , "RIRB Write Pointer" },
+    { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteU16          , "RINTCNT"   , "Response Interrupt Count" },
+    { 0x0005C, 0x00001, 0x00000007, 0x00000007, hdaRegReadU8           , hdaRegWriteU8           , "RIRBCTL"   , "RIRB Control" },
+    { 0x0005D, 0x00001, 0x00000005, 0x00000005, hdaRegReadU8           , hdaRegWriteRIRBSTS      , "RIRBSTS"   , "RIRB Status" },
+    { 0x0005E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "RIRBSIZE"  , "RIRB Size" },
+    { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "IC"        , "Immediate Command" },
+    { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteUnimplemented, "IR"        , "Immediate Response" },
+#ifdef OLD_REGISTER_TABLE
+    { 0x00068, 0x00004, 0x00000002, 0x00000002, hdaRegReadIRS          , hdaRegWriteIRS          , "IRS"       , "Immediate Command Status" },
+#else /* 18.2.30 as well as the table says 16-bit. Linux accesses it as a 16-bit register. */
+    { 0x00068, 0x00002, 0x00000002, 0x00000002, hdaRegReadIRS          , hdaRegWriteIRS          , "IRS"       , "Immediate Command Status" },
+#endif
+    { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32          , hdaRegWriteBase         , "DPLBASE"   , "DMA Position Lower Base" },
+    { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "DPUBASE"   , "DMA Position Upper Base" },
+
+    { 0x00080, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD0CTL"  , "Input Stream Descriptor 0 (ICD0) Control" },
+    { 0x00083, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD0STS"  , "ISD0 Status" },
+    { 0x00084, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD0LPIB" , "ISD0 Link Position In Buffer" },
+    { 0x00088, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD0CBL"  , "ISD0 Cyclic Buffer Length" },
+    { 0x0008C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD0LVI"  , "ISD0 Last Valid Index" },
+    { 0x0008E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD0FIFOW", "ISD0 FIFO Watermark" },
+    { 0x00090, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD0FIFOS", "ISD0 FIFO Size" },
+    { 0x00092, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD0FMT"  , "ISD0 Format" },
+    { 0x00098, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD0BDPL" , "ISD0 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x0009C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD0BDPU" , "ISD0 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x000A0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD1CTL"  , "Input Stream Descriptor 1 (ISD1) Control" },
+    { 0x000A3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD1STS"  , "ISD1 Status" },
+    { 0x000A4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD1LPIB" , "ISD1 Link Position In Buffer" },
+    { 0x000A8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD1CBL"  , "ISD1 Cyclic Buffer Length" },
+    { 0x000AC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD1LVI"  , "ISD1 Last Valid Index" },
+    { 0x000AE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD1FIFOW", "ISD1 FIFO Watermark" },
+    { 0x000B0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD1FIFOS", "ISD1 FIFO Size" },
+    { 0x000B2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD1FMT"  , "ISD1 Format" },
+    { 0x000B8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD1BDPL" , "ISD1 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x000BC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD1BDPU" , "ISD1 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x000C0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD2CTL"  , "Input Stream Descriptor 2 (ISD2) Control" },
+    { 0x000C3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD2STS"  , "ISD2 Status" },
+    { 0x000C4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD2LPIB" , "ISD2 Link Position In Buffer" },
+    { 0x000C8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD2CBL"  , "ISD2 Cyclic Buffer Length" },
+    { 0x000CC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD2LVI"  , "ISD2 Last Valid Index" },
+    { 0x000CE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD2FIFOW", "ISD2 FIFO Watermark" },
+    { 0x000D0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD2FIFOS", "ISD2 FIFO Size" },
+    { 0x000D2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD2FMT"  , "ISD2 Format" },
+    { 0x000D8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD2BDPL" , "ISD2 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x000DC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD2BDPU" , "ISD2 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x000E0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD3CTL"  , "Input Stream Descriptor 3 (ISD3) Control" },
+    { 0x000E3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD3STS"  , "ISD3 Status" },
+    { 0x000E4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD3LPIB" , "ISD3 Link Position In Buffer" },
+    { 0x000E8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD3CBL"  , "ISD3 Cyclic Buffer Length" },
+    { 0x000EC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD3LVI"  , "ISD3 Last Valid Index" },
+    { 0x000EE, 0x00002, 0x00000005, 0x00000005, hdaRegReadU16          , hdaRegWriteU16          , "ISD3FIFOW", "ISD3 FIFO Watermark" },
+    { 0x000F0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD3FIFOS", "ISD3 FIFO Size" },
+    { 0x000F2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD3FMT"  , "ISD3 Format" },
+    { 0x000F8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD3BDPL" , "ISD3 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x000FC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD3BDPU" , "ISD3 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x00100, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadSDCTL        , hdaRegWriteSDCTL        , "OSD0CTL"  , "Input Stream Descriptor 0 (OSD0) Control" },
+    { 0x00103, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD0STS"  , "OSD0 Status" },
+    { 0x00104, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD0LPIB" , "OSD0 Link Position In Buffer" },
+    { 0x00108, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD0CBL"  , "OSD0 Cyclic Buffer Length" },
+    { 0x0010C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD0LVI"  , "OSD0 Last Valid Index" },
+    { 0x0010E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD0FIFOW", "OSD0 FIFO Watermark" },
+    { 0x00110, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD0FIFOS", "OSD0 FIFO Size" },
+    { 0x00112, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD0FMT"  , "OSD0 Format" },
+    { 0x00118, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD0BDPL" , "OSD0 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x0011C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD0BDPU" , "OSD0 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x00120, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD1CTL"  , "Input Stream Descriptor 0 (OSD1) Control" },
+    { 0x00123, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD1STS"  , "OSD1 Status" },
+    { 0x00124, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD1LPIB" , "OSD1 Link Position In Buffer" },
+    { 0x00128, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD1CBL"  , "OSD1 Cyclic Buffer Length" },
+    { 0x0012C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD1LVI"  , "OSD1 Last Valid Index" },
+    { 0x0012E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD1FIFOW", "OSD1 FIFO Watermark" },
+    { 0x00130, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD1FIFOS", "OSD1 FIFO Size" },
+    { 0x00132, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD1FMT"  , "OSD1 Format" },
+    { 0x00138, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD1BDPL" , "OSD1 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x0013C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD1BDPU" , "OSD1 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x00140, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD2CTL"  , "Input Stream Descriptor 0 (OSD2) Control" },
+    { 0x00143, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD2STS"  , "OSD2 Status" },
+    { 0x00144, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD2LPIB" , "OSD2 Link Position In Buffer" },
+    { 0x00148, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD2CBL"  , "OSD2 Cyclic Buffer Length" },
+    { 0x0014C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD2LVI"  , "OSD2 Last Valid Index" },
+    { 0x0014E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD2FIFOW", "OSD2 FIFO Watermark" },
+    { 0x00150, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD2FIFOS", "OSD2 FIFO Size" },
+    { 0x00152, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD2FMT"  , "OSD2 Format" },
+    { 0x00158, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD2BDPL" , "OSD2 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x0015C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD2BDPU" , "OSD2 Buffer Descriptor List Pointer-Upper Base Address" },
+
+    { 0x00160, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD3CTL"  , "Input Stream Descriptor 0 (OSD3) Control" },
+    { 0x00163, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD3STS"  , "OSD3 Status" },
+    { 0x00164, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD3LPIB" , "OSD3 Link Position In Buffer" },
+    { 0x00168, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD3CBL"  , "OSD3 Cyclic Buffer Length" },
+    { 0x0016C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD3LVI"  , "OSD3 Last Valid Index" },
+    { 0x0016E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD3FIFOW", "OSD3 FIFO Watermark" },
+    { 0x00170, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD3FIFOS", "OSD3 FIFO Size" },
+    { 0x00172, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD3FMT"  , "OSD3 Format" },
+    { 0x00178, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD3BDPL" , "OSD3 Buffer Descriptor List Pointer-Lower Base Address" },
+    { 0x0017C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD3BDPU" , "OSD3 Buffer Descriptor List Pointer-Upper Base Address" },
+};
+
+/**
+ * HDA register aliases (HDA spec 3.3.45).
+ * @remarks Sorted by offReg.
+ */
+static const struct
+{
+    /** The alias register offset. */
+    uint32_t    offReg;
+    /** The register index. */
+    int         idxAlias;
+} g_aHdaRegAliases[] =
+{
+    { 0x2084, HDA_REG_IND_NAME(SD0LPIB) },
+    { 0x20a4, HDA_REG_IND_NAME(SD1LPIB) },
+    { 0x20c4, HDA_REG_IND_NAME(SD2LPIB) },
+    { 0x20e4, HDA_REG_IND_NAME(SD3LPIB) },
+    { 0x2104, HDA_REG_IND_NAME(SD4LPIB) },
+    { 0x2124, HDA_REG_IND_NAME(SD5LPIB) },
+    { 0x2144, HDA_REG_IND_NAME(SD6LPIB) },
+    { 0x2164, HDA_REG_IND_NAME(SD7LPIB) },
+};
+
+
+/** HDABDLEDESC field descriptors the v3+ saved state. */
+static SSMFIELD const g_aHdaBDLEDescFields[] =
+{
+    SSMFIELD_ENTRY(     HDABDLEDESC, u64BdleCviAddr),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleMaxCvi),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCvi),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviLen),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviPos),
+    SSMFIELD_ENTRY(     HDABDLEDESC, fBdleCviIoc),
+    SSMFIELD_ENTRY(     HDABDLEDESC, cbUnderFifoW),
+    SSMFIELD_ENTRY(     HDABDLEDESC, au8HdaBuffer),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/** HDABDLEDESC field descriptors the v1 and v2 saved state. */
+static SSMFIELD const g_aHdaBDLEDescFieldsOld[] =
+{
+    SSMFIELD_ENTRY(     HDABDLEDESC, u64BdleCviAddr),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleMaxCvi),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCvi),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviLen),
+    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviPos),
+    SSMFIELD_ENTRY(     HDABDLEDESC, fBdleCviIoc),
+    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
+    SSMFIELD_ENTRY(     HDABDLEDESC, cbUnderFifoW),
+    SSMFIELD_ENTRY(     HDABDLEDESC, au8HdaBuffer),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/**
+ * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
+ */
+static uint32_t const   g_afMasks[5] =
+{
+    UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0xffffff00), UINT32_C(0xffffffff)
+};
+
+
+DECLINLINE(void) hdaUpdatePosBuf(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+    if (pThis->u64DPBase & DPBASE_ENABLED)
+        PDMDevHlpPhysWrite(pThis->pDevIns,
+                           (pThis->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm * 8,
+                           pStreamDesc->pu32Lpib, sizeof(uint32_t));
+}
+DECLINLINE(uint32_t) hdaFifoWToSz(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+#if 0
+    switch(HDA_STREAM_REG2(pThis, FIFOW, pStreamDesc->u8Strm))
+    {
+        case HDA_SDFIFOW_8B: return 8;
+        case HDA_SDFIFOW_16B: return 16;
+        case HDA_SDFIFOW_32B: return 32;
+        default:
+            AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pThis, pStreamDesc->u8Strm), pStreamDesc->u8Strm));
+    }
+#endif
+    return 0;
+}
+
+static int hdaProcessInterrupt(PHDASTATE pThis)
+{
+#define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \
+        (   INTCTL_SX((pThis), num) \
+         && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
+    bool fIrq = false;
+    if (   INTCTL_CIE(pThis)
+       && (   RIRBSTS_RINTFL(pThis)
+           || RIRBSTS_RIRBOIS(pThis)
+           || (STATESTS(pThis) & WAKEEN(pThis))))
+        fIrq = true;
+
+    if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
+        || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4))
+        fIrq = true;
+
+    if (INTCTL_GIE(pThis))
+    {
+        Log(("hda: irq %s\n", fIrq ? "asserted" : "deasserted"));
+        PDMDevHlpPCISetIrq(pThis->pDevIns, 0 , fIrq);
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * Looks up a register at the exact offset given by @a offReg.
+ *
+ * @returns Register index on success, -1 if not found.
+ * @param   pThis               The HDA device state.
+ * @param   offReg              The register offset.
+ */
+static int hdaRegLookup(PHDASTATE pThis, uint32_t offReg)
+{
+    /*
+     * Aliases.
+     */
+    if (offReg >= g_aHdaRegAliases[0].offReg)
+    {
+        for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
+            if (offReg == g_aHdaRegAliases[i].offReg)
+                return g_aHdaRegAliases[i].idxAlias;
+        Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
+        return -1;
+    }
+
+    /*
+     * Binary search the
+     */
+    int idxEnd  = RT_ELEMENTS(g_aHdaRegMap);
+    int idxLow  = 0;
+    for (;;)
+    {
+        int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
+        if (offReg < g_aHdaRegMap[idxMiddle].offset)
+        {
+            if (idxLow == idxMiddle)
+                break;
+            idxEnd = idxMiddle;
+        }
+        else if (offReg > g_aHdaRegMap[idxMiddle].offset)
+        {
+            idxLow = idxMiddle + 1;
+            if (idxLow >= idxEnd)
+                break;
+        }
+        else
+            return idxMiddle;
+    }
+
+#ifdef RT_STRICT
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
+        Assert(g_aHdaRegMap[i].offset != offReg);
+#endif
+    return -1;
+}
+
+/**
+ * Looks up a register covering the offset given by @a offReg.
+ *
+ * @returns Register index on success, -1 if not found.
+ * @param   pThis               The HDA device state.
+ * @param   offReg              The register offset.
+ */
+static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg)
+{
+    /*
+     * Aliases.
+     */
+    if (offReg >= g_aHdaRegAliases[0].offReg)
+    {
+        for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
+        {
+            uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
+            if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
+                return g_aHdaRegAliases[i].idxAlias;
+        }
+        Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
+        return -1;
+    }
+
+    /*
+     * Binary search the
+     */
+    int idxEnd  = RT_ELEMENTS(g_aHdaRegMap);
+    int idxLow  = 0;
+    for (;;)
+    {
+        int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
+        if (offReg < g_aHdaRegMap[idxMiddle].offset)
+        {
+            if (idxLow == idxMiddle)
+                break;
+            idxEnd = idxMiddle;
+        }
+        else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
+        {
+            idxLow = idxMiddle + 1;
+            if (idxLow >= idxEnd)
+                break;
+        }
+        else
+            return idxMiddle;
+    }
+
+#ifdef RT_STRICT
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
+        Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
+#endif
+    return -1;
+}
+
+
+static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
+{
+    int rc = VINF_SUCCESS;
+    if (fLocal)
+    {
+        Assert((HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)));
+        rc = PDMDevHlpPhysRead(pThis->pDevIns, pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+#ifdef DEBUG_CMD_BUFFER
+        uint8_t i = 0;
+        do
+        {
+            Log(("hda: corb%02x: ", i));
+            uint8_t j = 0;
+            do
+            {
+                const char *prefix;
+                if ((i + j) == CORBRP(pThis))
+                    prefix = "[R]";
+                else if ((i + j) == CORBWP(pThis))
+                    prefix = "[W]";
+                else
+                    prefix = "   "; /* three spaces */
+                Log(("%s%08x", prefix, pThis->pu32CorbBuf[i + j]));
+                j++;
+            } while (j < 8);
+            Log(("\n"));
+            i += 8;
+        } while(i != 0);
+#endif
+    }
+    else
+    {
+        Assert((HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA)));
+        rc = PDMDevHlpPhysWrite(pThis->pDevIns, pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+#ifdef DEBUG_CMD_BUFFER
+        uint8_t i = 0;
+        do {
+            Log(("hda: rirb%02x: ", i));
+            uint8_t j = 0;
+            do {
+                const char *prefix;
+                if ((i + j) == RIRBWP(pThis))
+                    prefix = "[W]";
+                else
+                    prefix = "   ";
+                Log((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
+            } while (++j < 8);
+            Log(("\n"));
+            i += 8;
+        } while (i != 0);
+#endif
+    }
+    return rc;
+}
+
+static int hdaCORBCmdProcess(PHDASTATE pThis)
+{
+    int rc;
+    uint8_t corbRp;
+    uint8_t corbWp;
+    uint8_t rirbWp;
+
+    PFNHDACODECVERBPROCESSOR pfn = (PFNHDACODECVERBPROCESSOR)NULL;
+
+    rc = hdaCmdSync(pThis, true);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, rc);
+    corbRp = CORBRP(pThis);
+    corbWp = CORBWP(pThis);
+    rirbWp = RIRBWP(pThis);
+    Assert((corbWp != corbRp));
+    Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pThis), CORBWP(pThis), RIRBWP(pThis)));
+    while (corbRp != corbWp)
+    {
+        uint32_t cmd;
+        uint64_t resp;
+        pfn = NULL;
+        corbRp++;
+        cmd = pThis->pu32CorbBuf[corbRp];
+        rc = pThis->Codec.pfnLookup(&pThis->Codec, cmd, &pfn);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+        Assert(pfn);
+        (rirbWp)++;
+
+        if (RT_LIKELY(pfn))
+            rc = pfn(&pThis->Codec, cmd, &resp);
+        else
+            rc = VERR_INVALID_FUNCTION;
+
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+        Log(("hda: verb:%08x->%016lx\n", cmd, resp));
+        if (   (resp & CODEC_RESPONSE_UNSOLICITED)
+            && !HDA_REG_FLAG_VALUE(pThis, GCTL, UR))
+        {
+            Log(("hda: unexpected unsolicited response.\n"));
+            pThis->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
+            return rc;
+        }
+        pThis->pu64RirbBuf[rirbWp] = resp;
+        pThis->u8Counter++;
+        if (pThis->u8Counter == RINTCNT_N(pThis))
+            break;
+    }
+    pThis->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
+    pThis->au32Regs[ICH6_HDA_REG_RIRBWP] = rirbWp;
+    rc = hdaCmdSync(pThis, false);
+    Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pThis), CORBWP(pThis), RIRBWP(pThis)));
+    if (RIRBCTL_RIRB_RIC(pThis))
+    {
+        RIRBSTS((pThis)) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
+        pThis->u8Counter = 0;
+        rc = hdaProcessInterrupt(pThis);
+    }
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, rc);
+    return rc;
+}
+
+static void hdaStreamReset(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm)
+{
+    Log(("hda: reset of stream (%d) started\n", u8Strm));
+    Assert((   pThis
+            && pBdle
+            && pStreamDesc
+            && u8Strm <= 7));
+    memset(pBdle, 0, sizeof(HDABDLEDESC));
+    *pStreamDesc->pu32Lpib = 0;
+    *pStreamDesc->pu32Sts = 0;
+    /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
+     * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */
+    HDA_STREAM_REG2(pThis, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG2(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
+
+    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
+    HDA_STREAM_REG2(pThis, FIFOS, u8Strm) =  u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
+    HDA_STREAM_REG2(pThis, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B;
+    HDA_STREAM_REG2(pThis, CBL, u8Strm) = 0;
+    HDA_STREAM_REG2(pThis, LVI, u8Strm) = 0;
+    HDA_STREAM_REG2(pThis, FMT, u8Strm) = 0;
+    HDA_STREAM_REG2(pThis, BDPU, u8Strm) = 0;
+    HDA_STREAM_REG2(pThis, BDPL, u8Strm) = 0;
+    Log(("hda: reset of stream (%d) finished\n", u8Strm));
+}
+
+
+/* Register access handlers. */
+
+static int hdaRegReadUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    *pu32Value = 0;
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    return VINF_SUCCESS;
+}
+
+/* U8 */
+static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
+    return hdaRegReadU32(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    Assert((u32Value & 0xffffff00) == 0);
+    return hdaRegWriteU32(pThis, iReg, u32Value);
+}
+
+/* U16 */
+static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
+    return hdaRegReadU32(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    Assert((u32Value & 0xffff0000) == 0);
+    return hdaRegWriteU32(pThis, iReg, u32Value);
+}
+
+/* U24 */
+static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
+    return hdaRegReadU32(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    Assert((u32Value & 0xff000000) == 0);
+    return hdaRegWriteU32(pThis, iReg, u32Value);
+}
+
+/* U32 */
+static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    *pu32Value = pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable;
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    pThis->au32Regs[iReg]  = (u32Value & g_aHdaRegMap[iReg].writable)
+                           | (pThis->au32Regs[iReg] & ~g_aHdaRegMap[iReg].writable);
+    return VINF_SUCCESS;
+}
+
+static int hdaRegReadGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    return hdaRegReadU32(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
+    {
+        /* exit reset state */
+        GCTL(pThis) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
+        pThis->fInReset = false;
+    }
+    else
+    {
+        /* enter reset state*/
+        if (   HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)
+            || HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA))
+        {
+            Log(("hda: HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
+                HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) ? "on" : "off",
+                HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA) ? "on" : "off"));
+        }
+        hdaReset(pThis->pDevIns);
+        GCTL(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
+        pThis->fInReset = true;
+    }
+    if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
+    {
+        /* Flush: GSTS:1 set,  see 6.2.6*/
+        GSTS(pThis) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
+        /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6)*/
+    }
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    uint32_t v = pThis->au32Regs[iReg];
+    uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
+    pThis->au32Regs[iReg] &= ~(v & nv); /* write of 1 clears corresponding bit */
+    return VINF_SUCCESS;
+}
+
+static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    uint32_t v = 0;
+    if (   RIRBSTS_RIRBOIS(pThis)
+        || RIRBSTS_RINTFL(pThis)
+        || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI)
+        || STATESTS(pThis))
+        v |= RT_BIT(30);
+#define HDA_IS_STREAM_EVENT(pThis, stream)             \
+       (   (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))  \
+        || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))  \
+        || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
+#define MARK_STREAM(pThis, stream, v) do { (v) |= HDA_IS_STREAM_EVENT((pThis),stream) ? RT_BIT((stream)) : 0; } while(0)
+    MARK_STREAM(pThis, 0, v);
+    MARK_STREAM(pThis, 1, v);
+    MARK_STREAM(pThis, 2, v);
+    MARK_STREAM(pThis, 3, v);
+    MARK_STREAM(pThis, 4, v);
+    MARK_STREAM(pThis, 5, v);
+    MARK_STREAM(pThis, 6, v);
+    MARK_STREAM(pThis, 7, v);
+    v |= v ? RT_BIT(31) : 0;
+    *pu32Value = v;
+    return VINF_SUCCESS;
+}
+
+static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
+    *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->pDevIns)
+                                                   - pThis->u64BaseTS, 24, 1000);
+    return VINF_SUCCESS;
+}
+
+static int hdaRegReadGCAP(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    return hdaRegReadU16(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
+        CORBRP(pThis) = 0;
+#ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO
+    else
+        return hdaRegWriteU8(pThis, iReg, u32Value);
+#endif
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc = hdaRegWriteU8(pThis, iReg, u32Value);
+    AssertRC(rc);
+    if (   CORBWP(pThis) != CORBRP(pThis)
+        && HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) != 0)
+        return hdaCORBCmdProcess(pThis);
+    return rc;
+}
+
+static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    uint32_t v = CORBSTS(pThis);
+    CORBSTS(pThis) &= ~(v & u32Value);
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc;
+    rc = hdaRegWriteU16(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, rc);
+    if (CORBWP(pThis) == CORBRP(pThis))
+        return VINF_SUCCESS;
+    if (!HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
+        return VINF_SUCCESS;
+    rc = hdaCORBCmdProcess(pThis);
+    return rc;
+}
+
+static int hdaRegReadSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    return hdaRegReadU24(pThis, iReg, pu32Value);
+}
+
+static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    bool fRun     = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    bool fInRun   = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    bool fReset   = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
+    bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
+    int rc = VINF_SUCCESS;
+    if (fInReset)
+    {
+        /* Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit
+         * from reset
+         */
+        Assert((!fReset));
+        Log(("hda: guest initiated exit of stream reset.\n"));
+        goto l_done;
+    }
+    else if (fReset)
+    {
+        /*
+         * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset.
+         */
+        uint8_t u8Strm = 0;
+        PHDABDLEDESC pBdle = NULL;
+        HDASTREAMTRANSFERDESC StreamDesc;
+        Assert((!fInRun && !fRun));
+        switch (iReg)
+        {
+            case ICH6_HDA_REG_SD0CTL:
+                u8Strm = 0;
+                pBdle = &pThis->StInBdle;
+                break;
+            case ICH6_HDA_REG_SD4CTL:
+                u8Strm = 4;
+                pBdle = &pThis->StOutBdle;
+                break;
+            default:
+                Log(("hda: changing SRST bit on non-attached stream\n"));
+                goto l_done;
+        }
+        Log(("hda: guest initiated enter to stream reset.\n"));
+        hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
+        hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
+        goto l_done;
+    }
+
+    /* we enter here to change DMA states only */
+    if (   (fInRun && !fRun)
+        || (fRun && !fInRun))
+    {
+        Assert((!fReset && !fInReset));
+        switch (iReg)
+        {
+            case ICH6_HDA_REG_SD0CTL:
+                AUD_set_active_in(pThis->Codec.SwVoiceIn, fRun);
+                break;
+            case ICH6_HDA_REG_SD4CTL:
+                AUD_set_active_out(pThis->Codec.SwVoiceOut, fRun);
+                break;
+            default:
+                Log(("hda: changing RUN bit on non-attached stream\n"));
+                goto l_done;
+        }
+    }
+
+l_done:
+    rc = hdaRegWriteU24(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, VINF_SUCCESS);
+    return rc;
+}
+
+static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    uint32_t v = HDA_REG_IND(pThis, iReg);
+    v &= ~(u32Value & v);
+    HDA_REG_IND(pThis, iReg) = v;
+    hdaProcessInterrupt(pThis);
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, VINF_SUCCESS);
+    return rc;
+}
+
+static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    switch (u32Value)
+    {
+        case HDA_SDFIFOW_8B:
+        case HDA_SDFIFOW_16B:
+        case HDA_SDFIFOW_32B:
+            return hdaRegWriteU16(pThis, iReg, u32Value);
+        default:
+            Log(("hda: Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
+            return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ * @note This method could be called for changing value on Output Streams
+ *       only (ICH6 datasheet 18.2.39)
+ */
+static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    switch (iReg)
+    {
+        /* SDInFIFOS is RO, n=0-3 */
+        case ICH6_HDA_REG_SD0FIFOS:
+        case ICH6_HDA_REG_SD1FIFOS:
+        case ICH6_HDA_REG_SD2FIFOS:
+        case ICH6_HDA_REG_SD3FIFOS:
+            Log(("hda: Guest tries change value of FIFO size of Input Stream\n"));
+            return VINF_SUCCESS;
+        case ICH6_HDA_REG_SD4FIFOS:
+        case ICH6_HDA_REG_SD5FIFOS:
+        case ICH6_HDA_REG_SD6FIFOS:
+        case ICH6_HDA_REG_SD7FIFOS:
+            switch(u32Value)
+            {
+                case HDA_SDONFIFO_16B:
+                case HDA_SDONFIFO_32B:
+                case HDA_SDONFIFO_64B:
+                case HDA_SDONFIFO_128B:
+                case HDA_SDONFIFO_192B:
+                    return hdaRegWriteU16(pThis, iReg, u32Value);
+
+                case HDA_SDONFIFO_256B:
+                    Log(("hda: 256-bit is unsupported, HDA is switched into 192-bit mode\n"));
+                default:
+                    return hdaRegWriteU16(pThis, iReg, HDA_SDONFIFO_192B);
+            }
+            return VINF_SUCCESS;
+        default:
+            AssertMsgFailed(("Something weird happened with register lookup routine"));
+    }
+    return VINF_SUCCESS;
+}
+
+static void hdaSdFmtToAudSettings(uint32_t u32SdFmt, audsettings_t *pAudSetting)
+{
+    Assert((pAudSetting));
+#define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
+    uint32_t u32Hz = (u32SdFmt & ICH6_HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
+    uint32_t u32HzMult = 1;
+    uint32_t u32HzDiv = 1;
+    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_MULT_MASK, ICH6_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:
+            Log(("hda: unsupported multiplier %x\n", u32SdFmt));
+    }
+    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_DIV_MASK, ICH6_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;
+    }
+    pAudSetting->freq = u32Hz * u32HzMult / u32HzDiv;
+
+    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_BITS_MASK, ICH6_HDA_SDFMT_BITS_SHIFT))
+    {
+        case 0:
+            Log(("hda: %s requested 8-bit\n", __FUNCTION__));
+            pAudSetting->fmt = AUD_FMT_S8;
+            break;
+        case 1:
+            Log(("hda: %s requested 16-bit\n", __FUNCTION__));
+            pAudSetting->fmt = AUD_FMT_S16;
+            break;
+        case 2:
+            Log(("hda: %s requested 20-bit\n", __FUNCTION__));
+            break;
+        case 3:
+            Log(("hda: %s requested 24-bit\n", __FUNCTION__));
+            break;
+        case 4:
+            Log(("hda: %s requested 32-bit\n", __FUNCTION__));
+            pAudSetting->fmt = AUD_FMT_S32;
+            break;
+        default:
+            AssertMsgFailed(("Unsupported"));
+    }
+    pAudSetting->nchannels = (u32SdFmt & 0xf) + 1;
+    pAudSetting->fmt = AUD_FMT_S16;
+    pAudSetting->endianness = 0;
+#undef EXTRACT_VALUE
+}
+
+static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+#ifdef VBOX_WITH_HDA_CODEC_EMU
+    /** @todo a bit more investigation is required here. */
+    int rc = 0;
+    audsettings_t as;
+    /* no reason to reopen voice with same settings */
+    if (u32Value == HDA_REG_IND(pThis, iReg))
+        return VINF_SUCCESS;
+    hdaSdFmtToAudSettings(u32Value, &as);
+    switch (iReg)
+    {
+        case ICH6_HDA_REG_SD0FMT:
+            rc = hdaCodecOpenVoice(&pThis->Codec, PI_INDEX, &as);
+            break;
+        case ICH6_HDA_REG_SD4FMT:
+            rc = hdaCodecOpenVoice(&pThis->Codec, PO_INDEX, &as);
+            break;
+        default:
+            Log(("HDA: attempt to change format on %d\n", iReg));
+            rc = 0;
+    }
+    return hdaRegWriteU16(pThis, iReg, u32Value);
+#else
+    return hdaRegWriteU16(pThis, iReg, u32Value);
+#endif
+}
+
+static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, VINF_SUCCESS);
+    return rc;
+}
+
+static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, VINF_SUCCESS);
+    return rc;
+}
+
+static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
+{
+    int rc = VINF_SUCCESS;
+    /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
+    if (   CORBWP(pThis) != CORBRP(pThis)
+        || HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
+        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB);  /* busy */
+
+    rc = hdaRegReadU32(pThis, iReg, pu32Value);
+    return rc;
+}
+
+static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int                         rc  = VINF_SUCCESS;
+    PFNHDACODECVERBPROCESSOR    pfn = NULL;
+    uint64_t                    resp;
+
+    /*
+     * if guest set the ICB bit of IRS register, HDA should process the verb in IC register,
+     * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
+     */
+    if (   u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
+        && !IRS_ICB(pThis))
+    {
+        uint32_t cmd = IC(pThis);
+        if (CORBWP(pThis) != CORBRP(pThis))
+        {
+            /*
+             * 3.4.3 defines behavior of immediate Command status register.
+             */
+            LogRel(("hda: guest attempted process immediate verb (%x) with active CORB\n", cmd));
+            return rc;
+        }
+        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB);  /* busy */
+        Log(("hda: IC:%x\n", cmd));
+        rc = pThis->Codec.pfnLookup(&pThis->Codec, cmd, &pfn);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+        rc = pfn(&pThis->Codec, cmd, &resp);
+        if (RT_FAILURE(rc))
+            AssertRCReturn(rc, rc);
+        IR(pThis) = (uint32_t)resp;
+        Log(("hda: IR:%x\n", IR(pThis)));
+        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV);  /* result is ready  */
+        IRS(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
+        return rc;
+    }
+    /*
+     * Once the guest read the response, it should clean the IRV bit of the IRS register.
+     */
+    if (   u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
+        && IRS_IRV(pThis))
+        IRS(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
+    return rc;
+}
+
+static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
+    {
+        RIRBWP(pThis) = 0;
+    }
+    /* The remaining bits are O, see 6.2.22 */
+    return VINF_SUCCESS;
+}
+
+static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, rc);
+    switch(iReg)
+    {
+        case ICH6_HDA_REG_CORBLBASE:
+            pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
+            pThis->u64CORBBase |= pThis->au32Regs[iReg];
+            break;
+        case ICH6_HDA_REG_CORBUBASE:
+            pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
+            pThis->u64CORBBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
+            break;
+        case ICH6_HDA_REG_RIRLBASE:
+            pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
+            pThis->u64RIRBBase |= pThis->au32Regs[iReg];
+            break;
+        case ICH6_HDA_REG_RIRUBASE:
+            pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
+            pThis->u64RIRBBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
+            break;
+        case ICH6_HDA_REG_DPLBASE:
+            /** @todo: first bit has special meaning */
+            pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
+            pThis->u64DPBase |= pThis->au32Regs[iReg];
+            break;
+        case ICH6_HDA_REG_DPUBASE:
+            pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
+            pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
+            break;
+        default:
+            AssertMsgFailed(("Invalid index"));
+    }
+    Log(("hda: CORB base:%llx RIRB base: %llx DP base: %llx\n", pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
+    return rc;
+}
+
+static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
+{
+    uint8_t v = RIRBSTS(pThis);
+    RIRBSTS(pThis) &= ~(v & u32Value);
+
+    return hdaProcessInterrupt(pThis);
+}
+
+#ifdef LOG_ENABLED
+static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
+{
+#if 0
+    uint64_t addr;
+    uint32_t len;
+    uint32_t ioc;
+    uint8_t  bdle[16];
+    uint32_t counter;
+    uint32_t i;
+    uint32_t sum = 0;
+    Assert(pBdle && pBdle->u32BdleMaxCvi);
+    for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
+    {
+        PDMDevHlpPhysRead(pThis->pDevIns, u64BaseDMA + i*16, bdle, 16);
+        addr = *(uint64_t *)bdle;
+        len = *(uint32_t *)&bdle[8];
+        ioc = *(uint32_t *)&bdle[12];
+        Log(("hda: %s bdle[%d] a:%llx, len:%d, ioc:%d\n",  (i == pBdle->u32BdleCvi? "[C]": "   "), i, addr, len, ioc & 0x1));
+        sum += len;
+    }
+    Log(("hda: sum: %d\n", sum));
+    for (i = 0; i < 8; ++i)
+    {
+        PDMDevHlpPhysRead(pThis->pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
+        Log(("hda: %s stream[%d] counter=%x\n", i == SDCTL_NUM(pThis, 4) || i == SDCTL_NUM(pThis, 0)? "[C]": "   ",
+             i , counter));
+    }
+#endif
+}
+#endif
+
+static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+    uint8_t  bdle[16];
+    Assert((   pStreamDesc->u64BaseDMA
+            && pBdle
+            && pBdle->u32BdleMaxCvi));
+    PDMDevHlpPhysRead(pThis->pDevIns, pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
+    pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
+    pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
+    pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
+#ifdef LOG_ENABLED
+    dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
+#endif
+}
+
+DECLINLINE(uint32_t) hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
+                                                      uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit)
+{
+    uint32_t cb2Copy;
+    /*
+     * Number of bytes depends on the current position in buffer (u32BdleCviLen-u32BdleCviPos)
+     */
+    Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
+    cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
+    /*
+     * we may increase the counter in range of [0, FIFOS + 1]
+     */
+    cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1);
+    Assert((u32SoundBackendBufferBytesAvail > 0));
+
+    /* sanity check to avoid overriding the backend audio buffer */
+    cb2Copy = RT_MIN(cb2Copy, u32SoundBackendBufferBytesAvail);
+    cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
+
+    if (cb2Copy <= pBdle->cbUnderFifoW)
+        return 0;
+    cb2Copy -= pBdle->cbUnderFifoW; /* forcibly reserve the amount of unreported bytes to copy */
+    return cb2Copy;
+}
+
+DECLINLINE(void) hdaBackendWriteTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
+                                                 uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
+{
+    Log(("hda:hdaBackendWriteTransferReported: cbArranged2Copy: %d, cbCopied: %d, pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
+        cbArranged2Copy, cbCopied, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
+    Assert((cbCopied));
+    Assert((pu32BackendBufferCapacity && *pu32BackendBufferCapacity));
+    /* Assertion!!! Fewer than cbUnderFifoW bytes were copied.
+     * Probably we need to move the buffer, but it is rather hard to imagine a situation
+     * where it might happen.
+     */
+    Assert((cbCopied == pBdle->cbUnderFifoW + cbArranged2Copy)); /* we assume that we write the entire buffer including unreported bytes */
+    if (   pBdle->cbUnderFifoW
+        && pBdle->cbUnderFifoW <= cbCopied)
+        Log(("hda:hdaBackendWriteTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+
+    pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbCopied);
+    Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Incorrect assumption */
+
+    /* We always increment the position of DMA buffer counter because we're always reading into an intermediate buffer */
+    pBdle->u32BdleCviPos += cbArranged2Copy;
+
+    Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32BackendBufferCapacity >= cbCopied)); /* sanity */
+    /* We report all bytes (including previously unreported bytes) */
+    *pu32DMACursor += cbCopied;
+    /* Decrease the backend counter by the number of bytes we copied to the backend */
+    *pu32BackendBufferCapacity -= cbCopied;
+    Log(("hda:hdaBackendWriteTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
+        pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, *pu32DMACursor, *pu32BackendBufferCapacity));
+}
+
+DECLINLINE(void) hdaBackendReadTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
+                                                uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
+{
+    Assert((cbCopied, cbArranged2Copy));
+    *pu32BackendBufferCapacity -= cbCopied;
+    pBdle->u32BdleCviPos += cbCopied;
+    Log(("hda:hdaBackendReadTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+    *pu32DMACursor += cbCopied + pBdle->cbUnderFifoW;
+    pBdle->cbUnderFifoW = 0;
+    Log(("hda:hdaBackendReadTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
+        pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
+}
+
+DECLINLINE(void) hdaBackendTransferUnreported(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
+                                              uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
+{
+    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+    pBdle->u32BdleCviPos += cbCopied;
+    pBdle->cbUnderFifoW += cbCopied;
+    /* In case of a read transaction we're always copying from the backend buffer */
+    if (pu32BackendBufferCapacity)
+        *pu32BackendBufferCapacity -= cbCopied;
+    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+    Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pThis, pStreamDesc)));
+}
+
+DECLINLINE(bool) hdaIsTransferCountersOverlapped(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+    bool fOnBufferEdge = (   *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl
+                          || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen);
+
+    Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
+
+    if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
+        *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl;
+    hdaUpdatePosBuf(pThis, pStreamDesc);
+
+    /* don't touch BdleCvi counter on uninitialized descriptor */
+    if (   pBdle->u32BdleCviPos
+        && pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
+    {
+        pBdle->u32BdleCviPos = 0;
+        pBdle->u32BdleCvi++;
+        if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
+            pBdle->u32BdleCvi = 0;
+    }
+    return fOnBufferEdge;
+}
+
+DECLINLINE(void) hdaStreamCounterUpdate(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
+                                        uint32_t cbInc)
+{
+    /*
+     * if we're below the FIFO Watermark, it's expected that HDA doesn't fetch anything.
+     * (ICH6 datasheet 18.2.38)
+     */
+    if (!pBdle->cbUnderFifoW)
+    {
+        *pStreamDesc->pu32Lpib += cbInc;
+
+        /*
+         * Assert. The buffer counters should never overlap.
+         */
+        Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
+
+        hdaUpdatePosBuf(pThis, pStreamDesc);
+
+    }
+}
+
+static bool hdaDoNextTransferCycle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+    bool fDoNextTransferLoop = true;
+    if (   pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
+        || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
+    {
+        if (    !pBdle->cbUnderFifoW
+             && pBdle->fBdleCviIoc)
+        {
+            /**
+             * @todo - more carefully investigate BCIS flag.
+             * Speech synthesis works fine on Mac Guest if this bit isn't set
+             * but in general sound quality gets worse.
+             */
+            *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
+
+            /*
+             * we should generate the interrupt if ICE bit of SDCTL register is set.
+             */
+            if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
+                hdaProcessInterrupt(pThis);
+        }
+        fDoNextTransferLoop = false;
+    }
+    return fDoNextTransferLoop;
+}
+
+/*
+ * hdaReadAudio - copies samples from audio backend to DMA.
+ * Note: this function writes to the DMA buffer immediately, but "reports bytes" when all conditions are met (FIFOW)
+ */
+static uint32_t hdaReadAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
+{
+    PHDABDLEDESC pBdle = &pThis->StInBdle;
+    uint32_t cbTransferred = 0;
+    uint32_t cb2Copy = 0;
+    uint32_t cbBackendCopy = 0;
+
+    Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+
+    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
+    if (!cb2Copy)
+    {
+        /* if we enter here we can't report "unreported bits" */
+        *fStop = true;
+        goto l_done;
+    }
+
+
+    /*
+     * read from backend input line to the last unreported position or at the begining.
+     */
+    cbBackendCopy = AUD_read(pThis->Codec.SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);
+    /*
+     * write the HDA DMA buffer
+     */
+    PDMDevHlpPhysWrite(pThis->pDevIns, pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy);
+
+    /* Don't see any reason why cb2Copy would differ from cbBackendCopy */
+    Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
+
+    if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pThis, 0))
+        hdaBackendReadTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransferred, pu32Avail);
+    else
+    {
+        hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbBackendCopy, pu32Avail);
+        *fStop = true;
+    }
+l_done:
+    Assert((cbTransferred <= (SDFIFOS(pThis, 0) + 1)));
+    Log(("hda:ra: CVI(pos:%d, len:%d) cbTransferred: %d\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred));
+    return cbTransferred;
+}
+
+static uint32_t hdaWriteAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
+{
+    PHDABDLEDESC pBdle = &pThis->StOutBdle;
+    uint32_t cbTransferred = 0;
+    uint32_t cb2Copy = 0; /* local byte counter (on local buffer) */
+    uint32_t cbBackendCopy = 0; /* local byte counter, how many bytes copied to backend */
+
+    Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
+
+    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
+
+    /*
+     * Copy from DMA to the corresponding hdaBuffer (if there are any bytes from the
+     * previous unreported transfer we write at offset 'pBdle->cbUnderFifoW').
+     */
+    if (!cb2Copy)
+    {
+        *fStop = true;
+        goto l_done;
+    }
+
+    PDMDevHlpPhysRead(pThis->pDevIns, pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
+    /*
+     * Write to audio backend. we should ensure that we have enough bytes to copy to the backend.
+     */
+    if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pThis, pStreamDesc))
+    {
+        /*
+         * Feed the newly fetched samples, including unreported ones, to the backend.
+         */
+        cbBackendCopy = AUD_write (pThis->Codec.SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
+        hdaBackendWriteTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransferred, pu32Avail);
+    }
+    else
+    {
+        /* Not enough bytes to be processed and reported, we'll try our luck next time around */
+        hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cb2Copy, NULL);
+        *fStop = true;
+    }
+
+l_done:
+    Assert(cbTransferred <= SDFIFOS(pThis, 4) + 1);
+    Log(("hda:wa: CVI(pos:%d, len:%d, cbTransferred:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred));
+    return cbTransferred;
+}
+
+/**
+ * @interface_method_impl{HDACODEC,pfnReset}
+ */
+DECLCALLBACK(int) hdaCodecReset(PHDACODEC pCodec)
+{
+    PHDASTATE pThis = (PHDASTATE)pCodec->pvHDAState;
+    NOREF(pThis);
+    return VINF_SUCCESS;
+}
+
+DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
+                                           PHDASTREAMTRANSFERDESC pStreamDesc)
+{
+    Assert(pThis); Assert(pBdle); Assert(pStreamDesc); Assert(u8Strm <= 7);
+
+    memset(pStreamDesc, 0, sizeof(HDASTREAMTRANSFERDESC));
+    pStreamDesc->u8Strm     = u8Strm;
+    pStreamDesc->u32Ctl     = HDA_STREAM_REG2(pThis, CTL, u8Strm);
+    pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG2(pThis, BDPL, u8Strm),
+                                          HDA_STREAM_REG2(pThis, BDPU, u8Strm));
+    pStreamDesc->pu32Lpib   = &HDA_STREAM_REG2(pThis, LPIB, u8Strm);
+    pStreamDesc->pu32Sts    = &HDA_STREAM_REG2(pThis, STS, u8Strm);
+    pStreamDesc->u32Cbl     = HDA_STREAM_REG2(pThis, CBL, u8Strm);
+    pStreamDesc->u32Fifos   = HDA_STREAM_REG2(pThis, FIFOS, u8Strm);
+
+    pBdle->u32BdleMaxCvi    = HDA_STREAM_REG2(pThis, LVI, u8Strm);
+
+#ifdef LOG_ENABLED
+    if (   pBdle
+        && pBdle->u32BdleMaxCvi)
+    {
+        Log(("Initialization of transfer descriptor:\n"));
+        dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
+    }
+#endif
+}
+
+
+/**
+ * @interface_method_impl{HDACODEC,pfnTransfer}
+ */
+static DECLCALLBACK(void) hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE src, int avail)
+{
+    PHDASTATE       pThis  = (PHDASTATE)pCodec->pvHDAState;
+    uint8_t         u8Strm = 0;
+    PHDABDLEDESC    pBdle  = NULL;
+
+    switch (src)
+    {
+        case PO_INDEX:
+        {
+            u8Strm = 4;
+            pBdle = &pThis->StOutBdle;
+            break;
+        }
+        case PI_INDEX:
+        {
+            u8Strm = 0;
+            pBdle = &pThis->StInBdle;
+            break;
+        }
+        default:
+            return;
+    }
+
+    HDASTREAMTRANSFERDESC StreamDesc;
+    hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
+
+    bool fStop = false;
+    while (avail && !fStop)
+    {
+        Assert(   (StreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
+               && avail
+               && StreamDesc.u64BaseDMA);
+
+        /* Fetch the Buffer Descriptor Entry (BDE). */
+
+        if (hdaIsTransferCountersOverlapped(pThis, pBdle, &StreamDesc))
+            hdaFetchBdle(pThis, pBdle, &StreamDesc);
+        *StreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
+        Assert((avail >= 0 && (StreamDesc.u32Cbl >= (*StreamDesc.pu32Lpib)))); /* sanity */
+        uint32_t u32CblLimit = StreamDesc.u32Cbl - (*StreamDesc.pu32Lpib);
+        Assert((u32CblLimit > hdaFifoWToSz(pThis, &StreamDesc)));
+        Log(("hda: CBL=%d, LPIB=%d\n", StreamDesc.u32Cbl, *StreamDesc.pu32Lpib));
+        uint32_t cb;
+        switch (src)
+        {
+            case PO_INDEX:
+                cb = hdaWriteAudio(pThis, &StreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
+                break;
+            case PI_INDEX:
+                cb = hdaReadAudio(pThis, &StreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
+                break;
+            default:
+                cb = 0;
+                fStop = true;
+                AssertMsgFailed(("Unsupported"));
+        }
+        Assert(cb <= StreamDesc.u32Fifos + 1);
+        *StreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
+
+        /* Process end of buffer condition. */
+        hdaStreamCounterUpdate(pThis, pBdle, &StreamDesc, cb);
+        fStop = !fStop ? !hdaDoNextTransferCycle(pThis, pBdle, &StreamDesc) : fStop;
+    }
+}
+
+
+/* MMIO callbacks */
+
+/**
+ * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
+ *
+ * @note During implementation, we discovered so-called "forgotten" or "hole"
+ *       registers whose description is not listed in the RPM, datasheet, or
+ *       spec.
+ */
+PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
+{
+    PHDASTATE   pThis  = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    int         rc;
+
+    /*
+     * Look up and log.
+     */
+    uint32_t        offReg = GCPhysAddr - pThis->MMIOBaseAddr;
+    int             idxReg = hdaRegLookup(pThis, offReg);
+#ifdef LOG_ENABLED
+    unsigned const  cbLog     = cb;
+    uint32_t        offRegLog = offReg;
+#endif
+
+    Log(("hdaMMIORead: offReg=%#x cb=%#x\n", offReg, cb));
+#define NEW_READ_CODE
+#ifdef NEW_READ_CODE
+    Assert(cb == 4); Assert((offReg & 3) == 0);
+
+    if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL)
+        Log(("hda: access to registers except GCTL is blocked while reset\n"));
+
+    if (idxReg == -1)
+        LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", offReg, cb));
+
+    if (idxReg != -1)
+    {
+        /* ASSUMES gapless DWORD at end of map. */
+        if (g_aHdaRegMap[idxReg].size == 4)
+        {
+            /*
+             * Straight forward DWORD access.
+             */
+            rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, (uint32_t *)pv);
+            Log(("hda: read %s => %x (%Rrc)\n", g_aHdaRegMap[idxReg].abbrev, *(uint32_t *)pv, rc));
+        }
+        else
+        {
+            /*
+             * Multi register read (unless there are trailing gaps).
+             * ASSUMES that only DWORD reads have sideeffects.
+             */
+            uint32_t u32Value = 0;
+            unsigned cbLeft   = 4;
+            do
+            {
+                uint32_t const  cbReg        = g_aHdaRegMap[idxReg].size;
+                uint32_t        u32Tmp       = 0;
+
+                rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Tmp);
+                Log(("hda: read %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxReg].abbrev, cbReg, *(uint32_t *)pv, rc));
+                if (rc != VINF_SUCCESS)
+                    break;
+                u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
+
+                cbLeft -= cbReg;
+                offReg += cbReg;
+                idxReg++;
+            } while (cbLeft > 0 && g_aHdaRegMap[idxReg].offset == offReg);
+
+            if (rc == VINF_SUCCESS)
+                *(uint32_t *)pv = u32Value;
+            else
+                Assert(!IOM_SUCCESS(rc));
+        }
+    }
+    else
+    {
+        rc = VINF_IOM_MMIO_UNUSED_FF;
+        Log(("hda: hole at %x is accessed for read\n", offReg));
+    }
+#else
+    if (idxReg != -1)
+    {
+        /** @todo r=bird: Accesses crossing register boundraries aren't handled
+         *        right from what I can tell?  If they are, please explain
+         *        what the rules are. */
+        uint32_t mask = 0;
+        uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
+        uint32_t u32Value = 0;
+        switch(cb)
+        {
+            case 1: mask = 0x000000ff; break;
+            case 2: mask = 0x0000ffff; break;
+            case 4:
+            /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
+            case 8:
+                mask = 0xffffffff;
+                cb = 4;
+                break;
+        }
+#if 0
+        /* Cross-register access. Mac guest hits this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL
+         */
+        //Assert((cb <= g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset)));
+        if (cb > g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset))
+        {
+            int off = cb - (g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset));
+            rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off);
+            if (RT_FAILURE(rc))
+                AssertRCReturn (rc, rc);
+        }
+        //Assert(((offReg - g_aHdaRegMap[idxReg].offset) == 0));
+#endif
+        mask <<= shift;
+        rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Value);
+        *(uint32_t *)pv |= (u32Value & mask);
+        Log(("hda: read %s[%x/%x]\n", g_aHdaRegMap[idxReg].abbrev, u32Value, *(uint32_t *)pv));
+    }
+    else
+    {
+        *(uint32_t *)pv = 0xFF;
+        Log(("hda: hole at %x is accessed for read\n", offReg));
+        rc = VINF_SUCCESS;
+    }
+#endif
+
+    /*
+     * Log the outcome.
+     */
+#ifdef LOG_ENABLED
+    if (cbLog == 4)
+        Log(("hdaMMIORead: @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
+    else if (cbLog == 2)
+        Log(("hdaMMIORead: @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
+    else if (cbLog == 1)
+        Log(("hdaMMIORead: @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
+#endif
+    return rc;
+}
+
+
+DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxReg, uint32_t u32Value, char const *pszLog)
+{
+    if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL)
+        Log(("hda: access to registers except GCTL is blocked while reset\n"));  /** @todo where is this enforced? */
+
+#ifdef LOG_ENABLED
+    uint32_t const u32CurValue = pThis->au32Regs[idxReg];
+#endif
+    int rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32Value);
+    Log(("hda: write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxReg].abbrev,
+         g_aHdaRegMap[idxReg].size, u32CurValue, pThis->au32Regs[idxReg], pszLog));
+    return rc;
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
+ */
+PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
+{
+    PHDASTATE               pThis  = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    int                     rc;
+
+    /*
+     * The behavior of accesses that aren't aligned on natural boundraries is
+     * undefined. Just reject them out right.
+     */
+    /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
+    Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
+    if (GCPhysAddr & (cb - 1))
+        return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
+
+    /*
+     * Lookup and log the access.
+     */
+    uint32_t    offReg = GCPhysAddr - pThis->MMIOBaseAddr;
+    int         idxReg = hdaRegLookup(pThis, offReg);
+    uint64_t    u64Value;
+    if (cb == 4)        u64Value = *(uint32_t const *)pv;
+    else if (cb == 2)   u64Value = *(uint16_t const *)pv;
+    else if (cb == 1)   u64Value = *(uint8_t const *)pv;
+    else if (cb == 8)   u64Value = *(uint64_t const *)pv;
+    else
+        AssertReleaseMsgFailed(("%d\n", cb));
+
+#ifdef LOG_ENABLED
+    uint32_t const u32LogOldValue = idxReg != -1 ? pThis->au32Regs[idxReg] : UINT32_MAX;
+    uint32_t const offRegLog = offReg;
+    int      const idxRegLog = idxReg;
+    if (idxReg == -1)
+        Log(("hdaMMIOWrite: @%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
+    else if (cb == 4)
+        Log(("hdaMMIOWrite: @%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
+    else if (cb == 2)
+        Log(("hdaMMIOWrite: @%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
+    else if (cb == 1)
+        Log(("hdaMMIOWrite: @%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
+    if (idxReg != -1 && g_aHdaRegMap[idxReg].size != cb)
+        Log(("hdaMMIOWrite: size=%d != cb=%d!!\n", g_aHdaRegMap[idxReg].size, cb));
+#endif
+
+#define NEW_WRITE_CODE
+#ifdef NEW_WRITE_CODE
+    /*
+     * Try for a direct hit first.
+     */
+    if (idxReg != -1 && g_aHdaRegMap[idxReg].size == cb)
+        rc = hdaWriteReg(pThis, idxReg, u64Value, "");
+    /*
+     * Partial or multiple register access, loop thru the requested memory.
+     */
+    else
+    {
+        /* If it's an access beyond the start of the register, shift the input
+           value and fill in missing bits. Natural alignment rules means we
+           will only see 1 or 2 byte accesses of this kind, so no risk of
+           shifting out input values. */
+        if (idxReg == -1 && (idxReg = hdaRegLookupWithin(pThis, offReg)) != -1)
+        {
+            uint32_t const cbBefore = g_aHdaRegMap[idxReg].offset - offReg; Assert(cbBefore > 0 && cbBefore < 4);
+            offReg    -= cbBefore;
+            u64Value <<= cbBefore * 8;
+            u64Value  |= pThis->au32Regs[idxReg] & g_afMasks[cbBefore];
+            Log(("hdaMMIOWrite: Within register, supplied %u leading bits: %#llx -> %#llx ...\n",
+                 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
+        }
+
+        /* Loop thru the write area, it may covert multiple registers. */
+        rc = VINF_SUCCESS;
+        for (;;)
+        {
+            uint32_t cbReg;
+            if (idxReg != -1)
+            {
+                cbReg = g_aHdaRegMap[idxReg].size;
+                if (cb < cbReg)
+                {
+                    u64Value |= pThis->au32Regs[idxReg] & g_afMasks[cbReg] & ~g_afMasks[cb];
+                    Log(("hdaMMIOWrite: Supplying missing bits (%#x): %#llx -> %#llx ...\n",
+                         g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
+                }
+                rc = hdaWriteReg(pThis, idxReg, u64Value, "*");
+            }
+            else
+            {
+                LogRel(("hda: Invalid write access @0x%x!\n", offReg));
+                cbReg = 1;
+            }
+            if (cbReg >= cb)
+                break;
+
+            /* advance */
+            offReg += cbReg;
+            cb     -= cbReg;
+            u64Value >>= cbReg * 8;
+            if (idxReg == -1)
+                idxReg = hdaRegLookup(pThis, offReg);
+            else
+            {
+                idxReg++;
+                if (   (unsigned)idxReg >= RT_ELEMENTS(g_aHdaRegMap)
+                    || g_aHdaRegMap[idxReg].offset != offReg)
+                    idxReg = -1;
+            }
+        }
+    }
+#else
+    if (idxReg != -1)
+    {
+        /** @todo r=bird: This looks like code for handling unaligned register
+         * accesses.  If it isn't, then add a comment explaining what you're
+         * trying to do here.  OTOH, if it is then it has the following
+         * issues:
+         *      -# You're calculating the wrong new value for the register.
+         *      -# You're not handling cross register accesses.  Imagine a
+         *       4-byte write starting at CORBCTL, or a 8-byte write.
+         *
+         * PS! consider dropping the 'offset' argument to pfnWrite/pfnRead as
+         * nobody seems to be using it and it just adds complexity when reading
+         * the code.
+         *
+         */
+        uint32_t u32CurValue = pThis->au32Regs[idxReg];
+        uint32_t u32NewValue;
+        uint32_t mask;
+        switch (cb)
+        {
+            case 1:
+                u32NewValue = *(uint8_t const *)pv;
+                mask = 0xff;
+                break;
+            case 2:
+                u32NewValue = *(uint16_t const *)pv;
+                mask = 0xffff;
+                break;
+            case 4:
+            case 8:
+                /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
+                u32NewValue = *(uint32_t const *)pv;
+                mask = 0xffffffff;
+                cb = 4;
+                break;
+            default:
+                AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */
+        }
+        /* cross-register access, see corresponding comment in hdaMMIORead */
+        uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
+        mask <<= shift;
+        u32NewValue <<= shift;
+        u32NewValue &= mask;
+        u32NewValue |= (u32CurValue & ~mask);
+
+        rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32NewValue);
+        Log(("hda: write %s:(%x) %x => %x\n", g_aHdaRegMap[idxReg].abbrev, u32NewValue,
+             u32CurValue, pThis->au32Regs[idxReg]));
+    }
+    else
+        rc = VINF_SUCCESS;
+#endif
+    Log(("hdaMMIOWrite: @%#05x %#x -> %#x\n", offRegLog, u32LogOldValue,
+         idxRegLog != -1 ? pThis->au32Regs[idxRegLog] : UINT32_MAX));
+    return rc;
+}
+
+
+/* PCI callback. */
+
+/**
+ * @callback_method_impl{FNPCIIOREGIONMAP}
+ */
+static DECLCALLBACK(int) hdaPciIoRegionMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
+                                           PCIADDRESSSPACE enmType)
+{
+    PPDMDEVINS  pDevIns = pPciDev->pDevIns;
+    PHDASTATE   pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
+    RTIOPORT    Port = (RTIOPORT)GCPhysAddress;
+    int         rc;
+
+    /*
+     * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
+     *
+     * Let IOM talk DWORDs when reading, saves a lot of complications. On
+     * writing though, we have to do it all ourselves because of sideeffects.
+     */
+    Assert(enmType == PCI_ADDRESS_SPACE_MEM);
+    rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
+#ifdef NEW_READ_CODE
+                               IOMMMIO_FLAGS_READ_DWORD |
+#else
+                               IOMMMIO_FLAGS_READ_PASSTHRU |
+#endif
+                               IOMMMIO_FLAGS_WRITE_PASSTHRU,
+                               hdaMMIOWrite, hdaMMIORead, "ICH6_HDA");
+
+    if (RT_FAILURE(rc))
+        return rc;
+
+    pThis->MMIOBaseAddr = GCPhysAddress;
+    return VINF_SUCCESS;
+}
+
+
+/* Saved state callbacks. */
+
+/**
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
+ */
+static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    /* Save Codec nodes states */
+    hdaCodecSaveState(&pThis->Codec, pSSM);
+
+    /* Save MMIO registers */
+    AssertCompile(RT_ELEMENTS(pThis->au32Regs) == 112);
+    SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
+    SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
+
+    /* Save HDA dma counters */
+    SSMR3PutStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
+    SSMR3PutStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
+    SSMR3PutStructEx(pSSM, &pThis->StInBdle,  sizeof(pThis->StInBdle),  0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
+ */
+static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+
+    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
+
+    /*
+     * Load Codec nodes states.
+     */
+    int rc = hdaCodecLoadState(&pThis->Codec, pSSM, uVersion);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Load MMIO registers.
+     */
+    uint32_t cRegs;
+    switch (uVersion)
+    {
+        case HDA_SSM_VERSION_1:
+            /* Starting with r71199, we would save 112 instead of 113
+               registers due to some code cleanups.  This only affected trunk
+               builds in the 4.1 development period. */
+            cRegs = 113;
+            if (SSMR3HandleRevision(pSSM) >= 71199)
+            {
+                uint32_t uVer = SSMR3HandleVersion(pSSM);
+                if (   VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
+                    && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
+                    && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
+                    cRegs = 112;
+            }
+            break;
+
+        case HDA_SSM_VERSION_2:
+        case HDA_SSM_VERSION_3:
+            cRegs = 112;
+            AssertCompile(RT_ELEMENTS(pThis->au32Regs) == 112);
+            break;
+
+        case HDA_SSM_VERSION:
+            rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
+            AssertLogRelMsgReturn(cRegs == RT_ELEMENTS(pThis->au32Regs),
+                                  ("cRegs is %d, expected %d\n", cRegs, RT_ELEMENTS(pThis->au32Regs)),
+                                  VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
+            break;
+
+        default:
+            return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+    }
+
+    if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
+    {
+        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
+        SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
+    }
+    else
+    {
+        RT_ZERO(pThis->au32Regs);
+        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
+    }
+
+    /*
+     * Load HDA dma counters.
+     */
+    uint32_t   fFlags   = uVersion <= HDA_SSM_VERSION_2 ? SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED : 0;
+    PCSSMFIELD paFields = uVersion <= HDA_SSM_VERSION_2 ? g_aHdaBDLEDescFieldsOld              : g_aHdaBDLEDescFields;
+    SSMR3GetStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), fFlags, paFields, NULL);
+    SSMR3GetStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), fFlags, paFields, NULL);
+    rc = SSMR3GetStructEx(pSSM, &pThis->StInBdle, sizeof(pThis->StInBdle), fFlags, paFields, NULL);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * Update stuff after the state changes.
+     */
+    AUD_set_active_in(pThis->Codec.SwVoiceIn, SDCTL(pThis, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+    AUD_set_active_out(pThis->Codec.SwVoiceOut, SDCTL(pThis, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
+
+    pThis->u64CORBBase = RT_MAKE_U64(CORBLBASE(pThis), CORBUBASE(pThis));
+    pThis->u64RIRBBase = RT_MAKE_U64(RIRLBASE(pThis), RIRUBASE(pThis));
+    pThis->u64DPBase   = RT_MAKE_U64(DPLBASE(pThis), DPUBASE(pThis));
+    return VINF_SUCCESS;
+}
+
+
+/* Debug and log type formatters. */
+
+/**
+ * @callback_method_impl{FNRTSTRFORMATTYPE}
+ */
+static DECLCALLBACK(size_t)
+hdaFormatStrmCtl(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                 const char *pszType, void const *pvValue,
+                 int cchWidth, int cchPrecision, unsigned fFlags,
+                 void *pvUser)
+{
+    uint32_t sdCtl = (uint32_t)(uintptr_t)pvValue;
+    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                       "SDCTL(raw: %#x, strm:%#x, dir:%RTbool, tp:%RTbool strip:%x, deie:%RTbool, ioce:%RTbool, run:%RTbool, srst:%RTbool)",
+                       sdCtl,
+                       (sdCtl & HDA_REG_FIELD_MASK(SDCTL, NUM)) >> ICH6_HDA_SDCTL_NUM_SHIFT,
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DIR)),
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, TP)),
+                       (sdCtl & HDA_REG_FIELD_MASK(SDCTL, STRIPE)) >> ICH6_HDA_SDCTL_STRIPE_SHIFT,
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DEIE)),
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)),
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
+                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
+}
+
+/**
+ * @callback_method_impl{FNRTSTRFORMATTYPE}
+ */
+static DECLCALLBACK(size_t)
+hdaFormatStrmFifos(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                   const char *pszType, void const *pvValue,
+                   int cchWidth, int cchPrecision, unsigned fFlags,
+                   void *pvUser)
+{
+    uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
+    uint32_t cb;
+    switch (uSdFifos)
+    {
+        case HDA_SDONFIFO_16B:  cb = 16; break;
+        case HDA_SDONFIFO_32B:  cb = 32; break;
+        case HDA_SDONFIFO_64B:  cb = 64; break;
+        case HDA_SDONFIFO_128B: cb = 128; break;
+        case HDA_SDONFIFO_192B: cb = 192; break;
+        case HDA_SDONFIFO_256B: cb = 256; break;
+        case HDA_SDINFIFO_120B: cb = 120; break;
+        case HDA_SDINFIFO_160B: cb = 160; break;
+        default:                cb = 0; break;
+    }
+    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw: %#x, sdfifos:%u B)", uSdFifos, cb);
+}
+
+/**
+ * @callback_method_impl{FNRTSTRFORMATTYPE}
+ */
+static DECLCALLBACK(size_t)
+hdaFormatStrmFifow(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                   const char *pszType, void const *pvValue,
+                   int cchWidth, int cchPrecision, unsigned fFlags,
+                   void *pvUser)
+{
+    uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
+    uint32_t cb;
+    switch (uSdFifos)
+    {
+        case HDA_SDFIFOW_8B:  cb = 8;  break;
+        case HDA_SDFIFOW_16B: cb = 16; break;
+        case HDA_SDFIFOW_32B: cb = 32; break;
+        default:              cb = 0;  break;
+    }
+    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSdFifos, cb);
+}
+
+/**
+ * @callback_method_impl{FNRTSTRFORMATTYPE}
+ */
+static DECLCALLBACK(size_t)
+hdaFormatStrmSts(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
+                 const char *pszType, void const *pvValue,
+                 int cchWidth, int cchPrecision, unsigned fFlags,
+                 void *pvUser)
+{
+    uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
+    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
+                       "SDSTS(raw: %#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
+                       uSdSts,
+                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY)),
+                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)),
+                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)),
+                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)));
+}
+
+
+static int hdaLookUpRegisterByName(PHDASTATE pThis, const char *pszArgs)
+{
+    int iReg = 0;
+    for (; iReg < HDA_NREGS; ++iReg)
+        if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
+            return iReg;
+    return -1;
+}
+
+
+static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
+{
+    Assert(   pThis
+           && iHdaIndex >= 0
+           && iHdaIndex < HDA_NREGS);
+    pHlp->pfnPrintf(pHlp, "hda: %s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[iHdaIndex]);
+}
+
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) hdaInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    int iHdaRegisterIndex = hdaLookUpRegisterByName(pThis, pszArgs);
+    if (iHdaRegisterIndex != -1)
+        hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
+    else
+        for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NREGS; ++iHdaRegisterIndex)
+            hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
+}
+
+
+static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaStrmIndex)
+{
+    Assert(   pThis
+           && iHdaStrmIndex >= 0
+           && iHdaStrmIndex < 7);
+    pHlp->pfnPrintf(pHlp, "Dump of %d HDA Stream:\n", iHdaStrmIndex);
+    pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, CTL, iHdaStrmIndex));
+    pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, STS, iHdaStrmIndex));
+    pHlp->pfnPrintf(pHlp, "SD%dFIFOS: %R[sdfifos]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, FIFOS, iHdaStrmIndex));
+    pHlp->pfnPrintf(pHlp, "SD%dFIFOW: %R[sdfifow]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, FIFOW, iHdaStrmIndex));
+}
+
+
+static int hdaLookUpStreamIndex(PHDASTATE pThis, const char *pszArgs)
+{
+    /* todo: add args parsing */
+    return -1;
+}
+
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) hdaInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    PHDASTATE   pThis         = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    int         iHdaStrmIndex = hdaLookUpStreamIndex(pThis, pszArgs);
+    if (iHdaStrmIndex != -1)
+        hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
+    else
+        for(iHdaStrmIndex = 0; iHdaStrmIndex < 7; ++iHdaStrmIndex)
+            hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
+}
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) hdaInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    if (pThis->Codec.pfnCodecDbgListNodes)
+        pThis->Codec.pfnCodecDbgListNodes(&pThis->Codec, pHlp, pszArgs);
+    else
+        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
+}
+
+
+/**
+ * @callback_method_impl{FNDBGFHANDLERDEV}
+ */
+static DECLCALLBACK(void) hdaInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    if (pThis->Codec.pfnCodecDbgSelector)
+        pThis->Codec.pfnCodecDbgSelector(&pThis->Codec, pHlp, pszArgs);
+    else
+        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
+}
+
+
+/* PDMIBASE */
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
+{
+    PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
+    Assert(&pThis->IBase == pInterface);
+
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
+    return NULL;
+}
+
+
+/* PDMDEVREG */
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param   pDevIns     The device instance data.
+ *
+ * @remark  The original sources didn't install a reset handler, but it seems to
+ *          make sense to me so we'll do it.
+ */
+static DECLCALLBACK(void)  hdaReset(PPDMDEVINS pDevIns)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    GCAP(pThis) = HDA_MAKE_GCAP(4,4,0,0,1); /* see 6.2.1 */
+    VMIN(pThis) = 0x00;       /* see 6.2.2 */
+    VMAJ(pThis) = 0x01;       /* see 6.2.3 */
+    VMAJ(pThis) = 0x01;       /* see 6.2.3 */
+    OUTPAY(pThis) = 0x003C;   /* see 6.2.4 */
+    INPAY(pThis)  = 0x001D;   /* see 6.2.5 */
+    pThis->au32Regs[ICH6_HDA_REG_CORBSIZE] = 0x42; /* see 6.2.1 */
+    pThis->au32Regs[ICH6_HDA_REG_RIRBSIZE] = 0x42; /* see 6.2.1 */
+    CORBRP(pThis) = 0x0;
+    RIRBWP(pThis) = 0x0;
+
+    Log(("hda: inter HDA reset.\n"));
+    pThis->cbCorbBuf = 256 * sizeof(uint32_t);
+
+    if (pThis->pu32CorbBuf)
+        memset(pThis->pu32CorbBuf, 0, pThis->cbCorbBuf);
+    else
+        pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
+
+    pThis->cbRirbBuf = 256 * sizeof(uint64_t);
+    if (pThis->pu64RirbBuf)
+        memset(pThis->pu64RirbBuf, 0, pThis->cbRirbBuf);
+    else
+        pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
+
+    pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
+
+    HDABDLEDESC StEmptyBdle;
+    for (uint8_t u8Strm = 0; u8Strm < 8; ++u8Strm)
+    {
+        HDASTREAMTRANSFERDESC StreamDesc;
+        PHDABDLEDESC pBdle = NULL;
+        if (u8Strm == 0)
+            pBdle = &pThis->StInBdle;
+        else if(u8Strm == 4)
+            pBdle = &pThis->StOutBdle;
+        else
+        {
+            memset(&StEmptyBdle, 0, sizeof(HDABDLEDESC));
+            pBdle = &StEmptyBdle;
+        }
+        hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
+        /* hdaStreamReset prevents changing the SRST bit, so we force it to zero here. */
+        HDA_STREAM_REG2(pThis, CTL, u8Strm) = 0;
+        hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
+    }
+
+    /* emulation of codec "wake up" (HDA spec 5.5.1 and 6.5)*/
+    STATESTS(pThis) = 0x1;
+
+    Log(("hda: reset finished\n"));
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
+ */
+static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
+{
+    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+
+    int rc = hdaCodecDestruct(&pThis->Codec);
+    AssertRC(rc);
+
+    RTMemFree(pThis->pu32CorbBuf);
+    pThis->pu32CorbBuf = NULL;
+
+    RTMemFree(pThis->pu64RirbBuf);
+    pThis->pu64RirbBuf = NULL;
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
+ */
+static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
+{
+    PHDASTATE   pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
+    int         rc;
+
+    Assert(iInstance == 0);
+    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+
+    /*
+     * Validations.
+     */
+    if (!CFGMR3AreValuesValid(pCfgHandle, "\0"))
+        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
+                                N_ ("Invalid configuration for the Intel HDA device"));
+
+    /// @todo r=michaln: This device may need R0/RC enabling, especially if guests
+    /// poll some register(pThis).
+
+    /*
+     * Initialize data (most of it anyway).
+     */
+    pThis->pDevIns                  = pDevIns;
+    /* IBase */
+    pThis->IBase.pfnQueryInterface  = hdaQueryInterface;
+
+    /* PCI Device */
+    PCIDevSetVendorId           (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
+    PCIDevSetDeviceId           (&pThis->PciDev, HDA_PCI_DEICE_ID); /* HDA */
+
+    PCIDevSetCommand            (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
+    PCIDevSetStatus             (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
+    PCIDevSetRevisionId         (&pThis->PciDev, 0x01);   /* 08 ro - rid. */
+    PCIDevSetClassProg          (&pThis->PciDev, 0x00);   /* 09 ro - pi. */
+    PCIDevSetClassSub           (&pThis->PciDev, 0x03);   /* 0a ro - scc; 03 == HDA. */
+    PCIDevSetClassBase          (&pThis->PciDev, 0x04);   /* 0b ro - bcc; 04 == multimedia. */
+    PCIDevSetHeaderType         (&pThis->PciDev, 0x00);   /* 0e ro - headtyp. */
+    PCIDevSetBaseAddress        (&pThis->PciDev, 0,       /* 10 rw - MMIO */
+                                 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
+    PCIDevSetInterruptLine      (&pThis->PciDev, 0x00);   /* 3c rw. */
+    PCIDevSetInterruptPin       (&pThis->PciDev, 0x01);   /* 3d ro - INTA#. */
+
+#if defined(HDA_AS_PCI_EXPRESS)
+    PCIDevSetCapabilityList     (&pThis->PciDev, 0x80);
+#elif defined(VBOX_WITH_MSI_DEVICES)
+    PCIDevSetCapabilityList     (&pThis->PciDev, 0x60);
+#else
+    PCIDevSetCapabilityList     (&pThis->PciDev, 0x50);   /* ICH6 datasheet 18.1.16 */
+#endif
+
+    /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
+    /// of these values needs to be properly documented!
+    /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
+    PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
+
+    /* Power Management */
+    PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
+    PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
+    PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
+
+#ifdef HDA_AS_PCI_EXPRESS
+    /* PCI Express */
+    PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
+    PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
+    /* Device flags */
+    PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
+                   /* version */ 0x1     |
+                   /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
+                   /* MSI */ (100) << 9 );
+    /* Device capabilities */
+    PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
+    /* Device control */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
+    /* Device status */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
+    /* Link caps */
+    PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
+    /* Link control */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
+    /* Link status */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
+    /* Slot capabilities */
+    PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
+    /* Slot control */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
+    /* Slot status */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
+    /* Root control */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
+    /* Root capabilities */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
+    /* Root status */
+    PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
+    /* Device capabilities 2 */
+    PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
+    /* Device control 2 */
+    PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
+    /* Link control 2 */
+    PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
+    /* Slot control 2 */
+    PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
+#endif
+
+    /*
+     * Register the PCI device.
+     */
+    rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
+    if (RT_FAILURE(rc))
+        return rc;
+
+#ifdef VBOX_WITH_MSI_DEVICES
+    PDMMSIREG MsiReg;
+    RT_ZERO(MsiReg);
+    MsiReg.cMsiVectors    = 1;
+    MsiReg.iMsiCapOffset  = 0x60;
+    MsiReg.iMsiNextOffset = 0x50;
+    rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
+        PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
+    }
+#endif
+
+    rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * Attach driver.
+     */
+    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port");
+    if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
+        Log(("hda: No attached driver!\n"));
+    else if (RT_FAILURE(rc))
+    {
+        AssertMsgFailed(("Failed to attach Intel HDA LUN #0! rc=%Rrc\n", rc));
+        return rc;
+    }
+
+    pThis->Codec.pvHDAState = pThis;
+    rc = hdaCodecConstruct(pDevIns, &pThis->Codec, pCfgHandle);
+    if (RT_FAILURE(rc))
+        AssertRCReturn(rc, rc);
+
+    /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
+       verb F20 should provide device/codec recognition. */
+    Assert(pThis->Codec.u16VendorId);
+    Assert(pThis->Codec.u16DeviceId);
+    PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->Codec.u16VendorId); /* 2c ro - intel.) */
+    PCIDevSetSubSystemId(      &pThis->PciDev, pThis->Codec.u16DeviceId); /* 2e ro. */
+
+    hdaReset(pDevIns);
+    pThis->Codec.id = 0;
+    pThis->Codec.pfnTransfer = hdaTransfer;
+    pThis->Codec.pfnReset = hdaCodecReset;
+
+    /*
+     * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
+     * hdaReset shouldn't affects these registers.
+     */
+    WAKEEN(pThis) = 0x0;
+    STATESTS(pThis) = 0x0;
+
+    /*
+     * Debug and string formatter types.
+     */
+    PDMDevHlpDBGFInfoRegister(pDevIns, "hda",         "HDA info. (hda [register case-insensitive])",    hdaInfo);
+    PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm",     "HDA stream info. (hdastrm [stream number])",     hdaInfoStream);
+    PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes",    "HDA codec nodes.",                               hdaInfoCodecNodes);
+    PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].",     hdaInfoCodecSelector);
+
+    rc = RTStrFormatTypeRegister("sdctl",   hdaFormatStrmCtl,   NULL);
+    AssertRC(rc);
+    rc = RTStrFormatTypeRegister("sdsts",   hdaFormatStrmSts,   NULL);
+    AssertRC(rc);
+    rc = RTStrFormatTypeRegister("sdfifos", hdaFormatStrmFifos, NULL);
+    AssertRC(rc);
+    rc = RTStrFormatTypeRegister("sdfifow", hdaFormatStrmFifow, NULL);
+    AssertRC(rc);
+#if 0
+    rc = RTStrFormatTypeRegister("sdfmt", printHdaStrmFmt, NULL);
+    AssertRC(rc);
+#endif
+
+    /*
+     * Some debug assertions.
+     */
+    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;
+
+        /* binary search order. */
+        AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
+                         ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
+                          i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
+
+        /* alignment. */
+        AssertReleaseMsg(   pReg->size == 1
+                         || (pReg->size == 2 && (pReg->offset & 1) == 0)
+                         || (pReg->size == 3 && (pReg->offset & 3) == 0)
+                         || (pReg->size == 4 && (pReg->offset & 3) == 0),
+                         ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
+
+        /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
+        AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
+        if (pReg->offset & 3)
+        {
+            struct HDAREGDESC const *pPrevReg = i > 0 ?  &g_aHdaRegMap[i - 1] : NULL;
+            AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
+            if (pPrevReg)
+                AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
+                                 ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
+                                  i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
+        }
+#if 0
+        if ((pReg->offset + pReg->size) & 3)
+        {
+            AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
+            if (pNextReg)
+                AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
+                                 ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
+                                  i, pReg->offset, pReg->size, i + 1,  pNextReg->offset, pNextReg->size));
+        }
+#endif
+
+        /* The final entry is a full dword, no gaps! Allows shortcuts. */
+        AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
+                         ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceICH6_HDA =
+{
+    /* u32Version */
+    PDM_DEVREG_VERSION,
+    /* szName */
+    "hda",
+    /* szRCMod */
+    "",
+    /* szR0Mod */
+    "",
+    /* pszDescription */
+    "Intel HD Audio Controller",
+    /* fFlags */
+    PDM_DEVREG_FLAGS_DEFAULT_BITS,
+    /* fClass */
+    PDM_DEVREG_CLASS_AUDIO,
+    /* cMaxInstances */
+    1,
+    /* cbInstance */
+    sizeof(HDASTATE),
+    /* pfnConstruct */
+    hdaConstruct,
+    /* pfnDestruct */
+    hdaDestruct,
+    /* pfnRelocate */
+    NULL,
+    /* pfnIOCtl */
+    NULL,
+    /* pfnPowerOn */
+    NULL,
+    /* pfnReset */
+    hdaReset,
+    /* pfnSuspend */
+    NULL,
+    /* pfnResume */
+    NULL,
+    /* pfnAttach */
+    NULL,
+    /* pfnDetach */
+    NULL,
+    /* pfnQueryInterface. */
+    NULL,
+    /* pfnInitComplete */
+    NULL,
+    /* pfnPowerOff */
+    NULL,
+    /* pfnSoftReset */
+    NULL,
+    /* u32VersionEnd */
+    PDM_DEVREG_VERSION
+};
Index: trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp	(revision 44669)
+++ trunk/src/VBox/Devices/Audio/DevIchHdaCodec.cpp	(revision 44669)
@@ -0,0 +1,2444 @@
+/* $Id$ */
+/** @file
+ * DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
+ *
+ * Implemented against "Intel I/O Controller Hub 6 (ICH6) High Definition
+ * Audio / AC '97 - Programmer's Reference Manual (PRM)", document number
+ * 302349-003.
+ */
+
+/*
+ * Copyright (C) 2006-2013 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_AUDIO
+#include <VBox/vmm/pdmdev.h>
+#include <iprt/assert.h>
+#include <iprt/uuid.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/asm.h>
+#include <iprt/cpp/utils.h>
+
+#include "VBoxDD.h"
+extern "C" {
+#include "audio.h"
+}
+#include "DevIchHdaCodec.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/* PRM 5.3.1 */
+#define CODEC_CAD_MASK              0xF0000000
+#define CODEC_CAD_SHIFT             28
+#define CODEC_DIRECT_MASK           RT_BIT(27)
+#define CODEC_NID_MASK              0x07F00000
+#define CODEC_NID_SHIFT             20
+#define CODEC_VERBDATA_MASK         0x000FFFFF
+#define CODEC_VERB_4BIT_CMD         0x000FFFF0
+#define CODEC_VERB_4BIT_DATA        0x0000000F
+#define CODEC_VERB_8BIT_CMD         0x000FFF00
+#define CODEC_VERB_8BIT_DATA        0x000000FF
+#define CODEC_VERB_16BIT_CMD        0x000F0000
+#define CODEC_VERB_16BIT_DATA       0x0000FFFF
+
+#define CODEC_CAD(cmd) ((cmd) & CODEC_CAD_MASK)
+#define CODEC_DIRECT(cmd) ((cmd) & CODEC_DIRECT_MASK)
+#define CODEC_NID(cmd) ((((cmd) & CODEC_NID_MASK)) >> CODEC_NID_SHIFT)
+#define CODEC_VERBDATA(cmd) ((cmd) & CODEC_VERBDATA_MASK)
+#define CODEC_VERB_CMD(cmd, mask, x) (((cmd) & (mask)) >> (x))
+#define CODEC_VERB_CMD4(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_4BIT_CMD, 4))
+#define CODEC_VERB_CMD8(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_8BIT_CMD, 8))
+#define CODEC_VERB_CMD16(cmd) (CODEC_VERB_CMD((cmd), CODEC_VERB_16BIT_CMD, 16))
+#define CODEC_VERB_PAYLOAD4(cmd) ((cmd) & CODEC_VERB_4BIT_DATA)
+#define CODEC_VERB_PAYLOAD8(cmd) ((cmd) & CODEC_VERB_8BIT_DATA)
+#define CODEC_VERB_PAYLOAD16(cmd) ((cmd) & CODEC_VERB_16BIT_DATA)
+
+#define CODEC_VERB_GET_AMP_DIRECTION  RT_BIT(15)
+#define CODEC_VERB_GET_AMP_SIDE       RT_BIT(13)
+#define CODEC_VERB_GET_AMP_INDEX      0x7
+
+/* HDA spec 7.3.3.7 NoteA */
+#define CODEC_GET_AMP_DIRECTION(cmd)  (((cmd) & CODEC_VERB_GET_AMP_DIRECTION) >> 15)
+#define CODEC_GET_AMP_SIDE(cmd)       (((cmd) & CODEC_VERB_GET_AMP_SIDE) >> 13)
+#define CODEC_GET_AMP_INDEX(cmd)      (CODEC_GET_AMP_DIRECTION(cmd) ? 0 : ((cmd) & CODEC_VERB_GET_AMP_INDEX))
+
+/* HDA spec 7.3.3.7 NoteC */
+#define CODEC_VERB_SET_AMP_OUT_DIRECTION  RT_BIT(15)
+#define CODEC_VERB_SET_AMP_IN_DIRECTION   RT_BIT(14)
+#define CODEC_VERB_SET_AMP_LEFT_SIDE      RT_BIT(13)
+#define CODEC_VERB_SET_AMP_RIGHT_SIDE     RT_BIT(12)
+#define CODEC_VERB_SET_AMP_INDEX          (0x7 << 8)
+
+#define CODEC_SET_AMP_IS_OUT_DIRECTION(cmd)  (((cmd) & CODEC_VERB_SET_AMP_OUT_DIRECTION) != 0)
+#define CODEC_SET_AMP_IS_IN_DIRECTION(cmd)   (((cmd) & CODEC_VERB_SET_AMP_IN_DIRECTION) != 0)
+#define CODEC_SET_AMP_IS_LEFT_SIDE(cmd)      (((cmd) & CODEC_VERB_SET_AMP_LEFT_SIDE) != 0)
+#define CODEC_SET_AMP_IS_RIGHT_SIDE(cmd)     (((cmd) & CODEC_VERB_SET_AMP_RIGHT_SIDE) != 0)
+#define CODEC_SET_AMP_INDEX(cmd)             (((cmd) & CODEC_VERB_SET_AMP_INDEX) >> 7)
+
+/* HDA spec 7.3.3.1 defines layout of configuration registers/verbs (0xF00) */
+/* VendorID (7.3.4.1) */
+#define CODEC_MAKE_F00_00(vendorID, deviceID) (((vendorID) << 16) | (deviceID))
+#define CODEC_F00_00_VENDORID(f00_00) (((f00_00) >> 16) & 0xFFFF)
+#define CODEC_F00_00_DEVICEID(f00_00) ((f00_00) & 0xFFFF)
+/* RevisionID (7.3.4.2)*/
+#define CODEC_MAKE_F00_02(MajRev, MinRev, RevisionID, SteppingID) (((MajRev) << 20)|((MinRev) << 16)|((RevisionID) << 8)|(SteppingID))
+/* Subordinate node count (7.3.4.3)*/
+#define CODEC_MAKE_F00_04(startNodeNumber, totalNodeNumber) ((((startNodeNumber) & 0xFF) << 16)|((totalNodeNumber) & 0xFF))
+#define CODEC_F00_04_TO_START_NODE_NUMBER(f00_04) (((f00_04) >> 16) & 0xFF)
+#define CODEC_F00_04_TO_NODE_COUNT(f00_04) ((f00_04) & 0xFF)
+/*
+ * Function Group Type  (7.3.4.4)
+ * 0 & [0x3-0x7f] are reserved types
+ * [0x80 - 0xff] are vendor defined function groups
+ */
+#define CODEC_MAKE_F00_05(UnSol, NodeType) (((UnSol) << 8)|(NodeType))
+#define CODEC_F00_05_UNSOL  RT_BIT(8)
+#define CODEC_F00_05_AFG    (0x1)
+#define CODEC_F00_05_MFG    (0x2)
+#define CODEC_F00_05_IS_UNSOL(f00_05) RT_BOOL((f00_05) & RT_BIT(8))
+#define CODEC_F00_05_GROUP(f00_05) ((f00_05) & 0xff)
+/*  Audio Function Group capabilities (7.3.4.5) */
+#define CODEC_MAKE_F00_08(BeepGen, InputDelay, OutputDelay) ((((BeepGen) & 0x1) << 16)| (((InputDelay) & 0xF) << 8) | ((OutputDelay) & 0xF))
+#define CODEC_F00_08_BEEP_GEN(f00_08) ((f00_08) & RT_BIT(16)
+
+/* Widget Capabilities (7.3.4.6) */
+#define CODEC_MAKE_F00_09(type, delay, chanel_count) \
+    ( (((type) & 0xF) << 20)            \
+    | (((delay) & 0xF) << 16)           \
+    | (((chanel_count) & 0xF) << 13))
+/* note: types 0x8-0xe are reserved */
+#define CODEC_F00_09_TYPE_AUDIO_OUTPUT      (0x0)
+#define CODEC_F00_09_TYPE_AUDIO_INPUT       (0x1)
+#define CODEC_F00_09_TYPE_AUDIO_MIXER       (0x2)
+#define CODEC_F00_09_TYPE_AUDIO_SELECTOR    (0x3)
+#define CODEC_F00_09_TYPE_PIN_COMPLEX       (0x4)
+#define CODEC_F00_09_TYPE_POWER_WIDGET      (0x5)
+#define CODEC_F00_09_TYPE_VOLUME_KNOB       (0x6)
+#define CODEC_F00_09_TYPE_BEEP_GEN          (0x7)
+#define CODEC_F00_09_TYPE_VENDOR_DEFINED    (0xF)
+
+#define CODEC_F00_09_CAP_CP                 RT_BIT(12)
+#define CODEC_F00_09_CAP_L_R_SWAP           RT_BIT(11)
+#define CODEC_F00_09_CAP_POWER_CTRL         RT_BIT(10)
+#define CODEC_F00_09_CAP_DIGITAL            RT_BIT(9)
+#define CODEC_F00_09_CAP_CONNECTION_LIST    RT_BIT(8)
+#define CODEC_F00_09_CAP_UNSOL              RT_BIT(7)
+#define CODEC_F00_09_CAP_PROC_WIDGET        RT_BIT(6)
+#define CODEC_F00_09_CAP_STRIPE             RT_BIT(5)
+#define CODEC_F00_09_CAP_FMT_OVERRIDE       RT_BIT(4)
+#define CODEC_F00_09_CAP_AMP_FMT_OVERRIDE   RT_BIT(3)
+#define CODEC_F00_09_CAP_OUT_AMP_PRESENT    RT_BIT(2)
+#define CODEC_F00_09_CAP_IN_AMP_PRESENT     RT_BIT(1)
+#define CODEC_F00_09_CAP_LSB                RT_BIT(0)
+
+#define CODEC_F00_09_TYPE(f00_09) (((f00_09) >> 20) & 0xF)
+
+#define CODEC_F00_09_IS_CAP_CP(f00_09)              RT_BOOL((f00_09) & RT_BIT(12))
+#define CODEC_F00_09_IS_CAP_L_R_SWAP(f00_09)        RT_BOOL((f00_09) & RT_BIT(11))
+#define CODEC_F00_09_IS_CAP_POWER_CTRL(f00_09)      RT_BOOL((f00_09) & RT_BIT(10))
+#define CODEC_F00_09_IS_CAP_DIGITAL(f00_09)         RT_BOOL((f00_09) & RT_BIT(9))
+#define CODEC_F00_09_IS_CAP_CONNECTION_LIST(f00_09) RT_BOOL((f00_09) & RT_BIT(8))
+#define CODEC_F00_09_IS_CAP_UNSOL(f00_09)           RT_BOOL((f00_09) & RT_BIT(7))
+#define CODEC_F00_09_IS_CAP_PROC_WIDGET(f00_09)     RT_BOOL((f00_09) & RT_BIT(6))
+#define CODEC_F00_09_IS_CAP_STRIPE(f00_09)          RT_BOOL((f00_09) & RT_BIT(5))
+#define CODEC_F00_09_IS_CAP_FMT_OVERRIDE(f00_09)    RT_BOOL((f00_09) & RT_BIT(4))
+#define CODEC_F00_09_IS_CAP_AMP_OVERRIDE(f00_09)    RT_BOOL((f00_09) & RT_BIT(3))
+#define CODEC_F00_09_IS_CAP_OUT_AMP_PRESENT(f00_09) RT_BOOL((f00_09) & RT_BIT(2))
+#define CODEC_F00_09_IS_CAP_IN_AMP_PRESENT(f00_09)  RT_BOOL((f00_09) & RT_BIT(1))
+#define CODEC_F00_09_IS_CAP_LSB(f00_09)             RT_BOOL((f00_09) & RT_BIT(0))
+
+/* Supported PCM size, rates (7.3.4.7) */
+#define CODEC_F00_0A_32_BIT             RT_BIT(19)
+#define CODEC_F00_0A_24_BIT             RT_BIT(18)
+#define CODEC_F00_0A_16_BIT             RT_BIT(17)
+#define CODEC_F00_0A_8_BIT              RT_BIT(16)
+
+#define CODEC_F00_0A_48KHZ_MULT_8X      RT_BIT(11)
+#define CODEC_F00_0A_48KHZ_MULT_4X      RT_BIT(10)
+#define CODEC_F00_0A_44_1KHZ_MULT_4X    RT_BIT(9)
+#define CODEC_F00_0A_48KHZ_MULT_2X      RT_BIT(8)
+#define CODEC_F00_0A_44_1KHZ_MULT_2X    RT_BIT(7)
+#define CODEC_F00_0A_48KHZ              RT_BIT(6)
+#define CODEC_F00_0A_44_1KHZ            RT_BIT(5)
+/* 2/3 * 48kHz */
+#define CODEC_F00_0A_48KHZ_2_3X         RT_BIT(4)
+/* 1/2 * 44.1kHz */
+#define CODEC_F00_0A_44_1KHZ_1_2X       RT_BIT(3)
+/* 1/3 * 48kHz */
+#define CODEC_F00_0A_48KHZ_1_3X         RT_BIT(2)
+/* 1/4 * 44.1kHz */
+#define CODEC_F00_0A_44_1KHZ_1_4X       RT_BIT(1)
+/* 1/6 * 48kHz */
+#define CODEC_F00_0A_48KHZ_1_6X         RT_BIT(0)
+
+/* Supported streams formats (7.3.4.8) */
+#define CODEC_F00_0B_AC3                RT_BIT(2)
+#define CODEC_F00_0B_FLOAT32            RT_BIT(1)
+#define CODEC_F00_0B_PCM                RT_BIT(0)
+
+/* Pin Capabilities (7.3.4.9)*/
+#define CODEC_MAKE_F00_0C(vref_ctrl) (((vref_ctrl) & 0xFF) << 8)
+#define CODEC_F00_0C_CAP_HBR                    RT_BIT(27)
+#define CODEC_F00_0C_CAP_DP                     RT_BIT(24)
+#define CODEC_F00_0C_CAP_EAPD                   RT_BIT(16)
+#define CODEC_F00_0C_CAP_HDMI                   RT_BIT(7)
+#define CODEC_F00_0C_CAP_BALANCED_IO            RT_BIT(6)
+#define CODEC_F00_0C_CAP_INPUT                  RT_BIT(5)
+#define CODEC_F00_0C_CAP_OUTPUT                 RT_BIT(4)
+#define CODEC_F00_0C_CAP_HP                     RT_BIT(3)
+#define CODEC_F00_0C_CAP_PRESENSE_DETECT        RT_BIT(2)
+#define CODEC_F00_0C_CAP_TRIGGER_REQUIRED       RT_BIT(1)
+#define CODEC_F00_0C_CAP_IMPENDANCE_SENSE       RT_BIT(0)
+
+#define CODEC_F00_0C_IS_CAP_HBR(f00_0c)                    ((f00_0c) & RT_BIT(27))
+#define CODEC_F00_0C_IS_CAP_DP(f00_0c)                     ((f00_0c) & RT_BIT(24))
+#define CODEC_F00_0C_IS_CAP_EAPD(f00_0c)                   ((f00_0c) & RT_BIT(16))
+#define CODEC_F00_0C_IS_CAP_HDMI(f00_0c)                   ((f00_0c) & RT_BIT(7))
+#define CODEC_F00_0C_IS_CAP_BALANCED_IO(f00_0c)            ((f00_0c) & RT_BIT(6))
+#define CODEC_F00_0C_IS_CAP_INPUT(f00_0c)                  ((f00_0c) & RT_BIT(5))
+#define CODEC_F00_0C_IS_CAP_OUTPUT(f00_0c)                 ((f00_0c) & RT_BIT(4))
+#define CODEC_F00_0C_IS_CAP_HP(f00_0c)                     ((f00_0c) & RT_BIT(3))
+#define CODEC_F00_0C_IS_CAP_PRESENSE_DETECT(f00_0c)        ((f00_0c) & RT_BIT(2))
+#define CODEC_F00_0C_IS_CAP_TRIGGER_REQUIRED(f00_0c)       ((f00_0c) & RT_BIT(1))
+#define CODEC_F00_0C_IS_CAP_IMPENDANCE_SENSE(f00_0c)       ((f00_0c) & RT_BIT(0))
+
+/* Input Amplifier capabilities (7.3.4.10) */
+#define CODEC_MAKE_F00_0D(mute_cap, step_size, num_steps, offset) \
+        (  (((mute_cap) & 0x1) << 31)                             \
+         | (((step_size) & 0xFF) << 16)                           \
+         | (((num_steps) & 0xFF) << 8)                            \
+         | ((offset) & 0xFF))
+
+/* Output Amplifier capabilities (7.3.4.10) */
+#define CODEC_MAKE_F00_12 CODEC_MAKE_F00_0D
+
+/* Connection list lenght (7.3.4.11) */
+#define CODEC_MAKE_F00_0E(long_form, length)    \
+    (  (((long_form) & 0x1) << 7)               \
+     | ((length) & 0x7F))
+#define CODEC_F00_0E_IS_LONG(f00_0e) RT_BOOL((f00_0e) & RT_BIT(7))
+#define CODEC_F00_0E_COUNT(f00_0e) ((f00_0e) & 0x7F)
+/* Supported Power States (7.3.4.12) */
+#define CODEC_F00_0F_EPSS       RT_BIT(31)
+#define CODEC_F00_0F_CLKSTOP    RT_BIT(30)
+#define CODEC_F00_0F_S3D3       RT_BIT(29)
+#define CODEC_F00_0F_D3COLD     RT_BIT(4)
+#define CODEC_F00_0F_D3         RT_BIT(3)
+#define CODEC_F00_0F_D2         RT_BIT(2)
+#define CODEC_F00_0F_D1         RT_BIT(1)
+#define CODEC_F00_0F_D0         RT_BIT(0)
+
+/* Processing capabilities 7.3.4.13 */
+#define CODEC_MAKE_F00_10(num, benign) ((((num) & 0xFF) << 8) | ((benign) & 0x1))
+#define CODEC_F00_10_NUM(f00_10) (((f00_10) & (0xFF << 8)) >> 8)
+#define CODEC_F00_10_BENING(f00_10) ((f00_10) & 0x1)
+
+/* CP/IO Count (7.3.4.14) */
+#define CODEC_MAKE_F00_11(wake, unsol, numgpi, numgpo, numgpio) \
+    (  (((wake) & 0x1) << 31)                                   \
+     | (((unsol) & 0x1) << 30)                                  \
+     | (((numgpi) & 0xFF) << 16)                                \
+     | (((numgpo) & 0xFF) << 8)                                 \
+     | ((numgpio) & 0xFF))
+
+/* Processing States (7.3.3.4) */
+#define CODEC_F03_OFF    (0)
+#define CODEC_F03_ON     RT_BIT(0)
+#define CODEC_F03_BENING RT_BIT(1)
+/* Power States (7.3.3.10) */
+#define CODEC_MAKE_F05(reset, stopok, error, act, set)          \
+    (   (((reset) & 0x1) << 10)                                 \
+      | (((stopok) & 0x1) << 9)                                 \
+      | (((error) & 0x1) << 8)                                  \
+      | (((act) & 0x7) << 4)                                    \
+      | ((set) & 0x7))
+#define CODEC_F05_D3COLD    (4)
+#define CODEC_F05_D3        (3)
+#define CODEC_F05_D2        (2)
+#define CODEC_F05_D1        (1)
+#define CODEC_F05_D0        (0)
+
+#define CODEC_F05_IS_RESET(value)   (((value) & RT_BIT(10)) != 0)
+#define CODEC_F05_IS_STOPOK(value)  (((value) & RT_BIT(9)) != 0)
+#define CODEC_F05_IS_ERROR(value)   (((value) & RT_BIT(8)) != 0)
+#define CODEC_F05_ACT(value)        (((value) & 0x7) >> 4)
+#define CODEC_F05_SET(value)        (((value) & 0x7))
+
+#define CODEC_F05_GE(p0, p1) ((p0) <= (p1))
+#define CODEC_F05_LE(p0, p1) ((p0) >= (p1))
+
+/* Pin Widged Control (7.3.3.13) */
+#define CODEC_F07_VREF_HIZ      (0)
+#define CODEC_F07_VREF_50       (0x1)
+#define CODEC_F07_VREF_GROUND   (0x2)
+#define CODEC_F07_VREF_80       (0x4)
+#define CODEC_F07_VREF_100      (0x5)
+#define CODEC_F07_IN_ENABLE     RT_BIT(5)
+#define CODEC_F07_OUT_ENABLE    RT_BIT(6)
+#define CODEC_F07_OUT_H_ENABLE  RT_BIT(7)
+
+/* Unsolicited enabled (7.3.3.14) */
+#define CODEC_MAKE_F08(enable, tag) ((((enable) & 1) << 7) | ((tag) & 0x3F))
+
+/* Converter formats (7.3.3.8) and (3.7.1) */
+#define CODEC_MAKE_A(fNonPCM, f44_1BaseRate, mult, div, bits, chan) \
+    (  (((fNonPCM) & 0x1) << 15)                                    \
+     | (((f44_1BaseRate) & 0x1) << 14)                              \
+     | (((mult) & 0x7) << 11)                                       \
+     | (((div) & 0x7) << 8)                                         \
+     | (((bits) & 0x7) << 4)                                        \
+     | ((chan) & 0xF))
+
+#define CODEC_A_MULT_1X     (0)
+#define CODEC_A_MULT_2X     (1)
+#define CODEC_A_MULT_3X     (2)
+#define CODEC_A_MULT_4X     (3)
+
+#define CODEC_A_DIV_1X      (0)
+#define CODEC_A_DIV_2X      (1)
+#define CODEC_A_DIV_3X      (2)
+#define CODEC_A_DIV_4X      (3)
+#define CODEC_A_DIV_5X      (4)
+#define CODEC_A_DIV_6X      (5)
+#define CODEC_A_DIV_7X      (6)
+#define CODEC_A_DIV_8X      (7)
+
+#define CODEC_A_8_BIT       (0)
+#define CODEC_A_16_BIT      (1)
+#define CODEC_A_20_BIT      (2)
+#define CODEC_A_24_BIT      (3)
+#define CODEC_A_32_BIT      (4)
+
+/* Pin Sense (7.3.3.15) */
+#define CODEC_MAKE_F09_ANALOG(fPresent, impedance)  \
+(  (((fPresent) & 0x1) << 31)                       \
+ | (((impedance) & 0x7FFFFFFF)))
+#define CODEC_F09_ANALOG_NA    0x7FFFFFFF
+#define CODEC_MAKE_F09_DIGITAL(fPresent, fELDValid) \
+(   (((fPresent) & 0x1) << 31)                      \
+  | (((fELDValid) & 0x1) << 30))
+
+#define CODEC_MAKE_F0C(lrswap, eapd, btl) ((((lrswap) & 1) << 2) | (((eapd) & 1) << 1) | ((btl) & 1))
+#define CODEC_FOC_IS_LRSWAP(f0c)    RT_BOOL((f0c) & RT_BIT(2))
+#define CODEC_FOC_IS_EAPD(f0c)      RT_BOOL((f0c) & RT_BIT(1))
+#define CODEC_FOC_IS_BTL(f0c)       RT_BOOL((f0c) & RT_BIT(0))
+/* HDA spec 7.3.3.31 defines layout of configuration registers/verbs (0xF1C) */
+/* Configuration's port connection */
+#define CODEC_F1C_PORT_MASK    (0x3)
+#define CODEC_F1C_PORT_SHIFT   (30)
+
+#define CODEC_F1C_PORT_COMPLEX (0x0)
+#define CODEC_F1C_PORT_NO_PHYS (0x1)
+#define CODEC_F1C_PORT_FIXED   (0x2)
+#define CODEC_F1C_BOTH         (0x3)
+
+/* Configuration's location */
+#define CODEC_F1C_LOCATION_MASK  (0x3F)
+#define CODEC_F1C_LOCATION_SHIFT (24)
+/* [4:5] bits of location region means chassis attachment */
+#define CODEC_F1C_LOCATION_PRIMARY_CHASSIS     (0)
+#define CODEC_F1C_LOCATION_INTERNAL            RT_BIT(4)
+#define CODEC_F1C_LOCATION_SECONDRARY_CHASSIS  RT_BIT(5)
+#define CODEC_F1C_LOCATION_OTHER               (RT_BIT(5))
+
+/* [0:3] bits of location region means geometry location attachment */
+#define CODEC_F1C_LOCATION_NA                  (0)
+#define CODEC_F1C_LOCATION_REAR                (0x1)
+#define CODEC_F1C_LOCATION_FRONT               (0x2)
+#define CODEC_F1C_LOCATION_LEFT                (0x3)
+#define CODEC_F1C_LOCATION_RIGTH               (0x4)
+#define CODEC_F1C_LOCATION_TOP                 (0x5)
+#define CODEC_F1C_LOCATION_BOTTOM              (0x6)
+#define CODEC_F1C_LOCATION_SPECIAL_0           (0x7)
+#define CODEC_F1C_LOCATION_SPECIAL_1           (0x8)
+#define CODEC_F1C_LOCATION_SPECIAL_2           (0x9)
+
+/* Configuration's devices */
+#define CODEC_F1C_DEVICE_MASK                  (0xF)
+#define CODEC_F1C_DEVICE_SHIFT                 (20)
+#define CODEC_F1C_DEVICE_LINE_OUT              (0)
+#define CODEC_F1C_DEVICE_SPEAKER               (0x1)
+#define CODEC_F1C_DEVICE_HP                    (0x2)
+#define CODEC_F1C_DEVICE_CD                    (0x3)
+#define CODEC_F1C_DEVICE_SPDIF_OUT             (0x4)
+#define CODEC_F1C_DEVICE_DIGITAL_OTHER_OUT     (0x5)
+#define CODEC_F1C_DEVICE_MODEM_LINE_SIDE       (0x6)
+#define CODEC_F1C_DEVICE_MODEM_HANDSET_SIDE    (0x7)
+#define CODEC_F1C_DEVICE_LINE_IN               (0x8)
+#define CODEC_F1C_DEVICE_AUX                   (0x9)
+#define CODEC_F1C_DEVICE_MIC                   (0xA)
+#define CODEC_F1C_DEVICE_PHONE                 (0xB)
+#define CODEC_F1C_DEVICE_SPDIF_IN              (0xC)
+#define CODEC_F1C_DEVICE_RESERVED              (0xE)
+#define CODEC_F1C_DEVICE_OTHER                 (0xF)
+
+/* Configuration's Connection type */
+#define CODEC_F1C_CONNECTION_TYPE_MASK         (0xF)
+#define CODEC_F1C_CONNECTION_TYPE_SHIFT        (16)
+
+#define CODEC_F1C_CONNECTION_TYPE_UNKNOWN               (0)
+#define CODEC_F1C_CONNECTION_TYPE_1_8INCHES             (0x1)
+#define CODEC_F1C_CONNECTION_TYPE_1_4INCHES             (0x2)
+#define CODEC_F1C_CONNECTION_TYPE_ATAPI                 (0x3)
+#define CODEC_F1C_CONNECTION_TYPE_RCA                   (0x4)
+#define CODEC_F1C_CONNECTION_TYPE_OPTICAL               (0x5)
+#define CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL         (0x6)
+#define CODEC_F1C_CONNECTION_TYPE_ANALOG                (0x7)
+#define CODEC_F1C_CONNECTION_TYPE_DIN                   (0x8)
+#define CODEC_F1C_CONNECTION_TYPE_XLR                   (0x9)
+#define CODEC_F1C_CONNECTION_TYPE_RJ_11                 (0xA)
+#define CODEC_F1C_CONNECTION_TYPE_COMBO                 (0xB)
+#define CODEC_F1C_CONNECTION_TYPE_OTHER                 (0xF)
+
+/* Configuration's color */
+#define CODEC_F1C_COLOR_MASK                  (0xF)
+#define CODEC_F1C_COLOR_SHIFT                 (12)
+#define CODEC_F1C_COLOR_UNKNOWN               (0)
+#define CODEC_F1C_COLOR_BLACK                 (0x1)
+#define CODEC_F1C_COLOR_GREY                  (0x2)
+#define CODEC_F1C_COLOR_BLUE                  (0x3)
+#define CODEC_F1C_COLOR_GREEN                 (0x4)
+#define CODEC_F1C_COLOR_RED                   (0x5)
+#define CODEC_F1C_COLOR_ORANGE                (0x6)
+#define CODEC_F1C_COLOR_YELLOW                (0x7)
+#define CODEC_F1C_COLOR_PURPLE                (0x8)
+#define CODEC_F1C_COLOR_PINK                  (0x9)
+#define CODEC_F1C_COLOR_RESERVED_0            (0xA)
+#define CODEC_F1C_COLOR_RESERVED_1            (0xB)
+#define CODEC_F1C_COLOR_RESERVED_2            (0xC)
+#define CODEC_F1C_COLOR_RESERVED_3            (0xD)
+#define CODEC_F1C_COLOR_WHITE                 (0xE)
+#define CODEC_F1C_COLOR_OTHER                 (0xF)
+
+/* Configuration's misc */
+#define CODEC_F1C_MISC_MASK                  (0xF)
+#define CODEC_F1C_MISC_SHIFT                 (8)
+#define CODEC_F1C_MISC_JACK_DETECT           (0)
+#define CODEC_F1C_MISC_RESERVED_0            (1)
+#define CODEC_F1C_MISC_RESERVED_1            (2)
+#define CODEC_F1C_MISC_RESERVED_2            (3)
+
+/* Configuration's association */
+#define CODEC_F1C_ASSOCIATION_MASK                  (0xF)
+#define CODEC_F1C_ASSOCIATION_SHIFT                 (4)
+/* Connection's sequence */
+#define CODEC_F1C_SEQ_MASK                  (0xF)
+#define CODEC_F1C_SEQ_SHIFT                 (0)
+
+/* Implementation identification (7.3.3.30) */
+#define CODEC_MAKE_F20(bmid, bsku, aid)     \
+    (  (((bmid) & 0xFFFF) << 16)            \
+     | (((bsku) & 0xFF) << 8)               \
+     | (((aid) & 0xFF))                     \
+    )
+
+/* macro definition helping in filling the configuration registers. */
+#define CODEC_MAKE_F1C(port_connectivity, location, device, connection_type, color, misc, association, sequence)    \
+    (  ((port_connectivity) << CODEC_F1C_PORT_SHIFT)          \
+     | ((location) << CODEC_F1C_LOCATION_SHIFT)               \
+     | ((device) << CODEC_F1C_DEVICE_SHIFT)                   \
+     | ((connection_type) << CODEC_F1C_CONNECTION_TYPE_SHIFT) \
+     | ((color) << CODEC_F1C_COLOR_SHIFT)                     \
+     | ((misc) << CODEC_F1C_MISC_SHIFT)                       \
+     | ((association) << CODEC_F1C_ASSOCIATION_SHIFT)         \
+     | ((sequence)))
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/** The F00 parameter length (in dwords). */
+#define CODECNODE_F00_PARAM_LENGTH  20
+/** The F02 parameter length (in dwords). */
+#define CODECNODE_F02_PARAM_LENGTH  16
+
+/**
+ * Common (or core) codec node structure.
+ */
+typedef struct CODECCOMMONNODE
+{
+    /** Node id - 7 bit format */
+    uint8_t         id;
+    /** The node name. */
+    char const     *pszName;
+    /* PRM 5.3.6 */
+    uint32_t au32F00_param[CODECNODE_F00_PARAM_LENGTH];
+    uint32_t au32F02_param[CODECNODE_F02_PARAM_LENGTH];
+} CODECCOMMONNODE;
+typedef CODECCOMMONNODE *PCODECCOMMONNODE;
+AssertCompile(CODECNODE_F00_PARAM_LENGTH == 20);  /* saved state */
+AssertCompile(CODECNODE_F02_PARAM_LENGTH == 16); /* saved state */
+
+/**
+ * Compile time assertion on the expected node size.
+ */
+#define AssertNodeSize(a_Node, a_cParams) \
+    AssertCompile((a_cParams) <= (60 + 6)); /* the max size - saved state */ \
+    AssertCompile(   sizeof(a_Node) - sizeof(CODECCOMMONNODE)  \
+                  == (((a_cParams) * sizeof(uint32_t) + sizeof(void *) - 1) & ~(sizeof(void *) - 1)) )
+
+typedef struct ROOTCODECNODE
+{
+    CODECCOMMONNODE node;
+} ROOTCODECNODE, *PROOTCODECNODE;
+AssertNodeSize(ROOTCODECNODE, 0);
+
+#define AMPLIFIER_SIZE 60
+typedef uint32_t AMPLIFIER[AMPLIFIER_SIZE];
+#define AMPLIFIER_IN    0
+#define AMPLIFIER_OUT   1
+#define AMPLIFIER_LEFT  1
+#define AMPLIFIER_RIGHT 0
+#define AMPLIFIER_REGISTER(amp, inout, side, index) ((amp)[30*(inout) + 15*(side) + (index)])
+typedef struct DACNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F0d_param;
+    uint32_t    u32F04_param;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F0c_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER B_params;
+
+} DACNODE, *PDACNODE;
+AssertNodeSize(DACNODE, 6 + 60);
+
+typedef struct ADCNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F03_param;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+
+    uint32_t    u32A_param;
+    uint32_t    u32F01_param;
+    AMPLIFIER   B_params;
+} ADCNODE, *PADCNODE;
+AssertNodeSize(DACNODE, 6 + 60);
+
+typedef struct SPDIFOUTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+    uint32_t    u32F0d_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} SPDIFOUTNODE, *PSPDIFOUTNODE;
+AssertNodeSize(SPDIFOUTNODE, 5 + 60);
+
+typedef struct SPDIFINNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F09_param;
+    uint32_t    u32F0d_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} SPDIFINNODE, *PSPDIFINNODE;
+AssertNodeSize(SPDIFINNODE, 5 + 60);
+
+typedef struct AFGCODECNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t  u32F05_param;
+    uint32_t  u32F08_param;
+    uint32_t  u32F20_param;
+    uint32_t  u32F17_param;
+} AFGCODECNODE, *PAFGCODECNODE;
+AssertNodeSize(AFGCODECNODE, 4);
+
+typedef struct PORTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F07_param;
+    uint32_t u32F08_param;
+    uint32_t u32F09_param;
+    uint32_t u32F01_param;
+    uint32_t u32F1c_param;
+    AMPLIFIER   B_params;
+} PORTNODE, *PPORTNODE;
+AssertNodeSize(PORTNODE, 5 + 60);
+
+typedef struct DIGOUTNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F01_param;
+    uint32_t u32F08_param;
+    uint32_t u32F07_param;
+    uint32_t u32F09_param;
+    uint32_t u32F1c_param;
+} DIGOUTNODE, *PDIGOUTNODE;
+AssertNodeSize(DIGOUTNODE, 5);
+
+typedef struct DIGINNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F05_param;
+    uint32_t u32F07_param;
+    uint32_t u32F08_param;
+    uint32_t u32F09_param;
+    uint32_t u32F0c_param;
+    uint32_t u32F1c_param;
+    uint32_t u32F1e_param;
+} DIGINNODE, *PDIGINNODE;
+AssertNodeSize(DIGINNODE, 7);
+
+typedef struct ADCMUXNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F01_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+} ADCMUXNODE, *PADCMUXNODE;
+AssertNodeSize(ADCMUXNODE, 2 + 60);
+
+typedef struct PCBEEPNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F07_param;
+    uint32_t    u32F0a_param;
+
+    uint32_t    u32A_param;
+    AMPLIFIER   B_params;
+    uint32_t    u32F1c_param;
+} PCBEEPNODE, *PPCBEEPNODE;
+AssertNodeSize(PCBEEPNODE, 3 + 60 + 1);
+
+typedef struct CDNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t u32F07_param;
+    uint32_t u32F1c_param;
+} CDNODE, *PCDNODE;
+AssertNodeSize(CDNODE, 2);
+
+typedef struct VOLUMEKNOBNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F08_param;
+    uint32_t    u32F0f_param;
+} VOLUMEKNOBNODE, *PVOLUMEKNOBNODE;
+AssertNodeSize(VOLUMEKNOBNODE, 2);
+
+typedef struct ADCVOLNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F0c_param;
+    uint32_t    u32F01_param;
+    uint32_t    u32A_params;
+    AMPLIFIER   B_params;
+} ADCVOLNODE, *PADCVOLNODE;
+AssertNodeSize(ADCVOLNODE, 3 + 60);
+
+typedef struct RESNODE
+{
+    CODECCOMMONNODE node;
+    uint32_t    u32F05_param;
+    uint32_t    u32F06_param;
+    uint32_t    u32F07_param;
+    uint32_t    u32F1c_param;
+} RESNODE, *PRESNODE;
+AssertNodeSize(RESNODE, 4);
+
+/**
+ * Used for the saved state.
+ */
+typedef struct CODECSAVEDSTATENODE
+{
+    CODECCOMMONNODE Core;
+    uint32_t        au32Params[60 + 6];
+} CODECSAVEDSTATENODE;
+AssertNodeSize(CODECSAVEDSTATENODE, 60 + 6);
+
+typedef union CODECNODE
+{
+    CODECCOMMONNODE node;
+    ROOTCODECNODE   root;
+    AFGCODECNODE    afg;
+    DACNODE         dac;
+    ADCNODE         adc;
+    SPDIFOUTNODE    spdifout;
+    SPDIFINNODE     spdifin;
+    PORTNODE        port;
+    DIGOUTNODE      digout;
+    DIGINNODE       digin;
+    ADCMUXNODE      adcmux;
+    PCBEEPNODE      pcbeep;
+    CDNODE          cdnode;
+    VOLUMEKNOBNODE  volumeKnob;
+    ADCVOLNODE      adcvol;
+    RESNODE         reserved;
+    CODECSAVEDSTATENODE SavedState;
+} CODECNODE, *PCODECNODE;
+AssertNodeSize(CODECNODE, 60 + 6);
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/* STAC9220 - Referenced thru STAC9220WIDGET in the constructor below. */
+static uint8_t const g_abStac9220Ports[]      = { 0x0A, 0xB, 0xC, 0xD, 0xE, 0xF, 0};
+static uint8_t const g_abStac9220Dacs[]       = { 0x02, 0x3, 0x4, 0x5, 0};
+static uint8_t const g_abStac9220Adcs[]       = { 0x06, 0x7, 0};
+static uint8_t const g_abStac9220SpdifOuts[]  = { 0x08, 0 };
+static uint8_t const g_abStac9220SpdifIns[]   = { 0x09, 0 };
+static uint8_t const g_abStac9220DigOutPins[] = { 0x10, 0 };
+static uint8_t const g_abStac9220DigInPins[]  = { 0x11, 0 };
+static uint8_t const g_abStac9220AdcVols[]    = { 0x17, 0x18, 0};
+static uint8_t const g_abStac9220AdcMuxs[]    = { 0x12, 0x13, 0};
+static uint8_t const g_abStac9220Pcbeeps[]    = { 0x14, 0 };
+static uint8_t const g_abStac9220Cds[]        = { 0x15, 0 };
+static uint8_t const g_abStac9220VolKnobs[]   = { 0x16, 0 };
+static uint8_t const g_abStac9220Reserveds[]  = { 0x09, 0x19, 0x1a, 0x1b, 0 };
+
+
+/** SSM description of a CODECNODE. */
+static SSMFIELD const g_aCodecNodeFields[] =
+{
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
+    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F00_param),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F02_param),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, au32Params),
+    SSMFIELD_ENTRY_TERM()
+};
+
+/** Backward compatibility with v1 of the CODECNODE. */
+static SSMFIELD const g_aCodecNodeFieldsV1[] =
+{
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.id),
+    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 7),
+    SSMFIELD_ENTRY_OLD_HCPTR(Core.name),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F00_param),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, Core.au32F02_param),
+    SSMFIELD_ENTRY(     CODECSAVEDSTATENODE, au32Params),
+    SSMFIELD_ENTRY_TERM()
+};
+
+
+
+
+static int stac9220ResetNode(PHDACODEC pThis, uint8_t nodenum, PCODECNODE pNode)
+{
+    pNode->node.id = nodenum;
+    pNode->node.au32F00_param[0xF] = 0; /* Power statest Supported: are the same as AFG reports */
+    switch (nodenum)
+    {
+        /* Root Node*/
+        case 0:
+            pNode->node.au32F00_param[0x02] = CODEC_MAKE_F00_02(0x1, 0x0, 0x34, 0x1); /* rev id */
+            break;
+        case 1:
+            pNode->node.au32F00_param[0x08] = CODEC_MAKE_F00_08(1, 0xd, 0xd);
+            pNode->node.au32F00_param[0x0C] = CODEC_MAKE_F00_0C(0x17)
+                                            | CODEC_F00_0C_CAP_BALANCED_IO
+                                            | CODEC_F00_0C_CAP_INPUT
+                                            | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                            | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                            | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//(17 << 8)|RT_BIT(6)|RT_BIT(5)|RT_BIT(2)|RT_BIT(1)|RT_BIT(0);
+            pNode->node.au32F00_param[0x0B] = CODEC_F00_0B_PCM;
+            pNode->node.au32F00_param[0x0D] = CODEC_MAKE_F00_0D(1, 0x5, 0xE, 0);//RT_BIT(31)|(0x5 << 16)|(0xE)<<8;
+            pNode->node.au32F00_param[0x12] = RT_BIT(31)|(0x2 << 16)|(0x7f << 8)|0x7f;
+            pNode->node.au32F00_param[0x11] = CODEC_MAKE_F00_11(1, 1, 0, 0, 4);//0xc0000004;
+            pNode->node.au32F00_param[0x0F] = CODEC_F00_0F_D3|CODEC_F00_0F_D2|CODEC_F00_0F_D1|CODEC_F00_0F_D0;
+            pNode->afg.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D2, CODEC_F05_D2);//0x2 << 4| 0x2; /* PS-Act: D3, PS->Set D3  */
+            pNode->afg.u32F08_param = 0;
+            pNode->afg.u32F17_param = 0;
+            break;
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+            memset(pNode->dac.B_params, 0, AMPLIFIER_SIZE);
+            pNode->dac.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 4)|0x1; /* 441000Hz/16bit/2ch */
+
+            AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_LEFT, 0) = 0x7F | RT_BIT(7);
+            AMPLIFIER_REGISTER(pNode->dac.B_params, AMPLIFIER_OUT, AMPLIFIER_RIGHT, 0) = 0x7F | RT_BIT(7);
+
+            pNode->dac.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0xD, 0)
+                                             | CODEC_F00_09_CAP_L_R_SWAP
+                                             | CODEC_F00_09_CAP_POWER_CTRL
+                                             | CODEC_F00_09_CAP_OUT_AMP_PRESENT
+                                             | CODEC_F00_09_CAP_LSB;//(0xD << 16) | RT_BIT(11) |  RT_BIT(10) | RT_BIT(2) | RT_BIT(0);
+            pNode->dac.u32F0c_param = 0;
+            pNode->dac.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3, Set: D3  */
+            break;
+        case 6:
+            pNode->node.au32F02_param[0] = 0x17;
+            goto adc_init;
+        case 7:
+            pNode->node.au32F02_param[0] = 0x18;
+        adc_init:
+            pNode->adc.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//RT_BIT(14)|(0x1 << 3)|0x1; /* 441000Hz/16bit/2ch */
+            pNode->adc.node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
+            pNode->adc.u32F03_param = RT_BIT(0);
+            pNode->adc.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 Set: D3 */
+            pNode->adc.u32F06_param = 0;
+            pNode->adc.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0xD, 0)
+                                             | CODEC_F00_09_CAP_POWER_CTRL
+                                             | CODEC_F00_09_CAP_CONNECTION_LIST
+                                             | CODEC_F00_09_CAP_PROC_WIDGET
+                                             | CODEC_F00_09_CAP_LSB;//RT_BIT(20)| (0xd << 16) |  RT_BIT(10) | RT_BIT(8) | RT_BIT(6)| RT_BIT(0);
+            break;
+        case 8:
+            pNode->spdifout.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(1<<14)|(0x1<<4) | 0x1;
+            pNode->spdifout.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x4, 0)
+                                                  | CODEC_F00_09_CAP_DIGITAL
+                                                  | CODEC_F00_09_CAP_FMT_OVERRIDE
+                                                  | CODEC_F00_09_CAP_LSB;//(4 << 16) | RT_BIT(9)|RT_BIT(4)|0x1;
+            pNode->node.au32F00_param[0xa] = pThis->paNodes[1].node.au32F00_param[0xA];
+            pNode->spdifout.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
+            pNode->spdifout.u32F06_param = 0;
+            pNode->spdifout.u32F0d_param = 0;
+            break;
+        case 9:
+            pNode->spdifin.u32A_param = CODEC_MAKE_A(0, 1, CODEC_A_MULT_1X, CODEC_A_DIV_1X, CODEC_A_16_BIT, 1);//(0x1<<4) | 0x1;
+            pNode->spdifin.node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_INPUT, 0x4, 0)
+                                                 | CODEC_F00_09_CAP_DIGITAL
+                                                 | CODEC_F00_09_CAP_CONNECTION_LIST
+                                                 | CODEC_F00_09_CAP_FMT_OVERRIDE
+                                                 | CODEC_F00_09_CAP_LSB;//(0x1 << 20)|(4 << 16) | RT_BIT(9)| RT_BIT(8)|RT_BIT(4)|0x1;
+            pNode->node.au32F00_param[0xA] = pThis->paNodes[1].node.au32F00_param[0xA];
+            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//RT_BIT(0);
+            pNode->node.au32F02_param[0] = 0x11;
+            pNode->spdifin.node.au32F00_param[0xB] = CODEC_F00_0B_PCM;
+            pNode->spdifin.u32F06_param = 0;
+            pNode->spdifin.u32F0d_param = 0;
+            break;
+        case 0xA:
+            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
+                                           | CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_HP
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x173f;
+            pNode->node.au32F02_param[0] = 0x2;
+            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE
+                                     | CODEC_F07_OUT_ENABLE;
+            pNode->port.u32F08_param = 0;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_FRONT,
+                                                          CODEC_F1C_DEVICE_HP,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_GREEN,
+                                                          CODEC_F1C_MISC_JACK_DETECT,
+                                                          0x2, 0);//RT_MAKE_U32_FROM_U8(0x20, 0x40, 0x21, 0x02);
+            goto port_init;
+        case 0xB:
+            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
+                                           | CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
+            pNode->node.au32F02_param[0] = 0x4;
+            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_INTERNAL|CODEC_F1C_LOCATION_REAR,
+                                                          CODEC_F1C_DEVICE_SPEAKER,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_BLACK,
+                                                          CODEC_F1C_MISC_JACK_DETECT,
+                                                          0x1, 0x1);//RT_MAKE_U32_FROM_U8(0x11, 0x60, 0x11, 0x01);
+            goto port_init;
+        case 0xC:
+            pNode->node.au32F02_param[0] = 0x3;
+            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
+                                           | CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
+            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_REAR,
+                                                          CODEC_F1C_DEVICE_SPEAKER,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_GREEN,
+                                                          0x0, 0x1, 0x0);//RT_MAKE_U32_FROM_U8(0x10, 0x40, 0x11, 0x01);
+            goto port_init;
+        case 0xD:
+            pNode->node.au32F00_param[0xC] = CODEC_MAKE_F00_0C(0x17)
+                                           | CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                           | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE;//0x1737;
+            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
+            pNode->node.au32F02_param[0] = 0x2;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_FRONT,
+                                                          CODEC_F1C_DEVICE_MIC,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_PINK,
+                                                          0x0, 0x5, 0x0);//RT_MAKE_U32_FROM_U8(0x50, 0x90, 0xA1, 0x02); /* Microphone */
+        port_init:
+            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(1, CODEC_F09_ANALOG_NA);//RT_BIT(31)|0x7fffffff;
+            pNode->port.u32F08_param = 0;
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
+                                         | CODEC_F00_09_CAP_CONNECTION_LIST
+                                         | CODEC_F00_09_CAP_UNSOL
+                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(0);
+            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
+            break;
+        case 0xE:
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0)
+                                         | CODEC_F00_09_CAP_UNSOL
+                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(7)|RT_BIT(0);
+            pNode->port.u32F08_param = 0;
+            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT;//0x34;
+            pNode->port.u32F07_param = CODEC_F07_IN_ENABLE;
+            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_REAR,
+                                                          CODEC_F1C_DEVICE_LINE_OUT,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_BLUE,
+                                                          0x0, 0x4, 0x0);//0x01013040;  /* Line Out */
+            break;
+        case 0xF:
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
+                                         | CODEC_F00_09_CAP_CONNECTION_LIST
+                                         | CODEC_F00_09_CAP_UNSOL
+                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT
+                                         | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(8)|RT_BIT(7)|RT_BIT(2)|RT_BIT(0);
+            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_OUTPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT
+                                           /* | CODEC_F00_0C_CAP_TRIGGER_REQUIRED
+                                           | CODEC_F00_0C_CAP_IMPENDANCE_SENSE */;//0x37;
+            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 1);//0x1;
+            pNode->port.u32F08_param = 0;
+            pNode->port.u32F07_param = CODEC_F07_OUT_ENABLE
+                                     | CODEC_F07_IN_ENABLE;
+            if (!pThis->fInReset)
+                pNode->port.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                          CODEC_F1C_LOCATION_INTERNAL,
+                                                          CODEC_F1C_DEVICE_SPEAKER,
+                                                          CODEC_F1C_CONNECTION_TYPE_1_8INCHES,
+                                                          CODEC_F1C_COLOR_ORANGE,
+                                                          0x0, 0x1, 0x2);//RT_MAKE_U32_FROM_U8(0x12, 0x60, 0x11, 0x01);
+            pNode->node.au32F02_param[0] = 0x5;
+            pNode->port.u32F09_param = CODEC_MAKE_F09_ANALOG(0, CODEC_F09_ANALOG_NA);//0x7fffffff;
+            break;
+        case 0x10:
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0x0, 0x0)
+                                         | CODEC_F00_09_CAP_DIGITAL
+                                         | CODEC_F00_09_CAP_CONNECTION_LIST
+                                         | CODEC_F00_09_CAP_LSB;//(4<<20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
+            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//RT_BIT(4);
+            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x3);
+            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x08, 0x17, 0x19, 0);
+            if (!pThis->fInReset)
+                pNode->digout.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                            CODEC_F1C_LOCATION_REAR,
+                                                            CODEC_F1C_DEVICE_SPDIF_OUT,
+                                                            CODEC_F1C_CONNECTION_TYPE_DIN,
+                                                            CODEC_F1C_COLOR_BLACK,
+                                                            0x0, 0x3, 0x0);//RT_MAKE_U32_FROM_U8(0x30, 0x10, 0x45, 0x01);
+            break;
+        case 0x11:
+            pNode->node.au32F00_param[9] = (4 << 20) | (3 << 16) | RT_BIT(10) | RT_BIT(9) | RT_BIT(7) | RT_BIT(0);
+            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_EAPD
+                                           | CODEC_F00_0C_CAP_INPUT
+                                           | CODEC_F00_0C_CAP_PRESENSE_DETECT;//RT_BIT(16)| RT_BIT(5)|RT_BIT(2);
+            pNode->digin.u32F05_param = CODEC_MAKE_F05(0, 0, 0, CODEC_F05_D3, CODEC_F05_D3);//0x3 << 4 | 0x3; /* PS-Act: D3 -> D3 */
+            pNode->digin.u32F07_param = 0;
+            pNode->digin.u32F08_param = 0;
+            pNode->digin.u32F09_param = 0;
+            pNode->digin.u32F0c_param = 0;
+            if (!pThis->fInReset)
+                pNode->digin.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_COMPLEX,
+                                                           CODEC_F1C_LOCATION_REAR,
+                                                           CODEC_F1C_DEVICE_SPDIF_IN,
+                                                           CODEC_F1C_CONNECTION_TYPE_OTHER_DIGITAL,
+                                                           CODEC_F1C_COLOR_BLACK,
+                                                           0x0, 0x6, 0x0);//(0x1 << 24) | (0xc5 << 16) | (0x10 << 8) | 0x60;
+            break;
+        case 0x12:
+            pNode->adcmux.u32F01_param = 0;
+            goto adcmux_init;
+        case 0x13:
+            pNode->adcmux.u32F01_param = 1;
+            adcmux_init:
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0x0, 0)
+                                         | CODEC_F00_09_CAP_CONNECTION_LIST
+                                         | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
+                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT
+                                         | CODEC_F00_09_CAP_LSB;//(3<<20)|RT_BIT(8)|RT_BIT(3)|RT_BIT(2)|RT_BIT(0);
+            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x7);
+            pNode->node.au32F00_param[0x12] = (0x27 << 16)|(0x4 << 8);
+            /* STAC 9220 v10 6.21-22.{4,5} both(left and right) out amplefiers inited with 0*/
+            memset(pNode->adcmux.B_params, 0, AMPLIFIER_SIZE);
+            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0xe, 0x15, 0xf, 0xb);
+            pNode->node.au32F02_param[4] = RT_MAKE_U32_FROM_U8(0xc, 0xd, 0xa, 0x0);
+            break;
+        case 0x14:
+            pNode->node.au32F00_param[9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_BEEP_GEN, 0, 0)
+                                         | CODEC_F00_09_CAP_AMP_FMT_OVERRIDE
+                                         | CODEC_F00_09_CAP_OUT_AMP_PRESENT;//(7 << 20) | RT_BIT(3) | RT_BIT(2);
+            pNode->node.au32F00_param[0x12] = (0x17 << 16)|(0x3 << 8)| 0x3;
+            pNode->pcbeep.u32F0a_param = 0;
+            memset(pNode->pcbeep.B_params, 0, AMPLIFIER_SIZE);
+            break;
+        case 0x15:
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
+                                           | CODEC_F00_09_CAP_LSB;//(4 << 20)|RT_BIT(0);
+            pNode->node.au32F00_param[0xc] = CODEC_F00_0C_CAP_INPUT;//RT_BIT(5);
+            if (!pThis->fInReset)
+                pNode->cdnode.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_FIXED,
+                                                            CODEC_F1C_LOCATION_INTERNAL,
+                                                            CODEC_F1C_DEVICE_CD,
+                                                            CODEC_F1C_CONNECTION_TYPE_ATAPI,
+                                                            CODEC_F1C_COLOR_UNKNOWN,
+                                                            0x0, 0x7, 0x0);//RT_MAKE_U32_FROM_U8(0x70, 0x0, 0x33, 0x90);
+            break;
+        case 0x16:
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VOLUME_KNOB, 0x0, 0x0);//(0x6 << 20);
+            pNode->node.au32F00_param[0x13] = RT_BIT(7)| 0x7F;
+            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x4);
+            pNode->node.au32F02_param[0] = RT_MAKE_U32_FROM_U8(0x2, 0x3, 0x4, 0x5);
+            pNode->volumeKnob.u32F08_param = 0;
+            pNode->volumeKnob.u32F0f_param = 0x7f;
+            break;
+        case 0x17:
+            pNode->node.au32F02_param[0] = 0x12;
+            goto adcvol_init;
+        case 0x18:
+            pNode->node.au32F02_param[0] = 0x13;
+        adcvol_init:
+            memset(pNode->adcvol.B_params, 0, AMPLIFIER_SIZE);
+
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_SELECTOR, 0, 0)
+                                           | CODEC_F00_09_CAP_L_R_SWAP
+                                           | CODEC_F00_09_CAP_CONNECTION_LIST
+                                           | CODEC_F00_09_CAP_IN_AMP_PRESENT
+                                           | CODEC_F00_09_CAP_LSB;//(0x3 << 20)|RT_BIT(11)|RT_BIT(8)|RT_BIT(1)|RT_BIT(0);
+            pNode->node.au32F00_param[0xe] = CODEC_MAKE_F00_0E(0, 0x1);
+            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_LEFT, 0) = RT_BIT(7);
+            AMPLIFIER_REGISTER(pNode->adcvol.B_params, AMPLIFIER_IN, AMPLIFIER_RIGHT, 0) = RT_BIT(7);
+            pNode->adcvol.u32F0c_param = 0;
+            break;
+        case 0x19:
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_VENDOR_DEFINED, 0x3, 0)
+                                           | CODEC_F00_09_CAP_DIGITAL
+                                           | CODEC_F00_09_CAP_LSB;//(0xF << 20)|(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
+            break;
+        case 0x1A:
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_AUDIO_OUTPUT, 0x3, 0)
+                                           | CODEC_F00_09_CAP_DIGITAL
+                                           | CODEC_F00_09_CAP_LSB;//(0x3 << 16)|RT_BIT(9)|RT_BIT(0);
+            break;
+        case 0x1B:
+            pNode->node.au32F00_param[0x9] = CODEC_MAKE_F00_09(CODEC_F00_09_TYPE_PIN_COMPLEX, 0, 0)
+                                           | CODEC_F00_09_CAP_DIGITAL
+                                           | CODEC_F00_09_CAP_CONNECTION_LIST
+                                           | CODEC_F00_09_CAP_LSB;//(0x4 << 20)|RT_BIT(9)|RT_BIT(8)|RT_BIT(0);
+            pNode->node.au32F00_param[0xE] = CODEC_MAKE_F00_0E(0, 0x1);
+            pNode->node.au32F00_param[0xC] = CODEC_F00_0C_CAP_OUTPUT;//0x10;
+            pNode->node.au32F02_param[0] = 0x1a;
+            pNode->reserved.u32F1c_param = CODEC_MAKE_F1C(CODEC_F1C_PORT_NO_PHYS,
+                                                          CODEC_F1C_LOCATION_NA,
+                                                          CODEC_F1C_DEVICE_LINE_OUT,
+                                                          CODEC_F1C_CONNECTION_TYPE_UNKNOWN,
+                                                          CODEC_F1C_COLOR_UNKNOWN,
+                                                          0x0, 0x0, 0xf);//0x4000000f;
+            break;
+        default:
+        break;
+    }
+    return VINF_SUCCESS;
+}
+
+
+static int stac9220Construct(PHDACODEC pThis)
+{
+    unconst(pThis->cTotalNodes) = 0x1C;
+    pThis->pfnCodecNodeReset = stac9220ResetNode;
+    pThis->u16VendorId = 0x8384;
+    pThis->u16DeviceId = 0x7680;
+    pThis->u8BSKU = 0x76;
+    pThis->u8AssemblyId = 0x80;
+    pThis->paNodes = (PCODECNODE)RTMemAllocZ(sizeof(CODECNODE) * pThis->cTotalNodes);
+    pThis->fInReset = false;
+#define STAC9220WIDGET(type) pThis->au8##type##s = g_abStac9220##type##s
+    STAC9220WIDGET(Port);
+    STAC9220WIDGET(Dac);
+    STAC9220WIDGET(Adc);
+    STAC9220WIDGET(AdcVol);
+    STAC9220WIDGET(AdcMux);
+    STAC9220WIDGET(Pcbeep);
+    STAC9220WIDGET(SpdifIn);
+    STAC9220WIDGET(SpdifOut);
+    STAC9220WIDGET(DigInPin);
+    STAC9220WIDGET(DigOutPin);
+    STAC9220WIDGET(Cd);
+    STAC9220WIDGET(VolKnob);
+    STAC9220WIDGET(Reserved);
+#undef STAC9220WIDGET
+    unconst(pThis->u8AdcVolsLineIn) = 0x17;
+    unconst(pThis->u8DacLineOut) = 0x2;
+
+    return VINF_SUCCESS;
+}
+
+
+/*
+ * Some generic predicate functions.
+ */
+
+#define DECLISNODEOFTYPE(type)                                                                  \
+    DECLINLINE(int) hdaCodecIs##type##Node(PHDACODEC pThis, uint8_t cNode)                     \
+    {                                                                                           \
+        Assert(pThis->au8##type##s);                                                           \
+        for (int i = 0; pThis->au8##type##s[i] != 0; ++i)                                      \
+            if (pThis->au8##type##s[i] == cNode)                                               \
+                return 1;                                                                       \
+        return 0;                                                                               \
+    }
+/* hdaCodecIsPortNode */
+DECLISNODEOFTYPE(Port)
+/* hdaCodecIsDacNode */
+DECLISNODEOFTYPE(Dac)
+/* hdaCodecIsAdcVolNode */
+DECLISNODEOFTYPE(AdcVol)
+/* hdaCodecIsAdcNode */
+DECLISNODEOFTYPE(Adc)
+/* hdaCodecIsAdcMuxNode */
+DECLISNODEOFTYPE(AdcMux)
+/* hdaCodecIsPcbeepNode */
+DECLISNODEOFTYPE(Pcbeep)
+/* hdaCodecIsSpdifOutNode */
+DECLISNODEOFTYPE(SpdifOut)
+/* hdaCodecIsSpdifInNode */
+DECLISNODEOFTYPE(SpdifIn)
+/* hdaCodecIsDigInPinNode */
+DECLISNODEOFTYPE(DigInPin)
+/* hdaCodecIsDigOutPinNode */
+DECLISNODEOFTYPE(DigOutPin)
+/* hdaCodecIsCdNode */
+DECLISNODEOFTYPE(Cd)
+/* hdaCodecIsVolKnobNode */
+DECLISNODEOFTYPE(VolKnob)
+/* hdaCodecIsReservedNode */
+DECLISNODEOFTYPE(Reserved)
+
+
+/*
+ * Misc helpers.
+ */
+
+static int hdaCodecToAudVolume(AMPLIFIER *pAmp, audmixerctl_t mt)
+{
+    uint32_t dir = AMPLIFIER_OUT;
+    switch (mt)
+    {
+        case AUD_MIXER_VOLUME:
+        case AUD_MIXER_PCM:
+            dir = AMPLIFIER_OUT;
+            break;
+        case AUD_MIXER_LINE_IN:
+            dir = AMPLIFIER_IN;
+            break;
+    }
+    int mute = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & RT_BIT(7);
+    mute |= AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & RT_BIT(7);
+    mute >>=7;
+    mute &= 0x1;
+    uint8_t lVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_LEFT, 0) & 0x7f;
+    uint8_t rVol = AMPLIFIER_REGISTER(*pAmp, dir, AMPLIFIER_RIGHT, 0) & 0x7f;
+    AUD_set_volume(mt, &mute, &lVol, &rVol);
+    return VINF_SUCCESS;
+}
+
+DECLINLINE(void) hdaCodecSetRegister(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset, uint32_t mask)
+{
+    Assert((pu32Reg && u8Offset < 32));
+    *pu32Reg &= ~(mask << u8Offset);
+    *pu32Reg |= (u32Cmd & mask) << u8Offset;
+}
+
+DECLINLINE(void) hdaCodecSetRegisterU8(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
+{
+    hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_8BIT_DATA);
+}
+
+DECLINLINE(void) hdaCodecSetRegisterU16(uint32_t *pu32Reg, uint32_t u32Cmd, uint8_t u8Offset)
+{
+    hdaCodecSetRegister(pu32Reg, u32Cmd, u8Offset, CODEC_VERB_16BIT_DATA);
+}
+
+
+/*
+ * Verb processor functions.
+ */
+
+static DECLCALLBACK(int) vrbProcUnimplemented(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Log(("vrbProcUnimplemented: cmd(raw:%x: cad:%x, d:%c, nid:%x, verb:%x)\n", cmd,
+        CODEC_CAD(cmd), CODEC_DIRECT(cmd) ? 'N' : 'Y', CODEC_NID(cmd), CODEC_VERBDATA(cmd)));
+    *pResp = 0;
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcBreak(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    int rc;
+    rc = vrbProcUnimplemented(pThis, cmd, pResp);
+    *pResp |= CODEC_RESPONSE_UNSOLICITED;
+    return rc;
+}
+
+/* B-- */
+static DECLCALLBACK(int) vrbProcGetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    /* HDA spec 7.3.3.7 Note A */
+    /** @todo: if index out of range response should be 0 */
+    uint8_t u8Index = CODEC_GET_AMP_DIRECTION(cmd) == AMPLIFIER_OUT? 0 : CODEC_GET_AMP_INDEX(cmd);
+
+    PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->dac.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->adcvol.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->adcmux.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->pcbeep.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->port.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = AMPLIFIER_REGISTER(pNode->adc.B_params,
+                            CODEC_GET_AMP_DIRECTION(cmd),
+                            CODEC_GET_AMP_SIDE(cmd),
+                            u8Index);
+    else
+        AssertMsgFailedReturn(("access to fields of %x need to be implemented\n", CODEC_NID(cmd)), VINF_SUCCESS);
+    return VINF_SUCCESS;
+}
+
+/* 3-- */
+static DECLCALLBACK(int) vrbProcSetAmplifier(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    bool fIsLeft = false;
+    bool fIsRight = false;
+    bool fIsOut = false;
+    bool fIsIn = false;
+    uint8_t u8Index = 0;
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    PCODECNODE pNode = &pThis->paNodes[CODEC_NID(cmd)];
+    AMPLIFIER *pAmplifier;
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->dac.B_params;
+    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->adcvol.B_params;
+    else if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->adcmux.B_params;
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->pcbeep.B_params;
+    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->port.B_params;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        pAmplifier = &pNode->adc.B_params;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+
+    fIsOut = CODEC_SET_AMP_IS_OUT_DIRECTION(cmd);
+    fIsIn = CODEC_SET_AMP_IS_IN_DIRECTION(cmd);
+    fIsRight = CODEC_SET_AMP_IS_RIGHT_SIDE(cmd);
+    fIsLeft = CODEC_SET_AMP_IS_LEFT_SIDE(cmd);
+    u8Index = CODEC_SET_AMP_INDEX(cmd);
+    if (   (!fIsLeft && !fIsRight)
+        || (!fIsOut && !fIsIn))
+        return VINF_SUCCESS;
+    if (fIsIn)
+    {
+        if (fIsLeft)
+            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_LEFT, u8Index), cmd, 0);
+        if (fIsRight)
+            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_IN, AMPLIFIER_RIGHT, u8Index), cmd, 0);
+    }
+    if (fIsOut)
+    {
+        if (fIsLeft)
+            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_LEFT, u8Index), cmd, 0);
+        if (fIsRight)
+            hdaCodecSetRegisterU8(&AMPLIFIER_REGISTER(*pAmplifier, AMPLIFIER_OUT, AMPLIFIER_RIGHT, u8Index), cmd, 0);
+    }
+    if (CODEC_NID(cmd) == pThis->u8DacLineOut)
+        hdaCodecToAudVolume(pAmplifier, AUD_MIXER_VOLUME);
+    if (CODEC_NID(cmd) == pThis->u8AdcVolsLineIn) /* Microphone */
+        hdaCodecToAudVolume(pAmplifier, AUD_MIXER_LINE_IN);
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcGetParameter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F00_PARAM_LENGTH);
+    if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F00_PARAM_LENGTH)
+    {
+        Log(("HdaCodec: invalid F00 parameter %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
+        return VINF_SUCCESS;
+    }
+    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F00_param[cmd & CODEC_VERB_8BIT_DATA];
+    return VINF_SUCCESS;
+}
+
+/* F01 */
+static DECLCALLBACK(int) vrbProcGetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
+    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
+    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
+    return VINF_SUCCESS;
+}
+
+/* 701 */
+static DECLCALLBACK(int) vrbProcSetConSelectCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (hdaCodecIsAdcMuxNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcmux.u32F01_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F01_param;
+    else if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F01_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F01_param;
+    else if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F01_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F07 */
+static DECLCALLBACK(int) vrbProcGetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
+    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
+    else
+        AssertMsgFailed(("Unsupported"));
+    return VINF_SUCCESS;
+}
+
+/* 707 */
+static DECLCALLBACK(int) vrbProcSetPinCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F07_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F07_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F07_param;
+    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F07_param;
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F07_param;
+    else if (   hdaCodecIsReservedNode(pThis, CODEC_NID(cmd))
+             && CODEC_NID(cmd) == 0x1b)
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F07_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F08 */
+static DECLCALLBACK(int) vrbProcGetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+    else if ((cmd) == 1 /* AFG */)
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
+    else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+    else
+        AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
+    return VINF_SUCCESS;
+}
+
+/* 708 */
+static DECLCALLBACK(int) vrbProcSetUnsolicitedEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F08_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+    else if (CODEC_NID(cmd) == 1 /* AFG */)
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F08_param;
+    else if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F08_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F08_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F08_param;
+    else
+        AssertMsgFailedReturn(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)), VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F09 */
+static DECLCALLBACK(int) vrbProcGetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
+    else
+        AssertMsgFailed(("unsupported operation %x on node: %x\n", CODEC_VERB_CMD8(cmd), CODEC_NID(cmd)));
+    return VINF_SUCCESS;
+}
+
+/* 709 */
+static DECLCALLBACK(int) vrbProcSetPinSense(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F09_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F09_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcGetConnectionListEntry(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    *pResp = 0;
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    Assert((cmd & CODEC_VERB_8BIT_DATA) < CODECNODE_F02_PARAM_LENGTH);
+    if ((cmd & CODEC_VERB_8BIT_DATA) >= CODECNODE_F02_PARAM_LENGTH)
+    {
+        Log(("HdaCodec: access to invalid F02 index %d\n", (cmd & CODEC_VERB_8BIT_DATA)));
+        return VINF_SUCCESS;
+    }
+    *pResp = pThis->paNodes[CODEC_NID(cmd)].node.au32F02_param[cmd & CODEC_VERB_8BIT_DATA];
+    return VINF_SUCCESS;
+}
+
+/* F03 */
+static DECLCALLBACK(int) vrbProcGetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param;
+    return VINF_SUCCESS;
+}
+
+/* 703 */
+static DECLCALLBACK(int) vrbProcSetProcessingState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].adc.u32F03_param, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F0D */
+static DECLCALLBACK(int) vrbProcGetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param;
+    return VINF_SUCCESS;
+}
+
+static int codecSetDigitalConverter(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F0d_param, cmd, u8Offset);
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU8(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F0d_param, cmd, u8Offset);
+    return VINF_SUCCESS;
+}
+
+/* 70D */
+static DECLCALLBACK(int) vrbProcSetDigitalConverter1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    return codecSetDigitalConverter(pThis, cmd, 0, pResp);
+}
+
+/* 70E */
+static DECLCALLBACK(int) vrbProcSetDigitalConverter2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    return codecSetDigitalConverter(pThis, cmd, 8, pResp);
+}
+
+/* F20 */
+static DECLCALLBACK(int) vrbProcGetSubId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    if (CODEC_NID(cmd) == 1 /* AFG */)
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
+    else
+        *pResp = 0;
+    return VINF_SUCCESS;
+}
+
+static int codecSetSubIdX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    uint32_t *pu32Reg;
+    if (CODEC_NID(cmd) == 0x1 /* AFG */)
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F20_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
+    return VINF_SUCCESS;
+}
+
+/* 720 */
+static DECLCALLBACK(int) vrbProcSetSubId0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetSubIdX(pThis, cmd, 0);
+}
+
+/* 721 */
+static DECLCALLBACK(int) vrbProcSetSubId1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetSubIdX(pThis, cmd, 8);
+}
+
+/* 722 */
+static DECLCALLBACK(int) vrbProcSetSubId2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetSubIdX(pThis, cmd, 16);
+}
+
+/* 723 */
+static DECLCALLBACK(int) vrbProcSetSubId3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetSubIdX(pThis, cmd, 24);
+}
+
+static DECLCALLBACK(int) vrbProcReset(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) == 1 /* AFG */);
+    if (   CODEC_NID(cmd) == 1 /* AFG */
+        && pThis->pfnCodecNodeReset)
+    {
+        uint8_t i;
+        Log(("HdaCodec: enters reset\n"));
+        Assert(pThis->pfnCodecNodeReset);
+        for (i = 0; i < pThis->cTotalNodes; ++i)
+        {
+            pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
+        }
+        pThis->fInReset = false;
+        Log(("HdaCodec: exits reset\n"));
+    }
+    *pResp = 0;
+    return VINF_SUCCESS;
+}
+
+/* F05 */
+static DECLCALLBACK(int) vrbProcGetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (CODEC_NID(cmd) == 1 /* AFG */)
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
+    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
+    return VINF_SUCCESS;
+}
+
+/* 705 */
+
+DECLINLINE(void) codecPropogatePowerState(uint32_t *pu32F05_param)
+{
+    Assert(pu32F05_param);
+    if (!pu32F05_param)
+        return;
+    bool fReset = CODEC_F05_IS_RESET(*pu32F05_param);
+    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32F05_param);
+    uint8_t u8SetPowerState = CODEC_F05_SET(*pu32F05_param);
+    *pu32F05_param = CODEC_MAKE_F05(fReset, fStopOk, 0, u8SetPowerState, u8SetPowerState);
+}
+
+static DECLCALLBACK(int) vrbProcSetPowerState(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (CODEC_NID(cmd) == 1 /* AFG */)
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].afg.u32F05_param;
+    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F05_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F05_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F05_param;
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F05_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F05_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F05_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+
+    bool fReset = CODEC_F05_IS_RESET(*pu32Reg);
+    bool fStopOk = CODEC_F05_IS_STOPOK(*pu32Reg);
+
+    if (CODEC_NID(cmd) != 1 /* AFG */)
+    {
+        /*
+         * We shouldn't propogate actual power state, which actual for AFG
+         */
+        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0,
+                                  CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param),
+                                  CODEC_F05_SET(cmd));
+    }
+
+    /* Propagate next power state only if AFG is on or verb modifies AFG power state */
+    if (   CODEC_NID(cmd) == 1 /* AFG */
+        || !CODEC_F05_ACT(pThis->paNodes[1].afg.u32F05_param))
+    {
+        *pu32Reg = CODEC_MAKE_F05(fReset, fStopOk, 0, CODEC_F05_SET(cmd), CODEC_F05_SET(cmd));
+        if (   CODEC_NID(cmd) == 1 /* AFG */
+            && (CODEC_F05_SET(cmd)) == CODEC_F05_D0)
+        {
+            /* now we're powered on AFG and may propogate power states on nodes */
+            const uint8_t *pu8NodeIndex = &pThis->au8Dacs[0];
+            while (*(++pu8NodeIndex))
+                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].dac.u32F05_param);
+
+            pu8NodeIndex = &pThis->au8Adcs[0];
+            while (*(++pu8NodeIndex))
+                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].adc.u32F05_param);
+
+            pu8NodeIndex = &pThis->au8DigInPins[0];
+            while (*(++pu8NodeIndex))
+                codecPropogatePowerState(&pThis->paNodes[*pu8NodeIndex].digin.u32F05_param);
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcGetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
+    else if (CODEC_NID(cmd) == 0x1A)
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcSetStreamId(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    uint32_t *pu32addr;
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F06_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].adc.u32F06_param;
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifout.u32F06_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].spdifin.u32F06_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        pu32addr = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F06_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32addr, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcGetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param;
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param;
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param;
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param;
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) vrbProcSetConverterFormat(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].dac.u32A_param, cmd, 0);
+    else if (hdaCodecIsAdcNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].adc.u32A_param, cmd, 0);
+    else if (hdaCodecIsSpdifOutNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifout.u32A_param, cmd, 0);
+    else if (hdaCodecIsSpdifInNode(pThis, CODEC_NID(cmd)))
+        hdaCodecSetRegisterU16(&pThis->paNodes[CODEC_NID(cmd)].spdifin.u32A_param, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F0C */
+static DECLCALLBACK(int) vrbProcGetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
+    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
+    return VINF_SUCCESS;
+}
+
+/* 70C */
+static DECLCALLBACK(int) vrbProcSetEAPD_BTLEnabled(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+
+    *pResp = 0;
+    uint32_t *pu32Reg;
+    if (hdaCodecIsAdcVolNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].adcvol.u32F0c_param;
+    else if (hdaCodecIsDacNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].dac.u32F0c_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F0c_param;
+    else
+        AssertFailedReturn(VINF_SUCCESS);
+    hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+
+    return VINF_SUCCESS;
+}
+
+/* F0F */
+static DECLCALLBACK(int) vrbProcGetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
+    return VINF_SUCCESS;
+}
+
+/* 70F */
+static DECLCALLBACK(int) vrbProcSetVolumeKnobCtrl(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    uint32_t *pu32Reg = NULL;
+    *pResp = 0;
+    if (hdaCodecIsVolKnobNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].volumeKnob.u32F0f_param;
+    Assert(pu32Reg);
+    if (pu32Reg)
+        hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F17 */
+static DECLCALLBACK(int) vrbProcGetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    /* note: this is true for ALC885 */
+    if (CODEC_NID(cmd) == 0x1 /* AFG */)
+        *pResp = pThis->paNodes[1].afg.u32F17_param;
+    return VINF_SUCCESS;
+}
+
+/* 717 */
+static DECLCALLBACK(int) vrbProcSetGPIOUnsolisted(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    uint32_t *pu32Reg = NULL;
+    *pResp = 0;
+    if (CODEC_NID(cmd) == 1 /* AFG */)
+        pu32Reg = &pThis->paNodes[1].afg.u32F17_param;
+    Assert(pu32Reg);
+    if (pu32Reg)
+        hdaCodecSetRegisterU8(pu32Reg, cmd, 0);
+    return VINF_SUCCESS;
+}
+
+/* F1C */
+static DECLCALLBACK(int) vrbProcGetConfig(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    *pResp = 0;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
+    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        *pResp = pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
+    return VINF_SUCCESS;
+}
+
+static int codecSetConfigX(PHDACODEC pThis, uint32_t cmd, uint8_t u8Offset)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
+    if (CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        Log(("HdaCodec: invalid node address %d\n", CODEC_NID(cmd)));
+        return VINF_SUCCESS;
+    }
+    uint32_t *pu32Reg = NULL;
+    if (hdaCodecIsPortNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].port.u32F1c_param;
+    else if (hdaCodecIsDigInPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digin.u32F1c_param;
+    else if (hdaCodecIsDigOutPinNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].digout.u32F1c_param;
+    else if (hdaCodecIsCdNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].cdnode.u32F1c_param;
+    else if (hdaCodecIsPcbeepNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].pcbeep.u32F1c_param;
+    else if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        pu32Reg = &pThis->paNodes[CODEC_NID(cmd)].reserved.u32F1c_param;
+    Assert(pu32Reg);
+    if (pu32Reg)
+        hdaCodecSetRegisterU8(pu32Reg, cmd, u8Offset);
+    return VINF_SUCCESS;
+}
+
+/* 71C */
+static DECLCALLBACK(int) vrbProcSetConfig0(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetConfigX(pThis, cmd, 0);
+}
+
+/* 71D */
+static DECLCALLBACK(int) vrbProcSetConfig1(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetConfigX(pThis, cmd, 8);
+}
+
+/* 71E */
+static DECLCALLBACK(int) vrbProcSetConfig2(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetConfigX(pThis, cmd, 16);
+}
+
+/* 71E */
+static DECLCALLBACK(int) vrbProcSetConfig3(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp)
+{
+    *pResp = 0;
+    return codecSetConfigX(pThis, cmd, 24);
+}
+
+
+/**
+ * HDA codec verb map.
+ * @todo Any reason not to use binary search here?
+ */
+static const CODECVERB g_aCodecVerbs[] =
+{
+/*     verb     | verb mask              | callback               */
+/*   -----------  --------------------   -----------------------  */
+    { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter           },
+    { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl       },
+    { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl       },
+    { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId            },
+    { 0x00070600, CODEC_VERB_8BIT_CMD , vrbProcSetStreamId            },
+    { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl             },
+    { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl             },
+    { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled  },
+    { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled  },
+    { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense            },
+    { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense            },
+    { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry },
+    { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState     },
+    { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState     },
+    { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter    },
+    { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1   },
+    { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2   },
+    { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId               },
+    { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0              },
+    { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1              },
+    { 0x00072200, CODEC_VERB_8BIT_CMD , vrbProcSetSubId2              },
+    { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3              },
+    { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset                  },
+    { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState          },
+    { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState          },
+    { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled     },
+    { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled     },
+    { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl      },
+    { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl      },
+    { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOUnsolisted      },
+    { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOUnsolisted      },
+    { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig              },
+    { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0             },
+    { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1             },
+    { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2             },
+    { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3             },
+    { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat     },
+    { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat     },
+    { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier           },
+    { 0x00030000, CODEC_VERB_16BIT_CMD, vrbProcSetAmplifier           },
+};
+
+static int codecLookup(PHDACODEC pThis, uint32_t cmd, PPFNHDACODECVERBPROCESSOR pfn)
+{
+    Assert(CODEC_CAD(cmd) == pThis->id);
+    if (hdaCodecIsReservedNode(pThis, CODEC_NID(cmd)))
+        Log(("HdaCodec: cmd %x was addressed to reserved node\n", cmd));
+
+    if (   CODEC_VERBDATA(cmd) == 0
+        || CODEC_NID(cmd) >= pThis->cTotalNodes)
+    {
+        *pfn = vrbProcUnimplemented;
+        /// @todo r=michaln: There needs to be a counter to avoid log flooding (see e.g. DevRTC.cpp)
+        Log(("HdaCodec: cmd %x was ignored\n", cmd));
+        return VINF_SUCCESS;
+    }
+
+    for (int i = 0; i < pThis->cVerbs; ++i)
+    {
+        if ((CODEC_VERBDATA(cmd) & pThis->paVerbs[i].mask) == pThis->paVerbs[i].verb)
+        {
+            *pfn = pThis->paVerbs[i].pfn;
+            return VINF_SUCCESS;
+        }
+    }
+
+    *pfn = vrbProcUnimplemented;
+    Log(("HdaCodec: callback for %x wasn't found\n", CODEC_VERBDATA(cmd)));
+    return VINF_SUCCESS;
+}
+
+static void pi_callback(void *opaque, int avail)
+{
+    PHDACODEC pThis = (PHDACODEC)opaque;
+    pThis->pfnTransfer(pThis, PI_INDEX, avail);
+}
+
+static void po_callback(void *opaque, int avail)
+{
+    PHDACODEC pThis = (PHDACODEC)opaque;
+    pThis->pfnTransfer(pThis, PO_INDEX, avail);
+}
+
+
+
+/*
+ * APIs exposed to DevHDA.
+ */
+
+
+/**
+ *
+ * routines open one of the voices (IN, OUT) with corresponding parameters.
+ * this routine could be called from HDA on setting/resseting sound format.
+ *
+ * @todo Probably passed settings should be verified (if AFG's declared proposed
+ *       format) before enabling.
+ */
+int hdaCodecOpenVoice(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings)
+{
+    int rc;
+    Assert(pThis && pAudioSettings);
+    if (   !pThis
+        || !pAudioSettings)
+        return -1;
+    switch (enmSoundSource)
+    {
+        case PI_INDEX:
+            pThis->SwVoiceIn = AUD_open_in(&pThis->card, pThis->SwVoiceIn, "hda.in", pThis, pi_callback, pAudioSettings);
+            rc = pThis->SwVoiceIn ? 0 : 1;
+            break;
+        case PO_INDEX:
+            pThis->SwVoiceOut = AUD_open_out(&pThis->card, pThis->SwVoiceOut, "hda.out", pThis, po_callback, pAudioSettings);
+            rc = pThis->SwVoiceOut ? 0 : 1;
+            break;
+        default:
+            return -1;
+    }
+    if (!rc)
+        LogRel(("HdaCodec: can't open %s fmt(freq: %d)\n", enmSoundSource == PI_INDEX? "in" : "out", pAudioSettings->freq));
+    return rc;
+}
+
+
+int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM)
+{
+    AssertLogRelMsgReturn(pThis->cTotalNodes == 0x1c, ("cTotalNodes=%#x, should be 0x1c", pThis->cTotalNodes),
+                          VERR_INTERNAL_ERROR);
+    SSMR3PutU32(pSSM, pThis->cTotalNodes);
+    for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
+        SSMR3PutStructEx(pSSM, &pThis->paNodes[idxNode].SavedState, sizeof(pThis->paNodes[idxNode].SavedState),
+                         0 /*fFlags*/, g_aCodecNodeFields, NULL /*pvUser*/);
+    return VINF_SUCCESS;
+}
+
+
+int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion)
+{
+    PCSSMFIELD pFields;
+    uint32_t   fFlags;
+    switch (uVersion)
+    {
+        case HDA_SSM_VERSION_1:
+            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
+            pFields = g_aCodecNodeFieldsV1;
+            fFlags  = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
+            break;
+
+        case HDA_SSM_VERSION_2:
+        case HDA_SSM_VERSION_3:
+            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
+            pFields = g_aCodecNodeFields;
+            fFlags  = SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED;
+            break;
+
+        case HDA_SSM_VERSION:
+        {
+            uint32_t cNodes;
+            int rc2 = SSMR3GetU32(pSSM, &cNodes);
+            AssertRCReturn(rc2, rc2);
+            if (cNodes != 0x1c)
+                return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
+            AssertReturn(pThis->cTotalNodes == 0x1c, VERR_INTERNAL_ERROR);
+
+            pFields = g_aCodecNodeFields;
+            fFlags  = 0;
+            break;
+        }
+
+        default:
+            return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+    }
+
+    for (unsigned idxNode = 0; idxNode < pThis->cTotalNodes; ++idxNode)
+    {
+        uint8_t idOld = pThis->paNodes[idxNode].SavedState.Core.id;
+        int rc = SSMR3GetStructEx(pSSM, &pThis->paNodes[idxNode].SavedState,
+                                  sizeof(pThis->paNodes[idxNode].SavedState),
+                                  fFlags, pFields, NULL);
+        if (RT_FAILURE(rc))
+            return rc;
+        AssertLogRelMsgReturn(idOld == pThis->paNodes[idxNode].SavedState.Core.id,
+                              ("loaded %#x, expected \n", pThis->paNodes[idxNode].SavedState.Core.id, idOld),
+                              VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
+    }
+
+    /*
+     * Update stuff after changing the state.
+     */
+    if (hdaCodecIsDacNode(pThis, pThis->u8DacLineOut))
+        hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
+    else if (hdaCodecIsSpdifOutNode(pThis, pThis->u8DacLineOut))
+        hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].spdifout.B_params, AUD_MIXER_VOLUME);
+    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
+
+    return VINF_SUCCESS;
+}
+
+
+int hdaCodecDestruct(PHDACODEC pThis)
+{
+    RTMemFree(pThis->paNodes);
+    pThis->paNodes = NULL;
+    return VINF_SUCCESS;
+}
+
+
+int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PCFGMNODE pCfg)
+{
+    pThis->paVerbs   = &g_aCodecVerbs[0];
+    pThis->cVerbs    = RT_ELEMENTS(g_aCodecVerbs);
+    pThis->pfnLookup = codecLookup;
+    int rc = stac9220Construct(pThis);
+    AssertRC(rc);
+
+    /* common root node initializers */
+    pThis->paNodes[0].node.au32F00_param[0] = CODEC_MAKE_F00_00(pThis->u16VendorId, pThis->u16DeviceId);
+    pThis->paNodes[0].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x1, 0x1);
+    /* common AFG node initializers */
+    pThis->paNodes[1].node.au32F00_param[4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
+    pThis->paNodes[1].node.au32F00_param[5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
+    pThis->paNodes[1].afg.u32F20_param = CODEC_MAKE_F20(pThis->u16VendorId, pThis->u8BSKU, pThis->u8AssemblyId);
+
+    /// @todo r=michaln: Was this meant to be 'HDA' or something like that? (AC'97 was on ICH0)
+    AUD_register_card ("ICH0", &pThis->card);
+
+    /* 44.1 kHz */
+    audsettings_t as;
+    as.freq = 44100;
+    as.nchannels = 2;
+    as.fmt = AUD_FMT_S16;
+    as.endianness = 0;
+
+    pThis->paNodes[1].node.au32F00_param[0xA] = CODEC_F00_0A_16_BIT;
+    hdaCodecOpenVoice(pThis, PI_INDEX, &as);
+    hdaCodecOpenVoice(pThis, PO_INDEX, &as);
+    pThis->paNodes[1].node.au32F00_param[0xA] |= CODEC_F00_0A_44_1KHZ;
+
+    uint8_t i;
+    Assert(pThis->paNodes);
+    Assert(pThis->pfnCodecNodeReset);
+    for (i = 0; i < pThis->cTotalNodes; ++i)
+    {
+        pThis->pfnCodecNodeReset(pThis, i, &pThis->paNodes[i]);
+    }
+
+    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8DacLineOut].dac.B_params, AUD_MIXER_VOLUME);
+    hdaCodecToAudVolume(&pThis->paNodes[pThis->u8AdcVolsLineIn].adcvol.B_params, AUD_MIXER_LINE_IN);
+
+    /* If no host voices were created, then fallback to nul audio. */
+    if (!AUD_is_host_voice_in_ok(pThis->SwVoiceIn))
+        LogRel (("HDA: WARNING: Unable to open PCM IN!\n"));
+    if (!AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
+        LogRel (("HDA: WARNING: Unable to open PCM OUT!\n"));
+
+    if (   !AUD_is_host_voice_in_ok(pThis->SwVoiceIn)
+        && !AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
+    {
+        /* Was not able initialize *any* voice. Select the NULL audio driver instead */
+        AUD_close_in  (&pThis->card, pThis->SwVoiceIn);
+        AUD_close_out (&pThis->card, pThis->SwVoiceOut);
+        pThis->SwVoiceOut = NULL;
+        pThis->SwVoiceIn = NULL;
+        AUD_init_null ();
+
+        PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
+            N_ ("No audio devices could be opened. Selecting the NULL audio backend "
+                "with the consequence that no sound is audible"));
+    }
+    else if (   !AUD_is_host_voice_in_ok(pThis->SwVoiceIn)
+             || !AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
+    {
+        char   szMissingVoices[128];
+        size_t len = 0;
+        if (!AUD_is_host_voice_in_ok(pThis->SwVoiceIn))
+            len = RTStrPrintf (szMissingVoices, sizeof(szMissingVoices), "PCM_in");
+        if (!AUD_is_host_voice_out_ok(pThis->SwVoiceOut))
+            len += RTStrPrintf (szMissingVoices + len, sizeof(szMissingVoices) - len, len ? ", PCM_out" : "PCM_out");
+
+        PDMDevHlpVMSetRuntimeError (pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
+            N_ ("Some audio devices (%s) could not be opened. Guest applications generating audio "
+                "output or depending on audio input may hang. Make sure your host audio device "
+                "is working properly. Check the logfile for error messages of the audio "
+                "subsystem"), szMissingVoices);
+    }
+
+    return VINF_SUCCESS;
+}
+
Index: trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h
===================================================================
--- trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h	(revision 44669)
+++ trunk/src/VBox/Devices/Audio/DevIchHdaCodec.h	(revision 44669)
@@ -0,0 +1,137 @@
+/* $Id$ */
+/** @file
+ * DevIchHdaCodec - VBox ICH Intel HD Audio Codec.
+ */
+
+/*
+ * Copyright (C) 2006-2013 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 DEV_CODEC_H
+#define DEV_CODEC_H
+
+/** The ICH HDA (Intel) codec state. */
+typedef struct HDACODEC HDACODEC;
+/** Pointer to the Intel ICH HDA codec state. */
+typedef HDACODEC *PHDACODEC;
+
+/**
+ * Verb processor method.
+ */
+typedef DECLCALLBACK(int) FNHDACODECVERBPROCESSOR(PHDACODEC pThis, uint32_t cmd, uint64_t *pResp);
+typedef FNHDACODECVERBPROCESSOR *PFNHDACODECVERBPROCESSOR;
+typedef FNHDACODECVERBPROCESSOR **PPFNHDACODECVERBPROCESSOR;
+
+/* PRM 5.3.1 */
+#define CODEC_RESPONSE_UNSOLICITED RT_BIT_64(34)
+
+
+#ifndef VBOX_WITH_HDA_CODEC_EMU
+typedef struct CODECVERB
+{
+    uint32_t verb;
+    /* operation bitness mask */
+    uint32_t mask;
+    PFNHDACODECVERBPROCESSOR pfn;
+} CODECVERB;
+#endif
+
+#ifndef VBOX_WITH_HDA_CODEC_EMU
+# define TYPE union
+#else
+# define TYPE struct
+typedef struct CODECEMU CODECEMU;
+typedef CODECEMU *PCODECEMU;
+#endif
+TYPE CODECNODE;
+typedef TYPE CODECNODE CODECNODE;
+typedef TYPE CODECNODE *PCODECNODE;
+
+typedef enum
+{
+    PI_INDEX = 0,    /* PCM in */
+    PO_INDEX,        /* PCM out */
+    MC_INDEX,        /* Mic in */
+    LAST_INDEX
+} ENMSOUNDSOURCE;
+
+
+typedef struct HDACODEC
+{
+    uint16_t                id;
+    uint16_t                u16VendorId;
+    uint16_t                u16DeviceId;
+    uint8_t                 u8BSKU;
+    uint8_t                 u8AssemblyId;
+#ifndef VBOX_WITH_HDA_CODEC_EMU
+    CODECVERB const        *paVerbs;
+    int                     cVerbs;
+#else
+    PCODECEMU               pCodecBackend;
+#endif
+    PCODECNODE              paNodes;
+    QEMUSoundCard           card;
+    /** PCM in */
+    SWVoiceIn               *SwVoiceIn;
+    /** PCM out */
+    SWVoiceOut              *SwVoiceOut;
+    void                   *pvHDAState;
+    bool                    fInReset;
+#ifndef VBOX_WITH_HDA_CODEC_EMU
+    const uint8_t           cTotalNodes;
+    const uint8_t           *au8Ports;
+    const uint8_t           *au8Dacs;
+    const uint8_t           *au8AdcVols;
+    const uint8_t           *au8Adcs;
+    const uint8_t           *au8AdcMuxs;
+    const uint8_t           *au8Pcbeeps;
+    const uint8_t           *au8SpdifIns;
+    const uint8_t           *au8SpdifOuts;
+    const uint8_t           *au8DigInPins;
+    const uint8_t           *au8DigOutPins;
+    const uint8_t           *au8Cds;
+    const uint8_t           *au8VolKnobs;
+    const uint8_t           *au8Reserveds;
+    const uint8_t           u8AdcVolsLineIn;
+    const uint8_t           u8DacLineOut;
+#endif
+    DECLR3CALLBACKMEMBER(int, pfnProcess, (PHDACODEC pCodec));
+    DECLR3CALLBACKMEMBER(void, pfnTransfer, (PHDACODEC pCodec, ENMSOUNDSOURCE, int avail));
+    /* These callbacks are set by Codec implementation. */
+    DECLR3CALLBACKMEMBER(int, pfnLookup, (PHDACODEC pThis, uint32_t verb, PPFNHDACODECVERBPROCESSOR));
+    DECLR3CALLBACKMEMBER(int, pfnReset, (PHDACODEC pThis));
+    DECLR3CALLBACKMEMBER(int, pfnCodecNodeReset, (PHDACODEC pThis, uint8_t, PCODECNODE));
+    /* These callbacks are set by codec implementation to answer debugger requests. */
+    DECLR3CALLBACKMEMBER(void, pfnCodecDbgListNodes, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
+    DECLR3CALLBACKMEMBER(void, pfnCodecDbgSelector, (PHDACODEC pThis, PCDBGFINFOHLP pHlp, const char *pszArgs));
+} CODECState;
+
+int hdaCodecConstruct(PPDMDEVINS pDevIns, PHDACODEC pThis, PCFGMNODE pCfg);
+int hdaCodecDestruct(PHDACODEC pThis);
+int hdaCodecSaveState(PHDACODEC pThis, PSSMHANDLE pSSM);
+int hdaCodecLoadState(PHDACODEC pThis, PSSMHANDLE pSSM, uint32_t uVersion);
+int hdaCodecOpenVoice(PHDACODEC pThis, ENMSOUNDSOURCE enmSoundSource, audsettings_t *pAudioSettings);
+
+#define HDA_SSM_VERSION   4
+#define HDA_SSM_VERSION_1 1
+#define HDA_SSM_VERSION_2 2
+#define HDA_SSM_VERSION_3 3
+
+# ifdef VBOX_WITH_HDA_CODEC_EMU
+/* */
+struct CODECEMU
+{
+    DECLR3CALLBACKMEMBER(int, pfnCodecEmuConstruct,(PHDACODEC pThis));
+    DECLR3CALLBACKMEMBER(int, pfnCodecEmuDestruct,(PHDACODEC pThis));
+    DECLR3CALLBACKMEMBER(int, pfnCodecEmuReset,(PHDACODEC pThis, bool fInit));
+};
+# endif
+#endif
Index: trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp	(revision 44668)
+++ 	(revision )
@@ -1,3086 +1,0 @@
-/* $Id$ */
-/** @file
- * DevIchIntelHDA - VBox ICH Intel HD Audio Controller.
- *
- * Implemented against the specifications found in "High Definition Audio
- * Specification", Revision 1.0a June 17, 2010, and  "Intel I/O Controller
- * HUB 6 (ICH6) Family, Datasheet", document number 301473-002.
- */
-
-/*
- * Copyright (C) 2006-2013 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_AUDIO
-#include <VBox/vmm/pdmdev.h>
-#include <VBox/version.h>
-
-#include <iprt/assert.h>
-#include <iprt/uuid.h>
-#include <iprt/string.h>
-#include <iprt/mem.h>
-#include <iprt/asm.h>
-#include <iprt/asm-math.h>
-
-#include "VBoxDD.h"
-
-extern "C" {
-#include "audio.h"
-}
-#include "DevCodec.h"
-
-
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
-//#define HDA_AS_PCI_EXPRESS
-#define VBOX_WITH_INTEL_HDA
-
-#if defined(VBOX_WITH_HP_HDA)
-/* HP Pavilion dv4t-1300 */
-# define HDA_PCI_VENDOR_ID 0x103c
-# define HDA_PCI_DEICE_ID 0x30f7
-#elif defined(VBOX_WITH_INTEL_HDA)
-/* Intel HDA controller */
-# define HDA_PCI_VENDOR_ID 0x8086
-# define HDA_PCI_DEICE_ID 0x2668
-#elif defined(VBOX_WITH_NVIDIA_HDA)
-/* nVidia HDA controller */
-# define HDA_PCI_VENDOR_ID 0x10de
-# define HDA_PCI_DEICE_ID 0x0ac0
-#else
-# error "Please specify your HDA device vendor/device IDs"
-#endif
-
-/** @todo r=bird: Looking at what the linux driver (accidentally?) does when
- * updating CORBWP, I belive that the ICH6 datahsheet is wrong and that CORBRP
- * is read only except for bit 15 like the HDA spec states.
- *
- * Btw. the CORBRPRST implementation is incomplete according to both docs (sw
- * writes 1, hw sets it to 1 (after completion), sw reads 1, sw writes 0). */
-#define BIRD_THINKS_CORBRP_IS_MOSTLY_RO
-
-#define HDA_NREGS 112
-/* Registers */
-#define HDA_REG_IND_NAME(x)                 ICH6_HDA_REG_##x
-#define HDA_REG_FIELD_NAME(reg, x)          ICH6_HDA_##reg##_##x
-#define HDA_REG_FIELD_MASK(reg, x)          ICH6_HDA_##reg##_##x##_MASK
-#define HDA_REG_FIELD_FLAG_MASK(reg, x)     RT_BIT(ICH6_HDA_##reg##_##x##_SHIFT)
-#define HDA_REG_FIELD_SHIFT(reg, x)         ICH6_HDA_##reg##_##x##_SHIFT
-#define HDA_REG_IND(pThis, x)               ((pThis)->au32Regs[(x)])
-#define HDA_REG(pThis, x)                   (HDA_REG_IND((pThis), HDA_REG_IND_NAME(x)))
-#define HDA_REG_VALUE(pThis, reg, val)      (HDA_REG((pThis),reg) & (((HDA_REG_FIELD_MASK(reg, val))) << (HDA_REG_FIELD_SHIFT(reg, val))))
-#define HDA_REG_FLAG_VALUE(pThis, reg, val) (HDA_REG((pThis),reg) & (((HDA_REG_FIELD_FLAG_MASK(reg, val)))))
-#define HDA_REG_SVALUE(pThis, reg, val)     (HDA_REG_VALUE(pThis, reg, val) >> (HDA_REG_FIELD_SHIFT(reg, val)))
-
-#define ICH6_HDA_REG_GCAP 0 /* range 0x00-0x01*/
-#define GCAP(pThis) (HDA_REG((pThis), GCAP))
-/* 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 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 ICH6_HDA_REG_VMIN           1 /* range 0x02 */
-#define VMIN(pThis)                 (HDA_REG((pThis), VMIN))
-
-#define ICH6_HDA_REG_VMAJ           2 /* range 0x03 */
-#define VMAJ(pThis)                 (HDA_REG((pThis), VMAJ))
-
-#define ICH6_HDA_REG_OUTPAY         3 /* range 0x04-0x05 */
-#define OUTPAY(pThis)               (HDA_REG((pThis), OUTPAY))
-
-#define ICH6_HDA_REG_INPAY          4 /* range 0x06-0x07 */
-#define INPAY(pThis)                (HDA_REG((pThis), INPAY))
-
-#define ICH6_HDA_REG_GCTL           (5)
-#define ICH6_HDA_GCTL_RST_SHIFT     (0)
-#define ICH6_HDA_GCTL_FSH_SHIFT     (1)
-#define ICH6_HDA_GCTL_UR_SHIFT      (8)
-#define GCTL(pThis)                 (HDA_REG((pThis), GCTL))
-
-#define ICH6_HDA_REG_WAKEEN         6 /* 0x0C */
-#define WAKEEN(pThis)               (HDA_REG((pThis), WAKEEN))
-
-#define ICH6_HDA_REG_STATESTS       7 /* range 0x0E */
-#define STATESTS(pThis)             (HDA_REG((pThis), STATESTS))
-#define ICH6_HDA_STATES_SCSF        0x7
-
-#define ICH6_HDA_REG_GSTS           8 /* range 0x10-0x11*/
-#define ICH6_HDA_GSTS_FSH_SHIFT     (1)
-#define GSTS(pThis)                 (HDA_REG(pThis, GSTS))
-
-#define ICH6_HDA_REG_INTCTL         9 /* 0x20 */
-#define ICH6_HDA_INTCTL_GIE_SHIFT   31
-#define ICH6_HDA_INTCTL_CIE_SHIFT   30
-#define ICH6_HDA_INTCTL_S0_SHIFT    (0)
-#define ICH6_HDA_INTCTL_S1_SHIFT    (1)
-#define ICH6_HDA_INTCTL_S2_SHIFT    (2)
-#define ICH6_HDA_INTCTL_S3_SHIFT    (3)
-#define ICH6_HDA_INTCTL_S4_SHIFT    (4)
-#define ICH6_HDA_INTCTL_S5_SHIFT    (5)
-#define ICH6_HDA_INTCTL_S6_SHIFT    (6)
-#define ICH6_HDA_INTCTL_S7_SHIFT    (7)
-#define INTCTL(pThis)               (HDA_REG((pThis), INTCTL))
-#define INTCTL_GIE(pThis)           (HDA_REG_FLAG_VALUE(pThis, INTCTL, GIE))
-#define INTCTL_CIE(pThis)           (HDA_REG_FLAG_VALUE(pThis, INTCTL, CIE))
-#define INTCTL_SX(pThis, X)         (HDA_REG_FLAG_VALUE((pThis), INTCTL, S##X))
-#define INTCTL_SALL(pThis)          (INTCTL((pThis)) & 0xFF)
-
-/* 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 ICH6_HDA_REG_SSYNC          12 /* 0x34 */
-#define SSYNC(pThis)                (HDA_REG((pThis), SSYNC))
-
-#define ICH6_HDA_REG_INTSTS         10 /* 0x24 */
-#define ICH6_HDA_INTSTS_GIS_SHIFT   (31)
-#define ICH6_HDA_INTSTS_CIS_SHIFT   (30)
-#define ICH6_HDA_INTSTS_S0_SHIFT    (0)
-#define ICH6_HDA_INTSTS_S1_SHIFT    (1)
-#define ICH6_HDA_INTSTS_S2_SHIFT    (2)
-#define ICH6_HDA_INTSTS_S3_SHIFT    (3)
-#define ICH6_HDA_INTSTS_S4_SHIFT    (4)
-#define ICH6_HDA_INTSTS_S5_SHIFT    (5)
-#define ICH6_HDA_INTSTS_S6_SHIFT    (6)
-#define ICH6_HDA_INTSTS_S7_SHIFT    (7)
-#define ICH6_HDA_INTSTS_S_MASK(num) RT_BIT(HDA_REG_FIELD_SHIFT(S##num))
-#define INTSTS(pThis)               (HDA_REG((pThis), INTSTS))
-#define INTSTS_GIS(pThis)           (HDA_REG_FLAG_VALUE((pThis), INTSTS, GIS)
-#define INTSTS_CIS(pThis)           (HDA_REG_FLAG_VALUE((pThis), INTSTS, CIS)
-#define INTSTS_SX(pThis, X)         (HDA_REG_FLAG_VALUE(pThis), INTSTS, S##X)
-#define INTSTS_SANY(pThis)          (INTSTS((pThis)) & 0xFF)
-
-#define ICH6_HDA_REG_CORBLBASE      13 /* 0x40 */
-#define CORBLBASE(pThis)            (HDA_REG((pThis), CORBLBASE))
-#define ICH6_HDA_REG_CORBUBASE      14 /* 0x44 */
-#define CORBUBASE(pThis)            (HDA_REG((pThis), CORBUBASE))
-#define ICH6_HDA_REG_CORBWP         15 /* 48 */
-#define ICH6_HDA_REG_CORBRP         16 /* 4A */
-#define ICH6_HDA_CORBRP_RST_SHIFT   15
-#define ICH6_HDA_CORBRP_WP_SHIFT    0
-#define ICH6_HDA_CORBRP_WP_MASK     0xFF
-
-#define CORBRP(pThis)               (HDA_REG(pThis, CORBRP))
-#define CORBWP(pThis)               (HDA_REG(pThis, CORBWP))
-
-#define ICH6_HDA_REG_CORBCTL        17 /* 0x4C */
-#define ICH6_HDA_CORBCTL_DMA_SHIFT  (1)
-#define ICH6_HDA_CORBCTL_CMEIE_SHIFT (0)
-
-#define CORBCTL(pThis)              (HDA_REG(pThis, CORBCTL))
-
-
-#define ICH6_HDA_REG_CORBSTS        18 /* 0x4D */
-#define CORBSTS(pThis)              (HDA_REG(pThis, CORBSTS))
-#define ICH6_HDA_CORBSTS_CMEI_SHIFT (0)
-
-#define ICH6_HDA_REG_CORBSIZE       19 /* 0x4E */
-#define ICH6_HDA_CORBSIZE_SZ_CAP    0xF0
-#define ICH6_HDA_CORBSIZE_SZ        0x3
-#define CORBSIZE_SZ(pThis)          (HDA_REG(pThis, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ)
-#define CORBSIZE_SZ_CAP(pThis)      (HDA_REG(pThis, ICH6_HDA_REG_CORBSIZE) & ICH6_HDA_CORBSIZE_SZ_CAP)
-/* till ich 10 sizes of CORB and RIRB are hardcoded to 256 in real hw */
-
-#define ICH6_HDA_REG_RIRLBASE       20 /* 0x50 */
-#define RIRLBASE(pThis)             (HDA_REG((pThis), RIRLBASE))
-
-#define ICH6_HDA_REG_RIRUBASE       21 /* 0x54 */
-#define RIRUBASE(pThis)             (HDA_REG((pThis), RIRUBASE))
-
-#define ICH6_HDA_REG_RIRBWP         22 /* 0x58 */
-#define ICH6_HDA_RIRBWP_RST_SHIFT   (15)
-#define ICH6_HDA_RIRBWP_WP_MASK     0xFF
-#define RIRBWP(pThis)              (HDA_REG(pThis, RIRBWP))
-
-#define ICH6_HDA_REG_RINTCNT        23 /* 0x5A */
-#define RINTCNT(pThis)              (HDA_REG((pThis), RINTCNT))
-#define RINTCNT_N(pThis)            (RINTCNT((pThis)) & 0xff)
-
-#define ICH6_HDA_REG_RIRBCTL        24 /* 0x5C */
-#define ICH6_HDA_RIRBCTL_RIC_SHIFT  (0)
-#define ICH6_HDA_RIRBCTL_DMA_SHIFT  (1)
-#define ICH6_HDA_ROI_DMA_SHIFT      (2)
-#define RIRBCTL(pThis)              (HDA_REG((pThis), RIRBCTL))
-#define RIRBCTL_RIRB_RIC(pThis)     (HDA_REG_FLAG_VALUE(pThis, RIRBCTL, RIC))
-#define RIRBCTL_RIRB_DMA(pThis)     (HDA_REG_FLAG_VALUE((pThis), RIRBCTL, DMA)
-#define RIRBCTL_ROI(pThis)          (HDA_REG_FLAG_VALUE((pThis), RIRBCTL, ROI))
-
-#define ICH6_HDA_REG_RIRBSTS        25 /* 0x5D */
-#define ICH6_HDA_RIRBSTS_RINTFL_SHIFT (0)
-#define ICH6_HDA_RIRBSTS_RIRBOIS_SHIFT (2)
-#define RIRBSTS(pThis)              (HDA_REG(pThis, RIRBSTS))
-#define RIRBSTS_RINTFL(pThis)       (HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RINTFL))
-#define RIRBSTS_RIRBOIS(pThis)      (HDA_REG_FLAG_VALUE(pThis, RIRBSTS, RIRBOIS))
-
-#define ICH6_HDA_REG_RIRBSIZE       26 /* 0x5E */
-#define ICH6_HDA_RIRBSIZE_SZ_CAP    0xF0
-#define ICH6_HDA_RIRBSIZE_SZ        0x3
-
-#define RIRBSIZE_SZ(pThis)          (HDA_REG(pThis, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ)
-#define RIRBSIZE_SZ_CAP(pThis)      (HDA_REG(pThis, ICH6_HDA_REG_RIRBSIZE) & ICH6_HDA_RIRBSIZE_SZ_CAP)
-
-
-#define ICH6_HDA_REG_IC             27 /* 0x60 */
-#define IC(pThis)                   (HDA_REG(pThis, IC))
-#define ICH6_HDA_REG_IR             28 /* 0x64 */
-#define IR(pThis)                   (HDA_REG(pThis, IR))
-#define ICH6_HDA_REG_IRS            29 /* 0x68 */
-#define ICH6_HDA_IRS_ICB_SHIFT      (0)
-#define ICH6_HDA_IRS_IRV_SHIFT      (1)
-#define IRS(pThis)                  (HDA_REG(pThis, IRS))
-#define IRS_ICB(pThis)              (HDA_REG_FLAG_VALUE(pThis, IRS, ICB))
-#define IRS_IRV(pThis)              (HDA_REG_FLAG_VALUE(pThis, IRS, IRV))
-
-#define ICH6_HDA_REG_DPLBASE        30 /* 0x70 */
-#define DPLBASE(pThis)              (HDA_REG((pThis), DPLBASE))
-#define ICH6_HDA_REG_DPUBASE        31 /* 0x74 */
-#define DPUBASE(pThis)              (HDA_REG((pThis), DPUBASE))
-#define DPBASE_ENABLED              1
-#define DPBASE_ADDR_MASK            (~(uint64_t)0x7f)
-
-#define HDA_STREAM_REG_DEF(name, num)           (ICH6_HDA_REG_SD##num##name)
-#define HDA_STREAM_REG(pThis, name, num)        (HDA_REG((pThis), N_(HDA_STREAM_REG_DEF(name, num))))
-/* Note: sdnum here _MUST_ be stream reg number [0,7] */
-#define HDA_STREAM_REG2(pThis, name, sdnum)     (HDA_REG_IND((pThis), ICH6_HDA_REG_SD0##name + (sdnum) * 10))
-
-#define ICH6_HDA_REG_SD0CTL         32 /* 0x80 */
-#define ICH6_HDA_REG_SD1CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 10) /* 0xA0 */
-#define ICH6_HDA_REG_SD2CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 20) /* 0xC0 */
-#define ICH6_HDA_REG_SD3CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 30) /* 0xE0 */
-#define ICH6_HDA_REG_SD4CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 40) /* 0x100 */
-#define ICH6_HDA_REG_SD5CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 50) /* 0x120 */
-#define ICH6_HDA_REG_SD6CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 60) /* 0x140 */
-#define ICH6_HDA_REG_SD7CTL         (HDA_STREAM_REG_DEF(CTL, 0) + 70) /* 0x160 */
-
-#define SD(func, num)               SD##num##func
-#define SDCTL(pThis, num)           HDA_REG((pThis), SD(CTL, num))
-#define SDCTL_NUM(pThis, num)       ((SDCTL((pThis), num) & HDA_REG_FIELD_MASK(SDCTL,NUM)) >> HDA_REG_FIELD_SHIFT(SDCTL, NUM))
-#define ICH6_HDA_SDCTL_NUM_MASK     (0xF)
-#define ICH6_HDA_SDCTL_NUM_SHIFT    (20)
-#define ICH6_HDA_SDCTL_DIR_SHIFT    (19)
-#define ICH6_HDA_SDCTL_TP_SHIFT     (18)
-#define ICH6_HDA_SDCTL_STRIPE_MASK  (0x3)
-#define ICH6_HDA_SDCTL_STRIPE_SHIFT (16)
-#define ICH6_HDA_SDCTL_DEIE_SHIFT   (4)
-#define ICH6_HDA_SDCTL_FEIE_SHIFT   (3)
-#define ICH6_HDA_SDCTL_ICE_SHIFT    (2)
-#define ICH6_HDA_SDCTL_RUN_SHIFT    (1)
-#define ICH6_HDA_SDCTL_SRST_SHIFT   (0)
-
-#define ICH6_HDA_REG_SD0STS         33 /* 0x83 */
-#define ICH6_HDA_REG_SD1STS         (HDA_STREAM_REG_DEF(STS, 0) + 10) /* 0xA3 */
-#define ICH6_HDA_REG_SD2STS         (HDA_STREAM_REG_DEF(STS, 0) + 20) /* 0xC3 */
-#define ICH6_HDA_REG_SD3STS         (HDA_STREAM_REG_DEF(STS, 0) + 30) /* 0xE3 */
-#define ICH6_HDA_REG_SD4STS         (HDA_STREAM_REG_DEF(STS, 0) + 40) /* 0x103 */
-#define ICH6_HDA_REG_SD5STS         (HDA_STREAM_REG_DEF(STS, 0) + 50) /* 0x123 */
-#define ICH6_HDA_REG_SD6STS         (HDA_STREAM_REG_DEF(STS, 0) + 60) /* 0x143 */
-#define ICH6_HDA_REG_SD7STS         (HDA_STREAM_REG_DEF(STS, 0) + 70) /* 0x163 */
-
-#define SDSTS(pThis, num)           HDA_REG((pThis), SD(STS, num))
-#define ICH6_HDA_SDSTS_FIFORDY_SHIFT (5)
-#define ICH6_HDA_SDSTS_DE_SHIFT     (4)
-#define ICH6_HDA_SDSTS_FE_SHIFT     (3)
-#define ICH6_HDA_SDSTS_BCIS_SHIFT   (2)
-
-#define ICH6_HDA_REG_SD0LPIB        34 /* 0x84 */
-#define ICH6_HDA_REG_SD1LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 10) /* 0xA4 */
-#define ICH6_HDA_REG_SD2LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 20) /* 0xC4 */
-#define ICH6_HDA_REG_SD3LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 30) /* 0xE4 */
-#define ICH6_HDA_REG_SD4LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 40) /* 0x104 */
-#define ICH6_HDA_REG_SD5LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 50) /* 0x124 */
-#define ICH6_HDA_REG_SD6LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 60) /* 0x144 */
-#define ICH6_HDA_REG_SD7LPIB        (HDA_STREAM_REG_DEF(LPIB, 0) + 70) /* 0x164 */
-
-#define SDLPIB(pThis, num)          HDA_REG((pThis), SD(LPIB, num))
-
-#define ICH6_HDA_REG_SD0CBL         35 /* 0x88 */
-#define ICH6_HDA_REG_SD1CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 10) /* 0xA8 */
-#define ICH6_HDA_REG_SD2CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 20) /* 0xC8 */
-#define ICH6_HDA_REG_SD3CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 30) /* 0xE8 */
-#define ICH6_HDA_REG_SD4CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 40) /* 0x108 */
-#define ICH6_HDA_REG_SD5CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 50) /* 0x128 */
-#define ICH6_HDA_REG_SD6CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 60) /* 0x148 */
-#define ICH6_HDA_REG_SD7CBL         (HDA_STREAM_REG_DEF(CBL, 0) + 70) /* 0x168 */
-
-#define SDLCBL(pThis, num)          HDA_REG((pThis), SD(CBL, num))
-
-#define ICH6_HDA_REG_SD0LVI         36 /* 0x8C */
-#define ICH6_HDA_REG_SD1LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 10) /* 0xAC */
-#define ICH6_HDA_REG_SD2LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 20) /* 0xCC */
-#define ICH6_HDA_REG_SD3LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 30) /* 0xEC */
-#define ICH6_HDA_REG_SD4LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 40) /* 0x10C */
-#define ICH6_HDA_REG_SD5LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 50) /* 0x12C */
-#define ICH6_HDA_REG_SD6LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 60) /* 0x14C */
-#define ICH6_HDA_REG_SD7LVI         (HDA_STREAM_REG_DEF(LVI, 0) + 70) /* 0x16C */
-
-#define SDLVI(pThis, num)           HDA_REG((pThis), SD(LVI, num))
-
-#define ICH6_HDA_REG_SD0FIFOW       37 /* 0x8E */
-#define ICH6_HDA_REG_SD1FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 10) /* 0xAE */
-#define ICH6_HDA_REG_SD2FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 20) /* 0xCE */
-#define ICH6_HDA_REG_SD3FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 30) /* 0xEE */
-#define ICH6_HDA_REG_SD4FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 40) /* 0x10E */
-#define ICH6_HDA_REG_SD5FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 50) /* 0x12E */
-#define ICH6_HDA_REG_SD6FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 60) /* 0x14E */
-#define ICH6_HDA_REG_SD7FIFOW       (HDA_STREAM_REG_DEF(FIFOW, 0) + 70) /* 0x16E */
-
-/*
- * 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 SDFIFOW(pThis, num)         HDA_REG((pThis), SD(FIFOW, num))
-
-#define ICH6_HDA_REG_SD0FIFOS       38 /* 0x90 */
-#define ICH6_HDA_REG_SD1FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 10) /* 0xB0 */
-#define ICH6_HDA_REG_SD2FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 20) /* 0xD0 */
-#define ICH6_HDA_REG_SD3FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 30) /* 0xF0 */
-#define ICH6_HDA_REG_SD4FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 40) /* 0x110 */
-#define ICH6_HDA_REG_SD5FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 50) /* 0x130 */
-#define ICH6_HDA_REG_SD6FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 60) /* 0x150 */
-#define ICH6_HDA_REG_SD7FIFOS       (HDA_STREAM_REG_DEF(FIFOS, 0) + 70) /* 0x170 */
-
-/*
- * ICH6 datasheet defines limits for FIFOS registers (18.2.39)
- * formula: size - 1
- * Other values not listed are not supported.
- */
-#define HDA_SDONFIFO_16B            (0x0F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
-#define HDA_SDONFIFO_32B            (0x1F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
-#define HDA_SDONFIFO_64B            (0x3F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
-#define HDA_SDONFIFO_128B           (0x7F) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
-#define HDA_SDONFIFO_192B           (0xBF) /* 8-, 16-, 20-, 24-, 32-bit Output Streams */
-#define HDA_SDONFIFO_256B           (0xFF) /* 20-, 24-bit Output Streams */
-#define HDA_SDINFIFO_120B           (0x77) /* 8-, 16-, 20-, 24-, 32-bit Input Streams */
-#define HDA_SDINFIFO_160B           (0x9F) /* 20-, 24-bit Input Streams Streams */
-#define SDFIFOS(pThis, num)         HDA_REG((pThis), SD(FIFOS, num))
-
-#define ICH6_HDA_REG_SD0FMT         39 /* 0x92 */
-#define ICH6_HDA_REG_SD1FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 10) /* 0xB2 */
-#define ICH6_HDA_REG_SD2FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 20) /* 0xD2 */
-#define ICH6_HDA_REG_SD3FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 30) /* 0xF2 */
-#define ICH6_HDA_REG_SD4FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 40) /* 0x112 */
-#define ICH6_HDA_REG_SD5FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 50) /* 0x132 */
-#define ICH6_HDA_REG_SD6FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 60) /* 0x152 */
-#define ICH6_HDA_REG_SD7FMT         (HDA_STREAM_REG_DEF(FMT, 0) + 70) /* 0x172 */
-
-#define SDFMT(pThis, num)           (HDA_REG((pThis), SD(FMT, num)))
-#define ICH6_HDA_SDFMT_BASE_RATE_SHIFT (14)
-#define ICH6_HDA_SDFMT_MULT_SHIFT   (11)
-#define ICH6_HDA_SDFMT_MULT_MASK    (0x7)
-#define ICH6_HDA_SDFMT_DIV_SHIFT    (8)
-#define ICH6_HDA_SDFMT_DIV_MASK     (0x7)
-#define ICH6_HDA_SDFMT_BITS_SHIFT   (4)
-#define ICH6_HDA_SDFMT_BITS_MASK    (0x7)
-#define SDFMT_BASE_RATE(pThis, num) ((SDFMT(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDFMT, BASE_RATE)) >> HDA_REG_FIELD_SHIFT(SDFMT, BASE_RATE))
-#define SDFMT_MULT(pThis, num)      ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,MULT)) >> HDA_REG_FIELD_SHIFT(SDFMT, MULT))
-#define SDFMT_DIV(pThis, num)       ((SDFMT((pThis), num) & HDA_REG_FIELD_MASK(SDFMT,DIV)) >> HDA_REG_FIELD_SHIFT(SDFMT, DIV))
-
-#define ICH6_HDA_REG_SD0BDPL        40 /* 0x98 */
-#define ICH6_HDA_REG_SD1BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 10) /* 0xB8 */
-#define ICH6_HDA_REG_SD2BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 20) /* 0xD8 */
-#define ICH6_HDA_REG_SD3BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 30) /* 0xF8 */
-#define ICH6_HDA_REG_SD4BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 40) /* 0x118 */
-#define ICH6_HDA_REG_SD5BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 50) /* 0x138 */
-#define ICH6_HDA_REG_SD6BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 60) /* 0x158 */
-#define ICH6_HDA_REG_SD7BDPL        (HDA_STREAM_REG_DEF(BDPL, 0) + 70) /* 0x178 */
-
-#define SDBDPL(pThis, num)          HDA_REG((pThis), SD(BDPL, num))
-
-#define ICH6_HDA_REG_SD0BDPU        41 /* 0x9C */
-#define ICH6_HDA_REG_SD1BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 10) /* 0xBC */
-#define ICH6_HDA_REG_SD2BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 20) /* 0xDC */
-#define ICH6_HDA_REG_SD3BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 30) /* 0xFC */
-#define ICH6_HDA_REG_SD4BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 40) /* 0x11C */
-#define ICH6_HDA_REG_SD5BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 50) /* 0x13C */
-#define ICH6_HDA_REG_SD6BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 60) /* 0x15C */
-#define ICH6_HDA_REG_SD7BDPU        (HDA_STREAM_REG_DEF(BDPU, 0) + 70) /* 0x17C */
-
-#define SDBDPU(pThis, num)          HDA_REG((pThis), SD(BDPU, num))
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-typedef struct HDABDLEDESC
-{
-    uint64_t    u64BdleCviAddr;
-    uint32_t    u32BdleMaxCvi;
-    uint32_t    u32BdleCvi;
-    uint32_t    u32BdleCviLen;
-    uint32_t    u32BdleCviPos;
-    bool        fBdleCviIoc;
-    uint32_t    cbUnderFifoW;
-    uint8_t     au8HdaBuffer[HDA_SDONFIFO_256B + 1];
-} HDABDLEDESC, *PHDABDLEDESC;
-
-typedef struct HDASTREAMTRANSFERDESC
-{
-    uint64_t u64BaseDMA;
-    uint32_t u32Ctl;
-    uint32_t *pu32Sts;
-    uint8_t  u8Strm;
-    uint32_t *pu32Lpib;
-    uint32_t u32Cbl;
-    uint32_t u32Fifos;
-} HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC;
-
-/**
- * ICH Intel HD Audio Controller state.
- */
-typedef struct HDASTATE
-{
-    /** The PCI device structure. */
-    PCIDevice               PciDev;
-    /** Pointer to the device instance. */
-    PPDMDEVINSR3            pDevIns;
-    /** Pointer to the connector of the attached audio driver. */
-    PPDMIAUDIOCONNECTOR     pDrv;
-    /** Pointer to the attached audio driver. */
-    PPDMIBASE               pDrvBase;
-    /** The base interface for LUN\#0. */
-    PDMIBASE                IBase;
-    RTGCPHYS                MMIOBaseAddr;
-    uint32_t                au32Regs[HDA_NREGS];
-    HDABDLEDESC             StInBdle;
-    HDABDLEDESC             StOutBdle;
-    HDABDLEDESC             StMicBdle;
-    /** Interrupt on completion */
-    bool                    fCviIoc;
-    uint64_t                u64CORBBase;
-    uint64_t                u64RIRBBase;
-    uint64_t                u64DPBase;
-    /** pointer to CORB buf */
-    uint32_t               *pu32CorbBuf;
-    /** size in bytes of CORB buf */
-    uint32_t                cbCorbBuf;
-    /** pointer on RIRB buf */
-    uint64_t               *pu64RirbBuf;
-    /** size in bytes of RIRB buf */
-    uint32_t                cbRirbBuf;
-    /** indicates if HDA in reset. */
-    bool                    fInReset;
-    /** The HDA codec state. */
-    HDACODEC                Codec;
-    /** 1.2.3.4.5.6.7. - someone please tell me what I'm counting! - .8.9.10... */
-    uint8_t                 u8Counter;
-    uint64_t                u64BaseTS;
-} HDASTATE;
-/** Pointer to the ICH Intel HD Audio Controller state. */
-typedef HDASTATE *PHDASTATE;
-
-#define ISD0FMT_TO_AUDIO_SELECTOR(pThis) \
-    ( AUDIO_FORMAT_SELECTOR(&(pThis)->Codec, In, SDFMT_BASE_RATE(pThis, 0), SDFMT_MULT(pThis, 0), SDFMT_DIV(pThis, 0)) )
-#define OSD0FMT_TO_AUDIO_SELECTOR(pThis) \
-    ( AUDIO_FORMAT_SELECTOR(&(pThis)->Codec, Out, SDFMT_BASE_RATE(pThis, 4), SDFMT_MULT(pThis, 4), SDFMT_DIV(pThis, 4)) )
-
-
-/*******************************************************************************
-*   Internal Functions                                                         *
-*******************************************************************************/
-static FNPDMDEVRESET hdaReset;
-
-static int hdaRegReadUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadGCAP(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegReadSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-
-static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t pu32Value);
-
-DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
-                                           PHDASTREAMTRANSFERDESC pStreamDesc);
-static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc);
-#ifdef LOG_ENABLED
-static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
-#endif
-
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
-/* see 302349 p 6.2*/
-static const 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;
-    /** Read callback. */
-    int       (*pfnRead)(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value);
-    /** Write callback. */
-    int       (*pfnWrite)(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value);
-    /** Abbreviated name. */
-    const char *abbrev;
-    /** Full name. */
-    const char *name;
-} g_aHdaRegMap[HDA_NREGS] =
-{
-    /* offset  size     read mask   write mask         read callback         write callback         abbrev      full name                     */
-    /*-------  -------  ----------  ----------  -----------------------  ------------------------ ----------    ------------------------------*/
-    { 0x00000, 0x00002, 0x0000FFFB, 0x00000000, hdaRegReadGCAP         , hdaRegWriteUnimplemented, "GCAP"      , "Global Capabilities" },
-    { 0x00002, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "VMIN"      , "Minor Version" },
-    { 0x00003, 0x00001, 0x000000FF, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "VMAJ"      , "Major Version" },
-    { 0x00004, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimplemented, "OUTPAY"    , "Output Payload Capabilities" },
-    { 0x00006, 0x00002, 0x0000FFFF, 0x00000000, hdaRegReadU16          , hdaRegWriteUnimplemented, "INPAY"     , "Input Payload Capabilities" },
-    { 0x00008, 0x00004, 0x00000103, 0x00000103, hdaRegReadGCTL         , hdaRegWriteGCTL         , "GCTL"      , "Global Control" },
-    { 0x0000c, 0x00002, 0x00007FFF, 0x00007FFF, hdaRegReadU16          , hdaRegWriteU16          , "WAKEEN"    , "Wake Enable" },
-    { 0x0000e, 0x00002, 0x00000007, 0x00000007, hdaRegReadU8           , hdaRegWriteSTATESTS     , "STATESTS"  , "State Change Status" },
-    { 0x00010, 0x00002, 0xFFFFFFFF, 0x00000000, hdaRegReadUnimplemented, hdaRegWriteUnimplemented, "GSTS"      , "Global Status" },
-    { 0x00020, 0x00004, 0xC00000FF, 0xC00000FF, hdaRegReadU32          , hdaRegWriteU32          , "INTCTL"    , "Interrupt Control" },
-    { 0x00024, 0x00004, 0xC00000FF, 0x00000000, hdaRegReadINTSTS       , hdaRegWriteUnimplemented, "INTSTS"    , "Interrupt Status" },
-    { 0x00030, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadWALCLK       , hdaRegWriteUnimplemented, "WALCLK"    , "Wall Clock Counter" },
-    /// @todo r=michaln: Doesn't the SSYNC register need to actually stop the stream(s)?
-    { 0x00034, 0x00004, 0x000000FF, 0x000000FF, hdaRegReadU32          , hdaRegWriteU32          , "SSYNC"     , "Stream Synchronization" },
-    { 0x00040, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteBase         , "CORBLBASE" , "CORB Lower Base Address" },
-    { 0x00044, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "CORBUBASE" , "CORB Upper Base Address" },
-    { 0x00048, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteCORBWP       , "CORBWP"    , "CORB Write Pointer" },
-#ifdef OLD_REGISTER_TABLE
-    { 0x0004A, 0x00002, 0x000000FF, 0x000080FF, hdaRegReadU8           , hdaRegWriteCORBRP       , "CORBRP"    , "CORB Read Pointer" },
-#else /** @todo 18.2.17 indicates that the 15th bit can be read as well as and written. hdaRegReadU8 is wrong, a special reader should be used. */
-    { 0x0004A, 0x00002, 0x000080FF, 0x000080FF, hdaRegReadU16          , hdaRegWriteCORBRP       , "CORBRP"    , "CORB Read Pointer" },
-#endif
-    { 0x0004C, 0x00001, 0x00000003, 0x00000003, hdaRegReadU8           , hdaRegWriteCORBCTL      , "CORBCTL"   , "CORB Control" },
-    { 0x0004D, 0x00001, 0x00000001, 0x00000001, hdaRegReadU8           , hdaRegWriteCORBSTS      , "CORBSTS"   , "CORB Status" },
-    { 0x0004E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "CORBSIZE"  , "CORB Size" },
-    { 0x00050, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteBase         , "RIRBLBASE" , "RIRB Lower Base Address" },
-    { 0x00054, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "RIRBUBASE" , "RIRB Upper Base Address" },
-    { 0x00058, 0x00002, 0x000000FF, 0x00008000, hdaRegReadU8           , hdaRegWriteRIRBWP       , "RIRBWP"    , "RIRB Write Pointer" },
-    { 0x0005A, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteU16          , "RINTCNT"   , "Response Interrupt Count" },
-    { 0x0005C, 0x00001, 0x00000007, 0x00000007, hdaRegReadU8           , hdaRegWriteU8           , "RIRBCTL"   , "RIRB Control" },
-    { 0x0005D, 0x00001, 0x00000005, 0x00000005, hdaRegReadU8           , hdaRegWriteRIRBSTS      , "RIRBSTS"   , "RIRB Status" },
-    { 0x0005E, 0x00001, 0x000000F3, 0x00000000, hdaRegReadU8           , hdaRegWriteUnimplemented, "RIRBSIZE"  , "RIRB Size" },
-    { 0x00060, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "IC"        , "Immediate Command" },
-    { 0x00064, 0x00004, 0x00000000, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteUnimplemented, "IR"        , "Immediate Response" },
-#ifdef OLD_REGISTER_TABLE
-    { 0x00068, 0x00004, 0x00000002, 0x00000002, hdaRegReadIRS          , hdaRegWriteIRS          , "IRS"       , "Immediate Command Status" },
-#else /* 18.2.30 as well as the table says 16-bit. Linux accesses it as a 16-bit register. */
-    { 0x00068, 0x00002, 0x00000002, 0x00000002, hdaRegReadIRS          , hdaRegWriteIRS          , "IRS"       , "Immediate Command Status" },
-#endif
-    { 0x00070, 0x00004, 0xFFFFFFFF, 0xFFFFFF81, hdaRegReadU32          , hdaRegWriteBase         , "DPLBASE"   , "DMA Position Lower Base" },
-    { 0x00074, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteBase         , "DPUBASE"   , "DMA Position Upper Base" },
-
-    { 0x00080, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD0CTL"  , "Input Stream Descriptor 0 (ICD0) Control" },
-    { 0x00083, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD0STS"  , "ISD0 Status" },
-    { 0x00084, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD0LPIB" , "ISD0 Link Position In Buffer" },
-    { 0x00088, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD0CBL"  , "ISD0 Cyclic Buffer Length" },
-    { 0x0008C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD0LVI"  , "ISD0 Last Valid Index" },
-    { 0x0008E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD0FIFOW", "ISD0 FIFO Watermark" },
-    { 0x00090, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD0FIFOS", "ISD0 FIFO Size" },
-    { 0x00092, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD0FMT"  , "ISD0 Format" },
-    { 0x00098, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD0BDPL" , "ISD0 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x0009C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD0BDPU" , "ISD0 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x000A0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD1CTL"  , "Input Stream Descriptor 1 (ISD1) Control" },
-    { 0x000A3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD1STS"  , "ISD1 Status" },
-    { 0x000A4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD1LPIB" , "ISD1 Link Position In Buffer" },
-    { 0x000A8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD1CBL"  , "ISD1 Cyclic Buffer Length" },
-    { 0x000AC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD1LVI"  , "ISD1 Last Valid Index" },
-    { 0x000AE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD1FIFOW", "ISD1 FIFO Watermark" },
-    { 0x000B0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD1FIFOS", "ISD1 FIFO Size" },
-    { 0x000B2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD1FMT"  , "ISD1 Format" },
-    { 0x000B8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD1BDPL" , "ISD1 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x000BC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD1BDPU" , "ISD1 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x000C0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD2CTL"  , "Input Stream Descriptor 2 (ISD2) Control" },
-    { 0x000C3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD2STS"  , "ISD2 Status" },
-    { 0x000C4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD2LPIB" , "ISD2 Link Position In Buffer" },
-    { 0x000C8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD2CBL"  , "ISD2 Cyclic Buffer Length" },
-    { 0x000CC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD2LVI"  , "ISD2 Last Valid Index" },
-    { 0x000CE, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "ISD2FIFOW", "ISD2 FIFO Watermark" },
-    { 0x000D0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD2FIFOS", "ISD2 FIFO Size" },
-    { 0x000D2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD2FMT"  , "ISD2 Format" },
-    { 0x000D8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD2BDPL" , "ISD2 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x000DC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD2BDPU" , "ISD2 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x000E0, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "ISD3CTL"  , "Input Stream Descriptor 3 (ISD3) Control" },
-    { 0x000E3, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "ISD3STS"  , "ISD3 Status" },
-    { 0x000E4, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "ISD3LPIB" , "ISD3 Link Position In Buffer" },
-    { 0x000E8, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "ISD3CBL"  , "ISD3 Cyclic Buffer Length" },
-    { 0x000EC, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "ISD3LVI"  , "ISD3 Last Valid Index" },
-    { 0x000EE, 0x00002, 0x00000005, 0x00000005, hdaRegReadU16          , hdaRegWriteU16          , "ISD3FIFOW", "ISD3 FIFO Watermark" },
-    { 0x000F0, 0x00002, 0x000000FF, 0x00000000, hdaRegReadU16          , hdaRegWriteU16          , "ISD3FIFOS", "ISD3 FIFO Size" },
-    { 0x000F2, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "ISD3FMT"  , "ISD3 Format" },
-    { 0x000F8, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "ISD3BDPL" , "ISD3 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x000FC, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "ISD3BDPU" , "ISD3 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x00100, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadSDCTL        , hdaRegWriteSDCTL        , "OSD0CTL"  , "Input Stream Descriptor 0 (OSD0) Control" },
-    { 0x00103, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD0STS"  , "OSD0 Status" },
-    { 0x00104, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD0LPIB" , "OSD0 Link Position In Buffer" },
-    { 0x00108, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD0CBL"  , "OSD0 Cyclic Buffer Length" },
-    { 0x0010C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD0LVI"  , "OSD0 Last Valid Index" },
-    { 0x0010E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD0FIFOW", "OSD0 FIFO Watermark" },
-    { 0x00110, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD0FIFOS", "OSD0 FIFO Size" },
-    { 0x00112, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD0FMT"  , "OSD0 Format" },
-    { 0x00118, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD0BDPL" , "OSD0 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x0011C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD0BDPU" , "OSD0 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x00120, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD1CTL"  , "Input Stream Descriptor 0 (OSD1) Control" },
-    { 0x00123, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD1STS"  , "OSD1 Status" },
-    { 0x00124, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD1LPIB" , "OSD1 Link Position In Buffer" },
-    { 0x00128, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD1CBL"  , "OSD1 Cyclic Buffer Length" },
-    { 0x0012C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD1LVI"  , "OSD1 Last Valid Index" },
-    { 0x0012E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD1FIFOW", "OSD1 FIFO Watermark" },
-    { 0x00130, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD1FIFOS", "OSD1 FIFO Size" },
-    { 0x00132, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD1FMT"  , "OSD1 Format" },
-    { 0x00138, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD1BDPL" , "OSD1 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x0013C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD1BDPU" , "OSD1 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x00140, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD2CTL"  , "Input Stream Descriptor 0 (OSD2) Control" },
-    { 0x00143, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD2STS"  , "OSD2 Status" },
-    { 0x00144, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD2LPIB" , "OSD2 Link Position In Buffer" },
-    { 0x00148, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD2CBL"  , "OSD2 Cyclic Buffer Length" },
-    { 0x0014C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD2LVI"  , "OSD2 Last Valid Index" },
-    { 0x0014E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD2FIFOW", "OSD2 FIFO Watermark" },
-    { 0x00150, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD2FIFOS", "OSD2 FIFO Size" },
-    { 0x00152, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD2FMT"  , "OSD2 Format" },
-    { 0x00158, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD2BDPL" , "OSD2 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x0015C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD2BDPU" , "OSD2 Buffer Descriptor List Pointer-Upper Base Address" },
-
-    { 0x00160, 0x00003, 0x00FF001F, 0x00F0001F, hdaRegReadU24          , hdaRegWriteSDCTL        , "OSD3CTL"  , "Input Stream Descriptor 0 (OSD3) Control" },
-    { 0x00163, 0x00001, 0x0000001C, 0x0000003C, hdaRegReadU8           , hdaRegWriteSDSTS        , "OSD3STS"  , "OSD3 Status" },
-    { 0x00164, 0x00004, 0xFFFFFFFF, 0x00000000, hdaRegReadU32          , hdaRegWriteU32          , "OSD3LPIB" , "OSD3 Link Position In Buffer" },
-    { 0x00168, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteU32          , "OSD3CBL"  , "OSD3 Cyclic Buffer Length" },
-    { 0x0016C, 0x00002, 0x0000FFFF, 0x0000FFFF, hdaRegReadU16          , hdaRegWriteSDLVI        , "OSD3LVI"  , "OSD3 Last Valid Index" },
-    { 0x0016E, 0x00002, 0x00000007, 0x00000007, hdaRegReadU16          , hdaRegWriteSDFIFOW      , "OSD3FIFOW", "OSD3 FIFO Watermark" },
-    { 0x00170, 0x00002, 0x000000FF, 0x000000FF, hdaRegReadU16          , hdaRegWriteSDFIFOS      , "OSD3FIFOS", "OSD3 FIFO Size" },
-    { 0x00172, 0x00002, 0x00007F7F, 0x00007F7F, hdaRegReadU16          , hdaRegWriteSDFMT        , "OSD3FMT"  , "OSD3 Format" },
-    { 0x00178, 0x00004, 0xFFFFFF80, 0xFFFFFF80, hdaRegReadU32          , hdaRegWriteSDBDPL       , "OSD3BDPL" , "OSD3 Buffer Descriptor List Pointer-Lower Base Address" },
-    { 0x0017C, 0x00004, 0xFFFFFFFF, 0xFFFFFFFF, hdaRegReadU32          , hdaRegWriteSDBDPU       , "OSD3BDPU" , "OSD3 Buffer Descriptor List Pointer-Upper Base Address" },
-};
-
-/**
- * HDA register aliases (HDA spec 3.3.45).
- * @remarks Sorted by offReg.
- */
-static const struct
-{
-    /** The alias register offset. */
-    uint32_t    offReg;
-    /** The register index. */
-    int         idxAlias;
-} g_aHdaRegAliases[] =
-{
-    { 0x2084, HDA_REG_IND_NAME(SD0LPIB) },
-    { 0x20a4, HDA_REG_IND_NAME(SD1LPIB) },
-    { 0x20c4, HDA_REG_IND_NAME(SD2LPIB) },
-    { 0x20e4, HDA_REG_IND_NAME(SD3LPIB) },
-    { 0x2104, HDA_REG_IND_NAME(SD4LPIB) },
-    { 0x2124, HDA_REG_IND_NAME(SD5LPIB) },
-    { 0x2144, HDA_REG_IND_NAME(SD6LPIB) },
-    { 0x2164, HDA_REG_IND_NAME(SD7LPIB) },
-};
-
-
-/** HDABDLEDESC field descriptors the v3+ saved state. */
-static SSMFIELD const g_aHdaBDLEDescFields[] =
-{
-    SSMFIELD_ENTRY(     HDABDLEDESC, u64BdleCviAddr),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleMaxCvi),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCvi),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviLen),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviPos),
-    SSMFIELD_ENTRY(     HDABDLEDESC, fBdleCviIoc),
-    SSMFIELD_ENTRY(     HDABDLEDESC, cbUnderFifoW),
-    SSMFIELD_ENTRY(     HDABDLEDESC, au8HdaBuffer),
-    SSMFIELD_ENTRY_TERM()
-};
-
-/** HDABDLEDESC field descriptors the v1 and v2 saved state. */
-static SSMFIELD const g_aHdaBDLEDescFieldsOld[] =
-{
-    SSMFIELD_ENTRY(     HDABDLEDESC, u64BdleCviAddr),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleMaxCvi),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCvi),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviLen),
-    SSMFIELD_ENTRY(     HDABDLEDESC, u32BdleCviPos),
-    SSMFIELD_ENTRY(     HDABDLEDESC, fBdleCviIoc),
-    SSMFIELD_ENTRY_PAD_HC_AUTO(3, 3),
-    SSMFIELD_ENTRY(     HDABDLEDESC, cbUnderFifoW),
-    SSMFIELD_ENTRY(     HDABDLEDESC, au8HdaBuffer),
-    SSMFIELD_ENTRY_TERM()
-};
-
-/**
- * 32-bit size indexed masks, i.e. g_afMasks[2 bytes] = 0xffff.
- */
-static uint32_t const   g_afMasks[5] =
-{
-    UINT32_C(0), UINT32_C(0x000000ff), UINT32_C(0x0000ffff), UINT32_C(0xffffff00), UINT32_C(0xffffffff)
-};
-
-
-DECLINLINE(void) hdaUpdatePosBuf(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-    if (pThis->u64DPBase & DPBASE_ENABLED)
-        PDMDevHlpPhysWrite(pThis->pDevIns,
-                           (pThis->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm * 8,
-                           pStreamDesc->pu32Lpib, sizeof(uint32_t));
-}
-DECLINLINE(uint32_t) hdaFifoWToSz(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-#if 0
-    switch(HDA_STREAM_REG2(pThis, FIFOW, pStreamDesc->u8Strm))
-    {
-        case HDA_SDFIFOW_8B: return 8;
-        case HDA_SDFIFOW_16B: return 16;
-        case HDA_SDFIFOW_32B: return 32;
-        default:
-            AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pThis, pStreamDesc->u8Strm), pStreamDesc->u8Strm));
-    }
-#endif
-    return 0;
-}
-
-static int hdaProcessInterrupt(PHDASTATE pThis)
-{
-#define IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, num) \
-        (   INTCTL_SX((pThis), num) \
-         && (SDSTS(pThis, num) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
-    bool fIrq = false;
-    if (   INTCTL_CIE(pThis)
-       && (   RIRBSTS_RINTFL(pThis)
-           || RIRBSTS_RIRBOIS(pThis)
-           || (STATESTS(pThis) & WAKEEN(pThis))))
-        fIrq = true;
-
-    if (   IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 0)
-        || IS_INTERRUPT_OCCURED_AND_ENABLED(pThis, 4))
-        fIrq = true;
-
-    if (INTCTL_GIE(pThis))
-    {
-        Log(("hda: irq %s\n", fIrq ? "asserted" : "deasserted"));
-        PDMDevHlpPCISetIrq(pThis->pDevIns, 0 , fIrq);
-    }
-    return VINF_SUCCESS;
-}
-
-/**
- * Looks up a register at the exact offset given by @a offReg.
- *
- * @returns Register index on success, -1 if not found.
- * @param   pThis               The HDA device state.
- * @param   offReg              The register offset.
- */
-static int hdaRegLookup(PHDASTATE pThis, uint32_t offReg)
-{
-    /*
-     * Aliases.
-     */
-    if (offReg >= g_aHdaRegAliases[0].offReg)
-    {
-        for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
-            if (offReg == g_aHdaRegAliases[i].offReg)
-                return g_aHdaRegAliases[i].idxAlias;
-        Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
-        return -1;
-    }
-
-    /*
-     * Binary search the
-     */
-    int idxEnd  = RT_ELEMENTS(g_aHdaRegMap);
-    int idxLow  = 0;
-    for (;;)
-    {
-        int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
-        if (offReg < g_aHdaRegMap[idxMiddle].offset)
-        {
-            if (idxLow == idxMiddle)
-                break;
-            idxEnd = idxMiddle;
-        }
-        else if (offReg > g_aHdaRegMap[idxMiddle].offset)
-        {
-            idxLow = idxMiddle + 1;
-            if (idxLow >= idxEnd)
-                break;
-        }
-        else
-            return idxMiddle;
-    }
-
-#ifdef RT_STRICT
-    for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
-        Assert(g_aHdaRegMap[i].offset != offReg);
-#endif
-    return -1;
-}
-
-/**
- * Looks up a register covering the offset given by @a offReg.
- *
- * @returns Register index on success, -1 if not found.
- * @param   pThis               The HDA device state.
- * @param   offReg              The register offset.
- */
-static int hdaRegLookupWithin(PHDASTATE pThis, uint32_t offReg)
-{
-    /*
-     * Aliases.
-     */
-    if (offReg >= g_aHdaRegAliases[0].offReg)
-    {
-        for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegAliases); i++)
-        {
-            uint32_t off = offReg - g_aHdaRegAliases[i].offReg;
-            if (off < 4 && off < g_aHdaRegMap[g_aHdaRegAliases[i].idxAlias].size)
-                return g_aHdaRegAliases[i].idxAlias;
-        }
-        Assert(g_aHdaRegMap[RT_ELEMENTS(g_aHdaRegMap) - 1].offset < offReg);
-        return -1;
-    }
-
-    /*
-     * Binary search the
-     */
-    int idxEnd  = RT_ELEMENTS(g_aHdaRegMap);
-    int idxLow  = 0;
-    for (;;)
-    {
-        int idxMiddle = idxLow + (idxEnd - idxLow) / 2;
-        if (offReg < g_aHdaRegMap[idxMiddle].offset)
-        {
-            if (idxLow == idxMiddle)
-                break;
-            idxEnd = idxMiddle;
-        }
-        else if (offReg >= g_aHdaRegMap[idxMiddle].offset + g_aHdaRegMap[idxMiddle].size)
-        {
-            idxLow = idxMiddle + 1;
-            if (idxLow >= idxEnd)
-                break;
-        }
-        else
-            return idxMiddle;
-    }
-
-#ifdef RT_STRICT
-    for (unsigned i = 0; i < RT_ELEMENTS(g_aHdaRegMap); i++)
-        Assert(offReg - g_aHdaRegMap[i].offset >= g_aHdaRegMap[i].size);
-#endif
-    return -1;
-}
-
-
-static int hdaCmdSync(PHDASTATE pThis, bool fLocal)
-{
-    int rc = VINF_SUCCESS;
-    if (fLocal)
-    {
-        Assert((HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)));
-        rc = PDMDevHlpPhysRead(pThis->pDevIns, pThis->u64CORBBase, pThis->pu32CorbBuf, pThis->cbCorbBuf);
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-#ifdef DEBUG_CMD_BUFFER
-        uint8_t i = 0;
-        do
-        {
-            Log(("hda: corb%02x: ", i));
-            uint8_t j = 0;
-            do
-            {
-                const char *prefix;
-                if ((i + j) == CORBRP(pThis))
-                    prefix = "[R]";
-                else if ((i + j) == CORBWP(pThis))
-                    prefix = "[W]";
-                else
-                    prefix = "   "; /* three spaces */
-                Log(("%s%08x", prefix, pThis->pu32CorbBuf[i + j]));
-                j++;
-            } while (j < 8);
-            Log(("\n"));
-            i += 8;
-        } while(i != 0);
-#endif
-    }
-    else
-    {
-        Assert((HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA)));
-        rc = PDMDevHlpPhysWrite(pThis->pDevIns, pThis->u64RIRBBase, pThis->pu64RirbBuf, pThis->cbRirbBuf);
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-#ifdef DEBUG_CMD_BUFFER
-        uint8_t i = 0;
-        do {
-            Log(("hda: rirb%02x: ", i));
-            uint8_t j = 0;
-            do {
-                const char *prefix;
-                if ((i + j) == RIRBWP(pThis))
-                    prefix = "[W]";
-                else
-                    prefix = "   ";
-                Log((" %s%016lx", prefix, pThis->pu64RirbBuf[i + j]));
-            } while (++j < 8);
-            Log(("\n"));
-            i += 8;
-        } while (i != 0);
-#endif
-    }
-    return rc;
-}
-
-static int hdaCORBCmdProcess(PHDASTATE pThis)
-{
-    int rc;
-    uint8_t corbRp;
-    uint8_t corbWp;
-    uint8_t rirbWp;
-
-    PFNHDACODECVERBPROCESSOR pfn = (PFNHDACODECVERBPROCESSOR)NULL;
-
-    rc = hdaCmdSync(pThis, true);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, rc);
-    corbRp = CORBRP(pThis);
-    corbWp = CORBWP(pThis);
-    rirbWp = RIRBWP(pThis);
-    Assert((corbWp != corbRp));
-    Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pThis), CORBWP(pThis), RIRBWP(pThis)));
-    while (corbRp != corbWp)
-    {
-        uint32_t cmd;
-        uint64_t resp;
-        pfn = NULL;
-        corbRp++;
-        cmd = pThis->pu32CorbBuf[corbRp];
-        rc = pThis->Codec.pfnLookup(&pThis->Codec, cmd, &pfn);
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-        Assert(pfn);
-        (rirbWp)++;
-
-        if (RT_LIKELY(pfn))
-            rc = pfn(&pThis->Codec, cmd, &resp);
-        else
-            rc = VERR_INVALID_FUNCTION;
-
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-        Log(("hda: verb:%08x->%016lx\n", cmd, resp));
-        if (   (resp & CODEC_RESPONSE_UNSOLICITED)
-            && !HDA_REG_FLAG_VALUE(pThis, GCTL, UR))
-        {
-            Log(("hda: unexpected unsolicited response.\n"));
-            pThis->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
-            return rc;
-        }
-        pThis->pu64RirbBuf[rirbWp] = resp;
-        pThis->u8Counter++;
-        if (pThis->u8Counter == RINTCNT_N(pThis))
-            break;
-    }
-    pThis->au32Regs[ICH6_HDA_REG_CORBRP] = corbRp;
-    pThis->au32Regs[ICH6_HDA_REG_RIRBWP] = rirbWp;
-    rc = hdaCmdSync(pThis, false);
-    Log(("hda: CORB(RP:%x, WP:%x) RIRBWP:%x\n", CORBRP(pThis), CORBWP(pThis), RIRBWP(pThis)));
-    if (RIRBCTL_RIRB_RIC(pThis))
-    {
-        RIRBSTS((pThis)) |= HDA_REG_FIELD_FLAG_MASK(RIRBSTS,RINTFL);
-        pThis->u8Counter = 0;
-        rc = hdaProcessInterrupt(pThis);
-    }
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, rc);
-    return rc;
-}
-
-static void hdaStreamReset(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm)
-{
-    Log(("hda: reset of stream (%d) started\n", u8Strm));
-    Assert((   pThis
-            && pBdle
-            && pStreamDesc
-            && u8Strm <= 7));
-    memset(pBdle, 0, sizeof(HDABDLEDESC));
-    *pStreamDesc->pu32Lpib = 0;
-    *pStreamDesc->pu32Sts = 0;
-    /* According to the ICH6 datasheet, 0x40000 is the default value for stream descriptor register 23:20
-     * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */
-    HDA_STREAM_REG2(pThis, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG2(pThis, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
-
-    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
-    HDA_STREAM_REG2(pThis, FIFOS, u8Strm) =  u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
-    HDA_STREAM_REG2(pThis, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B;
-    HDA_STREAM_REG2(pThis, CBL, u8Strm) = 0;
-    HDA_STREAM_REG2(pThis, LVI, u8Strm) = 0;
-    HDA_STREAM_REG2(pThis, FMT, u8Strm) = 0;
-    HDA_STREAM_REG2(pThis, BDPU, u8Strm) = 0;
-    HDA_STREAM_REG2(pThis, BDPL, u8Strm) = 0;
-    Log(("hda: reset of stream (%d) finished\n", u8Strm));
-}
-
-
-/* Register access handlers. */
-
-static int hdaRegReadUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    *pu32Value = 0;
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteUnimplemented(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    return VINF_SUCCESS;
-}
-
-/* U8 */
-static int hdaRegReadU8(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffffff00) == 0);
-    return hdaRegReadU32(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteU8(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    Assert((u32Value & 0xffffff00) == 0);
-    return hdaRegWriteU32(pThis, iReg, u32Value);
-}
-
-/* U16 */
-static int hdaRegReadU16(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xffff0000) == 0);
-    return hdaRegReadU32(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteU16(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    Assert((u32Value & 0xffff0000) == 0);
-    return hdaRegWriteU32(pThis, iReg, u32Value);
-}
-
-/* U24 */
-static int hdaRegReadU24(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    Assert(((pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable) & 0xff000000) == 0);
-    return hdaRegReadU32(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteU24(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    Assert((u32Value & 0xff000000) == 0);
-    return hdaRegWriteU32(pThis, iReg, u32Value);
-}
-
-/* U32 */
-static int hdaRegReadU32(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    *pu32Value = pThis->au32Regs[iReg] & g_aHdaRegMap[iReg].readable;
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteU32(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    pThis->au32Regs[iReg]  = (u32Value & g_aHdaRegMap[iReg].writable)
-                           | (pThis->au32Regs[iReg] & ~g_aHdaRegMap[iReg].writable);
-    return VINF_SUCCESS;
-}
-
-static int hdaRegReadGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    return hdaRegReadU32(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteGCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, RST))
-    {
-        /* exit reset state */
-        GCTL(pThis) |= HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
-        pThis->fInReset = false;
-    }
-    else
-    {
-        /* enter reset state*/
-        if (   HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA)
-            || HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA))
-        {
-            Log(("hda: HDA enters in reset with DMA(RIRB:%s, CORB:%s)\n",
-                HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) ? "on" : "off",
-                HDA_REG_FLAG_VALUE(pThis, RIRBCTL, DMA) ? "on" : "off"));
-        }
-        hdaReset(pThis->pDevIns);
-        GCTL(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(GCTL, RST);
-        pThis->fInReset = true;
-    }
-    if (u32Value & HDA_REG_FIELD_FLAG_MASK(GCTL, FSH))
-    {
-        /* Flush: GSTS:1 set,  see 6.2.6*/
-        GSTS(pThis) |= HDA_REG_FIELD_FLAG_MASK(GSTS, FSH); /* set the flush state */
-        /* DPLBASE and DPUBASE should be initialized with initial value (see 6.2.6)*/
-    }
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteSTATESTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    uint32_t v = pThis->au32Regs[iReg];
-    uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
-    pThis->au32Regs[iReg] &= ~(v & nv); /* write of 1 clears corresponding bit */
-    return VINF_SUCCESS;
-}
-
-static int hdaRegReadINTSTS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    uint32_t v = 0;
-    if (   RIRBSTS_RIRBOIS(pThis)
-        || RIRBSTS_RINTFL(pThis)
-        || HDA_REG_FLAG_VALUE(pThis, CORBSTS, CMEI)
-        || STATESTS(pThis))
-        v |= RT_BIT(30);
-#define HDA_IS_STREAM_EVENT(pThis, stream)             \
-       (   (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE))  \
-        || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE))  \
-        || (SDSTS((pThis),stream) & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)))
-#define MARK_STREAM(pThis, stream, v) do { (v) |= HDA_IS_STREAM_EVENT((pThis),stream) ? RT_BIT((stream)) : 0; } while(0)
-    MARK_STREAM(pThis, 0, v);
-    MARK_STREAM(pThis, 1, v);
-    MARK_STREAM(pThis, 2, v);
-    MARK_STREAM(pThis, 3, v);
-    MARK_STREAM(pThis, 4, v);
-    MARK_STREAM(pThis, 5, v);
-    MARK_STREAM(pThis, 6, v);
-    MARK_STREAM(pThis, 7, v);
-    v |= v ? RT_BIT(31) : 0;
-    *pu32Value = v;
-    return VINF_SUCCESS;
-}
-
-static int hdaRegReadWALCLK(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    /* HDA spec (1a): 3.3.16 WALCLK counter ticks with 24Mhz bitclock rate. */
-    *pu32Value = (uint32_t)ASMMultU64ByU32DivByU32(PDMDevHlpTMTimeVirtGetNano(pThis->pDevIns)
-                                                   - pThis->u64BaseTS, 24, 1000);
-    return VINF_SUCCESS;
-}
-
-static int hdaRegReadGCAP(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    return hdaRegReadU16(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteCORBRP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    if (u32Value & HDA_REG_FIELD_FLAG_MASK(CORBRP, RST))
-        CORBRP(pThis) = 0;
-#ifndef BIRD_THINKS_CORBRP_IS_MOSTLY_RO
-    else
-        return hdaRegWriteU8(pThis, iReg, u32Value);
-#endif
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteCORBCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc = hdaRegWriteU8(pThis, iReg, u32Value);
-    AssertRC(rc);
-    if (   CORBWP(pThis) != CORBRP(pThis)
-        && HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA) != 0)
-        return hdaCORBCmdProcess(pThis);
-    return rc;
-}
-
-static int hdaRegWriteCORBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    uint32_t v = CORBSTS(pThis);
-    CORBSTS(pThis) &= ~(v & u32Value);
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteCORBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc;
-    rc = hdaRegWriteU16(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, rc);
-    if (CORBWP(pThis) == CORBRP(pThis))
-        return VINF_SUCCESS;
-    if (!HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
-        return VINF_SUCCESS;
-    rc = hdaCORBCmdProcess(pThis);
-    return rc;
-}
-
-static int hdaRegReadSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    return hdaRegReadU24(pThis, iReg, pu32Value);
-}
-
-static int hdaRegWriteSDCTL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    bool fRun     = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-    bool fInRun   = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-    bool fReset   = RT_BOOL(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
-    bool fInReset = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
-    int rc = VINF_SUCCESS;
-    if (fInReset)
-    {
-        /* Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit
-         * from reset
-         */
-        Assert((!fReset));
-        Log(("hda: guest initiated exit of stream reset.\n"));
-        goto l_done;
-    }
-    else if (fReset)
-    {
-        /*
-         * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset.
-         */
-        uint8_t u8Strm = 0;
-        PHDABDLEDESC pBdle = NULL;
-        HDASTREAMTRANSFERDESC StreamDesc;
-        Assert((!fInRun && !fRun));
-        switch (iReg)
-        {
-            case ICH6_HDA_REG_SD0CTL:
-                u8Strm = 0;
-                pBdle = &pThis->StInBdle;
-                break;
-            case ICH6_HDA_REG_SD4CTL:
-                u8Strm = 4;
-                pBdle = &pThis->StOutBdle;
-                break;
-            default:
-                Log(("hda: changing SRST bit on non-attached stream\n"));
-                goto l_done;
-        }
-        Log(("hda: guest initiated enter to stream reset.\n"));
-        hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
-        hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
-        goto l_done;
-    }
-
-    /* we enter here to change DMA states only */
-    if (   (fInRun && !fRun)
-        || (fRun && !fInRun))
-    {
-        Assert((!fReset && !fInReset));
-        switch (iReg)
-        {
-            case ICH6_HDA_REG_SD0CTL:
-                AUD_set_active_in(pThis->Codec.SwVoiceIn, fRun);
-                break;
-            case ICH6_HDA_REG_SD4CTL:
-                AUD_set_active_out(pThis->Codec.SwVoiceOut, fRun);
-                break;
-            default:
-                Log(("hda: changing RUN bit on non-attached stream\n"));
-                goto l_done;
-        }
-    }
-
-l_done:
-    rc = hdaRegWriteU24(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, VINF_SUCCESS);
-    return rc;
-}
-
-static int hdaRegWriteSDSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    uint32_t v = HDA_REG_IND(pThis, iReg);
-    v &= ~(u32Value & v);
-    HDA_REG_IND(pThis, iReg) = v;
-    hdaProcessInterrupt(pThis);
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteSDLVI(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, VINF_SUCCESS);
-    return rc;
-}
-
-static int hdaRegWriteSDFIFOW(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    switch (u32Value)
-    {
-        case HDA_SDFIFOW_8B:
-        case HDA_SDFIFOW_16B:
-        case HDA_SDFIFOW_32B:
-            return hdaRegWriteU16(pThis, iReg, u32Value);
-        default:
-            Log(("hda: Attempt to store unsupported value(%x) in SDFIFOW\n", u32Value));
-            return hdaRegWriteU16(pThis, iReg, HDA_SDFIFOW_32B);
-    }
-    return VINF_SUCCESS;
-}
-
-/**
- * @note This method could be called for changing value on Output Streams
- *       only (ICH6 datasheet 18.2.39)
- */
-static int hdaRegWriteSDFIFOS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    switch (iReg)
-    {
-        /* SDInFIFOS is RO, n=0-3 */
-        case ICH6_HDA_REG_SD0FIFOS:
-        case ICH6_HDA_REG_SD1FIFOS:
-        case ICH6_HDA_REG_SD2FIFOS:
-        case ICH6_HDA_REG_SD3FIFOS:
-            Log(("hda: Guest tries change value of FIFO size of Input Stream\n"));
-            return VINF_SUCCESS;
-        case ICH6_HDA_REG_SD4FIFOS:
-        case ICH6_HDA_REG_SD5FIFOS:
-        case ICH6_HDA_REG_SD6FIFOS:
-        case ICH6_HDA_REG_SD7FIFOS:
-            switch(u32Value)
-            {
-                case HDA_SDONFIFO_16B:
-                case HDA_SDONFIFO_32B:
-                case HDA_SDONFIFO_64B:
-                case HDA_SDONFIFO_128B:
-                case HDA_SDONFIFO_192B:
-                    return hdaRegWriteU16(pThis, iReg, u32Value);
-
-                case HDA_SDONFIFO_256B:
-                    Log(("hda: 256-bit is unsupported, HDA is switched into 192-bit mode\n"));
-                default:
-                    return hdaRegWriteU16(pThis, iReg, HDA_SDONFIFO_192B);
-            }
-            return VINF_SUCCESS;
-        default:
-            AssertMsgFailed(("Something weird happened with register lookup routine"));
-    }
-    return VINF_SUCCESS;
-}
-
-static void hdaSdFmtToAudSettings(uint32_t u32SdFmt, audsettings_t *pAudSetting)
-{
-    Assert((pAudSetting));
-#define EXTRACT_VALUE(v, mask, shift) ((v & ((mask) << (shift))) >> (shift))
-    uint32_t u32Hz = (u32SdFmt & ICH6_HDA_SDFMT_BASE_RATE_SHIFT) ? 44100 : 48000;
-    uint32_t u32HzMult = 1;
-    uint32_t u32HzDiv = 1;
-    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_MULT_MASK, ICH6_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:
-            Log(("hda: unsupported multiplier %x\n", u32SdFmt));
-    }
-    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_DIV_MASK, ICH6_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;
-    }
-    pAudSetting->freq = u32Hz * u32HzMult / u32HzDiv;
-
-    switch (EXTRACT_VALUE(u32SdFmt, ICH6_HDA_SDFMT_BITS_MASK, ICH6_HDA_SDFMT_BITS_SHIFT))
-    {
-        case 0:
-            Log(("hda: %s requested 8-bit\n", __FUNCTION__));
-            pAudSetting->fmt = AUD_FMT_S8;
-            break;
-        case 1:
-            Log(("hda: %s requested 16-bit\n", __FUNCTION__));
-            pAudSetting->fmt = AUD_FMT_S16;
-            break;
-        case 2:
-            Log(("hda: %s requested 20-bit\n", __FUNCTION__));
-            break;
-        case 3:
-            Log(("hda: %s requested 24-bit\n", __FUNCTION__));
-            break;
-        case 4:
-            Log(("hda: %s requested 32-bit\n", __FUNCTION__));
-            pAudSetting->fmt = AUD_FMT_S32;
-            break;
-        default:
-            AssertMsgFailed(("Unsupported"));
-    }
-    pAudSetting->nchannels = (u32SdFmt & 0xf) + 1;
-    pAudSetting->fmt = AUD_FMT_S16;
-    pAudSetting->endianness = 0;
-#undef EXTRACT_VALUE
-}
-
-static int hdaRegWriteSDFMT(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-#ifdef VBOX_WITH_HDA_CODEC_EMU
-    /** @todo a bit more investigation is required here. */
-    int rc = 0;
-    audsettings_t as;
-    /* no reason to reopen voice with same settings */
-    if (u32Value == HDA_REG_IND(pThis, iReg))
-        return VINF_SUCCESS;
-    hdaSdFmtToAudSettings(u32Value, &as);
-    switch (iReg)
-    {
-        case ICH6_HDA_REG_SD0FMT:
-            rc = hdaCodecOpenVoice(&pThis->Codec, PI_INDEX, &as);
-            break;
-        case ICH6_HDA_REG_SD4FMT:
-            rc = hdaCodecOpenVoice(&pThis->Codec, PO_INDEX, &as);
-            break;
-        default:
-            Log(("HDA: attempt to change format on %d\n", iReg));
-            rc = 0;
-    }
-    return hdaRegWriteU16(pThis, iReg, u32Value);
-#else
-    return hdaRegWriteU16(pThis, iReg, u32Value);
-#endif
-}
-
-static int hdaRegWriteSDBDPL(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, VINF_SUCCESS);
-    return rc;
-}
-
-static int hdaRegWriteSDBDPU(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, VINF_SUCCESS);
-    return rc;
-}
-
-static int hdaRegReadIRS(PHDASTATE pThis, uint32_t iReg, uint32_t *pu32Value)
-{
-    int rc = VINF_SUCCESS;
-    /* regarding 3.4.3 we should mark IRS as busy in case CORB is active */
-    if (   CORBWP(pThis) != CORBRP(pThis)
-        || HDA_REG_FLAG_VALUE(pThis, CORBCTL, DMA))
-        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB);  /* busy */
-
-    rc = hdaRegReadU32(pThis, iReg, pu32Value);
-    return rc;
-}
-
-static int hdaRegWriteIRS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int                         rc  = VINF_SUCCESS;
-    PFNHDACODECVERBPROCESSOR    pfn = NULL;
-    uint64_t                    resp;
-
-    /*
-     * if guest set the ICB bit of IRS register, HDA should process the verb in IC register,
-     * write the response to IR register, and set the IRV (valid in case of success) bit of IRS register.
-     */
-    if (   u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, ICB)
-        && !IRS_ICB(pThis))
-    {
-        uint32_t cmd = IC(pThis);
-        if (CORBWP(pThis) != CORBRP(pThis))
-        {
-            /*
-             * 3.4.3 defines behavior of immediate Command status register.
-             */
-            LogRel(("hda: guest attempted process immediate verb (%x) with active CORB\n", cmd));
-            return rc;
-        }
-        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, ICB);  /* busy */
-        Log(("hda: IC:%x\n", cmd));
-        rc = pThis->Codec.pfnLookup(&pThis->Codec, cmd, &pfn);
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-        rc = pfn(&pThis->Codec, cmd, &resp);
-        if (RT_FAILURE(rc))
-            AssertRCReturn(rc, rc);
-        IR(pThis) = (uint32_t)resp;
-        Log(("hda: IR:%x\n", IR(pThis)));
-        IRS(pThis) = HDA_REG_FIELD_FLAG_MASK(IRS, IRV);  /* result is ready  */
-        IRS(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, ICB); /* busy is clear */
-        return rc;
-    }
-    /*
-     * Once the guest read the response, it should clean the IRV bit of the IRS register.
-     */
-    if (   u32Value & HDA_REG_FIELD_FLAG_MASK(IRS, IRV)
-        && IRS_IRV(pThis))
-        IRS(pThis) &= ~HDA_REG_FIELD_FLAG_MASK(IRS, IRV);
-    return rc;
-}
-
-static int hdaRegWriteRIRBWP(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    if (u32Value & HDA_REG_FIELD_FLAG_MASK(RIRBWP, RST))
-    {
-        RIRBWP(pThis) = 0;
-    }
-    /* The remaining bits are O, see 6.2.22 */
-    return VINF_SUCCESS;
-}
-
-static int hdaRegWriteBase(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    int rc = hdaRegWriteU32(pThis, iReg, u32Value);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, rc);
-    switch(iReg)
-    {
-        case ICH6_HDA_REG_CORBLBASE:
-            pThis->u64CORBBase &= UINT64_C(0xFFFFFFFF00000000);
-            pThis->u64CORBBase |= pThis->au32Regs[iReg];
-            break;
-        case ICH6_HDA_REG_CORBUBASE:
-            pThis->u64CORBBase &= UINT64_C(0x00000000FFFFFFFF);
-            pThis->u64CORBBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
-            break;
-        case ICH6_HDA_REG_RIRLBASE:
-            pThis->u64RIRBBase &= UINT64_C(0xFFFFFFFF00000000);
-            pThis->u64RIRBBase |= pThis->au32Regs[iReg];
-            break;
-        case ICH6_HDA_REG_RIRUBASE:
-            pThis->u64RIRBBase &= UINT64_C(0x00000000FFFFFFFF);
-            pThis->u64RIRBBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
-            break;
-        case ICH6_HDA_REG_DPLBASE:
-            /** @todo: first bit has special meaning */
-            pThis->u64DPBase &= UINT64_C(0xFFFFFFFF00000000);
-            pThis->u64DPBase |= pThis->au32Regs[iReg];
-            break;
-        case ICH6_HDA_REG_DPUBASE:
-            pThis->u64DPBase &= UINT64_C(0x00000000FFFFFFFF);
-            pThis->u64DPBase |= ((uint64_t)pThis->au32Regs[iReg] << 32);
-            break;
-        default:
-            AssertMsgFailed(("Invalid index"));
-    }
-    Log(("hda: CORB base:%llx RIRB base: %llx DP base: %llx\n", pThis->u64CORBBase, pThis->u64RIRBBase, pThis->u64DPBase));
-    return rc;
-}
-
-static int hdaRegWriteRIRBSTS(PHDASTATE pThis, uint32_t iReg, uint32_t u32Value)
-{
-    uint8_t v = RIRBSTS(pThis);
-    RIRBSTS(pThis) &= ~(v & u32Value);
-
-    return hdaProcessInterrupt(pThis);
-}
-
-#ifdef LOG_ENABLED
-static void dump_bd(PHDASTATE pThis, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
-{
-#if 0
-    uint64_t addr;
-    uint32_t len;
-    uint32_t ioc;
-    uint8_t  bdle[16];
-    uint32_t counter;
-    uint32_t i;
-    uint32_t sum = 0;
-    Assert(pBdle && pBdle->u32BdleMaxCvi);
-    for (i = 0; i <= pBdle->u32BdleMaxCvi; ++i)
-    {
-        PDMDevHlpPhysRead(pThis->pDevIns, u64BaseDMA + i*16, bdle, 16);
-        addr = *(uint64_t *)bdle;
-        len = *(uint32_t *)&bdle[8];
-        ioc = *(uint32_t *)&bdle[12];
-        Log(("hda: %s bdle[%d] a:%llx, len:%d, ioc:%d\n",  (i == pBdle->u32BdleCvi? "[C]": "   "), i, addr, len, ioc & 0x1));
-        sum += len;
-    }
-    Log(("hda: sum: %d\n", sum));
-    for (i = 0; i < 8; ++i)
-    {
-        PDMDevHlpPhysRead(pThis->pDevIns, (pThis->u64DPBase & DPBASE_ADDR_MASK) + i*8, &counter, sizeof(&counter));
-        Log(("hda: %s stream[%d] counter=%x\n", i == SDCTL_NUM(pThis, 4) || i == SDCTL_NUM(pThis, 0)? "[C]": "   ",
-             i , counter));
-    }
-#endif
-}
-#endif
-
-static void hdaFetchBdle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-    uint8_t  bdle[16];
-    Assert((   pStreamDesc->u64BaseDMA
-            && pBdle
-            && pBdle->u32BdleMaxCvi));
-    PDMDevHlpPhysRead(pThis->pDevIns, pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
-    pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
-    pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
-    pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
-#ifdef LOG_ENABLED
-    dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
-#endif
-}
-
-DECLINLINE(uint32_t) hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
-                                                      uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit)
-{
-    uint32_t cb2Copy;
-    /*
-     * Number of bytes depends on the current position in buffer (u32BdleCviLen-u32BdleCviPos)
-     */
-    Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos)); /* sanity */
-    cb2Copy = pBdle->u32BdleCviLen - pBdle->u32BdleCviPos;
-    /*
-     * we may increase the counter in range of [0, FIFOS + 1]
-     */
-    cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1);
-    Assert((u32SoundBackendBufferBytesAvail > 0));
-
-    /* sanity check to avoid overriding the backend audio buffer */
-    cb2Copy = RT_MIN(cb2Copy, u32SoundBackendBufferBytesAvail);
-    cb2Copy = RT_MIN(cb2Copy, u32CblLimit);
-
-    if (cb2Copy <= pBdle->cbUnderFifoW)
-        return 0;
-    cb2Copy -= pBdle->cbUnderFifoW; /* forcibly reserve the amount of unreported bytes to copy */
-    return cb2Copy;
-}
-
-DECLINLINE(void) hdaBackendWriteTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
-                                                 uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
-{
-    Log(("hda:hdaBackendWriteTransferReported: cbArranged2Copy: %d, cbCopied: %d, pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
-        cbArranged2Copy, cbCopied, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
-    Assert((cbCopied));
-    Assert((pu32BackendBufferCapacity && *pu32BackendBufferCapacity));
-    /* Assertion!!! Fewer than cbUnderFifoW bytes were copied.
-     * Probably we need to move the buffer, but it is rather hard to imagine a situation
-     * where it might happen.
-     */
-    Assert((cbCopied == pBdle->cbUnderFifoW + cbArranged2Copy)); /* we assume that we write the entire buffer including unreported bytes */
-    if (   pBdle->cbUnderFifoW
-        && pBdle->cbUnderFifoW <= cbCopied)
-        Log(("hda:hdaBackendWriteTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-
-    pBdle->cbUnderFifoW -= RT_MIN(pBdle->cbUnderFifoW, cbCopied);
-    Assert((!pBdle->cbUnderFifoW)); /* Assert!!! Incorrect assumption */
-
-    /* We always increment the position of DMA buffer counter because we're always reading into an intermediate buffer */
-    pBdle->u32BdleCviPos += cbArranged2Copy;
-
-    Assert((pBdle->u32BdleCviLen >= pBdle->u32BdleCviPos && *pu32BackendBufferCapacity >= cbCopied)); /* sanity */
-    /* We report all bytes (including previously unreported bytes) */
-    *pu32DMACursor += cbCopied;
-    /* Decrease the backend counter by the number of bytes we copied to the backend */
-    *pu32BackendBufferCapacity -= cbCopied;
-    Log(("hda:hdaBackendWriteTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
-        pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, *pu32DMACursor, *pu32BackendBufferCapacity));
-}
-
-DECLINLINE(void) hdaBackendReadTransferReported(PHDABDLEDESC pBdle, uint32_t cbArranged2Copy, uint32_t cbCopied,
-                                                uint32_t *pu32DMACursor, uint32_t *pu32BackendBufferCapacity)
-{
-    Assert((cbCopied, cbArranged2Copy));
-    *pu32BackendBufferCapacity -= cbCopied;
-    pBdle->u32BdleCviPos += cbCopied;
-    Log(("hda:hdaBackendReadTransferReported: CVI resetting cbUnderFifoW:%d(pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-    *pu32DMACursor += cbCopied + pBdle->cbUnderFifoW;
-    pBdle->cbUnderFifoW = 0;
-    Log(("hda:hdaBackendReadTransferReported: CVI(pos:%d, len:%d), pu32DMACursor: %d, pu32BackendBufferCapacity:%d\n",
-        pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, pu32DMACursor ? *pu32DMACursor : 0, pu32BackendBufferCapacity ? *pu32BackendBufferCapacity : 0));
-}
-
-DECLINLINE(void) hdaBackendTransferUnreported(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
-                                              uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
-{
-    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-    pBdle->u32BdleCviPos += cbCopied;
-    pBdle->cbUnderFifoW += cbCopied;
-    /* In case of a read transaction we're always copying from the backend buffer */
-    if (pu32BackendBufferCapacity)
-        *pu32BackendBufferCapacity -= cbCopied;
-    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-    Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pThis, pStreamDesc)));
-}
-
-DECLINLINE(bool) hdaIsTransferCountersOverlapped(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-    bool fOnBufferEdge = (   *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl
-                          || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen);
-
-    Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
-
-    if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
-        *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl;
-    hdaUpdatePosBuf(pThis, pStreamDesc);
-
-    /* don't touch BdleCvi counter on uninitialized descriptor */
-    if (   pBdle->u32BdleCviPos
-        && pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
-    {
-        pBdle->u32BdleCviPos = 0;
-        pBdle->u32BdleCvi++;
-        if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
-            pBdle->u32BdleCvi = 0;
-    }
-    return fOnBufferEdge;
-}
-
-DECLINLINE(void) hdaStreamCounterUpdate(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc,
-                                        uint32_t cbInc)
-{
-    /*
-     * if we're below the FIFO Watermark, it's expected that HDA doesn't fetch anything.
-     * (ICH6 datasheet 18.2.38)
-     */
-    if (!pBdle->cbUnderFifoW)
-    {
-        *pStreamDesc->pu32Lpib += cbInc;
-
-        /*
-         * Assert. The buffer counters should never overlap.
-         */
-        Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
-
-        hdaUpdatePosBuf(pThis, pStreamDesc);
-
-    }
-}
-
-static bool hdaDoNextTransferCycle(PHDASTATE pThis, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-    bool fDoNextTransferLoop = true;
-    if (   pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
-        || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
-    {
-        if (    !pBdle->cbUnderFifoW
-             && pBdle->fBdleCviIoc)
-        {
-            /**
-             * @todo - more carefully investigate BCIS flag.
-             * Speech synthesis works fine on Mac Guest if this bit isn't set
-             * but in general sound quality gets worse.
-             */
-            *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
-
-            /*
-             * we should generate the interrupt if ICE bit of SDCTL register is set.
-             */
-            if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
-                hdaProcessInterrupt(pThis);
-        }
-        fDoNextTransferLoop = false;
-    }
-    return fDoNextTransferLoop;
-}
-
-/*
- * hdaReadAudio - copies samples from audio backend to DMA.
- * Note: this function writes to the DMA buffer immediately, but "reports bytes" when all conditions are met (FIFOW)
- */
-static uint32_t hdaReadAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
-{
-    PHDABDLEDESC pBdle = &pThis->StInBdle;
-    uint32_t cbTransferred = 0;
-    uint32_t cb2Copy = 0;
-    uint32_t cbBackendCopy = 0;
-
-    Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-
-    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
-    if (!cb2Copy)
-    {
-        /* if we enter here we can't report "unreported bits" */
-        *fStop = true;
-        goto l_done;
-    }
-
-
-    /*
-     * read from backend input line to the last unreported position or at the begining.
-     */
-    cbBackendCopy = AUD_read(pThis->Codec.SwVoiceIn, pBdle->au8HdaBuffer, cb2Copy);
-    /*
-     * write the HDA DMA buffer
-     */
-    PDMDevHlpPhysWrite(pThis->pDevIns, pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer, cbBackendCopy);
-
-    /* Don't see any reason why cb2Copy would differ from cbBackendCopy */
-    Assert((cbBackendCopy == cb2Copy && (*pu32Avail) >= cb2Copy)); /* sanity */
-
-    if (pBdle->cbUnderFifoW + cbBackendCopy > hdaFifoWToSz(pThis, 0))
-        hdaBackendReadTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransferred, pu32Avail);
-    else
-    {
-        hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cbBackendCopy, pu32Avail);
-        *fStop = true;
-    }
-l_done:
-    Assert((cbTransferred <= (SDFIFOS(pThis, 0) + 1)));
-    Log(("hda:ra: CVI(pos:%d, len:%d) cbTransferred: %d\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred));
-    return cbTransferred;
-}
-
-static uint32_t hdaWriteAudio(PHDASTATE pThis, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
-{
-    PHDABDLEDESC pBdle = &pThis->StOutBdle;
-    uint32_t cbTransferred = 0;
-    uint32_t cb2Copy = 0; /* local byte counter (on local buffer) */
-    uint32_t cbBackendCopy = 0; /* local byte counter, how many bytes copied to backend */
-
-    Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
-
-    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
-
-    /*
-     * Copy from DMA to the corresponding hdaBuffer (if there are any bytes from the
-     * previous unreported transfer we write at offset 'pBdle->cbUnderFifoW').
-     */
-    if (!cb2Copy)
-    {
-        *fStop = true;
-        goto l_done;
-    }
-
-    PDMDevHlpPhysRead(pThis->pDevIns, pBdle->u64BdleCviAddr + pBdle->u32BdleCviPos, pBdle->au8HdaBuffer + pBdle->cbUnderFifoW, cb2Copy);
-    /*
-     * Write to audio backend. we should ensure that we have enough bytes to copy to the backend.
-     */
-    if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pThis, pStreamDesc))
-    {
-        /*
-         * Feed the newly fetched samples, including unreported ones, to the backend.
-         */
-        cbBackendCopy = AUD_write (pThis->Codec.SwVoiceOut, pBdle->au8HdaBuffer, cb2Copy + pBdle->cbUnderFifoW);
-        hdaBackendWriteTransferReported(pBdle, cb2Copy, cbBackendCopy, &cbTransferred, pu32Avail);
-    }
-    else
-    {
-        /* Not enough bytes to be processed and reported, we'll try our luck next time around */
-        hdaBackendTransferUnreported(pThis, pBdle, pStreamDesc, cb2Copy, NULL);
-        *fStop = true;
-    }
-
-l_done:
-    Assert(cbTransferred <= SDFIFOS(pThis, 4) + 1);
-    Log(("hda:wa: CVI(pos:%d, len:%d, cbTransferred:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen, cbTransferred));
-    return cbTransferred;
-}
-
-/**
- * @interface_method_impl{HDACODEC,pfnReset}
- */
-DECLCALLBACK(int) hdaCodecReset(PHDACODEC pCodec)
-{
-    PHDASTATE pThis = (PHDASTATE)pCodec->pvHDAState;
-    NOREF(pThis);
-    return VINF_SUCCESS;
-}
-
-DECLINLINE(void) hdaInitTransferDescriptor(PHDASTATE pThis, PHDABDLEDESC pBdle, uint8_t u8Strm,
-                                           PHDASTREAMTRANSFERDESC pStreamDesc)
-{
-    Assert(pThis); Assert(pBdle); Assert(pStreamDesc); Assert(u8Strm <= 7);
-
-    memset(pStreamDesc, 0, sizeof(HDASTREAMTRANSFERDESC));
-    pStreamDesc->u8Strm     = u8Strm;
-    pStreamDesc->u32Ctl     = HDA_STREAM_REG2(pThis, CTL, u8Strm);
-    pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG2(pThis, BDPL, u8Strm),
-                                          HDA_STREAM_REG2(pThis, BDPU, u8Strm));
-    pStreamDesc->pu32Lpib   = &HDA_STREAM_REG2(pThis, LPIB, u8Strm);
-    pStreamDesc->pu32Sts    = &HDA_STREAM_REG2(pThis, STS, u8Strm);
-    pStreamDesc->u32Cbl     = HDA_STREAM_REG2(pThis, CBL, u8Strm);
-    pStreamDesc->u32Fifos   = HDA_STREAM_REG2(pThis, FIFOS, u8Strm);
-
-    pBdle->u32BdleMaxCvi    = HDA_STREAM_REG2(pThis, LVI, u8Strm);
-
-#ifdef LOG_ENABLED
-    if (   pBdle
-        && pBdle->u32BdleMaxCvi)
-    {
-        Log(("Initialization of transfer descriptor:\n"));
-        dump_bd(pThis, pBdle, pStreamDesc->u64BaseDMA);
-    }
-#endif
-}
-
-
-/**
- * @interface_method_impl{HDACODEC,pfnTransfer}
- */
-static DECLCALLBACK(void) hdaTransfer(PHDACODEC pCodec, ENMSOUNDSOURCE src, int avail)
-{
-    PHDASTATE       pThis  = (PHDASTATE)pCodec->pvHDAState;
-    uint8_t         u8Strm = 0;
-    PHDABDLEDESC    pBdle  = NULL;
-
-    switch (src)
-    {
-        case PO_INDEX:
-        {
-            u8Strm = 4;
-            pBdle = &pThis->StOutBdle;
-            break;
-        }
-        case PI_INDEX:
-        {
-            u8Strm = 0;
-            pBdle = &pThis->StInBdle;
-            break;
-        }
-        default:
-            return;
-    }
-
-    HDASTREAMTRANSFERDESC StreamDesc;
-    hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
-
-    bool fStop = false;
-    while (avail && !fStop)
-    {
-        Assert(   (StreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
-               && avail
-               && StreamDesc.u64BaseDMA);
-
-        /* Fetch the Buffer Descriptor Entry (BDE). */
-
-        if (hdaIsTransferCountersOverlapped(pThis, pBdle, &StreamDesc))
-            hdaFetchBdle(pThis, pBdle, &StreamDesc);
-        *StreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
-        Assert((avail >= 0 && (StreamDesc.u32Cbl >= (*StreamDesc.pu32Lpib)))); /* sanity */
-        uint32_t u32CblLimit = StreamDesc.u32Cbl - (*StreamDesc.pu32Lpib);
-        Assert((u32CblLimit > hdaFifoWToSz(pThis, &StreamDesc)));
-        Log(("hda: CBL=%d, LPIB=%d\n", StreamDesc.u32Cbl, *StreamDesc.pu32Lpib));
-        uint32_t cb;
-        switch (src)
-        {
-            case PO_INDEX:
-                cb = hdaWriteAudio(pThis, &StreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
-                break;
-            case PI_INDEX:
-                cb = hdaReadAudio(pThis, &StreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
-                break;
-            default:
-                cb = 0;
-                fStop = true;
-                AssertMsgFailed(("Unsupported"));
-        }
-        Assert(cb <= StreamDesc.u32Fifos + 1);
-        *StreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
-
-        /* Process end of buffer condition. */
-        hdaStreamCounterUpdate(pThis, pBdle, &StreamDesc, cb);
-        fStop = !fStop ? !hdaDoNextTransferCycle(pThis, pBdle, &StreamDesc) : fStop;
-    }
-}
-
-
-/* MMIO callbacks */
-
-/**
- * @callback_method_impl{FNIOMMMIOREAD, Looks up and calls the appropriate handler.}
- *
- * @note During implementation, we discovered so-called "forgotten" or "hole"
- *       registers whose description is not listed in the RPM, datasheet, or
- *       spec.
- */
-PDMBOTHCBDECL(int) hdaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
-{
-    PHDASTATE   pThis  = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    int         rc;
-
-    /*
-     * Look up and log.
-     */
-    uint32_t        offReg = GCPhysAddr - pThis->MMIOBaseAddr;
-    int             idxReg = hdaRegLookup(pThis, offReg);
-#ifdef LOG_ENABLED
-    unsigned const  cbLog     = cb;
-    uint32_t        offRegLog = offReg;
-#endif
-
-    Log(("hdaMMIORead: offReg=%#x cb=%#x\n", offReg, cb));
-#define NEW_READ_CODE
-#ifdef NEW_READ_CODE
-    Assert(cb == 4); Assert((offReg & 3) == 0);
-
-    if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL)
-        Log(("hda: access to registers except GCTL is blocked while reset\n"));
-
-    if (idxReg == -1)
-        LogRel(("hda: Invalid read access @0x%x(of bytes:%d)\n", offReg, cb));
-
-    if (idxReg != -1)
-    {
-        /* ASSUMES gapless DWORD at end of map. */
-        if (g_aHdaRegMap[idxReg].size == 4)
-        {
-            /*
-             * Straight forward DWORD access.
-             */
-            rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, (uint32_t *)pv);
-            Log(("hda: read %s => %x (%Rrc)\n", g_aHdaRegMap[idxReg].abbrev, *(uint32_t *)pv, rc));
-        }
-        else
-        {
-            /*
-             * Multi register read (unless there are trailing gaps).
-             * ASSUMES that only DWORD reads have sideeffects.
-             */
-            uint32_t u32Value = 0;
-            unsigned cbLeft   = 4;
-            do
-            {
-                uint32_t const  cbReg        = g_aHdaRegMap[idxReg].size;
-                uint32_t        u32Tmp       = 0;
-
-                rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Tmp);
-                Log(("hda: read %s[%db] => %x (%Rrc)*\n", g_aHdaRegMap[idxReg].abbrev, cbReg, *(uint32_t *)pv, rc));
-                if (rc != VINF_SUCCESS)
-                    break;
-                u32Value |= (u32Tmp & g_afMasks[cbReg]) << ((4 - cbLeft) * 8);
-
-                cbLeft -= cbReg;
-                offReg += cbReg;
-                idxReg++;
-            } while (cbLeft > 0 && g_aHdaRegMap[idxReg].offset == offReg);
-
-            if (rc == VINF_SUCCESS)
-                *(uint32_t *)pv = u32Value;
-            else
-                Assert(!IOM_SUCCESS(rc));
-        }
-    }
-    else
-    {
-        rc = VINF_IOM_MMIO_UNUSED_FF;
-        Log(("hda: hole at %x is accessed for read\n", offReg));
-    }
-#else
-    if (idxReg != -1)
-    {
-        /** @todo r=bird: Accesses crossing register boundraries aren't handled
-         *        right from what I can tell?  If they are, please explain
-         *        what the rules are. */
-        uint32_t mask = 0;
-        uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
-        uint32_t u32Value = 0;
-        switch(cb)
-        {
-            case 1: mask = 0x000000ff; break;
-            case 2: mask = 0x0000ffff; break;
-            case 4:
-            /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
-            case 8:
-                mask = 0xffffffff;
-                cb = 4;
-                break;
-        }
-#if 0
-        /* Cross-register access. Mac guest hits this assert doing assumption 4 byte access to 3 byte registers e.g. {I,O}SDnCTL
-         */
-        //Assert((cb <= g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset)));
-        if (cb > g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset))
-        {
-            int off = cb - (g_aHdaRegMap[idxReg].size - (offReg - g_aHdaRegMap[idxReg].offset));
-            rc = hdaMMIORead(pDevIns, pvUser, GCPhysAddr + cb - off, (char *)pv + cb - off, off);
-            if (RT_FAILURE(rc))
-                AssertRCReturn (rc, rc);
-        }
-        //Assert(((offReg - g_aHdaRegMap[idxReg].offset) == 0));
-#endif
-        mask <<= shift;
-        rc = g_aHdaRegMap[idxReg].pfnRead(pThis, idxReg, &u32Value);
-        *(uint32_t *)pv |= (u32Value & mask);
-        Log(("hda: read %s[%x/%x]\n", g_aHdaRegMap[idxReg].abbrev, u32Value, *(uint32_t *)pv));
-    }
-    else
-    {
-        *(uint32_t *)pv = 0xFF;
-        Log(("hda: hole at %x is accessed for read\n", offReg));
-        rc = VINF_SUCCESS;
-    }
-#endif
-
-    /*
-     * Log the outcome.
-     */
-#ifdef LOG_ENABLED
-    if (cbLog == 4)
-        Log(("hdaMMIORead: @%#05x -> %#010x %Rrc\n", offRegLog, *(uint32_t *)pv, rc));
-    else if (cbLog == 2)
-        Log(("hdaMMIORead: @%#05x -> %#06x %Rrc\n", offRegLog, *(uint16_t *)pv, rc));
-    else if (cbLog == 1)
-        Log(("hdaMMIORead: @%#05x -> %#04x %Rrc\n", offRegLog, *(uint8_t *)pv, rc));
-#endif
-    return rc;
-}
-
-
-DECLINLINE(int) hdaWriteReg(PHDASTATE pThis, int idxReg, uint32_t u32Value, char const *pszLog)
-{
-    if (pThis->fInReset && idxReg != ICH6_HDA_REG_GCTL)
-        Log(("hda: access to registers except GCTL is blocked while reset\n"));  /** @todo where is this enforced? */
-
-#ifdef LOG_ENABLED
-    uint32_t const u32CurValue = pThis->au32Regs[idxReg];
-#endif
-    int rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32Value);
-    Log(("hda: write %#x -> %s[%db]; %x => %x%s\n", u32Value, g_aHdaRegMap[idxReg].abbrev,
-         g_aHdaRegMap[idxReg].size, u32CurValue, pThis->au32Regs[idxReg], pszLog));
-    return rc;
-}
-
-
-/**
- * @callback_method_impl{FNIOMMMIOWRITE, Looks up and calls the appropriate handler.}
- */
-PDMBOTHCBDECL(int) hdaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
-{
-    PHDASTATE               pThis  = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    int                     rc;
-
-    /*
-     * The behavior of accesses that aren't aligned on natural boundraries is
-     * undefined. Just reject them out right.
-     */
-    /** @todo IOM could check this, it could also split the 8 byte accesses for us. */
-    Assert(cb == 1 || cb == 2 || cb == 4 || cb == 8);
-    if (GCPhysAddr & (cb - 1))
-        return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "misaligned write access: GCPhysAddr=%RGp cb=%u\n", GCPhysAddr, cb);
-
-    /*
-     * Lookup and log the access.
-     */
-    uint32_t    offReg = GCPhysAddr - pThis->MMIOBaseAddr;
-    int         idxReg = hdaRegLookup(pThis, offReg);
-    uint64_t    u64Value;
-    if (cb == 4)        u64Value = *(uint32_t const *)pv;
-    else if (cb == 2)   u64Value = *(uint16_t const *)pv;
-    else if (cb == 1)   u64Value = *(uint8_t const *)pv;
-    else if (cb == 8)   u64Value = *(uint64_t const *)pv;
-    else
-        AssertReleaseMsgFailed(("%d\n", cb));
-
-#ifdef LOG_ENABLED
-    uint32_t const u32LogOldValue = idxReg != -1 ? pThis->au32Regs[idxReg] : UINT32_MAX;
-    uint32_t const offRegLog = offReg;
-    int      const idxRegLog = idxReg;
-    if (idxReg == -1)
-        Log(("hdaMMIOWrite: @%#05x u32=%#010x cb=%d\n", offReg, *(uint32_t const *)pv, cb));
-    else if (cb == 4)
-        Log(("hdaMMIOWrite: @%#05x u32=%#010x %s\n", offReg, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
-    else if (cb == 2)
-        Log(("hdaMMIOWrite: @%#05x u16=%#06x (%#010x) %s\n", offReg, *(uint16_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
-    else if (cb == 1)
-        Log(("hdaMMIOWrite: @%#05x u8=%#04x (%#010x) %s\n", offReg, *(uint8_t *)pv, *(uint32_t *)pv, g_aHdaRegMap[idxReg].abbrev));
-    if (idxReg != -1 && g_aHdaRegMap[idxReg].size != cb)
-        Log(("hdaMMIOWrite: size=%d != cb=%d!!\n", g_aHdaRegMap[idxReg].size, cb));
-#endif
-
-#define NEW_WRITE_CODE
-#ifdef NEW_WRITE_CODE
-    /*
-     * Try for a direct hit first.
-     */
-    if (idxReg != -1 && g_aHdaRegMap[idxReg].size == cb)
-        rc = hdaWriteReg(pThis, idxReg, u64Value, "");
-    /*
-     * Partial or multiple register access, loop thru the requested memory.
-     */
-    else
-    {
-        /* If it's an access beyond the start of the register, shift the input
-           value and fill in missing bits. Natural alignment rules means we
-           will only see 1 or 2 byte accesses of this kind, so no risk of
-           shifting out input values. */
-        if (idxReg == -1 && (idxReg = hdaRegLookupWithin(pThis, offReg)) != -1)
-        {
-            uint32_t const cbBefore = g_aHdaRegMap[idxReg].offset - offReg; Assert(cbBefore > 0 && cbBefore < 4);
-            offReg    -= cbBefore;
-            u64Value <<= cbBefore * 8;
-            u64Value  |= pThis->au32Regs[idxReg] & g_afMasks[cbBefore];
-            Log(("hdaMMIOWrite: Within register, supplied %u leading bits: %#llx -> %#llx ...\n",
-                 cbBefore * 8, ~g_afMasks[cbBefore] & u64Value, u64Value));
-        }
-
-        /* Loop thru the write area, it may covert multiple registers. */
-        rc = VINF_SUCCESS;
-        for (;;)
-        {
-            uint32_t cbReg;
-            if (idxReg != -1)
-            {
-                cbReg = g_aHdaRegMap[idxReg].size;
-                if (cb < cbReg)
-                {
-                    u64Value |= pThis->au32Regs[idxReg] & g_afMasks[cbReg] & ~g_afMasks[cb];
-                    Log(("hdaMMIOWrite: Supplying missing bits (%#x): %#llx -> %#llx ...\n",
-                         g_afMasks[cbReg] & ~g_afMasks[cb], u64Value & g_afMasks[cb], u64Value));
-                }
-                rc = hdaWriteReg(pThis, idxReg, u64Value, "*");
-            }
-            else
-            {
-                LogRel(("hda: Invalid write access @0x%x!\n", offReg));
-                cbReg = 1;
-            }
-            if (cbReg >= cb)
-                break;
-
-            /* advance */
-            offReg += cbReg;
-            cb     -= cbReg;
-            u64Value >>= cbReg * 8;
-            if (idxReg == -1)
-                idxReg = hdaRegLookup(pThis, offReg);
-            else
-            {
-                idxReg++;
-                if (   (unsigned)idxReg >= RT_ELEMENTS(g_aHdaRegMap)
-                    || g_aHdaRegMap[idxReg].offset != offReg)
-                    idxReg = -1;
-            }
-        }
-    }
-#else
-    if (idxReg != -1)
-    {
-        /** @todo r=bird: This looks like code for handling unaligned register
-         * accesses.  If it isn't, then add a comment explaining what you're
-         * trying to do here.  OTOH, if it is then it has the following
-         * issues:
-         *      -# You're calculating the wrong new value for the register.
-         *      -# You're not handling cross register accesses.  Imagine a
-         *       4-byte write starting at CORBCTL, or a 8-byte write.
-         *
-         * PS! consider dropping the 'offset' argument to pfnWrite/pfnRead as
-         * nobody seems to be using it and it just adds complexity when reading
-         * the code.
-         *
-         */
-        uint32_t u32CurValue = pThis->au32Regs[idxReg];
-        uint32_t u32NewValue;
-        uint32_t mask;
-        switch (cb)
-        {
-            case 1:
-                u32NewValue = *(uint8_t const *)pv;
-                mask = 0xff;
-                break;
-            case 2:
-                u32NewValue = *(uint16_t const *)pv;
-                mask = 0xffff;
-                break;
-            case 4:
-            case 8:
-                /* 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word */
-                u32NewValue = *(uint32_t const *)pv;
-                mask = 0xffffffff;
-                cb = 4;
-                break;
-            default:
-                AssertFailedReturn(VERR_INTERNAL_ERROR_4); /* shall not happen. */
-        }
-        /* cross-register access, see corresponding comment in hdaMMIORead */
-        uint32_t shift = (g_aHdaRegMap[idxReg].offset - offReg) % sizeof(uint32_t) * 8;
-        mask <<= shift;
-        u32NewValue <<= shift;
-        u32NewValue &= mask;
-        u32NewValue |= (u32CurValue & ~mask);
-
-        rc = g_aHdaRegMap[idxReg].pfnWrite(pThis, idxReg, u32NewValue);
-        Log(("hda: write %s:(%x) %x => %x\n", g_aHdaRegMap[idxReg].abbrev, u32NewValue,
-             u32CurValue, pThis->au32Regs[idxReg]));
-    }
-    else
-        rc = VINF_SUCCESS;
-#endif
-    Log(("hdaMMIOWrite: @%#05x %#x -> %#x\n", offRegLog, u32LogOldValue,
-         idxRegLog != -1 ? pThis->au32Regs[idxRegLog] : UINT32_MAX));
-    return rc;
-}
-
-
-/* PCI callback. */
-
-/**
- * @callback_method_impl{FNPCIIOREGIONMAP}
- */
-static DECLCALLBACK(int) hdaPciIoRegionMap(PPCIDEVICE pPciDev, int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb,
-                                           PCIADDRESSSPACE enmType)
-{
-    PPDMDEVINS  pDevIns = pPciDev->pDevIns;
-    PHDASTATE   pThis = RT_FROM_MEMBER(pPciDev, HDASTATE, PciDev);
-    RTIOPORT    Port = (RTIOPORT)GCPhysAddress;
-    int         rc;
-
-    /*
-     * 18.2 of the ICH6 datasheet defines the valid access widths as byte, word, and double word.
-     *
-     * Let IOM talk DWORDs when reading, saves a lot of complications. On
-     * writing though, we have to do it all ourselves because of sideeffects.
-     */
-    Assert(enmType == PCI_ADDRESS_SPACE_MEM);
-    rc = PDMDevHlpMMIORegister(pPciDev->pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
-#ifdef NEW_READ_CODE
-                               IOMMMIO_FLAGS_READ_DWORD |
-#else
-                               IOMMMIO_FLAGS_READ_PASSTHRU |
-#endif
-                               IOMMMIO_FLAGS_WRITE_PASSTHRU,
-                               hdaMMIOWrite, hdaMMIORead, "ICH6_HDA");
-
-    if (RT_FAILURE(rc))
-        return rc;
-
-    pThis->MMIOBaseAddr = GCPhysAddress;
-    return VINF_SUCCESS;
-}
-
-
-/* Saved state callbacks. */
-
-/**
- * @callback_method_impl{FNSSMDEVSAVEEXEC}
- */
-static DECLCALLBACK(int) hdaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    /* Save Codec nodes states */
-    hdaCodecSaveState(&pThis->Codec, pSSM);
-
-    /* Save MMIO registers */
-    AssertCompile(RT_ELEMENTS(pThis->au32Regs) == 112);
-    SSMR3PutU32(pSSM, RT_ELEMENTS(pThis->au32Regs));
-    SSMR3PutMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
-
-    /* Save HDA dma counters */
-    SSMR3PutStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
-    SSMR3PutStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), 0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
-    SSMR3PutStructEx(pSSM, &pThis->StInBdle,  sizeof(pThis->StInBdle),  0 /*fFlags*/, g_aHdaBDLEDescFields, NULL);
-    return VINF_SUCCESS;
-}
-
-
-/**
- * @callback_method_impl{FNSSMDEVLOADEXEC}
- */
-static DECLCALLBACK(int) hdaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-
-    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
-
-    /*
-     * Load Codec nodes states.
-     */
-    int rc = hdaCodecLoadState(&pThis->Codec, pSSM, uVersion);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /*
-     * Load MMIO registers.
-     */
-    uint32_t cRegs;
-    switch (uVersion)
-    {
-        case HDA_SSM_VERSION_1:
-            /* Starting with r71199, we would save 112 instead of 113
-               registers due to some code cleanups.  This only affected trunk
-               builds in the 4.1 development period. */
-            cRegs = 113;
-            if (SSMR3HandleRevision(pSSM) >= 71199)
-            {
-                uint32_t uVer = SSMR3HandleVersion(pSSM);
-                if (   VBOX_FULL_VERSION_GET_MAJOR(uVer) == 4
-                    && VBOX_FULL_VERSION_GET_MINOR(uVer) == 0
-                    && VBOX_FULL_VERSION_GET_BUILD(uVer) >= 51)
-                    cRegs = 112;
-            }
-            break;
-
-        case HDA_SSM_VERSION_2:
-        case HDA_SSM_VERSION_3:
-            cRegs = 112;
-            AssertCompile(RT_ELEMENTS(pThis->au32Regs) == 112);
-            break;
-
-        case HDA_SSM_VERSION:
-            rc = SSMR3GetU32(pSSM, &cRegs); AssertRCReturn(rc, rc);
-            AssertLogRelMsgReturn(cRegs == RT_ELEMENTS(pThis->au32Regs),
-                                  ("cRegs is %d, expected %d\n", cRegs, RT_ELEMENTS(pThis->au32Regs)),
-                                  VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
-            break;
-
-        default:
-            return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
-    }
-
-    if (cRegs >= RT_ELEMENTS(pThis->au32Regs))
-    {
-        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(pThis->au32Regs));
-        SSMR3Skip(pSSM, sizeof(uint32_t) * (cRegs - RT_ELEMENTS(pThis->au32Regs)));
-    }
-    else
-    {
-        RT_ZERO(pThis->au32Regs);
-        SSMR3GetMem(pSSM, pThis->au32Regs, sizeof(uint32_t) * cRegs);
-    }
-
-    /*
-     * Load HDA dma counters.
-     */
-    uint32_t   fFlags   = uVersion <= HDA_SSM_VERSION_2 ? SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED : 0;
-    PCSSMFIELD paFields = uVersion <= HDA_SSM_VERSION_2 ? g_aHdaBDLEDescFieldsOld              : g_aHdaBDLEDescFields;
-    SSMR3GetStructEx(pSSM, &pThis->StOutBdle, sizeof(pThis->StOutBdle), fFlags, paFields, NULL);
-    SSMR3GetStructEx(pSSM, &pThis->StMicBdle, sizeof(pThis->StMicBdle), fFlags, paFields, NULL);
-    rc = SSMR3GetStructEx(pSSM, &pThis->StInBdle, sizeof(pThis->StInBdle), fFlags, paFields, NULL);
-    AssertRCReturn(rc, rc);
-
-    /*
-     * Update stuff after the state changes.
-     */
-    AUD_set_active_in(pThis->Codec.SwVoiceIn, SDCTL(pThis, 0) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-    AUD_set_active_out(pThis->Codec.SwVoiceOut, SDCTL(pThis, 4) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN));
-
-    pThis->u64CORBBase = RT_MAKE_U64(CORBLBASE(pThis), CORBUBASE(pThis));
-    pThis->u64RIRBBase = RT_MAKE_U64(RIRLBASE(pThis), RIRUBASE(pThis));
-    pThis->u64DPBase   = RT_MAKE_U64(DPLBASE(pThis), DPUBASE(pThis));
-    return VINF_SUCCESS;
-}
-
-
-/* Debug and log type formatters. */
-
-/**
- * @callback_method_impl{FNRTSTRFORMATTYPE}
- */
-static DECLCALLBACK(size_t)
-hdaFormatStrmCtl(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
-                 const char *pszType, void const *pvValue,
-                 int cchWidth, int cchPrecision, unsigned fFlags,
-                 void *pvUser)
-{
-    uint32_t sdCtl = (uint32_t)(uintptr_t)pvValue;
-    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
-                       "SDCTL(raw: %#x, strm:%#x, dir:%RTbool, tp:%RTbool strip:%x, deie:%RTbool, ioce:%RTbool, run:%RTbool, srst:%RTbool)",
-                       sdCtl,
-                       (sdCtl & HDA_REG_FIELD_MASK(SDCTL, NUM)) >> ICH6_HDA_SDCTL_NUM_SHIFT,
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DIR)),
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, TP)),
-                       (sdCtl & HDA_REG_FIELD_MASK(SDCTL, STRIPE)) >> ICH6_HDA_SDCTL_STRIPE_SHIFT,
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, DEIE)),
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE)),
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)),
-                       RT_BOOL(sdCtl & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
-}
-
-/**
- * @callback_method_impl{FNRTSTRFORMATTYPE}
- */
-static DECLCALLBACK(size_t)
-hdaFormatStrmFifos(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
-                   const char *pszType, void const *pvValue,
-                   int cchWidth, int cchPrecision, unsigned fFlags,
-                   void *pvUser)
-{
-    uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
-    uint32_t cb;
-    switch (uSdFifos)
-    {
-        case HDA_SDONFIFO_16B:  cb = 16; break;
-        case HDA_SDONFIFO_32B:  cb = 32; break;
-        case HDA_SDONFIFO_64B:  cb = 64; break;
-        case HDA_SDONFIFO_128B: cb = 128; break;
-        case HDA_SDONFIFO_192B: cb = 192; break;
-        case HDA_SDONFIFO_256B: cb = 256; break;
-        case HDA_SDINFIFO_120B: cb = 120; break;
-        case HDA_SDINFIFO_160B: cb = 160; break;
-        default:                cb = 0; break;
-    }
-    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOS(raw: %#x, sdfifos:%u B)", uSdFifos, cb);
-}
-
-/**
- * @callback_method_impl{FNRTSTRFORMATTYPE}
- */
-static DECLCALLBACK(size_t)
-hdaFormatStrmFifow(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
-                   const char *pszType, void const *pvValue,
-                   int cchWidth, int cchPrecision, unsigned fFlags,
-                   void *pvUser)
-{
-    uint32_t uSdFifos = (uint32_t)(uintptr_t)pvValue;
-    uint32_t cb;
-    switch (uSdFifos)
-    {
-        case HDA_SDFIFOW_8B:  cb = 8;  break;
-        case HDA_SDFIFOW_16B: cb = 16; break;
-        case HDA_SDFIFOW_32B: cb = 32; break;
-        default:              cb = 0;  break;
-    }
-    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "SDFIFOW(raw: %#0x, sdfifow:%d B)", uSdFifos, cb);
-}
-
-/**
- * @callback_method_impl{FNRTSTRFORMATTYPE}
- */
-static DECLCALLBACK(size_t)
-hdaFormatStrmSts(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
-                 const char *pszType, void const *pvValue,
-                 int cchWidth, int cchPrecision, unsigned fFlags,
-                 void *pvUser)
-{
-    uint32_t uSdSts = (uint32_t)(uintptr_t)pvValue;
-    return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
-                       "SDSTS(raw: %#0x, fifordy:%RTbool, dese:%RTbool, fifoe:%RTbool, bcis:%RTbool)",
-                       uSdSts,
-                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY)),
-                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, DE)),
-                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, FE)),
-                       RT_BOOL(uSdSts & HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS)));
-}
-
-
-static int hdaLookUpRegisterByName(PHDASTATE pThis, const char *pszArgs)
-{
-    int iReg = 0;
-    for (; iReg < HDA_NREGS; ++iReg)
-        if (!RTStrICmp(g_aHdaRegMap[iReg].abbrev, pszArgs))
-            return iReg;
-    return -1;
-}
-
-
-static void hdaDbgPrintRegister(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaIndex)
-{
-    Assert(   pThis
-           && iHdaIndex >= 0
-           && iHdaIndex < HDA_NREGS);
-    pHlp->pfnPrintf(pHlp, "hda: %s: 0x%x\n", g_aHdaRegMap[iHdaIndex].abbrev, pThis->au32Regs[iHdaIndex]);
-}
-
-
-/**
- * @callback_method_impl{FNDBGFHANDLERDEV}
- */
-static DECLCALLBACK(void) hdaInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    int iHdaRegisterIndex = hdaLookUpRegisterByName(pThis, pszArgs);
-    if (iHdaRegisterIndex != -1)
-        hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
-    else
-        for(iHdaRegisterIndex = 0; (unsigned int)iHdaRegisterIndex < HDA_NREGS; ++iHdaRegisterIndex)
-            hdaDbgPrintRegister(pThis, pHlp, iHdaRegisterIndex);
-}
-
-
-static void hdaDbgPrintStream(PHDASTATE pThis, PCDBGFINFOHLP pHlp, int iHdaStrmIndex)
-{
-    Assert(   pThis
-           && iHdaStrmIndex >= 0
-           && iHdaStrmIndex < 7);
-    pHlp->pfnPrintf(pHlp, "Dump of %d HDA Stream:\n", iHdaStrmIndex);
-    pHlp->pfnPrintf(pHlp, "SD%dCTL: %R[sdctl]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, CTL, iHdaStrmIndex));
-    pHlp->pfnPrintf(pHlp, "SD%dCTS: %R[sdsts]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, STS, iHdaStrmIndex));
-    pHlp->pfnPrintf(pHlp, "SD%dFIFOS: %R[sdfifos]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, FIFOS, iHdaStrmIndex));
-    pHlp->pfnPrintf(pHlp, "SD%dFIFOW: %R[sdfifow]\n", iHdaStrmIndex, HDA_STREAM_REG2(pThis, FIFOW, iHdaStrmIndex));
-}
-
-
-static int hdaLookUpStreamIndex(PHDASTATE pThis, const char *pszArgs)
-{
-    /* todo: add args parsing */
-    return -1;
-}
-
-
-/**
- * @callback_method_impl{FNDBGFHANDLERDEV}
- */
-static DECLCALLBACK(void) hdaInfoStream(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    PHDASTATE   pThis         = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    int         iHdaStrmIndex = hdaLookUpStreamIndex(pThis, pszArgs);
-    if (iHdaStrmIndex != -1)
-        hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
-    else
-        for(iHdaStrmIndex = 0; iHdaStrmIndex < 7; ++iHdaStrmIndex)
-            hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
-}
-
-/**
- * @callback_method_impl{FNDBGFHANDLERDEV}
- */
-static DECLCALLBACK(void) hdaInfoCodecNodes(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    if (pThis->Codec.pfnCodecDbgListNodes)
-        pThis->Codec.pfnCodecDbgListNodes(&pThis->Codec, pHlp, pszArgs);
-    else
-        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
-}
-
-
-/**
- * @callback_method_impl{FNDBGFHANDLERDEV}
- */
-static DECLCALLBACK(void) hdaInfoCodecSelector(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    if (pThis->Codec.pfnCodecDbgSelector)
-        pThis->Codec.pfnCodecDbgSelector(&pThis->Codec, pHlp, pszArgs);
-    else
-        pHlp->pfnPrintf(pHlp, "Codec implementation doesn't provide corresponding callback.\n");
-}
-
-
-/* PDMIBASE */
-
-/**
- * @interface_method_impl{PDMIBASE,pfnQueryInterface}
- */
-static DECLCALLBACK(void *) hdaQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
-{
-    PHDASTATE pThis = RT_FROM_MEMBER(pInterface, HDASTATE, IBase);
-    Assert(&pThis->IBase == pInterface);
-
-    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
-    return NULL;
-}
-
-
-/* PDMDEVREG */
-
-/**
- * Reset notification.
- *
- * @returns VBox status.
- * @param   pDevIns     The device instance data.
- *
- * @remark  The original sources didn't install a reset handler, but it seems to
- *          make sense to me so we'll do it.
- */
-static DECLCALLBACK(void)  hdaReset(PPDMDEVINS pDevIns)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    GCAP(pThis) = HDA_MAKE_GCAP(4,4,0,0,1); /* see 6.2.1 */
-    VMIN(pThis) = 0x00;       /* see 6.2.2 */
-    VMAJ(pThis) = 0x01;       /* see 6.2.3 */
-    VMAJ(pThis) = 0x01;       /* see 6.2.3 */
-    OUTPAY(pThis) = 0x003C;   /* see 6.2.4 */
-    INPAY(pThis)  = 0x001D;   /* see 6.2.5 */
-    pThis->au32Regs[ICH6_HDA_REG_CORBSIZE] = 0x42; /* see 6.2.1 */
-    pThis->au32Regs[ICH6_HDA_REG_RIRBSIZE] = 0x42; /* see 6.2.1 */
-    CORBRP(pThis) = 0x0;
-    RIRBWP(pThis) = 0x0;
-
-    Log(("hda: inter HDA reset.\n"));
-    pThis->cbCorbBuf = 256 * sizeof(uint32_t);
-
-    if (pThis->pu32CorbBuf)
-        memset(pThis->pu32CorbBuf, 0, pThis->cbCorbBuf);
-    else
-        pThis->pu32CorbBuf = (uint32_t *)RTMemAllocZ(pThis->cbCorbBuf);
-
-    pThis->cbRirbBuf = 256 * sizeof(uint64_t);
-    if (pThis->pu64RirbBuf)
-        memset(pThis->pu64RirbBuf, 0, pThis->cbRirbBuf);
-    else
-        pThis->pu64RirbBuf = (uint64_t *)RTMemAllocZ(pThis->cbRirbBuf);
-
-    pThis->u64BaseTS = PDMDevHlpTMTimeVirtGetNano(pDevIns);
-
-    HDABDLEDESC StEmptyBdle;
-    for (uint8_t u8Strm = 0; u8Strm < 8; ++u8Strm)
-    {
-        HDASTREAMTRANSFERDESC StreamDesc;
-        PHDABDLEDESC pBdle = NULL;
-        if (u8Strm == 0)
-            pBdle = &pThis->StInBdle;
-        else if(u8Strm == 4)
-            pBdle = &pThis->StOutBdle;
-        else
-        {
-            memset(&StEmptyBdle, 0, sizeof(HDABDLEDESC));
-            pBdle = &StEmptyBdle;
-        }
-        hdaInitTransferDescriptor(pThis, pBdle, u8Strm, &StreamDesc);
-        /* hdaStreamReset prevents changing the SRST bit, so we force it to zero here. */
-        HDA_STREAM_REG2(pThis, CTL, u8Strm) = 0;
-        hdaStreamReset(pThis, pBdle, &StreamDesc, u8Strm);
-    }
-
-    /* emulation of codec "wake up" (HDA spec 5.5.1 and 6.5)*/
-    STATESTS(pThis) = 0x1;
-
-    Log(("hda: reset finished\n"));
-}
-
-
-/**
- * @interface_method_impl{PDMDEVREG,pfnDestruct}
- */
-static DECLCALLBACK(int) hdaDestruct(PPDMDEVINS pDevIns)
-{
-    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-
-    int rc = hdaCodecDestruct(&pThis->Codec);
-    AssertRC(rc);
-
-    RTMemFree(pThis->pu32CorbBuf);
-    pThis->pu32CorbBuf = NULL;
-
-    RTMemFree(pThis->pu64RirbBuf);
-    pThis->pu64RirbBuf = NULL;
-
-    return VINF_SUCCESS;
-}
-
-/**
- * @interface_method_impl{PDMDEVREG,pfnConstruct}
- */
-static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
-{
-    PHDASTATE   pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
-    int         rc;
-
-    Assert(iInstance == 0);
-    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
-
-    /*
-     * Validations.
-     */
-    if (!CFGMR3AreValuesValid(pCfgHandle, "\0"))
-        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
-                                N_ ("Invalid configuration for the Intel HDA device"));
-
-    /// @todo r=michaln: This device may need R0/RC enabling, especially if guests
-    /// poll some register(pThis).
-
-    /*
-     * Initialize data (most of it anyway).
-     */
-    pThis->pDevIns                  = pDevIns;
-    /* IBase */
-    pThis->IBase.pfnQueryInterface  = hdaQueryInterface;
-
-    /* PCI Device */
-    PCIDevSetVendorId           (&pThis->PciDev, HDA_PCI_VENDOR_ID); /* nVidia */
-    PCIDevSetDeviceId           (&pThis->PciDev, HDA_PCI_DEICE_ID); /* HDA */
-
-    PCIDevSetCommand            (&pThis->PciDev, 0x0000); /* 04 rw,ro - pcicmd. */
-    PCIDevSetStatus             (&pThis->PciDev, VBOX_PCI_STATUS_CAP_LIST); /* 06 rwc?,ro? - pcists. */
-    PCIDevSetRevisionId         (&pThis->PciDev, 0x01);   /* 08 ro - rid. */
-    PCIDevSetClassProg          (&pThis->PciDev, 0x00);   /* 09 ro - pi. */
-    PCIDevSetClassSub           (&pThis->PciDev, 0x03);   /* 0a ro - scc; 03 == HDA. */
-    PCIDevSetClassBase          (&pThis->PciDev, 0x04);   /* 0b ro - bcc; 04 == multimedia. */
-    PCIDevSetHeaderType         (&pThis->PciDev, 0x00);   /* 0e ro - headtyp. */
-    PCIDevSetBaseAddress        (&pThis->PciDev, 0,       /* 10 rw - MMIO */
-                                 false /* fIoSpace */, false /* fPrefetchable */, true /* f64Bit */, 0x00000000);
-    PCIDevSetInterruptLine      (&pThis->PciDev, 0x00);   /* 3c rw. */
-    PCIDevSetInterruptPin       (&pThis->PciDev, 0x01);   /* 3d ro - INTA#. */
-
-#if defined(HDA_AS_PCI_EXPRESS)
-    PCIDevSetCapabilityList     (&pThis->PciDev, 0x80);
-#elif defined(VBOX_WITH_MSI_DEVICES)
-    PCIDevSetCapabilityList     (&pThis->PciDev, 0x60);
-#else
-    PCIDevSetCapabilityList     (&pThis->PciDev, 0x50);   /* ICH6 datasheet 18.1.16 */
-#endif
-
-    /// @todo r=michaln: If there are really no PCIDevSetXx for these, the meaning
-    /// of these values needs to be properly documented!
-    /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */
-    PCIDevSetByte(&pThis->PciDev, 0x40, 0x01);
-
-    /* Power Management */
-    PCIDevSetByte(&pThis->PciDev, 0x50 + 0, VBOX_PCI_CAP_ID_PM);
-    PCIDevSetByte(&pThis->PciDev, 0x50 + 1, 0x0); /* next */
-    PCIDevSetWord(&pThis->PciDev, 0x50 + 2, VBOX_PCI_PM_CAP_DSI | 0x02 /* version, PM1.1 */ );
-
-#ifdef HDA_AS_PCI_EXPRESS
-    /* PCI Express */
-    PCIDevSetByte(&pThis->PciDev, 0x80 + 0, VBOX_PCI_CAP_ID_EXP); /* PCI_Express */
-    PCIDevSetByte(&pThis->PciDev, 0x80 + 1, 0x60); /* next */
-    /* Device flags */
-    PCIDevSetWord(&pThis->PciDev, 0x80 + 2,
-                   /* version */ 0x1     |
-                   /* Root Complex Integrated Endpoint */ (VBOX_PCI_EXP_TYPE_ROOT_INT_EP << 4) |
-                   /* MSI */ (100) << 9 );
-    /* Device capabilities */
-    PCIDevSetDWord(&pThis->PciDev, 0x80 + 4, VBOX_PCI_EXP_DEVCAP_FLRESET);
-    /* Device control */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 8, 0);
-    /* Device status */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 10, 0);
-    /* Link caps */
-    PCIDevSetDWord(&pThis->PciDev, 0x80 + 12, 0);
-    /* Link control */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 16, 0);
-    /* Link status */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 18, 0);
-    /* Slot capabilities */
-    PCIDevSetDWord(&pThis->PciDev, 0x80 + 20, 0);
-    /* Slot control */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 24, 0);
-    /* Slot status */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 26, 0);
-    /* Root control */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 28, 0);
-    /* Root capabilities */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 30, 0);
-    /* Root status */
-    PCIDevSetDWord(&pThis->PciDev, 0x80 + 32, 0);
-    /* Device capabilities 2 */
-    PCIDevSetDWord(&pThis->PciDev, 0x80 + 36, 0);
-    /* Device control 2 */
-    PCIDevSetQWord(&pThis->PciDev, 0x80 + 40, 0);
-    /* Link control 2 */
-    PCIDevSetQWord(&pThis->PciDev, 0x80 + 48, 0);
-    /* Slot control 2 */
-    PCIDevSetWord( &pThis->PciDev, 0x80 + 56, 0);
-#endif
-
-    /*
-     * Register the PCI device.
-     */
-    rc = PDMDevHlpPCIRegister(pDevIns, &pThis->PciDev);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 0x4000, PCI_ADDRESS_SPACE_MEM, hdaPciIoRegionMap);
-    if (RT_FAILURE(rc))
-        return rc;
-
-#ifdef VBOX_WITH_MSI_DEVICES
-    PDMMSIREG MsiReg;
-    RT_ZERO(MsiReg);
-    MsiReg.cMsiVectors    = 1;
-    MsiReg.iMsiCapOffset  = 0x60;
-    MsiReg.iMsiNextOffset = 0x50;
-    rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
-        PCIDevSetCapabilityList(&pThis->PciDev, 0x50);
-    }
-#endif
-
-    rc = PDMDevHlpSSMRegister(pDevIns, HDA_SSM_VERSION, sizeof(*pThis), hdaSaveExec, hdaLoadExec);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    /*
-     * Attach driver.
-     */
-    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Audio Driver Port");
-    if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
-        Log(("hda: No attached driver!\n"));
-    else if (RT_FAILURE(rc))
-    {
-        AssertMsgFailed(("Failed to attach Intel HDA LUN #0! rc=%Rrc\n", rc));
-        return rc;
-    }
-
-    pThis->Codec.pvHDAState = pThis;
-    rc = hdaCodecConstruct(pDevIns, &pThis->Codec, pCfgHandle);
-    if (RT_FAILURE(rc))
-        AssertRCReturn(rc, rc);
-
-    /* ICH6 datasheet defines 0 values for SVID and SID (18.1.14-15), which together with values returned for
-       verb F20 should provide device/codec recognition. */
-    Assert(pThis->Codec.u16VendorId);
-    Assert(pThis->Codec.u16DeviceId);
-    PCIDevSetSubSystemVendorId(&pThis->PciDev, pThis->Codec.u16VendorId); /* 2c ro - intel.) */
-    PCIDevSetSubSystemId(      &pThis->PciDev, pThis->Codec.u16DeviceId); /* 2e ro. */
-
-    hdaReset(pDevIns);
-    pThis->Codec.id = 0;
-    pThis->Codec.pfnTransfer = hdaTransfer;
-    pThis->Codec.pfnReset = hdaCodecReset;
-
-    /*
-     * 18.2.6,7 defines that values of this registers might be cleared on power on/reset
-     * hdaReset shouldn't affects these registers.
-     */
-    WAKEEN(pThis) = 0x0;
-    STATESTS(pThis) = 0x0;
-
-    /*
-     * Debug and string formatter types.
-     */
-    PDMDevHlpDBGFInfoRegister(pDevIns, "hda",         "HDA info. (hda [register case-insensitive])",    hdaInfo);
-    PDMDevHlpDBGFInfoRegister(pDevIns, "hdastrm",     "HDA stream info. (hdastrm [stream number])",     hdaInfoStream);
-    PDMDevHlpDBGFInfoRegister(pDevIns, "hdcnodes",    "HDA codec nodes.",                               hdaInfoCodecNodes);
-    PDMDevHlpDBGFInfoRegister(pDevIns, "hdcselector", "HDA codec's selector states [node number].",     hdaInfoCodecSelector);
-
-    rc = RTStrFormatTypeRegister("sdctl",   hdaFormatStrmCtl,   NULL);
-    AssertRC(rc);
-    rc = RTStrFormatTypeRegister("sdsts",   hdaFormatStrmSts,   NULL);
-    AssertRC(rc);
-    rc = RTStrFormatTypeRegister("sdfifos", hdaFormatStrmFifos, NULL);
-    AssertRC(rc);
-    rc = RTStrFormatTypeRegister("sdfifow", hdaFormatStrmFifow, NULL);
-    AssertRC(rc);
-#if 0
-    rc = RTStrFormatTypeRegister("sdfmt", printHdaStrmFmt, NULL);
-    AssertRC(rc);
-#endif
-
-    /*
-     * Some debug assertions.
-     */
-    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;
-
-        /* binary search order. */
-        AssertReleaseMsg(!pNextReg || pReg->offset + pReg->size <= pNextReg->offset,
-                         ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
-                          i, pReg->offset, pReg->size, i + 1, pNextReg->offset, pNextReg->size));
-
-        /* alignment. */
-        AssertReleaseMsg(   pReg->size == 1
-                         || (pReg->size == 2 && (pReg->offset & 1) == 0)
-                         || (pReg->size == 3 && (pReg->offset & 3) == 0)
-                         || (pReg->size == 4 && (pReg->offset & 3) == 0),
-                         ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
-
-        /* registers are packed into dwords - with 3 exceptions with gaps at the end of the dword. */
-        AssertRelease(((pReg->offset + pReg->size) & 3) == 0 || pNextReg);
-        if (pReg->offset & 3)
-        {
-            struct HDAREGDESC const *pPrevReg = i > 0 ?  &g_aHdaRegMap[i - 1] : NULL;
-            AssertReleaseMsg(pPrevReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
-            if (pPrevReg)
-                AssertReleaseMsg(pPrevReg->offset + pPrevReg->size == pReg->offset,
-                                 ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
-                                  i - 1, pPrevReg->offset, pPrevReg->size, i + 1, pReg->offset, pReg->size));
-        }
-#if 0
-        if ((pReg->offset + pReg->size) & 3)
-        {
-            AssertReleaseMsg(pNextReg, ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
-            if (pNextReg)
-                AssertReleaseMsg(pReg->offset + pReg->size == pNextReg->offset,
-                                 ("[%#x] = {%#x LB %#x}  vs. [%#x] = {%#x LB %#x}\n",
-                                  i, pReg->offset, pReg->size, i + 1,  pNextReg->offset, pNextReg->size));
-        }
-#endif
-
-        /* The final entry is a full dword, no gaps! Allows shortcuts. */
-        AssertReleaseMsg(pNextReg || ((pReg->offset + pReg->size) & 3) == 0,
-                         ("[%#x] = {%#x LB %#x}\n", i, pReg->offset, pReg->size));
-    }
-
-    return VINF_SUCCESS;
-}
-
-/**
- * The device registration structure.
- */
-const PDMDEVREG g_DeviceICH6_HDA =
-{
-    /* u32Version */
-    PDM_DEVREG_VERSION,
-    /* szName */
-    "hda",
-    /* szRCMod */
-    "",
-    /* szR0Mod */
-    "",
-    /* pszDescription */
-    "Intel HD Audio Controller",
-    /* fFlags */
-    PDM_DEVREG_FLAGS_DEFAULT_BITS,
-    /* fClass */
-    PDM_DEVREG_CLASS_AUDIO,
-    /* cMaxInstances */
-    1,
-    /* cbInstance */
-    sizeof(HDASTATE),
-    /* pfnConstruct */
-    hdaConstruct,
-    /* pfnDestruct */
-    hdaDestruct,
-    /* pfnRelocate */
-    NULL,
-    /* pfnIOCtl */
-    NULL,
-    /* pfnPowerOn */
-    NULL,
-    /* pfnReset */
-    hdaReset,
-    /* pfnSuspend */
-    NULL,
-    /* pfnResume */
-    NULL,
-    /* pfnAttach */
-    NULL,
-    /* pfnDetach */
-    NULL,
-    /* pfnQueryInterface. */
-    NULL,
-    /* pfnInitComplete */
-    NULL,
-    /* pfnPowerOff */
-    NULL,
-    /* pfnSoftReset */
-    NULL,
-    /* u32VersionEnd */
-    PDM_DEVREG_VERSION
-};
Index: trunk/src/VBox/Devices/Makefile.kmk
===================================================================
--- trunk/src/VBox/Devices/Makefile.kmk	(revision 44668)
+++ trunk/src/VBox/Devices/Makefile.kmk	(revision 44669)
@@ -168,6 +168,6 @@
  	Audio/DevIchAc97.cpp \
  	Audio/DevSB16.cpp \
- 	Audio/DevIchIntelHDA.cpp \
- 	Audio/DevCodec.cpp \
+ 	Audio/DevIchHda.cpp \
+ 	Audio/DevIchHdaCodec.cpp \
  	PC/DevDMA.cpp \
  	PC/DevHPET.cpp \
