Index: /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 71750)
+++ /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 71751)
@@ -197,5 +197,5 @@
 #define AC97_AD_MISC_HPSEL       RT_BIT(10)  /**< PCM (front) goes to headphone outputs. */
 
-#define ICHAC97STATE_2_DEVINS(a_pAC97)   ((a_pAC97)->pDevInsR3)
+#define ICHAC97STATE_2_DEVINS(a_pAC97)   ((a_pAC97)->CTX_SUFF(pDevIns))
 
 enum
@@ -396,6 +396,12 @@
     /** Critical section protecting the AC'97 state. */
     PDMCRITSECT             CritSect;
-    /** R3 Pointer to the device instance. */
+    /** R3 pointer to the device instance. */
     PPDMDEVINSR3            pDevInsR3;
+    /** R0 pointer to the device instance. */
+    PPDMDEVINSR0            pDevInsR0;
+    /** RC pointer to the device instance. */
+    PPDMDEVINSRC            pDevInsRC;
+    /** Set if R0/RC is enabled. */
+    bool                    fRZEnabled;
     /** Global Control (Bus Master Control Register). */
     uint32_t                glob_cnt;
@@ -415,9 +421,11 @@
     uint8_t                 cStreamsActive;
 #ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
-    /** The timer for pumping data thru the attached LUN drivers. */
-    PTMTIMERR3              pTimer;
-# if HC_ARCH_BITS == 32
+    /** The timer for pumping data thru the attached LUN drivers - R3Ptr. */
+    PTMTIMERR3              pTimerR3;
+    /** The timer for pumping data thru the attached LUN drivers - R0Ptr. */
+    PTMTIMERR0              pTimerR0;
+    /** The timer for pumping data thru the attached LUN drivers - RCPtr. */
+    PTMTIMERRC              pTimerRC;
     uint32_t                Padding0;
-# endif
     /** Flag indicating whether the timer is active or not. */
     bool                    fTimerActive;
@@ -437,5 +445,5 @@
 #endif
     /** List of associated LUN drivers (AC97DRIVER). */
-    RTLISTANCHOR            lstDrv;
+    RTLISTANCHORR3          lstDrv;
     /** The device's software mixer. */
     R3PTRTYPE(PAUDIOMIXER)  pMixer;
