summaryrefslogtreecommitdiff
path: root/src/pirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pirq.c')
-rw-r--r--src/pirq.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/pirq.c b/src/pirq.c
new file mode 100644
index 0000000..a342ac3
--- /dev/null
+++ b/src/pirq.c
@@ -0,0 +1,150 @@
+/*
+ * PCI IRQ Routing Table dumper
+ * Copyright (c) 2006 Dell, Inc.
+ * by Matt Domsch <Matt_Domsch@dell.com>
+ *
+ * Based on the description of said table found at
+ * http://www.microsoft.com/hwdev/busbios/pciirq.htm
+ * Licensed under the GNU General Public license, version 2.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <sys/mman.h>
+#include "pirq.h"
+
+/* If unknown, use INT_MAX so they get sorted last */
+int pirq_pci_dev_to_slot(struct routing_table *table, int bus, int dev)
+{
+ int i, num_slots;
+ struct slot_entry *slot;
+
+ if (!table)
+ return INT_MAX;
+
+ num_slots = (table->size - 32) / sizeof(*slot);
+ for (i=0; i<num_slots; i++) {
+ slot = &table->slot[i];
+ if (slot->bus == bus &&
+ PCI_DEVICE(slot->device) == dev)
+ return slot->slot;
+ }
+ return INT_MAX;
+}
+
+
+
+struct routing_table * pirq_alloc_read_table()
+{
+ struct routing_table *table = NULL;
+ uint16_t size = 0;
+ uint8_t checksum = 0;
+ int i;
+ void *mem;
+ off_t offset=0L;
+ int fd=open("/dev/mem", O_RDONLY);
+
+ if(fd==-1)
+ {
+ perror("open(/dev/mem)");
+ return NULL;
+ }
+
+ mem = mmap(0, 64*1024, PROT_READ, MAP_SHARED, fd, 0xF0000L);
+ if (!mem) {
+ perror("mmap(/dev/mem)");
+ goto out;
+ }
+
+ while( offset < 0xFFFF)
+ {
+ if(memcmp(mem+offset, "$PIR", 4)==0)
+ {
+ table = (struct routing_table *)(mem+offset);
+ size = table->size;
+ /* quick sanity checks */
+ /* Version must be 1.0 */
+ if (! (table->version >> 8)==1 &&
+ (table->version && 0xFF) == 0) break;
+
+ table = malloc(size);
+ if (!table) break;
+
+ memcpy(table, mem+offset, size);
+ for (i=0; i<size; i++)
+ checksum +=*(((uint8_t *)table)+i);
+ if (checksum) {
+ free (table);
+ table = NULL;
+ }
+ break;
+ }
+ offset += 16;
+ }
+ munmap(mem, 64*1024);
+out:
+ close(fd);
+ return table;
+}
+
+void pirq_free_table(struct routing_table *table)
+{
+ free(table);
+}
+
+
+#ifdef UNIT_TEST_PIRQ
+
+static void
+pirq_unparse_slot(struct slot_entry *slot)
+{
+ printf("Slot %d: PCI %x:%x. ",
+ slot->slot, slot->bus, PCI_DEVICE(slot->device));
+ printf("INTA link %x irq %x ", slot->inta_link, slot->inta_irq);
+ printf("B link %x irq %x ", slot->intb_link, slot->intb_irq);
+ printf("C link %x irq %x ", slot->intc_link, slot->intc_irq);
+ printf("D link %x irq %x ", slot->intd_link, slot->intd_irq);
+ printf("\n");
+}
+
+static void
+pirq_unparse_routing_table(struct routing_table *table)
+{
+ int i, num_slots;
+ struct slot_entry *slot;
+ char buf[5]; buf[4] = 0;
+ memcpy(buf, &table->signature, 4);
+
+ printf("PCI IRQ Routing Table\n");
+ printf("Signature: %s\n", buf);
+ printf("Version : %x\n", table->version);
+ printf("Size : %xh\n", table->size);
+ printf("Bus : %x\n", table->router_bus);
+ printf("DevFn : %x\n", table->router_devfn);
+ printf("Exclusive IRQs : %x\n", table->exclusive_irqs);
+ printf("Compatable Router: %x\n", table->compatable_router);
+
+ num_slots = (table->size - 32) / sizeof(*slot);
+ slot = &table->slot[0];
+ for (i=0; i<num_slots; i++) {
+ pirq_unparse_slot(&slot[i]);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ struct routing_table *table;
+ table = pirq_alloc_read_table();
+ if (!table)
+ return 1;
+ pirq_unparse_routing_table(table);
+ pirq_free_table(table);
+ return 0;
+}
+
+#endif