Index: trunk/src/VBox/Devices/Serial/DevOxPcie958.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DevOxPcie958.cpp	(revision 81889)
+++ trunk/src/VBox/Devices/Serial/DevOxPcie958.cpp	(revision 81891)
@@ -107,10 +107,5 @@
     /** Pointer to the device instance - RC ptr. */
     PPDMDEVINSRC                    pDevInsRC;
-    /** Flag whether R0 is enabled. */
-    bool                            fR0Enabled;
-    /** Flag whether RC is enabled. */
-    bool                            fRCEnabled;
-    /** Alignment. */
-    bool                            afAlignment[2];
+    uint32_t                        u32Alignment;
     /** UART global IRQ status. */
     volatile uint32_t               u32RegIrqStsGlob;
@@ -123,7 +118,8 @@
     /** MMIO Base address. */
     RTGCPHYS                        GCPhysMMIO;
+    /** Handle to the MMIO region (PCI region \#0). */
+    IOMMMIOHANDLE                   hMmio;
     /** The UARTs. */
     OX958UART                       aUarts[OX958_UARTS_MAX];
-
 } DEVOX958;
 /** Pointer to an OXPCIe958 device instance. */
@@ -138,7 +134,8 @@
  *
  * @returns nothing.
+ * @param   pDevIns             The device instance.
  * @param   pThis               The OXPCIe958 device instance.
  */
-static void ox958IrqUpdate(PDEVOX958 pThis)
+static void ox958IrqUpdate(PPDMDEVINS pDevIns, PDEVOX958 pThis)
 {
     uint32_t u32IrqSts = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob);
@@ -146,7 +143,7 @@
 
     if (u32IrqSts & u32IrqEn)
-        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_HIGH);
+        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
     else
-        PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW);
+        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
 }
 
@@ -155,5 +152,5 @@
  * Performs a register read from the given UART.
  *
- * @returns nothing.
+ * @returns Strict VBox status code.
  * @param   pThis               The OXPCIe958 device instance.
  * @param   pUart               The UART accessed.
@@ -162,7 +159,7 @@
  * @param   cb                  Number of bytes to read.
  */