@@ -502,5 +510,5 @@
 #define DEVAC97_LOCK_BOTH_RETURN_VOID(a_pThis) \
     do { \
-        int rcLock = TMTimerLock((a_pThis)->pTimer, VERR_IGNORED); \
+        int rcLock = TMTimerLock((a_pThis)->CTX_SUFF(pTimer), VERR_IGNORED); \
         if (rcLock != VINF_SUCCESS) \
         { \
@@ -512,5 +520,5 @@
         { \
             AssertRC(rcLock); \
-            TMTimerUnlock((a_pThis)->pTimer); \
+            TMTimerUnlock((a_pThis)->CTX_SUFF(pTimer)); \
             return; \
         } \
@@ -522,5 +530,5 @@
 #define DEVAC97_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \
     do { \
-        int rcLock = TMTimerLock((a_pThis)->pTimer, (a_rcBusy)); \
+        int rcLock = TMTimerLock((a_pThis)->CTX_SUFF(pTimer), (a_rcBusy)); \
         if (rcLock != VINF_SUCCESS) \
             return rcLock; \
@@ -529,5 +537,5 @@
         { \
             AssertRC(rcLock); \
-            TMTimerUnlock((a_pThis)->pTimer); \
+            TMTimerUnlock((a_pThis)->CTX_SUFF(pTimer)); \
             return rcLock; \
         } \
@@ -540,5 +548,5 @@
     do { \
         PDMCritSectLeave(&(a_pThis)->CritSect); \
-        TMTimerUnlock((a_pThis)->pTimer); \
+        TMTimerUnlock((a_pThis)->CTX_SUFF(pTimer)); \
     } while (0)
 
@@ -607,4 +615,6 @@
 }
 
+#ifdef IN_RING3
+
 /**
  * Retrieves the audio mixer sink of a corresponding AC'97 stream index.
@@ -648,6 +658,6 @@
     PDMDevHlpPhysRead(pDevIns, pRegs->bdbar + pRegs->civ * 8, &u32[0], sizeof(u32));
     pRegs->bd_valid   = 1;
-#if !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64)
-# error Please adapt the code (audio buffers are little endian)!
+#ifndef RT_LITTLE_ENDIAN
+# error "Please adapt the code (audio buffers are little endian)!"
 #else
     pRegs->bd.addr    = RT_H2LE_U32(u32[0] & ~3);
@@ -661,4 +671,6 @@
 }
 
+#endif /* IN_RING3 */
+
 /**
  * Updates the status register (SR) of an AC'97 audio stream.
@@ -716,4 +728,6 @@
     }
 }
+
+#ifdef IN_RING3
 
 /**
@@ -1405,4 +1419,6 @@
 }
 
+#endif /* IN_RING3 */
+
 /**
  * Sets a AC'97 mixer control to a specific value.
@@ -1435,4 +1451,6 @@
     return RT_MAKE_U16(pThis->mixer_data[uMixerIdx + 0], pThis->mixer_data[uMixerIdx + 1]);
 }
+
+#ifdef IN_RING3
 
 /**
@@ -1960,4 +1978,6 @@
 }
 
+#endif /* IN_RING3 */
+
 /**
  * Retrieves an AC'97 audio stream from an AC'97 stream index.
@@ -1978,4 +1998,6 @@
 
 }
+
+#ifdef IN_RING3
 
 /**
@@ -2123,5 +2145,5 @@
     DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
 
-    AssertPtr(pThis->pTimer);
+    AssertPtr(pThis->CTX_SUFF(pTimer));
 
     if (!pThis->fTimerActive)
@@ -2150,5 +2172,5 @@
     LogFlowFuncEnter();
 
-    if (!pThis->pTimer)
+    if (!pThis->CTX_SUFF(pTimer))
         return VERR_WRONG_ORDER;
 
@@ -2172,5 +2194,5 @@
     LogFlowFuncEnter();
 
-    if (!pThis->pTimer) /* Only can happen on device construction time, so no locking needed here. */
+    if (!pThis->CTX_SUFF(pTimer)) /* Only can happen on device construction time, so no locking needed here. */
         return VINF_SUCCESS;
 
@@ -2205,5 +2227,5 @@
     LogFlowFuncEnter();
 
-    if (!pThis->pTimer)
+    if (!pThis->CTX_SUFF(pTimer))
         return VERR_WRONG_ORDER;
 
@@ -2230,29 +2252,35 @@
     DEVAC97_LOCK_BOTH_RETURN_VOID(pThis);
 
-    uint64_t cTicksNow = TMTimerGet(pThis->pTimer);
+    uint64_t cTicksNow = TMTimerGet(pThis->CTX_SUFF(pTimer));
 
     /* Update current time timestamp. */
     pThis->uTimerTS = cTicksNow;
 
-    /* Flag indicating whether to kick the timer again for the next DMA transfer or sink processing. */
-    bool fKickTimer = false;
+    /* Flag indicating whether to arm the timer again for the next DMA transfer or sink processing. */
+    bool fArmTimer = false;
 
     ichac97DoTransfers(pThis);
 
-    /* Do we need to kick the timer again? */
+    /* Do we need to arm the timer again? */
     if (   AudioMixerSinkIsActive(ichac97IndexToSink(pThis, pThis->StreamLineIn.u8SD))
         || AudioMixerSinkIsActive(ichac97IndexToSink(pThis, pThis->StreamMicIn.u8SD))
         || AudioMixerSinkIsActive(ichac97IndexToSink(pThis, pThis->StreamOut.u8SD)))
     {
-        fKickTimer = true;
-    }
-
-    if (   ASMAtomicReadBool(&pThis->fTimerActive)
-        || fKickTimer)
-    {
-        /* Kick the timer again. */
+        fArmTimer = true;
+    }
+
+    if (   ASMAtomicReadBool(&pThis->fTimerActive) /** @todo r=bird: totally unnecessary to do atomic read here, isn't it? */
+        || fArmTimer)
+    {
+/** @todo r=bird: This is simplitic insanity.  Nobody wants a timer running
+ *        every 5 ms (see AC97_TIMER_HZ) all the time the VM is up running!
+ *
+ *        If there isn't a way of detecting that guest is up to something, at
+ *        least try lowering the frequency when idle.
+ */
+        /* Arm the timer again. */
         uint64_t cTicks = pThis->cTimerTicks;
         /** @todo adjust cTicks down by now much cbOutMin represents. */
-        TMTimerSet(pThis->pTimer, cTicksNow + cTicks);
+        TMTimerSet(pThis->CTX_SUFF(pTimer), cTicksNow + cTicks);
     }
     else
@@ -2520,4 +2548,7 @@
 }
 
+#endif /* IN_RING3 */
+
+
 /**
  * Port I/O Handler for IN operations.
@@ -2533,12 +2564,10 @@
  * @param   cbVal       Number of bytes read.
  */
-static DECLCALLBACK(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort,
-                                               uint32_t *pu32Val, unsigned cbVal)
-{
-    RT_NOREF(pDevIns);
-
-    PAC97STATE pThis = (PAC97STATE)pvUser;
-
-    DEVAC97_LOCK(pThis);
+PDMBOTHCBDECL(int) ichac97IOPortNABMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32Val, unsigned cbVal)
+{
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+    RT_NOREF(pvUser);
+
+    DEVAC97_LOCK_RETURN(pThis, VINF_IOM_R3_IOPORT_READ);
 
     /* Get the index of the NABMBAR port. */
@@ -2706,10 +2735,8 @@
  * @param   cbVal       The value size in bytes.
  */
-static DECLCALLBACK(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort,
-                                                uint32_t u32Val, unsigned cbVal)
-{
-    RT_NOREF(pDevIns);
-
-    PAC97STATE pThis = (PAC97STATE)pvUser;
+PDMBOTHCBDECL(int) ichac97IOPortNABMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32Val, unsigned cbVal)
+{
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+    RT_NOREF(pvUser);
 
     DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
@@ -2724,4 +2751,5 @@
         pRegs = &pStream->Regs;
 
+    int rc = VINF_SUCCESS;
     switch (cbVal)
     {
@@ -2740,4 +2768,5 @@
                         && (pRegs->sr & AC97_SR_DCH))
                     {
+#ifdef IN_RING3
                         pRegs->sr &= ~(AC97_SR_DCH | AC97_SR_CELV);
                         pRegs->civ = pRegs->piv;
@@ -2745,4 +2774,7 @@
 
                         ichac97StreamFetchBDLE(pThis, pStream);
+#else
+                        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     }
                     pRegs->lvi = u32Val % AC97_MAX_BDLE;
@@ -2758,6 +2790,6 @@
                 case MC_CR:
                 {
+#ifdef IN_RING3
                     Log3Func(("[SD%RU8] CR <- %#x (cr %#x)\n", pStream->u8SD, u32Val, pRegs->cr));
-
                     if (u32Val & AC97_CR_RR) /* Busmaster reset. */
                     {
@@ -2799,4 +2831,7 @@
                         }
                     }
+#else /* !IN_RING3 */
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 }
@@ -2882,5 +2917,5 @@
     DEVAC97_UNLOCK_BOTH(pThis);
 
-    return VINF_SUCCESS;
+    return rc;
 }
 
@@ -2898,10 +2933,10 @@
  * @param   cbVal       Number of bytes read.
  */
-static DECLCALLBACK(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32Val, unsigned cbVal)
-{
-    RT_NOREF(pDevIns);
-    PAC97STATE pThis = (PAC97STATE)pvUser;
-
-    DEVAC97_LOCK(pThis);
+PDMBOTHCBDECL(int) ichac97IOPortNAMRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32Val, unsigned cbVal)
+{
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+    RT_NOREF(pvUser);
+
+    DEVAC97_LOCK_RETURN(pThis, VINF_IOM_R3_IOPORT_READ);
 
     int rc = VINF_SUCCESS;
@@ -2959,13 +2994,13 @@
  * @remarks Caller enters the device critical section.
  */
-static DECLCALLBACK(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32Val, unsigned cbVal)
-{
-    RT_NOREF(pDevIns);
-    PAC97STATE pThis = (PAC97STATE)pvUser;
+PDMBOTHCBDECL(int) ichac97IOPortNAMWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32Val, unsigned cbVal)
+{
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+    RT_NOREF(pvUser);
 
     DEVAC97_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_IOPORT_WRITE);
 
     uint32_t uPortIdx = uPort - pThis->IOPortBase[0];
-
+    int rc = VINF_SUCCESS;
     switch (cbVal)
     {
@@ -2983,5 +3018,9 @@
             {
                 case AC97_Reset:
+#ifdef IN_RING3
                     ichac97Reset(pThis->CTX_SUFF(pDevIns));
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Powerdown_Ctrl_Stat:
@@ -2996,5 +3035,9 @@
                             break; /* Register controls surround (rear), do nothing. */
                     }
+#ifdef IN_RING3
                     ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_VOLUME_MASTER, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Headphone_Volume_Mute:
@@ -3004,25 +3047,49 @@
                         {
                             /* Register controls PCM (front) outputs. */
+#ifdef IN_RING3
                             ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_VOLUME_MASTER, u32Val);
+#else
+                            rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                         }
                     }
                     break;
                 case AC97_PCM_Out_Volume_Mute:
+#ifdef IN_RING3
                     ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_FRONT, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Line_In_Volume_Mute:
+#ifdef IN_RING3
                     ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Record_Select:
+#ifdef IN_RING3
                     ichac97MixerRecordSelect(pThis, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Record_Gain_Mute:
+#ifdef IN_RING3
                     /* Newer Ubuntu guests rely on that when controlling gain and muting
                      * the recording (capturing) levels. */
                     ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_LINE_IN, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Record_Gain_Mic_Mute:
+#ifdef IN_RING3
                     /* Ditto; see note above. */
                     ichac97MixerSetVolume(pThis, uPortIdx, PDMAUDIOMIXERCTL_MIC_IN,  u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_Vendor_ID1:
@@ -3034,4 +3101,5 @@
                     break;
                 case AC97_Extended_Audio_Ctrl_Stat:
+#ifdef IN_RING3
                     if (!(u32Val & AC97_EACS_VRA))
                     {
@@ -3055,11 +3123,18 @@
                     LogFunc(("Setting extended audio control to %#x\n", u32Val));
                     ichac97MixerSet(pThis, AC97_Extended_Audio_Ctrl_Stat, u32Val);
+#else
+                    rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     break;
                 case AC97_PCM_Front_DAC_Rate:
                     if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRA)
                     {
+#ifdef IN_RING3
                         ichac97MixerSet(pThis, uPortIdx, u32Val);
                         LogFunc(("Set front DAC rate to %RU32\n", u32Val));
                         ichac97StreamReOpen(pThis, &pThis->StreamOut);
+#else
+                        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     }
                     else
@@ -3069,7 +3144,11 @@
                     if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRM)
                     {
+#ifdef IN_RING3
                         ichac97MixerSet(pThis, uPortIdx, u32Val);
                         LogFunc(("Set MIC ADC rate to %RU32\n", u32Val));
                         ichac97StreamReOpen(pThis, &pThis->StreamMicIn);
+#else
+                        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     }
                     else
@@ -3079,7 +3158,11 @@
                     if (ichac97MixerGet(pThis, AC97_Extended_Audio_Ctrl_Stat) & AC97_EACS_VRA)
                     {
+#ifdef IN_RING3
                         ichac97MixerSet(pThis, uPortIdx, u32Val);
                         LogFunc(("Set front LR ADC rate to %RU32\n", u32Val));
                         ichac97StreamReOpen(pThis, &pThis->StreamLineIn);
+#else
+                        rc = VINF_IOM_R3_IOPORT_WRITE;
+#endif
                     }
                     else
@@ -3108,7 +3191,8 @@
     DEVAC97_UNLOCK_BOTH(pThis);
 
-    return VINF_SUCCESS;
-}
-
+    return rc;
+}
+
+#ifdef IN_RING3
 
 /**
@@ -3131,13 +3215,34 @@
     int rc;
     if (iRegion == 0)
-        rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, pThis,
-                                     ichac97IOPortNAMWrite, ichac97IOPortNAMRead,
+    {
+        rc = PDMDevHlpIOPortRegister(pDevIns, Port, 256, NULL, ichac97IOPortNAMWrite, ichac97IOPortNAMRead,
                                      NULL, NULL, "ICHAC97 NAM");
+        AssertRCReturn(rc, rc);
+        if (pThis->fRZEnabled)
+        {
+            rc = PDMDevHlpIOPortRegisterR0(pDevIns, Port, 256, NIL_RTR0PTR, "ichac97IOPortNAMWrite", "ichac97IOPortNAMRead",
+                                           NULL, NULL, "ICHAC97 NAM");
+            AssertRCReturn(rc, rc);
+            rc = PDMDevHlpIOPortRegisterRC(pDevIns, Port, 256, NIL_RTRCPTR, "ichac97IOPortNAMWrite", "ichac97IOPortNAMRead",
+                                           NULL, NULL, "ICHAC97 NAM");
+            AssertRCReturn(rc, rc);
+        }
+    }
     else
-        rc = PDMDevHlpIOPortRegister(pDevIns, Port, 64, pThis,
-                                     ichac97IOPortNABMWrite, ichac97IOPortNABMRead,
+    {
+        rc = PDMDevHlpIOPortRegister(pDevIns, Port, 64, NULL, ichac97IOPortNABMWrite, ichac97IOPortNABMRead,
                                      NULL, NULL, "ICHAC97 NABM");
-    if (RT_FAILURE(rc))
-        return rc;
+        AssertRCReturn(rc, rc);
+        if (pThis->fRZEnabled)
+        {
+            rc = PDMDevHlpIOPortRegisterR0(pDevIns, Port, 64, NIL_RTR0PTR, "ichac97IOPortNABMWrite", "ichac97IOPortNABMRead",
+                                           NULL, NULL, "ICHAC97 NABM");
+            AssertRCReturn(rc, rc);
+            rc = PDMDevHlpIOPortRegisterRC(pDevIns, Port, 64, NIL_RTRCPTR, "ichac97IOPortNABMWrite", "ichac97IOPortNABMRead",
+                                           NULL, NULL, "ICHAC97 NABM");
+            AssertRCReturn(rc, rc);
+
+        }
+    }
 
     pThis->IOPortBase[iRegion] = Port;
@@ -3145,5 +3250,5 @@
 }
 
-#ifdef IN_RING3
+
 /**
  * Saves (serializes) an AC'97 stream using SSM.
@@ -3619,4 +3724,17 @@
 
 /**
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) ichac97Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+    NOREF(offDelta);
+    PAC97STATE pThis = PDMINS_2_DATA(pDevIns, PAC97STATE);
+    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
+    pThis->pTimerRC = TMTimerRCPtr(pThis->pTimerR3);
+#endif
+}
+
+/**
  * @interface_method_impl{PDMDEVREG,pfnDestruct}
  */
