Index: trunk/src/VBox/Devices/Serial/DevSerial.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DevSerial.cpp	(revision 11274)
+++ trunk/src/VBox/Devices/Serial/DevSerial.cpp	(revision 11277)
@@ -1,6 +1,5 @@
+/* $Id$ */
 /** @file
- *
- * VBox serial device:
- * Serial communication port driver
+ * DevSerial - 16450 UART emulation.
  */
 
@@ -47,5 +46,4 @@
  *
  */
-
 
 /*******************************************************************************
@@ -60,12 +58,16 @@
 #include <iprt/critsect.h>
 
-#include "Builtins.h"
+#include "../Builtins.h"
 
 #undef VBOX_SERIAL_PCI /* The PCI variant has lots of problems: wrong IRQ line and wrong IO base assigned. */
 
 #ifdef VBOX_SERIAL_PCI
-#include <VBox/pci.h>
+# include <VBox/pci.h>
 #endif /* VBOX_SERIAL_PCI */
 
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
 #define SERIAL_SAVED_STATE_VERSION  3
 
@@ -115,4 +117,8 @@
 #define UART_LSR_DR	                0x01	/* Receiver data ready */
 
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
 struct SerialState
 {
@@ -120,11 +126,11 @@
     PDMCRITSECT                     CritSect;
 
-    /** Pointer to the device instance. */
-    R3PTRTYPE(PPDMDEVINS)           pDevInsHC;
-    /** Pointer to the device instance. */
-    RCPTRTYPE(PPDMDEVINS)           pDevInsGC;
-#if HC_ARCH_BITS == 64
-    RTRCPTR                         Alignment0;
-#endif
+    /** Pointer to the device instance - R3 Ptr. */
+    PPDMDEVINSR3                    pDevInsR3;
+    /** Pointer to the device instance - R0 Ptr. */
+    PPDMDEVINSR0                    pDevInsR0;
+    /** Pointer to the device instance - RC Ptr. */
+    PPDMDEVINSRC                    pDevInsRC;
+    RTRCPTR                         Alignment0; /**< Alignment. */
     /** The base interface. */
     PDMIBASE                        IBase;
@@ -175,4 +181,7 @@
 
 
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
 __BEGIN_DECLS
 PDMBOTHCBDECL(int) serialIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
@@ -181,4 +190,5 @@
 
 #ifdef IN_RING3
+
 static void serial_update_irq(SerialState *s)
 {
@@ -194,16 +204,16 @@
     if (s->iir != UART_IIR_NO_INT) {
         Log(("serial_update_irq %d 1\n", s->irq));
-#ifdef VBOX_SERIAL_PCI
-        PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 1);
-#else /* !VBOX_SERIAL_PCI */
-        PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 1);
-#endif /* !VBOX_SERIAL_PCI */
+# ifdef VBOX_SERIAL_PCI
+        PDMDevHlpPCISetIrqNoWait(s->CTX_SUFF(pDevIns), 0, 1);
+# else /* !VBOX_SERIAL_PCI */
+        PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 1);
+# endif /* !VBOX_SERIAL_PCI */
     } else {
         Log(("serial_update_irq %d 0\n", s->irq));
-#ifdef VBOX_SERIAL_PCI
-        PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 0);
-#else /* !VBOX_SERIAL_PCI */
-        PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 0);
-#endif /* !VBOX_SERIAL_PCI */
+# ifdef VBOX_SERIAL_PCI
+        PDMDevHlpPCISetIrqNoWait(s->CTX_SUFF(pDevIns), 0, 0);
+# else /* !VBOX_SERIAL_PCI */
+        PDMDevHlpISASetIrqNoWait(s->CTX_SUFF(pDevIns), s->irq, 0);
+# endif /* !VBOX_SERIAL_PCI */
     }
 }
@@ -233,5 +243,6 @@
         s->pDrvChar->pfnSetParameters(s->pDrvChar, speed, parity, data_bits, stop_bits);
 }
-#endif
+
+#endif /* IN_RING3 */
 
 static int serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -398,4 +409,5 @@
 
 #ifdef IN_RING3
