diff options
Diffstat (limited to 'pci.c')
-rw-r--r-- | pci.c | 75 |
1 files changed, 75 insertions, 0 deletions
@@ -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; +} |