@@ -3653,6 +3771,9 @@
      * Initialize data so we can run the destructor without scewing up.
      */
+    pThis->pDevInsR3                = pDevIns;
+    pThis->pDevInsR0                = PDMDEVINS_2_R0PTR(pDevIns);
+    pThis->pDevInsRC                = PDMDEVINS_2_RCPTR(pDevIns);
+    pThis->IBase.pfnQueryInterface  = ichac97QueryInterface;
     RTListInit(&pThis->lstDrv);
-
 
     /*
@@ -3660,4 +3781,5 @@
      */
     if (!CFGMR3AreValuesValid(pCfg,
+                              "RZEnabled\0"
                               "Codec\0"
                               "TimerHz\0"))
@@ -3668,6 +3790,11 @@
      * Read config data.
      */
+    int rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &pThis->fRZEnabled, true);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("HDA configuration error: failed to read RCEnabled as boolean"));
+
     char szCodec[20];
-    int rc = CFGMR3QueryStringDef(pCfg, "Codec", &szCodec[0], sizeof(szCodec), "STAC9700");
+    rc = CFGMR3QueryStringDef(pCfg, "Codec", &szCodec[0], sizeof(szCodec), "STAC9700");
     if (RT_FAILURE(rc))
         return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
@@ -3711,8 +3838,4 @@
      * Initialize data (most of it anyway).
      */
