/* Linux PCI helpers. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include #include #include #include #include namespace villas { namespace kernel { namespace pci { #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) #define PCI_FUNC(devfn) ((devfn) & 0x07) class Id { public: Id(const std::string &str); Id(int vid = 0, int did = 0, int cc = 0) : vendor(vid), device(did), class_code(cc) {} bool operator==(const Id &i); unsigned int vendor; unsigned int device; unsigned int class_code; }; class Slot { public: Slot(const std::string &str); Slot(int dom = 0, int b = 0, int dev = 0, int fcn = 0) : domain(dom), bus(b), device(dev), function(fcn) {} bool operator==(const Slot &s); unsigned int domain; unsigned int bus; unsigned int device; unsigned int function; }; struct Region { int num; uintptr_t start; uintptr_t end; unsigned long long flags; }; class Device { public: Device(Id i, Slot s) : id(i), slot(s), log(Log::get("kernel:pci")) {} Device(Id i) : id(i), log(Log::get("kernel:pci")) {} Device(Slot s) : slot(s), log(Log::get("kernel:pci")) {} bool operator==(const Device &other); // Get currently loaded driver for device std::string getDriver() const; // Bind a new LKM to the PCI device bool attachDriver(const std::string &driver) const; // Return the IOMMU group of this PCI device or -1 if the device is not in a group int getIommuGroup() const; std::list getRegions() const; // Write 32-bit BAR value from to the PCI configuration space void writeBar(uint32_t addr, unsigned bar = 0); // If BAR values in config space and in the kernel do not match, rewrite // the BAR value of the kernel to PCIe config space void rewriteBar(unsigned bar = 0); // Read 32-bit BAR value from the PCI configuration space uint32_t readBar(unsigned bar = 0) const; // Read 32-bit BAR value from the devices resource file. // This is what the kernel thinks the BAR should be. uint32_t readHostBar(unsigned bar = 0) const; Id id; Slot slot; private: villas::Logger log; protected: std::fstream openSysFs(const std::string &subPath, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) const; }; class DeviceList : public std::list> { private: // Initialize Linux PCI handle. // // This search for all available PCI devices under /sys/bus/pci DeviceList(); DeviceList &operator=(const DeviceList &); static DeviceList *instance; public: static DeviceList *getInstance(); DeviceList::value_type lookupDevice(const Slot &s); DeviceList::value_type lookupDevice(const Id &i); DeviceList::value_type lookupDevice(const Device &f); }; } // namespace pci } // namespace kernel } // namespace villas