+
 static DECLCALLBACK(int) serialNotifyRead(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead)
 {
@@ -496,5 +508,5 @@
         {
             Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
-            rc = serial_ioport_write (pThis, Port, u32);
+            rc = serial_ioport_write(pThis, Port, u32);
             PDMCritSectLeave(&pThis->CritSect);
         }
@@ -528,5 +540,5 @@
         if (rc == VINF_SUCCESS)
         {
-            *pu32 = serial_ioport_read (pThis, Port, &rc);
+            *pu32 = serial_ioport_read(pThis, Port, &rc);
             Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
             PDMCritSectLeave(&pThis->CritSect);
@@ -540,4 +552,5 @@
 
 #ifdef IN_RING3
+
 /**
  * Saves a state of the serial port device.
@@ -610,5 +623,5 @@
     if (u32 != ~0U)
     {
-        AssertMsgFailed(("u32=%#x expected ~0\n", u32));
+        AssertLogRelMsgFailed(("u32=%#x expected ~0\n", u32));
         return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
     }
@@ -621,6 +634,9 @@
         AssertRC(rc);
     }
-    pThis->pDevInsHC = pDevIns;
-    pThis->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
+
+    /* this isn't strictly necessary but cannot hurt... */
+    pThis->pDevInsR3 = pDevIns;
+    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     return VINF_SUCCESS;
 }
@@ -633,5 +649,5 @@
 {
     SerialState *pThis = PDMINS_2_DATA(pDevIns, SerialState *);
-    pThis->pDevInsGC   = PDMDEVINS_2_GCPTR(pDevIns);
+    pThis->pDevInsRC   = PDMDEVINS_2_RCPTR(pDevIns);
 }
 
@@ -723,29 +739,15 @@
     Assert(iInstance < 4);
 
-    pThis->pDevInsHC = pDevIns;
-    pThis->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
-
     /*
-     * Validate configuration.
+     * Initialize the instance data.
+     * (Do this early or the destructor might choke on something!)
      */
-    if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0IOBase\0"))
-    {
-        AssertMsgFailed(("serialConstruct Invalid configuration values\n"));
-        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
-    }
-
-    rc = CFGMR3QueryBool(pCfgHandle, "GCEnabled", &pThis->fGCEnabled);
-    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-        pThis->fGCEnabled = true;
-    else if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("Configuration error: Failed to get the \"GCEnabled\" value"));
-
-    rc = CFGMR3QueryBool(pCfgHandle, "R0Enabled", &pThis->fR0Enabled);
-    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-        pThis->fR0Enabled = true;
-    else if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("Configuration error: Failed to get the \"R0Enabled\" value"));
+    pThis->pDevInsR3 = pDevIns;
+    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+
+    pThis->lsr = UART_LSR_TEMT | UART_LSR_THRE;
+    pThis->iir = UART_IIR_NO_INT;
+    pThis->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 
     /* IBase */
@@ -756,50 +758,6 @@
     pThis->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
 
-    rc = RTSemEventCreate(&pThis->ReceiveSem);
-    AssertRC(rc);
-
-    /*
-     * Initialize critical section.
-     * This must of course be done before attaching drivers or anything else which can call us back..
-     */
-    char szName[24];
-    RTStrPrintf(szName, sizeof(szName), "Serial#%d", iInstance);
-    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = CFGMR3QueryU8 (pCfgHandle, "IRQ", &irq_lvl);
-    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-    {
-        /* Provide sensible defaults. */
-        if (iInstance == 0)
-            irq_lvl = 4;
-        else if (iInstance == 1)
-            irq_lvl = 3;
-    }
-    else if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("Configuration error: Failed to get the \"IRQ\" value"));
-
-    rc = CFGMR3QueryU16 (pCfgHandle, "IOBase", &io_base);
-    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-    {
-        if (iInstance == 0)
-            io_base = 0x3f8;
-        else if (iInstance == 1)
-            io_base = 0x2f8;
-    }
-    else if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("Configuration error: Failed to get the \"IOBase\" value"));
-
-    Log(("serialConstruct instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
-
-    pThis->irq = irq_lvl;
-    pThis->lsr = UART_LSR_TEMT | UART_LSR_THRE;
-    pThis->iir = UART_IIR_NO_INT;
-    pThis->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
 #ifdef VBOX_SERIAL_PCI
-    pThis->base = -1;
+    /* the PCI device */
     pThis->dev.config[0x00] = 0xee; /* Vendor: ??? */
     pThis->dev.config[0x01] = 0x80;
@@ -813,19 +771,96 @@
     pThis->dev.config[0x3c] = irq_lvl; /* preconfigure IRQ number (0 = autoconfig)*/
     pThis->dev.config[0x3d] = 1;    /* interrupt pin 0 */
+#endif /* VBOX_SERIAL_PCI */
+
+    /*
+     * Validate and read the configuration.
+     */
+    if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0" "IOBase\0" "GCEnabled\0" "R0Enabled\0"))
+    {
+        AssertMsgFailed(("serialConstruct Invalid configuration values\n"));
+        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
+    }
+
+    rc = CFGMR3QueryBoolDef(pCfgHandle, "GCEnabled", &pThis->fGCEnabled, true);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Failed to get the \"GCEnabled\" value"));
+
+    rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &pThis->fR0Enabled, true);
+    if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Failed to get the \"R0Enabled\" value"));
+
+    rc = CFGMR3QueryU8(pCfgHandle, "IRQ", &irq_lvl);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+    {
+        /* Provide sensible defaults. */
+        if (iInstance == 0)
+            irq_lvl = 4;
+        else if (iInstance == 1)
+            irq_lvl = 3;
+        else
+            AssertReleaseFailed(); /* irq_lvl is undefined. */
+    }
+    else if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Failed to get the \"IRQ\" value"));
+
+    rc = CFGMR3QueryU16(pCfgHandle, "IOBase", &io_base);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+    {
+        if (iInstance == 0)
+            io_base = 0x3f8;
+        else if (iInstance == 1)
+            io_base = 0x2f8;
+        else
+            AssertReleaseFailed(); /* io_base is undefined */
+    }
+    else if (RT_FAILURE(rc))
+        return PDMDEV_SET_ERROR(pDevIns, rc,
+                                N_("Configuration error: Failed to get the \"IOBase\" value"));
+
+    Log(("DevSerial: instance %d iobase=%04x irq=%d\n", iInstance, io_base, irq_lvl));
+
+    pThis->irq = irq_lvl;
+#ifdef VBOX_SERIAL_PCI
+    pThis->base = -1;
+#else
+    pThis->base = io_base;
+#endif
+
+    /*
+     * Initialize critical section and the semaphore.
+     * This must of course be done before attaching drivers or anything else which can call us back..
+     */
+    char szName[24];
+    RTStrPrintf(szName, sizeof(szName), "Serial#%d", iInstance);
+    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = RTSemEventCreate(&pThis->ReceiveSem);
+    AssertRC(rc);
+
+#ifdef VBOX_SERIAL_PCI
+    /*
+     * Register the PCI Device and region.
+     */
     rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev);
     if (RT_FAILURE(rc))
         return rc;