-    pThis->pDevInsR3                = pDevIns;
-    /* IBase */
-    pThis->IBase.pfnQueryInterface  = ichac97QueryInterface;
-
     /* PCI Device */
     PCIDevSetVendorId     (&pThis->PciDev, 0x8086); /* 00 ro - intel. */               Assert(pThis->PciDev.abConfig[0x00] == 0x86); Assert(pThis->PciDev.abConfig[0x01] == 0x80);
@@ -3937,14 +4060,16 @@
          */
         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, ichac97Timer, pThis,
-                                    TMTIMER_FLAGS_NO_CRIT_SECT, "AC'97 Timer", &pThis->pTimer);
+                                    TMTIMER_FLAGS_NO_CRIT_SECT, "AC'97 Timer", &pThis->pTimerR3);
         AssertRCReturn(rc, rc);
+        pThis->pTimerR0 = TMTimerR0Ptr(pThis->pTimerR3);
+        pThis->pTimerRC = TMTimerRCPtr(pThis->pTimerR3);
 
         /* Use our own critcal section for the device timer.
          * That way we can control more fine-grained when to lock what. */
-        rc = TMR3TimerSetCritSect(pThis->pTimer, &pThis->CritSect);
+        rc = TMR3TimerSetCritSect(pThis->pTimerR3, &pThis->CritSect);
         AssertRCReturn(rc, rc);
 
