[PATCH 4/5] lib: add pci bus scan support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add API to scan bus for a given device,
as well as API to access BAR registers.

Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
---
 config-x86-common.mak |  1 +
 lib/x86/pci.c         | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/x86/pci.h         | 16 +++++++++++++++
 3 files changed, 72 insertions(+)
 create mode 100644 lib/x86/pci.c
 create mode 100644 lib/x86/pci.h

diff --git a/config-x86-common.mak b/config-x86-common.mak
index 1f0f1ba..455032b 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -14,6 +14,7 @@ cflatobjs += lib/x86/apic.o
 cflatobjs += lib/x86/atomic.o
 cflatobjs += lib/x86/desc.o
 cflatobjs += lib/x86/isr.o
+cflatobjs += lib/x86/pci.o
 
 $(libcflat): LDFLAGS += -nostdlib
 $(libcflat): CFLAGS += -ffreestanding -I lib
diff --git a/lib/x86/pci.c b/lib/x86/pci.c
new file mode 100644
index 0000000..f95cd88
--- /dev/null
+++ b/lib/x86/pci.c
@@ -0,0 +1,55 @@
+#include <linux/pci_regs.h>
+#include "pci.h"
+
+static void outl(unsigned short port, unsigned val)
+{
+    asm volatile("outl %d0, %w1" : : "a"(val), "Nd"(port));
+}
+
+static unsigned inl(unsigned short port)
+{
+    unsigned data;
+    asm volatile("inl %w1, %d0" : "=a"(data) : "Nd"(port));
+    return data;
+}
+static uint32_t pci_config_read(pcidevaddr_t dev, uint8_t reg)
+{
+    uint32_t index = reg | (dev << 8) | (0x1 << 31); 
+    outl(0xCF8, index);
+    return inl(0xCFC);
+}
+
+/* Scan bus look for a specific device. Only bus 0 scanned for now. */
+pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id)
+{
+    unsigned dev;
+    for (dev = 0; dev < 256; ++dev) {
+    uint32_t id = pci_config_read(dev, 0);
+    if ((id & 0xFFFF) == vendor_id && (id >> 16) == device_id) {
+        return dev;
+    }
+    }
+    return PCIDEVADDR_INVALID;
+}
+
+unsigned long pci_bar_addr(pcidevaddr_t dev, int bar_num)
+{
+    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
+    if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
+        return bar & PCI_BASE_ADDRESS_IO_MASK;
+    } else {
+        return bar & PCI_BASE_ADDRESS_MEM_MASK;
+    }
+}
+
+bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num)
+{
+    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
+    return !(bar & PCI_BASE_ADDRESS_SPACE_IO);
+}
+
+bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num)
+{
+    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
+    return bar;
+}
diff --git a/lib/x86/pci.h b/lib/x86/pci.h
new file mode 100644
index 0000000..0f69ef0
--- /dev/null
+++ b/lib/x86/pci.h
@@ -0,0 +1,16 @@
+#ifndef PCI_H
+#define PCI_H
+
+#include <inttypes.h>
+#include "libcflat.h"
+
+typedef uint16_t pcidevaddr_t;
+enum {
+    PCIDEVADDR_INVALID = 0x0
+};
+pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id);
+unsigned long pci_bar_addr(pcidevaddr_t dev, int bar_num);
+bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num);
+bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
+
+#endif
-- 
MST

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux