]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/x86/pci/irq.c
x86/PCI: use for_each_pci_dev()
[net-next-2.6.git] / arch / x86 / pci / irq.c
CommitLineData
1da177e4
LT
1/*
2 * Low-Level PCI Support for PC -- Routing of Interrupts
3 *
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5 */
6
1da177e4
LT
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/pci.h>
10#include <linux/init.h>
1da177e4 11#include <linux/interrupt.h>
1da177e4 12#include <linux/dmi.h>
7058b061
PC
13#include <linux/io.h>
14#include <linux/smp.h>
1da177e4 15#include <asm/io_apic.h>
b33fa1f3 16#include <linux/irq.h>
1da177e4 17#include <linux/acpi.h>
82487711 18#include <asm/pci_x86.h>
1da177e4
LT
19
20#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
21#define PIRQ_VERSION 0x0100
22
23static int broken_hp_bios_irq9;
24static int acer_tm360_irqrouting;
25
26static struct irq_routing_table *pirq_table;
27
28static int pirq_enable_irq(struct pci_dev *dev);
29
30/*
31 * Never use: 0, 1, 2 (timer, keyboard, and cascade)
32 * Avoid using: 13, 14 and 15 (FP error and IDE).
33 * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
34 */
35unsigned int pcibios_irq_mask = 0xfff8;
36
37static int pirq_penalty[16] = {
38 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
39 0, 0, 0, 0, 1000, 100000, 100000, 100000
40};
41
42struct irq_router {
43 char *name;
44 u16 vendor, device;
45 int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
273c1127
MV
46 int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq,
47 int new);
1da177e4
LT
48};
49
50struct irq_router_handler {
51 u16 vendor;
52 int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
53};
54
ab3b3793 55int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
87bec66b 56void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
1da177e4 57
120bb424 58/*
59 * Check passed address for the PCI IRQ Routing Table signature
60 * and perform checksum verification.
61 */
62
7058b061 63static inline struct irq_routing_table *pirq_check_routing_table(u8 *addr)
120bb424 64{
65 struct irq_routing_table *rt;
66 int i;
67 u8 sum;
68
69 rt = (struct irq_routing_table *) addr;
70 if (rt->signature != PIRQ_SIGNATURE ||
71 rt->version != PIRQ_VERSION ||
72 rt->size % 16 ||
73 rt->size < sizeof(struct irq_routing_table))
74 return NULL;
75 sum = 0;
7058b061 76 for (i = 0; i < rt->size; i++)
120bb424 77 sum += addr[i];
78 if (!sum) {
273c1127
MV
79 DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n",
80 rt);
120bb424 81 return rt;
82 }
83 return NULL;
84}
85
86
87
1da177e4
LT
88/*
89 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
90 */
91
92static struct irq_routing_table * __init pirq_find_routing_table(void)
93{
94 u8 *addr;
95 struct irq_routing_table *rt;
1da177e4 96
120bb424 97 if (pirq_table_addr) {
98 rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
99 if (rt)
100 return rt;
101 printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
102 }
7058b061 103 for (addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
120bb424 104 rt = pirq_check_routing_table(addr);
105 if (rt)
1da177e4 106 return rt;
1da177e4
LT
107 }
108 return NULL;
109}
110
111/*
112 * If we have a IRQ routing table, use it to search for peer host
113 * bridges. It's a gross hack, but since there are no other known
114 * ways how to get a list of buses, we have to go this way.
115 */
116
117static void __init pirq_peer_trick(void)
118{
119 struct irq_routing_table *rt = pirq_table;
120 u8 busmap[256];
121 int i;
122 struct irq_info *e;
123
124 memset(busmap, 0, sizeof(busmap));
7058b061 125 for (i = 0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
1da177e4
LT
126 e = &rt->slots[i];
127#ifdef DEBUG
128 {
129 int j;