-static int ox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb)
-{
-    int rc = VINF_SUCCESS;
+static VBOXSTRICTRC ox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb)
+{
+    VBOXSTRICTRC rc;
     RT_NOREF(pThis);
 
@@ -170,4 +167,5 @@
     {
         /* Access to the DMA registers. */
+        rc = VINF_SUCCESS;
     }
     else /* Access UART registers. */
@@ -181,5 +179,5 @@
  * Performs a register write to the given UART.
  *
- * @returns nothing.
+ * @returns Strict VBox status code.
  * @param   pThis               The OXPCIe958 device instance.
  * @param   pUart               The UART accessed.
@@ -188,7 +186,7 @@
  * @param   cb                  Number of bytes to write.
  */
-static int ox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb)
-{
-    int rc = VINF_SUCCESS;
+static VBOXSTRICTRC ox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb)
+{
+    VBOXSTRICTRC rc;
     RT_NOREF(pThis);
 
@@ -196,4 +194,5 @@
     {
         /* Access to the DMA registers. */
+        rc = VINF_SUCCESS;
     }
     else /* Access UART registers. */
@@ -222,31 +221,23 @@
     else
         ASMAtomicAndU32(&pThis->u32RegIrqStsGlob, ~RT_BIT_32(iLUN));
-    ox958IrqUpdate(pThis);
-}
-
-
-/**
- * Read a MMIO register.
- *
- * @returns VBox status code suitable for scheduling.
- * @param   pDevIns     The device instance.
- * @param   pvUser      A user argument (ignored).
- * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
- * @param   pv          Where to put the data we read.
- * @param   cb          The size of the read.
- */
-PDMBOTHCBDECL(int) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
-{
-    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
-    uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
-    int       rc = VINF_SUCCESS;
-    RT_NOREF(pThis, pvUser);
-
-    if (offReg < OX958_REG_UART_REGION_OFFSET)
+    ox958IrqUpdate(pDevIns, pThis);
+}
+
+
+/**
+ * @callback_method_impl{FNIOMMMIONEWREAD}
+ */
+static DECLCALLBACK(VBOXSTRICTRC) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
+{
+    PDEVOX958    pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
+    VBOXSTRICTRC rc    = VINF_SUCCESS;
+    RT_NOREF(pvUser);
+
+    if (off < OX958_REG_UART_REGION_OFFSET)
     {
         uint32_t *pu32 = (uint32_t *)pv;
         Assert(cb == 4);
 
-        switch (offReg)
+        switch ((uint32_t)off)
         {
             case OX958_REG_CC_REV_ID:
@@ -278,8 +269,8 @@
     {
         /* Figure out the UART accessed from the offset. */
-        offReg -= OX958_REG_UART_REGION_OFFSET;
-        uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
-        uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
-        if (iUart < pThis->cUarts)
+        off -= OX958_REG_UART_REGION_OFFSET;
+        uint32_t iUart      = (uint32_t)off / OX958_REG_UART_REGION_SIZE;
+        uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE;
+        if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
         {
             POX958UART pUart = &pThis->aUarts[iUart];
@@ -297,34 +288,26 @@
 
 /**
- * Write to a MMIO register.
- *
- * @returns VBox status code suitable for scheduling.
- * @param   pDevIns     The device instance.
- * @param   pvUser      A user argument (ignored).
- * @param   GCPhysAddr  The physical address being written to. (This is within our MMIO memory range.)
- * @param   pv          Pointer to the data being written.
- * @param   cb          The size of the data being written.
- */
-PDMBOTHCBDECL(int) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
-{
-    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
-    uint32_t  offReg = (GCPhysAddr - pThis->GCPhysMMIO);
-    int       rc = VINF_SUCCESS;
+ * @callback_method_impl{FNIOMMMIONEWWRITE}
+ */
+static DECLCALLBACK(VBOXSTRICTRC) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
+{
+    PDEVOX958    pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
+    VBOXSTRICTRC rc    = VINF_SUCCESS;
     RT_NOREF1(pvUser);
 
-    if (offReg < OX958_REG_UART_REGION_OFFSET)
+    if (off < OX958_REG_UART_REGION_OFFSET)
     {
         const uint32_t u32 = *(const uint32_t *)pv;
         Assert(cb == 4);
 
-        switch (offReg)
+        switch ((uint32_t)off)
         {
             case OX958_REG_UART_IRQ_ENABLE:
                 ASMAtomicOrU32(&pThis->u32RegIrqEnGlob, u32);
-                ox958IrqUpdate(pThis);
+                ox958IrqUpdate(pDevIns, pThis);
                 break;
             case OX958_REG_UART_IRQ_DISABLE:
                 ASMAtomicAndU32(&pThis->u32RegIrqEnGlob, ~u32);
-                ox958IrqUpdate(pThis);
+                ox958IrqUpdate(pDevIns, pThis);
                 break;
             case OX958_REG_UART_WAKE_IRQ_ENABLE:
@@ -338,5 +321,5 @@
             case OX958_REG_UART_CNT:     /* Readonly */
             default:
-                rc = VINF_SUCCESS;
+                break;
         }
     }
@@ -344,8 +327,8 @@
     {
         /* Figure out the UART accessed from the offset. */
-        offReg -= OX958_REG_UART_REGION_OFFSET;
-        uint32_t iUart = offReg / OX958_REG_UART_REGION_SIZE;
-        uint32_t offUartReg = offReg % OX958_REG_UART_REGION_SIZE;
-        if (iUart < pThis->cUarts)
+        off -= OX958_REG_UART_REGION_OFFSET;
+        uint32_t iUart      = (uint32_t)off / OX958_REG_UART_REGION_SIZE;
+        uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE;
+        if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
         {
             POX958UART pUart = &pThis->aUarts[iUart];
@@ -361,48 +344,4 @@
 
 #ifdef IN_RING3
-/**
- * @callback_method_impl{FNPCIIOREGIONMAP}
- */
-static DECLCALLBACK(int) ox958R3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
-                                    RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
-{
-    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
-    int       rc    = VINF_SUCCESS;
-    RT_NOREF(pPciDev, enmType);
-    Assert(pPciDev == pDevIns->apPciDevs[0]);
-
-    if (iRegion == 0)
-    {
-        Assert(enmType == PCI_ADDRESS_SPACE_MEM);
-
-        rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
-                                   IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
-                                   ox958MmioWrite, ox958MmioRead, "OxPCIe958");
-        if (RT_FAILURE(rc))
-            return rc;
-
-        /* Enable (or not) RC/R0 support. */
-        if (pThis->fRCEnabled)
-        {
-            rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
-                                         "ox958MmioWrite", "ox958MmioRead");
-            if (RT_FAILURE(rc))
-                return rc;
-        }
-
-        if (pThis->fR0Enabled)
-        {
-            rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,
-                                         "ox958MmioWrite", "ox958MmioRead");
-            if (RT_FAILURE(rc))
-                return rc;
-        }
-
-        pThis->GCPhysMMIO = GCPhysAddress;
-    }
-
-    return VINF_SUCCESS;
-}
-
 
 /** @interface_method_impl{PDMDEVREG,pfnDetach} */
@@ -425,5 +364,5 @@
     RT_NOREF(fFlags);
 
-    if (iLUN >= pThis->cUarts)
+    if (iLUN >= RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)))
         return VERR_PDM_LUN_NOT_FOUND;
 
@@ -441,5 +380,6 @@
     pThis->u32RegIrqEnWake  = 0x00;
 
-    for (uint32_t i = 0; i < pThis->cUarts; i++)
+    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
+    for (uint32_t i = 0; i < cUarts; i++)
         uartR3Reset(&pThis->aUarts[i].UartCore);
 }
@@ -453,5 +393,6 @@
 
     pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
-    for (uint32_t i = 0; i < pThis->cUarts; i++)
+    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
+    for (uint32_t i = 0; i < cUarts; i++)
         uartR3Relocate(&pThis->aUarts[i].UartCore, offDelta);
 }
@@ -461,8 +402,9 @@
 static DECLCALLBACK(int) ox958R3Destruct(PPDMDEVINS pDevIns)
 {
+    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
     PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
-    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
-
-    for (uint32_t i = 0; i < pThis->cUarts; i++)
+
+    uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts));
+    for (uint32_t i = 0; i < cUarts; i++)
         uartR3Destruct(&pThis->aUarts[i].UartCore);
 
@@ -474,42 +416,33 @@
 static DECLCALLBACK(int) ox958R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
 {
+    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     RT_NOREF(iInstance);
-    PDEVOX958   pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
-    bool        fRCEnabled = true;
-    bool        fR0Enabled = true;
-    bool        fMsiXSupported = false;
-    int         rc;
-
-    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+    PDEVOX958       pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
+    PCPDMDEVHLPR3   pHlp  = pDevIns->pHlpR3;
+    bool            fMsiXSupported = false;
+    int             rc;
+
+    /*
+     * Init instance data.
+     */
+    pThis->pDevInsR3             = pDevIns;
+    pThis->pDevInsR0             = PDMDEVINS_2_R0PTR(pDevIns);
+    pThis->pDevInsRC             = PDMDEVINS_2_RCPTR(pDevIns);
+
+    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+    AssertRCReturn(rc, rc);
 
     /*
      * Validate and read configuration.
      */
-    if (!CFGMR3AreValuesValid(pCfg, "RCEnabled\0"
-                                    "R0Enabled\0"
-                                    "MsiXSupported\0"
-                                    "UartCount\0"))
-        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
-                                N_("OXPCIe958 configuration error: Unknown option specified"));
-
-    rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true);
+    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "MsiXSupported|UartCount", "");
+
+    rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true);
     if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("OXPCIe958 configuration error: Failed to read \"RCEnabled\" as boolean"));
