genode/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h

112 lines
2.6 KiB
C++

/*
* \brief Registry of PCI devices
* \author Norman Feske
* \date 2015-09-09
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_
#define _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_
/* Linux emulation environment includes */
#include <lx_emul/impl/internal/pci_dev.h>
namespace Lx {
class Pci_dev_registry;
/**
* Return singleton 'Pci_dev_registry' object
*
* Implementation must be provided by the driver.
*/
Pci_dev_registry *pci_dev_registry();
}
class Lx::Pci_dev_registry
{
private:
List<Pci_dev> _devs;
public:
void insert(Pci_dev *pci_dev)
{
PDBG("insert pci_dev %p", pci_dev);
_devs.insert(pci_dev);
}
Genode::Io_mem_dataspace_capability io_mem(resource_size_t phys,
Genode::Cache_attribute cache_attribute,
Genode::size_t size)
{
enum { PCI_ROM_RESOURCE = 6 };
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
unsigned bar = 0;
for (; bar < PCI_ROM_RESOURCE; bar++) {
if ((pci_resource_flags(d, bar) & IORESOURCE_MEM) &&
(pci_resource_start(d, bar) == phys))
break;
}
if (bar >= PCI_ROM_RESOURCE)
continue;
Platform::Device &device = d->client();
unsigned const resource_id =
device.phys_bar_to_virt(bar);
/* offset from the beginning of the PCI resource */
Genode::addr_t const offset =
phys - pci_resource_start(d, bar);
Genode::Io_mem_session_capability io_mem_cap =
device.io_mem(resource_id, cache_attribute, offset, size);
return Genode::Io_mem_session_client(io_mem_cap).dataspace();
}
PERR("Device using i/o memory of address %zx is unknown", phys);
return Genode::Io_mem_dataspace_capability();
}
template <typename T>
T io_read(unsigned port)
{
PDBG("io_read %u", port);
/* try I/O access on all PCI devices */
for (Pci_dev *d = _devs.first(); d; d = d->next()) {
T value = 0;
if (d->io_port().in<T>(port, &value))
return value;
}
PWRN("I/O port(%u) read failed", port);
return (T)~0;
}
template <typename T>
void io_write(unsigned port, T value)
{
PDBG("io_write %u", port);
/* try I/O access on all PCI devices, return on first success */
for (Pci_dev *d = _devs.first(); d; d = d->next())
if (d->io_port().out<T>(port, value))
return;
PWRN("I/O port(%u) write failed", port);
}
};
#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ */