mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
kernel/pci: parse BAR regions
This commit is contained in:
parent
2bfb9e2450
commit
ad820a3618
2 changed files with 77 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "list.h"
|
||||
|
||||
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
|
||||
|
@ -33,6 +34,13 @@ struct pci_device {
|
|||
} slot; /**< Bus, Device, Function (BDF) */
|
||||
};
|
||||
|
||||
struct pci_region {
|
||||
int num;
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
unsigned long long flags;
|
||||
};
|
||||
|
||||
struct pci {
|
||||
struct list devices; /**< List of available PCI devices in the system (struct pci_device) */
|
||||
};
|
||||
|
@ -66,6 +74,8 @@ int pci_attach_driver(const struct pci_device *d, const char *driver);
|
|||
/** Return the IOMMU group of this PCI device or -1 if the device is not in a group. */
|
||||
int pci_get_iommu_group(const struct pci_device *d);
|
||||
|
||||
size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -254,6 +254,73 @@ struct pci_device * pci_lookup_device(struct pci *p, struct pci_device *f)
|
|||
return list_search(&p->devices, (cmp_cb_t) pci_device_compare, (void *) f);
|
||||
}
|
||||
|
||||
size_t pci_get_regions(const struct pci_device *d, struct pci_region** regions)
|
||||
{
|
||||
FILE* f;
|
||||
char sysfs[1024];
|
||||
|
||||
assert(regions != NULL);
|
||||
|
||||
snprintf(sysfs, sizeof(sysfs), "%s/bus/pci/devices/%04x:%02x:%02x.%x/resource",
|
||||
SYSFS_PATH, d->slot.domain, d->slot.bus, d->slot.device, d->slot.function);
|
||||
|
||||
f = fopen(sysfs, "r");
|
||||
if (!f)
|
||||
serror("Failed to open resource mapping %s", sysfs);
|
||||
|
||||
struct pci_region _regions[8];
|
||||
struct pci_region* cur_region = _regions;
|
||||
size_t valid_regions = 0;
|
||||
|
||||
ssize_t bytesRead;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
int region = 0;
|
||||
// cap to 8 regions, just because we don't know how many may exist
|
||||
while(region < 8 && (bytesRead = getline(&line, &len, f)) != -1) {
|
||||
unsigned long long tokens[3];
|
||||
char* s = line;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
char* end;
|
||||
tokens[i] = strtoull(s, &end, 16);
|
||||
if(s == end) {
|
||||
printf("Error parsing line %d of %s\n", region + 1, sysfs);
|
||||
tokens[0] = tokens[1] = 0; // mark invalid
|
||||
break;
|
||||
}
|
||||
s = end;
|
||||
}
|
||||
|
||||
free(line);
|
||||
|
||||
// required for getline() to allocate a new buffer on the next iteration
|
||||
line = NULL;
|
||||
len = 0;
|
||||
|
||||
if(tokens[0] != tokens[1]) {
|
||||
// this is a valid region
|
||||
cur_region->num = region;
|
||||
cur_region->start = tokens[0];
|
||||
cur_region->end = tokens[1];
|
||||
cur_region->flags = tokens[2];
|
||||
cur_region++;
|
||||
valid_regions++;
|
||||
}
|
||||
|
||||
region++;
|
||||
}
|
||||
|
||||
if(valid_regions > 0) {
|
||||
const size_t len = valid_regions * sizeof (struct pci_region);
|
||||
*regions = malloc(len);
|
||||
memcpy(*regions, _regions, len);
|
||||
}
|
||||
|
||||
return valid_regions;
|
||||
}
|
||||
|
||||
|
||||
int pci_get_driver(const struct pci_device *d, char *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
|
Loading…
Add table
Reference in a new issue