aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/pci')
-rw-r--r--arch/i386/pci/common.c6
-rw-r--r--arch/i386/pci/irq.c51
-rw-r--r--arch/i386/pci/pci.h1
3 files changed, 43 insertions, 15 deletions
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 720975e1af50..2a2e79fbfef8 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
25 25
26int pci_routeirq; 26int pci_routeirq;
27int pcibios_last_bus = -1; 27int pcibios_last_bus = -1;
28struct pci_bus *pci_root_bus = NULL; 28unsigned long pirq_table_addr;
29struct pci_bus *pci_root_bus;
29struct pci_raw_ops *raw_pci_ops; 30struct pci_raw_ops *raw_pci_ops;
30 31
31static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 32static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
@@ -188,6 +189,9 @@ char * __devinit pcibios_setup(char *str)
188 } else if (!strcmp(str, "biosirq")) { 189 } else if (!strcmp(str, "biosirq")) {
189 pci_probe |= PCI_BIOS_IRQ_SCAN; 190 pci_probe |= PCI_BIOS_IRQ_SCAN;
190 return NULL; 191 return NULL;
192 } else if (!strncmp(str, "pirqaddr=", 9)) {
193 pirq_table_addr = simple_strtoul(str+9, NULL, 0);
194 return NULL;
191 } 195 }
192#endif 196#endif
193#ifdef CONFIG_PCI_DIRECT 197#ifdef CONFIG_PCI_DIRECT
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 83458f81e661..78ca1ecbb907 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -58,6 +58,35 @@ struct irq_router_handler {
58int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 58int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
59 59
60/* 60/*
61 * Check passed address for the PCI IRQ Routing Table signature
62 * and perform checksum verification.
63 */
64
65static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
66{
67 struct irq_routing_table *rt;
68 int i;
69 u8 sum;
70
71 rt = (struct irq_routing_table *) addr;
72 if (rt->signature != PIRQ_SIGNATURE ||
73 rt->version != PIRQ_VERSION ||
74 rt->size % 16 ||
75 rt->size < sizeof(struct irq_routing_table))
76 return NULL;
77 sum = 0;
78 for (i=0; i < rt->size; i++)
79 sum += addr[i];
80 if (!sum) {
81 DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
82 return rt;
83 }
84 return NULL;
85}
86
87
88
89/*
61 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. 90 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
62 */ 91 */
63 92
@@ -65,23 +94,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void)
65{ 94{
66 u8 *addr; 95 u8 *addr;
67 struct irq_routing_table *rt; 96 struct irq_routing_table *rt;
68 int i;
69 u8 sum;
70 97
98 if (pirq_table_addr) {
99 rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
100 if (rt)
101 return rt;
102 printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
103 }
71 for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { 104 for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
72 rt = (struct irq_routing_table *) addr; 105 rt = pirq_check_routing_table(addr);
73 if (rt->signature != PIRQ_SIGNATURE || 106 if (rt)
74 rt->version != PIRQ_VERSION ||
75 rt->size % 16 ||
76 rt->size < sizeof(struct irq_routing_table))
77 continue;
78 sum = 0;
79 for(i=0; i<rt->size; i++)
80 sum += addr[i];
81 if (!sum) {
82 DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
83 return rt; 107 return rt;
84 }
85 } 108 }
86 return NULL; 109 return NULL;
87} 110}
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index a8fc80ca69f3..a80f0f55ff51 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -27,6 +27,7 @@
27#define PCI_ASSIGN_ALL_BUSSES 0x4000 27#define PCI_ASSIGN_ALL_BUSSES 0x4000
28 28
29extern unsigned int pci_probe; 29extern unsigned int pci_probe;
30extern unsigned long pirq_table_addr;
30 31
31/* pci-i386.c */ 32/* pci-i386.c */
32 33