diff --git a/repos/dde_linux/src/include/lx_emul/pci_config_space.h b/repos/dde_linux/src/include/lx_emul/pci_config_space.h new file mode 100644 index 0000000000..4ea46796a1 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/pci_config_space.h @@ -0,0 +1,28 @@ +/* + * \brief Lx_emul support for accessing PCI(e) config space + * \author Josef Soentgen + * \date 2022-01-18 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_EMUL__PCI_CONFIG_SPACE_H_ +#define _LX_EMUL__PCI_CONFIG_SPACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int lx_emul_pci_read_config(unsigned bus, unsigned devfn, unsigned reg, unsigned len, unsigned *val); +int lx_emul_pci_write_config(unsigned bus, unsigned devfn, unsigned reg, unsigned len, unsigned val); + +#ifdef __cplusplus +} +#endif + +#endif /* _LX_EMUL__PCI_CONFIG_SPACE_H_ */ diff --git a/repos/dde_linux/src/include/lx_kit/device.h b/repos/dde_linux/src/include/lx_kit/device.h index f619562281..cfce48ee10 100644 --- a/repos/dde_linux/src/include/lx_kit/device.h +++ b/repos/dde_linux/src/include/lx_kit/device.h @@ -122,6 +122,9 @@ class Lx_kit::Device : List::Element bool irq_unmask(unsigned irq); void irq_mask(unsigned irq); void irq_ack(unsigned irq); + + bool read_config(unsigned reg, unsigned len, unsigned *val); + bool write_config(unsigned reg, unsigned len, unsigned val); }; diff --git a/repos/dde_linux/src/lib/lx_emul/pci_config_space.cc b/repos/dde_linux/src/lib/lx_emul/pci_config_space.cc new file mode 100644 index 0000000000..3fb22b4c72 --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/pci_config_space.cc @@ -0,0 +1,82 @@ +/* + * \brief Lx_emul backend for accessing PCI(e) config space + * \author Josef Soentgen + * \date 2022-01-18 + */ + +/* + * Copyright (C) 2022 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + + +using Device_name = Genode::String<16>; + +template +static Device_name to_string(T const &arg, TAIL &&... args) +{ + return Device_name(arg, args...); +} + + +static Device_name assemble(unsigned bus, unsigned devfn) +{ + using namespace Genode; + return to_string("pci-", + Hex(bus, Hex::OMIT_PREFIX), ":", + Hex((devfn >> 3) & 0x1fu, Hex::OMIT_PREFIX), ".", + Hex(devfn & 0x7u, Hex::OMIT_PREFIX)); +} + + +int lx_emul_pci_read_config(unsigned bus, unsigned devfn, + unsigned reg, unsigned len, unsigned *val) +{ + using namespace Lx_kit; + using namespace Genode; + + Device_name name = assemble(bus, devfn); + + bool result = false; + bool matched = false; + + env().devices.for_each([&] (Device & d) { + matched = name == d.name(); + if (matched && val) + result = d.read_config(reg, len, val); + }); + + if (!result && matched) + error("could not read config space register ", Hex(reg)); + + return result ? 0 : -1; +} + + +int lx_emul_pci_write_config(unsigned bus, unsigned devfn, + unsigned reg, unsigned len, unsigned val) +{ + using namespace Lx_kit; + using namespace Genode; + + Device_name name = assemble(bus, devfn); + + bool result = false; + bool matched = false; + env().devices.for_each ([&] (Device & d) { + matched = name == d.name(); + if (matched) + result = d.write_config(reg, len, val); + }); + + if (!result && matched) + error("could not write config space register ", Hex(reg), + " with ", Hex(val)); + + return result ? 0 : -1; +}