/** 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 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 */ bool writeBar(uint32_t new_bar); /** If BAR values in config space and in the kernel do not match, rewrite * the BAR value of the kernel to PCIe config space. */ bool rewriteBar(); /** Read 32-bit BAR value from the PCI configuration space */ bool readBar(uint32_t &bar) const; /** Read 32-bit BAR value from the devices resource file. This is what the kernel * thinks the BAR should be. */ bool readHostBar(uint32_t &bar) const; Id id; Slot slot; private: villas::Logger log; }; 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