-    /*
-     * Register the PCI I/O ports.
-     */
     rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, serialIOPortRegionMap);
     if (RT_FAILURE(rc))
         return rc;
+
 #else /* !VBOX_SERIAL_PCI */
+    /*
+     * Register the I/O ports.
+     */
     pThis->base = io_base;
     rc = PDMDevHlpIOPortRegister(pDevIns, io_base, 8, 0,
                                  serialIOPortWrite, serialIOPortRead,
                                  NULL, NULL, "SERIAL");
-    if (RT_FAILURE (rc))
+    if (RT_FAILURE(rc))
         return rc;
 
@@ -837,34 +872,10 @@
         rc = PDMDevHlpIOPortRegisterR0(pDevIns, io_base, 8, 0, "serialIOPortWrite",
                                       "serialIOPortRead", NULL, NULL, "Serial");
-
 #endif /* !VBOX_SERIAL_PCI */
 
-    /* Attach the char driver and get the interfaces. For now no run-time
-     * changes are supported. */
-    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char");
-    if (RT_SUCCESS(rc))
-    {
-        pThis->pDrvChar = (PDMICHAR *)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_CHAR);
-        if (!pThis->pDrvChar)
-        {
-            AssertMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
-            return VERR_PDM_MISSING_INTERFACE;
-        }
-        /** @todo provide read notification interface!!!! */
-    }
-    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
-    {
-        pThis->pDrvBase = NULL;
-        pThis->pDrvChar = NULL;
-        LogRel(("Serial%d: no unit\n", iInstance));
-    }
-    else
-    {
-        AssertMsgFailed(("Serial%d: Failed to attach to char driver. rc=%Vrc\n", iInstance, rc));
-        /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
-        return rc;
-    }
-
-    rc = PDMDevHlpSSMRegister (
+    /*
+     * Saved state.
+     */
+    rc = PDMDevHlpSSMRegister(
         pDevIns,                /* pDevIns */
         pDevIns->pDevReg->szDeviceName, /* pszName */
@@ -882,6 +893,35 @@
         return rc;
 
+    /*
+     * Attach the char driver and get the interfaces.
+     * For now no run-time changes are supported.
+     */
+    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->IBase, &pThis->pDrvBase, "Serial Char");
+    if (RT_SUCCESS(rc))
+    {
+        pThis->pDrvChar = (PDMICHAR *)pThis->pDrvBase->pfnQueryInterface(pThis->pDrvBase, PDMINTERFACE_CHAR);
+        if (!pThis->pDrvChar)
+        {
+            AssertLogRelMsgFailed(("Configuration error: instance %d has no char interface!\n", iInstance));
+            return VERR_PDM_MISSING_INTERFACE;
+        }
+        /** @todo provide read notification interface!!!! */
+    }
+    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
+    {
+        pThis->pDrvBase = NULL;
+        pThis->pDrvChar = NULL;
+        LogRel(("Serial%d: no unit\n", iInstance));
+    }
+    else
+    {
+        AssertLogRelMsgFailed(("Serial%d: Failed to attach to char driver. rc=%Vrc\n", iInstance, rc));
+        /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
+        return rc;
+    }
+
     return VINF_SUCCESS;
 }
+
 
 /**
Index: trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp	(revision 11274)
+++ trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp	(revision 11277)
@@ -901,6 +901,7 @@
     GEN_CHECK_OFF(SerialState, fGCEnabled);
     GEN_CHECK_OFF(SerialState, fR0Enabled);
-    GEN_CHECK_OFF(SerialState, pDevInsGC);
-    GEN_CHECK_OFF(SerialState, pDevInsHC);
+    GEN_CHECK_OFF(SerialState, pDevInsR3);
+    GEN_CHECK_OFF(SerialState, pDevInsR0);
+    GEN_CHECK_OFF(SerialState, pDevInsRC);
     GEN_CHECK_OFF(SerialState, IBase);
     GEN_CHECK_OFF(SerialState, ICharPort);