-
-    rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
+        return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean"));
+
+    rc = pHlp->pfnCFGMQueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX);
     if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("OXPCIe958 configuration error: failed to read \"R0Enabled\" as boolean"));
-
-    rc = CFGMR3QueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true);
-    if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean"));
-
-    rc = CFGMR3QueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX);
-    if (RT_FAILURE(rc))
-        return PDMDEV_SET_ERROR(pDevIns, rc,
-                                N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer"));
+        return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer"));
 
     if (!pThis->cUarts || pThis->cUarts > OX958_UARTS_MAX)
@@ -519,13 +452,6 @@
 
     /*
-     * Init instance data.
+     * Fill PCI config space.
      */
-    pThis->fR0Enabled            = fR0Enabled;
-    pThis->fRCEnabled            = fRCEnabled;
-    pThis->pDevInsR3             = pDevIns;
-    pThis->pDevInsR0             = PDMDEVINS_2_R0PTR(pDevIns);
-    pThis->pDevInsRC             = PDMDEVINS_2_RCPTR(pDevIns);
-
-    /* Fill PCI config space. */
     PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
@@ -534,10 +460,10 @@
     PDMPciDevSetDeviceId(pPciDev,           OX958_PCI_DEVICE_ID);
     PDMPciDevSetCommand(pPciDev,            0x0000);
-#ifdef VBOX_WITH_MSI_DEVICES
+# ifdef VBOX_WITH_MSI_DEVICES
     PDMPciDevSetStatus(pPciDev,             VBOX_PCI_STATUS_CAP_LIST);
     PDMPciDevSetCapabilityList(pPciDev,     OX958_PCI_MSI_CAP_OFS);
-#else
+# else
     PDMPciDevSetCapabilityList(pPciDev,     0x70);
-#endif
+# endif
     PDMPciDevSetRevisionId(pPciDev,         0x00);
     PDMPciDevSetClassBase(pPciDev,          0x07); /* Communication controller. */
@@ -552,8 +478,4 @@
     PDMPciDevSetInterruptPin(pPciDev,       0x01);
     /** @todo More Capabilities. */
-
-    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
-    if (RT_FAILURE(rc))
-        return rc;
 
     /*
@@ -564,5 +486,5 @@
         return rc;
 
-#ifdef VBOX_WITH_MSI_DEVICES
+# ifdef VBOX_WITH_MSI_DEVICES
     PDMMSIREG MsiReg;
     RT_ZERO(MsiReg);
@@ -584,9 +506,11 @@
         /* That's OK, we can work without MSI */
     }
