summaryrefslogtreecommitdiffstats
path: root/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'pci.c')
-rw-r--r--pci.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/pci.c b/pci.c
new file mode 100644
index 0000000..16569ae
--- /dev/null
+++ b/pci.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "pci.h"
+
+struct pci_access *pci;
+struct pci_dev *dev;
+
+void find_device(char *name,
+ unsigned int vendor,
+ unsigned int device)
+{
+ struct pci_filter filter;
+ struct pci_dev *d;
+
+ if (!pci) {
+ pci = pci_alloc();
+ if (!pci) {
+ fprintf(stderr, "libpci alloc failed\n");
+ exit(1);
+ }
+ pci_init(pci);
+ pci_scan_bus(pci);
+ }
+
+ pci_filter_init(pci, &filter);
+ filter.vendor = vendor;
+ filter.device = device;
+
+ for (d = pci->devices; d != NULL; d = d->next) {
+ if (!pci_filter_match(&filter, d))
+ continue;
+ dev = d;
+ fprintf(stderr, "%s found at %02x:%02x.%x\n",
+ name, dev->bus, dev->dev, dev->func);
+ return;
+ }
+ fprintf(stderr, "%s not found\n", name);
+ exit(1);
+}
+
+void *mmap_bar(int nr)
+{
+ char filename[128];
+ size_t size;
+ int fd;
+ void *bar;
+
+ snprintf(filename, sizeof(filename),
+ "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource%d",
+ dev->domain, dev->bus, dev->dev, dev->func, nr);
+ size = dev->size[nr];
+ fd = open(filename, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "open %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ bar = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
+ if (bar == MAP_FAILED) {
+ fprintf(stderr, "mmap %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+ if (size >= (1 << 20)) {
+ fprintf(stderr, "bar %d mapped (%zd MB)\n", nr, size >> 20);
+ } else {
+ fprintf(stderr, "bar %d mapped (%zd bytes)\n", nr, size);
+ }
+ return bar;
+}