Index: /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp	(revision 33686)
+++ /trunk/src/VBox/Devices/Bus/DevPciIch9.cpp	(revision 33687)
@@ -253,8 +253,10 @@
     {
         PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
+
         PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
         pThis->uConfigReg = u32 & ~3; /* Bits 0-1 are reserved and we silently clear them */
         PCI_UNLOCK(pDevIns);
     }
+
     return VINF_SUCCESS;
 }
@@ -311,4 +313,8 @@
                 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, pAddr->iBus, pAddr->iDeviceFunc, pAddr->iRegister, val, cb);
             }
+            else
+            {
+                // do nothing, bridge not found
+            }
 #else
             rc = rcReschedule;
@@ -360,5 +366,6 @@
 static void ich9pciNoMem(void* ptr, int cb)
 {
-    memset(ptr, 0xff, cb);
+    for (int i = 0; i < cb; i++)
+        ((uint8_t*)ptr)[i] = 0xff;
 }
 
@@ -448,9 +455,11 @@
 }
 
-static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int len, uint32_t *pu32)
+static int ich9pciDataRead(PPCIGLOBALS pGlobals, uint32_t addr, int cb, uint32_t *pu32)
 {
     PciAddress aPciAddr;
 
-    LogFlow(("ich9pciDataRead: config=%x len=%d\n",  pGlobals->uConfigReg, len));
+    LogFlow(("ich9pciDataRead: config=%x cb=%d\n",  pGlobals->uConfigReg, cb));
+
+    *pu32 = 0xffffffff;
 
     if (!(pGlobals->uConfigReg & (1 << 31)))
@@ -463,5 +472,5 @@
     ich9pciStateToPciAddr(pGlobals, addr, &aPciAddr);
 
-    return ich9pciDataReadAddr(pGlobals, &aPciAddr, len, pu32, VINF_IOM_HC_IOPORT_READ);
+    return ich9pciDataReadAddr(pGlobals, &aPciAddr, cb, pu32, VINF_IOM_HC_IOPORT_READ);
 }
 
@@ -1038,5 +1047,5 @@
         }
         else
-            ich9pciNoMem(&u32Value, cb);
+            ich9pciNoMem(&u32Value, 4);
     }
     else
@@ -1050,5 +1059,5 @@
         }
         else
-            ich9pciNoMem(&u32Value, cb);
+            ich9pciNoMem(&u32Value, 4);
     }
 
@@ -1979,9 +1988,7 @@
     },
     /* Disable, if we may wish to have multiple AHCI controllers */
-#if 1
     {
         "ahci",     31, 2 /* SATA controller */
     },
