Commit 1e72e806 authored by Daniel Krebs's avatar Daniel Krebs
Browse files

kernel/pci: parse BAR regions

parent b34d776c
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment