PCI helper find_cap
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 26 Jan 2015 18:40:42 +0000 (13:40 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 Feb 2015 15:12:30 +0000 (10:12 -0500)
Adds a find_cap helper, similar to the BSD one.

kern/arch/x86/ioapic.c
kern/arch/x86/pci.c
kern/arch/x86/pci.h
kern/arch/x86/trap.c

index 215c2c9..a4f8f58 100644 (file)
@@ -521,7 +521,8 @@ static void ioapic_unmask_irq(struct irq_handler *unused, int apic_vector)
  * appropriately.
  *
  * Callers init irq_h->dev_irq and ->tbdf.  tbdf encodes the bus type and the
- * classic PCI bus:dev:func.
+ * classic PCI bus:dev:func.  dev_irq may be ignored based on the bus type (e.g.
+ * PCI, esp MSI).
  *
  * In plan9, this was ioapicintrenable(), which also unmasked.  We don't have a
  * deinit/disable method that would tear down the route yet.  All the plan9 one
index 1aa5435..505be0b 100644 (file)
@@ -12,6 +12,7 @@
 #include <assert.h>
 #include <kmalloc.h>
 #include <arch/pci_defs.h>
+#include <ros/errno.h>
 
 /* List of all discovered devices */
 struct pcidev_stailq pci_devices = STAILQ_HEAD_INITIALIZER(pci_devices);
@@ -562,3 +563,16 @@ void pci_dump_config(struct pci_device *pcidev, size_t len)
        for (int i = 0; i < len; i += 4)
                printk("0x%03x | %08x\n", i, pcidev_read32(pcidev, i));
 }
+
+int pci_find_cap(struct pci_device *pcidev, uint8_t cap_id, uint32_t *cap_reg)
+{
+       if (cap_id > PCI_CAP_ID_MAX)
+               return -EINVAL;
+       if (!pcidev->caps[cap_id])
+               return -ENOENT;
+       /* The actual value at caps[id] is the offset in the PCI config space where
+        * that ID was stored.  That's needed for accessing the capability. */
+       if (cap_reg)
+               *cap_reg = pcidev->caps[cap_id];
+       return 0;
+}
index fa1d4df..6088720 100644 (file)
@@ -414,6 +414,7 @@ uint16_t pci_get_device(struct pci_device *pcidev);
 uint16_t pci_get_subvendor(struct pci_device *pcidev);
 uint16_t pci_get_subdevice(struct pci_device *pcidev);
 void pci_dump_config(struct pci_device *pcidev, size_t len);
+int pci_find_cap(struct pci_device *pcidev, uint8_t cap_id, uint32_t *cap_reg);
 
 /* MSI functions, msi.c */
 int pci_msi_enable(struct pci_device *p, uint64_t vec);
index 10526be..78a3d2b 100644 (file)
@@ -539,6 +539,7 @@ out_no_eoi:
        assert(0);
 }
 
+/* The irq field may be ignored based on the type of Bus. */
 int register_irq(int irq, isr_t handler, void *irq_arg, uint32_t tbdf)
 {
        struct irq_handler *irq_h;