-#endif
     {
         "smbus",    31, 3 /* System Management Bus */
@@ -2021,10 +2028,4 @@
 
     int iStartPos = 0;
-
-    /* We add bridges starting slot 22 */
-    if (!strcmp(pszName, "ich9pcibridge"))
-    {
-        iStartPos = 22 * 8;
-    }
 
     /* Otherwise when assigning a slot, we need to make sure all its functions are available */
Index: /trunk/src/VBox/Main/BusAssignmentManager.cpp
===================================================================
--- /trunk/src/VBox/Main/BusAssignmentManager.cpp	(revision 33687)
+++ /trunk/src/VBox/Main/BusAssignmentManager.cpp	(revision 33687)
@@ -0,0 +1,160 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VirtualBox bus slots assignment manager
+ */
+
+/*
+ * Copyright (C) 2010 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.
+ */
+#include "BusAssignmentManager.h"
+
+#include <iprt/asm.h>
+
+#include <VBox/cfgm.h>
+
+#include <map>
+
+struct BusAssignmentManager::State
+{
+    struct PciDeviceRecord
+    {
+        char szDevName[16];
+    };
+
+    typedef std::map <PciBusAddress, PciDeviceRecord > PciMap;
+
+    volatile int32_t cRefCnt;
+    ChipsetType_T    mChipsetType;
+    PciMap           mPciMap;
+
+    State()
+        : cRefCnt(1), mChipsetType(ChipsetType_Null)
+    {}
+    ~State()
+    {}
+
+    HRESULT init(ChipsetType_T chipsetType);
+
+    HRESULT autoAssign(const char* pszName, PciBusAddress& Address);
+    bool checkAvailable(PciBusAddress& Address);    
+};
+
+HRESULT BusAssignmentManager::State::init(ChipsetType_T chipsetType)
+{
+    mChipsetType = chipsetType;
+    return S_OK;
+}
+
+HRESULT BusAssignmentManager::State::autoAssign(const char* pszName, PciBusAddress& Address)
+{
+    // unimplemented yet
+    Assert(false);
+    return S_OK;
+}
+
+bool BusAssignmentManager::State::checkAvailable(PciBusAddress& Address)
+{
+    PciMap::const_iterator it = mPciMap.find(Address);
+    
+    return (it == mPciMap.end());
+}
+
+BusAssignmentManager::BusAssignmentManager()
+    : pState(NULL)
+{
+    pState = new State();
+    Assert(pState);
+}
+
+BusAssignmentManager::~BusAssignmentManager()
+{
+    if (pState)
+    {
+        delete pState;
+        pState = NULL;
+    }
+}
+
+
+BusAssignmentManager* BusAssignmentManager::pInstance = NULL;
+
+BusAssignmentManager* BusAssignmentManager::getInstance(ChipsetType_T chipsetType)
+{
+    if (pInstance == NULL)
+    {
+        pInstance = new BusAssignmentManager();
+        pInstance->pState->init(chipsetType);
+        Assert(pInstance);
+        return pInstance;
+    }
+
+    pInstance->AddRef();
+    return pInstance;
+}
+
+void BusAssignmentManager::AddRef()
+{
+    ASMAtomicIncS32(&pState->cRefCnt);
+}
+void BusAssignmentManager::Release()
+{
+    if (ASMAtomicDecS32(&pState->cRefCnt) == 1)
+        delete this;
+}
+
+DECLINLINE(HRESULT) InsertConfigInteger(PCFGMNODE pCfg,  const char* pszName, uint64_t u64)
+{
+    int vrc = CFGMR3InsertInteger(pCfg, pszName, u64);
+    if (RT_FAILURE(vrc))
+        return E_INVALIDARG;
+
+    return S_OK;
+}
+
+HRESULT BusAssignmentManager::assignPciDevice(const char* pszDevName, PCFGMNODE pCfg,
+                                           PciBusAddress& Address,    bool fAddressRequired)
+{
+    HRESULT rc = S_OK;
+
+    if (!Address.valid())
+        rc = pState->autoAssign(pszDevName, Address);
+    else
+    {
+        bool fAvailable = pState->checkAvailable(Address);
+
+        if (!fAvailable)
+        {
+            if (fAddressRequired)
+                return E_ACCESSDENIED;
+            else
+                rc = pState->autoAssign(pszDevName, Address);
+        }
+    }
+
+    if (FAILED(rc))
+        return rc;
+
+    Assert(Address.valid());
+
+    rc = InsertConfigInteger(pCfg, "PCIBusNo",             Address.iBus);
+    if (FAILED(rc))
+        return rc;
+    rc = InsertConfigInteger(pCfg, "PCIDeviceNo",          Address.iDevice);
+    if (FAILED(rc))
+        return rc;
+    rc = InsertConfigInteger(pCfg, "PCIFunctionNo",        Address.iFn);
+    if (FAILED(rc))
+        return rc;
+
+    return S_OK;
+}
Index: /trunk/src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 33686)
+++ /trunk/src/VBox/Main/ConsoleImpl2.cpp	(revision 33687)
@@ -108,4 +108,5 @@
 
 #include "DHCPServerRunner.h"
+#include "BusAssignmentManager.h"
 
 #if defined(RT_OS_DARWIN)
@@ -467,6 +468,5 @@
 {
     LogFlowFuncEnter();
-    /* Note: hardcoded assumption about number of slots; see rom bios */
-    bool afPciDeviceNo[32] = {false};
+    PciBusAddress         PciAddr;
     bool fFdcEnabled = false;
     BOOL fIs64BitGuest = false;
@@ -547,4 +547,7 @@
         u64McfgBase = _4G - cbRamHole;
     }
+
+    ComPtr<BusAssignmentManager> BusMgr =
+            BusAssignmentManager::getInstance(chipsetType);
 
     ULONG cCpus = 1;