-        pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimer) / uTimerHz;
-        pThis->uTimerTS    = TMTimerGet(pThis->pTimer);
+        pThis->cTimerTicks = TMTimerGetFreq(pThis->pTimerR3) / uTimerHz;
+        pThis->uTimerTS    = TMTimerGet(pThis->pTimerR3);
         LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTimerTicks, uTimerHz));
     }
@@ -4016,11 +4141,11 @@
     "ichac97",
     /* szRCMod */
-    "",
+    "VBoxDDRC.rc",
     /* szR0Mod */
-    "",
+    "VBoxDDR0.r0",
     /* pszDescription */
     "ICH AC'97 Audio Controller",
     /* fFlags */
-    PDM_DEVREG_FLAGS_DEFAULT_BITS,
+    PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
     /* fClass */
     PDM_DEVREG_CLASS_AUDIO,
@@ -4034,5 +4159,5 @@
     ichac97Destruct,
     /* pfnRelocate */
-    NULL,
+    ichac97Relocate,
     /* pfnMemSetup */
     NULL,
Index: /trunk/src/VBox/Devices/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/Makefile.kmk	(revision 71750)
+++ /trunk/src/VBox/Devices/Makefile.kmk	(revision 71751)
@@ -934,5 +934,6 @@
   VBoxDDRC_SOURCES      += \
  	Audio/DevHDA.cpp \
