2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/machine/Device.h"
4#include "pedigree/kernel/machine/Pci.h"
5#include "pedigree/kernel/machine/PciDrivers.h"
6#include "pedigree/kernel/process/Mutex.h"
7#include "pedigree/kernel/utilities/List.h"
8#include "pedigree/kernel/utilities/new"
11enum class State { Available, SlotPrepared, UnloadPrepared, Retired };
20 Registration* owner =
nullptr;
22 Device* controller =
nullptr;
23 State state = State::Available;
31uint16_t routeId(
Device* device) {
32 return (device->getPciBusPosition() << 8) | (device->getPciDevicePosition() << 3) |
33 device->getPciFunctionNumber();
36bool pciFunction(
Device* device) {
37 Device* parent = device->getParent();
38 return parent && parent->
getSpecificType() ==
"pci" && device->getPciVendorId() &&
39 device->getPciVendorId() != 0xffff && device->getPciBusPosition() < 256 &&
40 device->getPciDevicePosition() < 32 && device->getPciFunctionNumber() < 8;
43Function* findFunction(uint16_t route) {
44 for (
auto* function : g_Functions) {
45 if (function->route == route) {
53 for (
auto* registration : g_Drivers) {
54 if (registration->driver == driver) {
63 bool duplicate =
false;
65 if (pciFunction(device) && routeId(device) == route &&
66 (!driver || (device->getPciClassCode() == driver->classCode &&
67 device->getPciSubclassCode() == driver->subclass &&
68 device->getPciProgInterface() == driver->progInterface &&
69 device->getType() ==
Device::Root && !device->getNumChildren()))) {
70 duplicate |= result !=
nullptr;
75 pedigree_std::Callable<
decltype(visit)> callback(visit);
77 return duplicate ? nullptr : result;
80bool bind(Function& function, Registration& registration) {
81 if (registration.closing || function.owner || function.state != State::Available) {
86 const auto& driver = *registration.driver;
87 Device* pci = resolve(function.route, &driver);
91 Device* controller = driver.attach(pci);
96 function.controller = controller;
97 function.owner = ®istration;
101void unbind(Function& function) {
102 function.owner->driver->remove(function.controller);
103 function.owner =
nullptr;
104 function.controller =
nullptr;
105 function.pci =
nullptr;
106 function.state = State::Available;
110namespace PciDrivers {
118 if (valid && pciFunction(device)) {
119 const uint16_t route = routeId(device);
120 if (findFunction(route)) {
123 auto* function =
new Function{route};
124 if (!function || !g_Functions.
tryPushBack(function)) {
132 pedigree_std::Callable<
decltype(visit)> callback(visit);
135 while (g_Functions.
count()) {
144bool registerDriver(
const Driver* driver) {
145 if (!driver || !driver->attach || !driver->prepareRemove || !driver->cancelRemove ||
150 if (!g_Ready || findDriver(driver)) {
153 auto* registration =
new Registration{driver};
154 if (!registration || !g_Drivers.
tryPushBack(registration)) {
158 for (
auto* function : g_Functions) {
159 bind(*function, *registration);
164bool prepareUnregisterDriver(
const Driver* driver) {
166 Registration* registration = findDriver(driver);
167 if (!registration || registration->closing) {
170 for (
auto* function : g_Functions) {
171 if (function->owner == registration && function->state != State::Available) {
175 registration->closing =
true;
176 for (
auto* function : g_Functions) {
177 if (function->owner != registration) {
180 if (!driver->prepareRemove(function->controller)) {
181 for (
auto* prepared : g_Functions) {
182 if (prepared->owner == registration && prepared->state == State::UnloadPrepared) {
183 driver->cancelRemove(prepared->controller);
184 prepared->state = State::Available;
187 registration->closing =
false;
190 function->state = State::UnloadPrepared;
195bool unregisterDriver(
const Driver* driver) {
197 Registration* registration = findDriver(driver);
201 if (!registration->closing) {
204 for (
auto* function : g_Functions) {
205 if (function->owner == registration && function->state != State::UnloadPrepared) {
209 for (
auto* function : g_Functions) {
210 if (function->owner == registration) {
214 for (
auto it = g_Drivers.
begin(); it != g_Drivers.
end(); ++it) {
215 if (*it == registration) {
229 if (!g_Ready || resolve(routeId(pci)) != pci) {
232 Function* function = findFunction(routeId(pci));
234 function =
new Function{routeId(pci)};
235 if (!function || !g_Functions.
tryPushBack(function)) {
240 if (function->owner) {
241 return function->pci == pci && function->state == State::Available;
243 if (function->state == State::Retired) {
244 function->state = State::Available;
246 for (
auto* registration : g_Drivers) {
247 if (bind(*function, *registration)) {
254bool prepareRemove(
Device* pci) {
259 Function* function = findFunction(routeId(pci));
260 if (!function || function->state != State::Available ||
261 (function->owner && function->pci != pci)) {
266 auto& bus = PciBus::instance();
267 if (bus.hasDmaRemapping(pci) && !bus.hasDmaIsolation(pci)) {
270 if (function->owner) {
271 if (function->owner->closing || !function->owner->driver->prepareRemove(function->controller)) {
275 if (resolve(function->route) != pci || bus.hasDmaRemapping(pci)) {
284 uint16_t command = 0;
285 if (!PciBus::instance().readConfig16(pci, 4, command) || (command & 4)) {
290 function->state = State::SlotPrepared;
294void cancelRemove(
Device* pci) {
299 Function* function = findFunction(routeId(pci));
300 if (!function || function->state != State::SlotPrepared || function->pci != pci) {
303 if (function->owner) {
304 function->owner->driver->cancelRemove(function->controller);
306 function->pci =
nullptr;
308 function->state = State::Available;
316 Function* function = findFunction(routeId(pci));
317 if (!function || function->state != State::SlotPrepared || function->pci != pci) {
320 if (function->owner) {
323 function->pci =
nullptr;
324 function->state = State::Retired;
static void foreach(Callback callback, Device *root=0)
@ Root
The device is the root of the device tree.
virtual const String & getSpecificType()
Iterator erase(Iterator &Iter)
bool tryPushBack(const T &value)