/** Linux PCI helpers * * @file * @author Steffen Vogel * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC * @license Apache License 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(logging.get("kernel:pci")) { } Device(Id i) : id(i), log(logging.get("kernel:pci")) { } Device(Slot s) : slot(s), log(logging.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> { public: // Initialize Linux PCI handle. // // This search for all available PCI devices under /sys/bus/pci DeviceList(); 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