BusAssignmentManager.cpp revision 8af676a2588a2b1eb143f1a47abd295c1499cd2f
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/* $Id$ */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** @file
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox bus slots assignment manager
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2010 Oracle Corporation
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License (GPL) as published by the Free Software
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include "BusAssignmentManager.h"
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <iprt/asm.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <VBox/cfgm.h>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync#include <map>
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstruct BusAssignmentManager::State
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync struct PciDeviceRecord
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync char szDevName[16];
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync };
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync typedef std::map <PciBusAddress, PciDeviceRecord > PciMap;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync volatile int32_t cRefCnt;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ChipsetType_T mChipsetType;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PciMap mPciMap;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync State()
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync : cRefCnt(1), mChipsetType(ChipsetType_Null)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ~State()
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync HRESULT init(ChipsetType_T chipsetType);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync HRESULT autoAssign(const char* pszName, PciBusAddress& Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync bool checkAvailable(PciBusAddress& Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync};
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncHRESULT BusAssignmentManager::State::init(ChipsetType_T chipsetType)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync mChipsetType = chipsetType;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return S_OK;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncHRESULT BusAssignmentManager::State::autoAssign(const char* pszName, PciBusAddress& Address)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync // unimplemented yet
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(false);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return S_OK;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncbool BusAssignmentManager::State::checkAvailable(PciBusAddress& Address)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync PciMap::const_iterator it = mPciMap.find(Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return (it == mPciMap.end());
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncBusAssignmentManager::BusAssignmentManager()
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync : pState(NULL)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pState = new State();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(pState);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsyncBusAssignmentManager::~BusAssignmentManager()
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync{
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync if (pState)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync delete pState;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pState = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncBusAssignmentManager* BusAssignmentManager::pInstance = NULL;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncBusAssignmentManager* BusAssignmentManager::getInstance(ChipsetType_T chipsetType)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (pInstance == NULL)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pInstance = new BusAssignmentManager();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync pInstance->pState->init(chipsetType);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(pInstance);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return pInstance;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync pInstance->AddRef();
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync return pInstance;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync}
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid BusAssignmentManager::AddRef()
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync ASMAtomicIncS32(&pState->cRefCnt);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncvoid BusAssignmentManager::Release()
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (ASMAtomicDecS32(&pState->cRefCnt) == 1)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync delete this;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncDECLINLINE(HRESULT) InsertConfigInteger(PCFGMNODE pCfg, const char* pszName, uint64_t u64)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int vrc = CFGMR3InsertInteger(pCfg, pszName, u64);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (RT_FAILURE(vrc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return E_INVALIDARG;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return S_OK;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncHRESULT BusAssignmentManager::assignPciDevice(const char* pszDevName, PCFGMNODE pCfg,
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync PciBusAddress& Address, bool fAddressRequired)
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync{
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync HRESULT rc = S_OK;
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync if (!Address.valid())
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsync rc = pState->autoAssign(pszDevName, Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync else
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync bool fAvailable = pState->checkAvailable(Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (!fAvailable)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync {
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (fAddressRequired)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return E_ACCESSDENIED;
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync else
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync rc = pState->autoAssign(pszDevName, Address);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync }
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (FAILED(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync Assert(Address.valid());
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = InsertConfigInteger(pCfg, "PCIBusNo", Address.iBus);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (FAILED(rc))
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync return rc;
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync rc = InsertConfigInteger(pCfg, "PCIDeviceNo", Address.iDevice);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (FAILED(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync rc = InsertConfigInteger(pCfg, "PCIFunctionNo", Address.iFn);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync if (FAILED(rc))
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return rc;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync return S_OK;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync}
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync