genode/repos/dde_linux/src/include/lx_emul/impl/pci.h
2017-02-28 12:59:29 +01:00

78 lines
1.8 KiB
C++

/*
* \brief Implementation of linux/pci.h
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux kit includes */
#include <lx_kit/env.h>
#include <lx_kit/pci_dev_registry.h>
#include <lx_kit/mapped_io_mem_range.h>
#include <lx_emul/impl/pci_resource.h>
extern "C" int pci_register_driver(struct pci_driver *driver)
{
driver->driver.name = driver->name;
pci_device_id const *id_table = driver->id_table;
if (!id_table)
return -ENODEV;
using namespace Genode;
Lx::Pci_dev *pci_dev = nullptr;
auto lamda = [&] (Platform::Device_capability cap) {
Platform::Device_client client(cap);
/* request device ID from platform driver */
unsigned const device_id = client.device_id();
/* look if we find the device ID in the driver's 'id_table' */
pci_device_id const *matching_id = nullptr;
for (pci_device_id const *id = id_table; id->device; id++) {
if (id->device == device_id)
matching_id = id;
}
/* skip device that is not handled by driver */
if (!matching_id)
return false;
/* create 'pci_dev' struct for matching device */
pci_dev = new (&Lx_kit::env().heap()) Lx::Pci_dev(cap);
/* enable ioremap to work */
Lx::pci_dev_registry()->insert(pci_dev);
/* register driver at the 'pci_dev' struct */
pci_dev->dev.driver = &driver->driver;
/* call probe function of the Linux driver */
if (driver->probe(pci_dev, matching_id)) {
/* if the probing failed, revert the creation of 'pci_dev' */
pci_dev_put(pci_dev);
pci_dev = nullptr;
return false;
}
/* aquire the device, stop iterating */
return true;
};
Lx::for_each_pci_device(lamda);
return pci_dev ? 0 : -ENODEV;
}