From 77ab7bf68bb34db6d297df938902bc65144203d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Tue, 1 Feb 2022 15:00:05 +0100 Subject: [PATCH] lx_emul: add PCI config space handling Ref genodelabs/genode#4411 --- .../src/include/lx_emul/pci_config_space.h | 28 +++++++ repos/dde_linux/src/include/lx_kit/device.h | 3 + .../src/lib/lx_emul/pci_config_space.cc | 82 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 repos/dde_linux/src/include/lx_emul/pci_config_space.h create mode 100644 repos/dde_linux/src/lib/lx_emul/pci_config_space.cc 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; +}