- 	Audio/DevHDACommon.cpp
+ 	Audio/DevHDACommon.cpp \
+	Audio/DevIchAc97.cpp
 
   VBoxDDRC_DEFS         += \
@@ -1118,5 +1119,6 @@
  VBoxDDR0_SOURCES += \
  	Audio/DevHDA.cpp \
- 	Audio/DevHDACommon.cpp
+ 	Audio/DevHDACommon.cpp \
+	Audio/DevIchAc97.cpp
 
  ifdef VBOX_WITH_E1000
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 71750)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 71751)
@@ -132,8 +132,8 @@
 #undef LOG_GROUP
 #include "../PC/DevHPET.cpp"
-# undef LOG_GROUP
-# include "../Audio/DevIchAc97.cpp"
-# undef LOG_GROUP
-# include "../Audio/DevHDA.cpp"
+#undef LOG_GROUP
+#include "../Audio/DevIchAc97.cpp"
+#undef LOG_GROUP
+#include "../Audio/DevHDA.cpp"
 #ifdef VBOX_WITH_NVME_IMPL
 # undef LOG_GROUP
@@ -1861,4 +1861,47 @@
     GEN_CHECK_OFF(AC97DRIVER, Out);
 
+    GEN_CHECK_SIZE(AC97STATE);
+    GEN_CHECK_OFF(AC97STATE, CritSect);
+    GEN_CHECK_OFF(AC97STATE, pDevInsR3);
+    GEN_CHECK_OFF(AC97STATE, pDevInsR0);
+    GEN_CHECK_OFF(AC97STATE, pDevInsRC);
+    GEN_CHECK_OFF(AC97STATE, fRZEnabled);
+    GEN_CHECK_OFF(AC97STATE, glob_cnt);
+    GEN_CHECK_OFF(AC97STATE, glob_sta);
+    GEN_CHECK_OFF(AC97STATE, cas);
+    GEN_CHECK_OFF(AC97STATE, last_samp);
+    GEN_CHECK_OFF(AC97STATE, mixer_data);
+    GEN_CHECK_OFF(AC97STATE, StreamLineIn);
+    GEN_CHECK_OFF(AC97STATE, StreamMicIn);
+    GEN_CHECK_OFF(AC97STATE, StreamOut);
+    GEN_CHECK_OFF(AC97STATE, cStreamsActive);
+#ifndef VBOX_WITH_AUDIO_AC97_CALLBACKS
+    GEN_CHECK_OFF(AC97STATE, pTimerR3);
+    GEN_CHECK_OFF(AC97STATE, pTimerR0);
+    GEN_CHECK_OFF(AC97STATE, pTimerRC);
+    GEN_CHECK_OFF(AC97STATE, Padding0);
+    GEN_CHECK_OFF(AC97STATE, fTimerActive);
+    GEN_CHECK_OFF(AC97STATE, u8Padding1);
+    GEN_CHECK_OFF(AC97STATE, cTimerTicks);
+    GEN_CHECK_OFF(AC97STATE, uTimerTS);
+#endif
+#ifdef VBOX_WITH_STATISTICS
+    GEN_CHECK_OFF(AC97STATE, StatTimer);
+    GEN_CHECK_OFF(AC97STATE, StatIn);
+    GEN_CHECK_OFF(AC97STATE, StatOut);
+    GEN_CHECK_OFF(AC97STATE, StatBytesRead);
+    GEN_CHECK_OFF(AC97STATE, StatBytesWritten);
+#endif
+    GEN_CHECK_OFF(AC97STATE, lstDrv);
+    GEN_CHECK_OFF(AC97STATE, pMixer);
+    GEN_CHECK_OFF(AC97STATE, pSinkOut);
+    GEN_CHECK_OFF(AC97STATE, pSinkLineIn);
+    GEN_CHECK_OFF(AC97STATE, pSinkMicIn);
+    GEN_CHECK_OFF(AC97STATE, silence);
+    GEN_CHECK_OFF(AC97STATE, bup_flag);
+    GEN_CHECK_OFF(AC97STATE, IBase);
+    GEN_CHECK_OFF(AC97STATE, IOPortBase);
+    GEN_CHECK_OFF(AC97STATE, uCodecModel);
+
     GEN_CHECK_SIZE(HDADRIVERSTREAM);
     GEN_CHECK_OFF(HDADRIVERSTREAM, DestSource);