@@ -879,7 +882,11 @@
             InsertConfigNode(pDev,     "0", &pInst);
             InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
+            PciAddr = PciBusAddress(0, 24, 0);
+            hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst, PciAddr);                               H();
 
             InsertConfigNode(pDev,     "1", &pInst);
             InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
+            PciAddr = PciBusAddress(0, 25, 0);
+            hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst, PciAddr);                               H();
         }
 
@@ -1049,8 +1056,7 @@
         InsertConfigNode(pDev,     "0", &pInst);
         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
-        InsertConfigInteger(pInst, "PCIDeviceNo",          2);
-        Assert(!afPciDeviceNo[2]);
-        afPciDeviceNo[2] = true;
-        InsertConfigInteger(pInst, "PCIFunctionNo",        0);
+
+        PciAddr = PciBusAddress(0, 2, 0);
+        hrc = BusMgr->assignPciDevice("vga", pInst, PciAddr);                               H();
         InsertConfigNode(pInst,    "Config", &pCfg);
         ULONG cVRamMBs;
@@ -1319,9 +1325,7 @@
                 case StorageControllerType_LsiLogic:
                 {
-                    // InsertConfigInteger(pCtlInst, "PCIBusNo",             1);
-                    InsertConfigInteger(pCtlInst, "PCIDeviceNo",          20);
-                    Assert(!afPciDeviceNo[20]);
-                    afPciDeviceNo[20] = true;
-                    InsertConfigInteger(pCtlInst, "PCIFunctionNo",        0);
+                    PciAddr = PciBusAddress(1, 20, 0);
+                    hrc = BusMgr->assignPciDevice("lsilogic", pCtlInst, PciAddr);                               H();
+
 
                     /* Attach the status driver */
@@ -1339,8 +1343,6 @@
                 case StorageControllerType_BusLogic:
                 {
-                    InsertConfigInteger(pCtlInst, "PCIDeviceNo",          21);
-                    Assert(!afPciDeviceNo[21]);
-                    afPciDeviceNo[21] = true;
-                    InsertConfigInteger(pCtlInst, "PCIFunctionNo",        0);
+                    PciAddr = PciBusAddress(0, 21, 0);
+                    hrc = BusMgr->assignPciDevice("buslogic", pCtlInst, PciAddr);                               H();
 
                     /* Attach the status driver */
@@ -1358,8 +1360,6 @@
                 case StorageControllerType_IntelAhci:
                 {
-                    InsertConfigInteger(pCtlInst, "PCIDeviceNo",          13);
-                    Assert(!afPciDeviceNo[13]);
-                    afPciDeviceNo[13] = true;
-                    InsertConfigInteger(pCtlInst, "PCIFunctionNo",        0);
+                    PciAddr = PciBusAddress(0, 13, 0);
+                    hrc = BusMgr->assignPciDevice("ahci", pCtlInst, PciAddr);                               H();
 
                     ULONG cPorts = 0;
@@ -1406,8 +1406,6 @@
                      * IDE (update this when the main interface changes)
                      */
-                    InsertConfigInteger(pCtlInst, "PCIDeviceNo",          1);
-                    Assert(!afPciDeviceNo[1]);
-                    afPciDeviceNo[1] = true;
-                    InsertConfigInteger(pCtlInst, "PCIFunctionNo",        1);
+                    PciAddr = PciBusAddress(0, 1, 1);
+                    hrc = BusMgr->assignPciDevice("ide", pCtlInst, PciAddr);                               H();
                     InsertConfigString(pCfg,   "Type", controllerString(enmCtrlType));
 
@@ -1454,8 +1452,6 @@
                 case StorageControllerType_LsiLogicSas:
                 {
-                    InsertConfigInteger(pCtlInst, "PCIDeviceNo",          22);
-                    Assert(!afPciDeviceNo[22]);
-                    afPciDeviceNo[22] = true;
-                    InsertConfigInteger(pCtlInst, "PCIFunctionNo",        0);
+                    PciAddr = PciBusAddress(0, 22, 0);
+                    hrc = BusMgr->assignPciDevice("lsilogicsas", pCtlInst, PciAddr);                               H();
 
                     InsertConfigString(pCfg,  "ControllerType", "SAS1068");
@@ -1591,8 +1587,7 @@
                 iPciDeviceNo = 3;
 #endif
-            InsertConfigInteger(pInst, "PCIDeviceNo", iPciDeviceNo);
-            Assert(!afPciDeviceNo[iPciDeviceNo]);
-            afPciDeviceNo[iPciDeviceNo] = true;
-            InsertConfigInteger(pInst, "PCIFunctionNo",        0);
+            PciAddr = PciBusAddress(0, iPciDeviceNo, 0);
+            hrc = BusMgr->assignPciDevice(pszAdapterName, pInst, PciAddr);                               H();
+
             InsertConfigNode(pInst, "Config", &pCfg);
 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE   /* not safe here yet. */
@@ -1819,8 +1814,7 @@
         InsertConfigNode(pInst,    "Config", &pCfg);
         InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
-        InsertConfigInteger(pInst, "PCIDeviceNo",          4);
-        Assert(!afPciDeviceNo[4]);
-        afPciDeviceNo[4] = true;
-        InsertConfigInteger(pInst, "PCIFunctionNo",        0);
+        PciAddr = PciBusAddress(0, 4, 0);
+        hrc = BusMgr->assignPciDevice("VMMDev", pInst, PciAddr);                               H();
+
         Bstr hwVersion;
         hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam());                 H();
@@ -1883,8 +1877,6 @@
                     InsertConfigNode(pDev,     "0", &pInst);
                     InsertConfigInteger(pInst, "Trusted",          1); /* boolean */
-                    InsertConfigInteger(pInst, "PCIDeviceNo",      5);
-                    Assert(!afPciDeviceNo[5]);
-                    afPciDeviceNo[5] = true;
-                    InsertConfigInteger(pInst, "PCIFunctionNo",    0);
+                    PciAddr = PciBusAddress(0, 5, 0);
+                    hrc = BusMgr->assignPciDevice("ichac97", pInst, PciAddr);                               H();
                     InsertConfigNode(pInst,    "Config", &pCfg);
                     break;
@@ -1910,8 +1902,6 @@
                     InsertConfigNode(pDev,     "0", &pInst);
                     InsertConfigInteger(pInst, "Trusted",          1); /* boolean */
-                    InsertConfigInteger(pInst, "PCIDeviceNo",      5);
-                    Assert(!afPciDeviceNo[5]);
-                    afPciDeviceNo[5] = true;
-                    InsertConfigInteger(pInst, "PCIFunctionNo",    0);
+                    PciAddr = PciBusAddress(0, 5, 0);
+                    hrc = BusMgr->assignPciDevice("hda", pInst, PciAddr);                               H();
                     InsertConfigNode(pInst,    "Config", &pCfg);
                 }
@@ -2012,9 +2002,6 @@
                 InsertConfigNode(pInst,    "Config", &pCfg);
                 InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
-                InsertConfigInteger(pInst, "PCIDeviceNo",          6);
-                Assert(!afPciDeviceNo[6]);
-                afPciDeviceNo[6] = true;
-                InsertConfigInteger(pInst, "PCIFunctionNo",        0);
-
+                PciAddr = PciBusAddress(0, 6, 0);
+                hrc = BusMgr->assignPciDevice("usb-ohci", pInst, PciAddr);                               H();
                 InsertConfigNode(pInst,    "LUN#0", &pLunL0);
                 InsertConfigString(pLunL0, "Driver",               "VUSBRootHub");
@@ -2040,8 +2027,6 @@
                     InsertConfigNode(pInst,    "Config", &pCfg);
                     InsertConfigInteger(pInst, "Trusted",              1); /* boolean */
-                    InsertConfigInteger(pInst, "PCIDeviceNo",          11);
-                    Assert(!afPciDeviceNo[11]);
-                    afPciDeviceNo[11] = true;
-                    InsertConfigInteger(pInst, "PCIFunctionNo",        0);
+                    PciAddr = PciBusAddress(0, 11, 0);
+                    hrc = BusMgr->assignPciDevice("usb-ohci", pInst, PciAddr);                               H();
 
                     InsertConfigNode(pInst,    "LUN#0", &pLunL0);
@@ -2302,4 +2287,7 @@
             InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
             InsertConfigNode(pInst,    "Config", &pCfg);
+            PciAddr = PciBusAddress(0, 7, 0);
+            hrc = BusMgr->assignPciDevice("acpi", pInst, PciAddr);                               H();
+
             InsertConfigInteger(pCfg,  "RamSize",          cbRam);
             InsertConfigInteger(pCfg,  "RamHoleSize",      cbRamHole);
@@ -2332,8 +2320,4 @@
             InsertConfigInteger(pCfg,  "ShowCpu", fShowCpu);
             InsertConfigInteger(pCfg,  "CpuHotPlug", fCpuHotPlug);
-            InsertConfigInteger(pInst, "PCIDeviceNo",          7);
-            Assert(!afPciDeviceNo[7]);
-            afPciDeviceNo[7] = true;
-            InsertConfigInteger(pInst, "PCIFunctionNo",        0);
 
             InsertConfigNode(pInst,    "LUN#0", &pLunL0);
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 33686)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 33687)
@@ -636,4 +636,5 @@
 	VMMDevInterface.cpp \
 	EventImpl.cpp \
