-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathpci_device.hpp
More file actions
138 lines (101 loc) · 3.38 KB
/
pci_device.hpp
File metadata and controls
138 lines (101 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Linux PCI helpers.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <fstream>
#include <list>
#include <cstddef>
#include <cstdint>
#include <villas/log.hpp>
#include <villas/kernel/devices/device.hpp>
namespace villas {
namespace kernel {
namespace devices {
#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 PciDevice : public Device {
private:
static constexpr char PROBE_DEFAULT[] = "/sys/bus/pci/drivers_probe";
static constexpr char OVERRIDE_DEFAULT[] = "driver_override";
public:
PciDevice(Id i, Slot s) : id(i), slot(s), log(Log::get("kernel:pci")) {}
PciDevice(Id i) : id(i), log(Log::get("kernel:pci")) {}
PciDevice(Slot s) : slot(s), log(Log::get("kernel:pci")) {}
bool operator==(const PciDevice &other);
// Implement device interface
std::optional<std::unique_ptr<Driver>> driver() const override;
std::optional<int> iommu_group() const override;
std::string name() const override;
std::filesystem::path override_path() const override;
std::filesystem::path path() const override;
void probe() const override;
// Bind a new LKM to the PCI device
bool attachDriver(const std::string &driver) const;
std::list<Region> 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 PciDeviceList : public std::list<std::shared_ptr<PciDevice>> {
private:
// Initialize Linux PCI handle.
//
// This search for all available PCI devices under /sys/bus/pci
PciDeviceList();
PciDeviceList &operator=(const PciDeviceList &);
static PciDeviceList *instance;
public:
static PciDeviceList *getInstance();
PciDeviceList::value_type lookupDevice(const Slot &s);
PciDeviceList::value_type lookupDevice(const Id &i);
PciDeviceList::value_type lookupDevice(const PciDevice &f);
};
} // namespace devices
} // namespace kernel
} // namespace villas