diff options
Diffstat (limited to 'arch/i386/pci/irq.c')
-rw-r--r-- | arch/i386/pci/irq.c | 73 |
1 files changed, 59 insertions, 14 deletions
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index d21b3a2dc978..766b104ac1a1 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c | |||
@@ -58,6 +58,35 @@ struct irq_router_handler { | |||
58 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; | 58 | int (*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 | |||
65 | static 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 | } |
@@ -227,6 +250,24 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i | |||
227 | } | 250 | } |
228 | 251 | ||
229 | /* | 252 | /* |
253 | * The VIA pirq rules are nibble-based, like ALI, | ||
254 | * but without the ugly irq number munging. | ||
255 | * However, for 82C586, nibble map is different . | ||
256 | */ | ||
257 | static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
258 | { | ||
259 | static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; | ||
260 | return read_config_nybble(router, 0x55, pirqmap[pirq-1]); | ||
261 | } | ||
262 | |||
263 | static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
264 | { | ||
265 | static unsigned int pirqmap[4] = { 3, 2, 5, 1 }; | ||
266 | write_config_nybble(router, 0x55, pirqmap[pirq-1], irq); | ||
267 | return 1; | ||
268 | } | ||
269 | |||
270 | /* | ||
230 | * ITE 8330G pirq rules are nibble-based | 271 | * ITE 8330G pirq rules are nibble-based |
231 | * FIXME: pirqmap may be { 1, 0, 3, 2 }, | 272 | * FIXME: pirqmap may be { 1, 0, 3, 2 }, |
232 | * 2+3 are both mapped to irq 9 on my system | 273 | * 2+3 are both mapped to irq 9 on my system |
@@ -512,6 +553,10 @@ static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, | |||
512 | switch(device) | 553 | switch(device) |
513 | { | 554 | { |
514 | case PCI_DEVICE_ID_VIA_82C586_0: | 555 | case PCI_DEVICE_ID_VIA_82C586_0: |
556 | r->name = "VIA"; | ||
557 | r->get = pirq_via586_get; | ||
558 | r->set = pirq_via586_set; | ||
559 | return 1; | ||
515 | case PCI_DEVICE_ID_VIA_82C596: | 560 | case PCI_DEVICE_ID_VIA_82C596: |
516 | case PCI_DEVICE_ID_VIA_82C686: | 561 | case PCI_DEVICE_ID_VIA_82C686: |
517 | case PCI_DEVICE_ID_VIA_8231: | 562 | case PCI_DEVICE_ID_VIA_8231: |