-#endif
-
-    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, _16K, PCI_ADDRESS_SPACE_MEM, ox958R3Map);
-    if (RT_FAILURE(rc))
-        return rc;
+# endif
+
+    rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0 /*iPciRegion*/, _16K, PCI_ADDRESS_SPACE_MEM,
+                                        ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/,
+                                        IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
+                                        "OxPCIe958", &pThis->hMmio);
+    AssertRCReturn(rc, rc);
 
     /** @todo This dynamic symbol resolving will be reworked later! */
@@ -595,6 +519,6 @@
     RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR;
 
-#ifdef VBOX_WITH_RAW_MODE_KEEP
-    if (   fRCEnabled
+# ifdef VBOX_WITH_RAW_MODE_KEEP
+    if (   pDevIns->fRCEnabled
         && VM_IS_RAW_MODE_ENABLED(pVM))
     {
@@ -603,7 +527,7 @@
             return rc;
     }
-#endif
-
-    if (fR0Enabled)
+# endif
+
+    if (pDevIns->fR0Enabled)
     {
         rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->pszR0Mod, "ox958IrqReq", &pfnSerialIrqReqR0);
@@ -625,5 +549,24 @@
 }
 
-#endif /* IN_RING3 */
+#else  /* !IN_RING3 */
+
+/**
+ * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
+ */
+static DECLCALLBACK(int) ox958RZConstruct(PPDMDEVINS pDevIns)
+{
+    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
+    PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);
+
+    int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+    AssertRCReturn(rc, rc);
+
+    rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/);
+    AssertRCReturn(rc, rc);
+
+    return VINF_SUCCESS;
+}
+
+#endif /* !IN_RING3 */
 
 
@@ -670,5 +613,5 @@
 #elif defined(IN_RING0)
     /* .pfnEarlyConstruct = */      NULL,
-    /* .pfnConstruct = */           NULL,
+    /* .pfnConstruct = */           ox958RZConstruct,
     /* .pfnDestruct = */            NULL,
     /* .pfnFinalDestruct = */       NULL,
@@ -683,5 +626,5 @@
     /* .pfnReserved7 = */           NULL,
 #elif defined(IN_RC)
-    /* .pfnConstruct = */           NULL,
+    /* .pfnConstruct = */           ox958RZConstruct,
     /* .pfnReserved0 = */           NULL,
     /* .pfnReserved1 = */           NULL,