+	BusAssignmentManager.cpp \
 	$(VBOX_AUTOGEN_EVENT_CPP) \
 	$(VBOX_XML_SCHEMADEFS_CPP) \
Index: /trunk/src/VBox/Main/include/BusAssignmentManager.h
===================================================================
--- /trunk/src/VBox/Main/include/BusAssignmentManager.h	(revision 33687)
+++ /trunk/src/VBox/Main/include/BusAssignmentManager.h	(revision 33687)
@@ -0,0 +1,114 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VirtualBox bus slots assignment manager
+ */
+
+/*
+ * Copyright (C) 2010 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 __BusAssignmentManager_h
+#define __BusAssignmentManager_h
+
+#include "VBox/types.h"
+#include "VirtualBoxBase.h"
+
+struct PciBusAddress
+{
+    int  iBus;
+    int  iDevice;
+    int  iFn;
+
+    PciBusAddress()
+    {
+        clear();
+    }
+
+    PciBusAddress(int bus, int device, int fn)
+        : iBus(bus), iDevice(device), iFn(fn)
+    {
+    }
+
+    PciBusAddress& clear()
+    {
+        iBus = iDevice = iFn = -1;
+        return *this;
+    }
+
+    bool operator<(const PciBusAddress &a) const
+    {
+        if (iBus < a.iBus)
+            return true;
+        
+        if (iBus > a.iBus)
+            return false;
+
+        if (iDevice < a.iDevice)
+            return true;
+        
+        if (iDevice > a.iDevice)
+            return false;
+
+        if (iFn < a.iFn)
+            return true;
+        
+        if (iFn > a.iFn)
+            return false;
+
+        return false;
+    }
+
+    bool operator==(const PciBusAddress &a) const
+    {
+        return     (iBus == a.iBus)
+                && (iDevice == a.iDevice)
+                && (iFn == a.iFn);
+    }
+
+    bool operator!=(const PciBusAddress &a) const
+    {
+        return     (iBus != a.iBus)
+                || (iDevice != a.iDevice)
+                || (iFn  != a.iFn);
+    }
+
+    bool valid() const
+    {
+        return (iBus != -1) && (iDevice != -1) && (iFn != -1);
+    }
+};
+
+class BusAssignmentManager
+{
+private:
+    struct State;
+    State* pState;
+
+    BusAssignmentManager();
+    virtual ~BusAssignmentManager();
+
+    static BusAssignmentManager* pInstance;
+
+public:
+    static BusAssignmentManager* getInstance(ChipsetType_T chipsetType);
+    virtual void AddRef();
+    virtual void Release();
+
+    virtual HRESULT assignPciDevice(const char* pszDevName, PCFGMNODE pCfg, PciBusAddress& Address, bool fAddressRequired = false);
+    virtual HRESULT assignPciDevice(const char* pszDevName, PCFGMNODE pCfg)
+    {
+        PciBusAddress Address;
+        return assignPciDevice(pszDevName, pCfg, Address, false);
+    }
+};
+
+#endif //  __BusAssignmentManager_h
