diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:16:36 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2007-10-11 05:16:36 -0400 |
commit | fb9aa6f1d4a1e11e66a680460b2c2b2b10b62f79 (patch) | |
tree | e0ad51f39b48a342244cef62099bd1a8a93927db /arch/x86 | |
parent | 4b60eb8380a0b588a03b6052d7ac93e1964c75b8 (diff) |
i386: move pci
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/pci/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/pci/Makefile_32 | 14 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 90 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 480 | ||||
-rw-r--r-- | arch/x86/pci/direct.c | 302 | ||||
-rw-r--r-- | arch/x86/pci/early.c | 59 | ||||
-rw-r--r-- | arch/x86/pci/fixup.c | 446 | ||||
-rw-r--r-- | arch/x86/pci/i386.c | 315 | ||||
-rw-r--r-- | arch/x86/pci/init.c | 37 | ||||
-rw-r--r-- | arch/x86/pci/irq.c | 1173 | ||||
-rw-r--r-- | arch/x86/pci/legacy.c | 56 | ||||
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 315 | ||||
-rw-r--r-- | arch/x86/pci/mmconfig_32.c | 148 | ||||
-rw-r--r-- | arch/x86/pci/numa.c | 135 | ||||
-rw-r--r-- | arch/x86/pci/pcbios.c | 492 | ||||
-rw-r--r-- | arch/x86/pci/pci.h | 149 | ||||
-rw-r--r-- | arch/x86/pci/visws.c | 111 |
17 files changed, 4327 insertions, 0 deletions
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile new file mode 100644 index 000000000000..b3e54c45d408 --- /dev/null +++ b/arch/x86/pci/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | ifeq ($(CONFIG_X86_32),y) | ||
2 | include ${srctree}/arch/x86/pci/Makefile_32 | ||
3 | else | ||
4 | include ${srctree}/arch/x86_64/pci/Makefile_64 | ||
5 | endif | ||
diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32 new file mode 100644 index 000000000000..cdd6828b5abb --- /dev/null +++ b/arch/x86/pci/Makefile_32 | |||
@@ -0,0 +1,14 @@ | |||
1 | obj-y := i386.o init.o | ||
2 | |||
3 | obj-$(CONFIG_PCI_BIOS) += pcbios.o | ||
4 | obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_32.o direct.o mmconfig-shared.o | ||
5 | obj-$(CONFIG_PCI_DIRECT) += direct.o | ||
6 | |||
7 | pci-y := fixup.o | ||
8 | pci-$(CONFIG_ACPI) += acpi.o | ||
9 | pci-y += legacy.o irq.o | ||
10 | |||
11 | pci-$(CONFIG_X86_VISWS) := visws.o fixup.o | ||
12 | pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o | ||
13 | |||
14 | obj-y += $(pci-y) common.o early.o | ||
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c new file mode 100644 index 000000000000..bc8a44bddaa7 --- /dev/null +++ b/arch/x86/pci/acpi.c | |||
@@ -0,0 +1,90 @@ | |||
1 | #include <linux/pci.h> | ||
2 | #include <linux/acpi.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/irq.h> | ||
5 | #include <asm/numa.h> | ||
6 | #include "pci.h" | ||
7 | |||
8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | ||
9 | { | ||
10 | struct pci_bus *bus; | ||
11 | struct pci_sysdata *sd; | ||
12 | int pxm; | ||
13 | |||
14 | /* Allocate per-root-bus (not per bus) arch-specific data. | ||
15 | * TODO: leak; this memory is never freed. | ||
16 | * It's arguable whether it's worth the trouble to care. | ||
17 | */ | ||
18 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | ||
19 | if (!sd) { | ||
20 | printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); | ||
21 | return NULL; | ||
22 | } | ||
23 | |||
24 | if (domain != 0) { | ||
25 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | ||
26 | kfree(sd); | ||
27 | return NULL; | ||
28 | } | ||
29 | |||
30 | sd->node = -1; | ||
31 | |||
32 | pxm = acpi_get_pxm(device->handle); | ||
33 | #ifdef CONFIG_ACPI_NUMA | ||
34 | if (pxm >= 0) | ||
35 | sd->node = pxm_to_node(pxm); | ||
36 | #endif | ||
37 | |||
38 | bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); | ||
39 | if (!bus) | ||
40 | kfree(sd); | ||
41 | |||
42 | #ifdef CONFIG_ACPI_NUMA | ||
43 | if (bus != NULL) { | ||
44 | if (pxm >= 0) { | ||
45 | printk("bus %d -> pxm %d -> node %d\n", | ||
46 | busnum, pxm, sd->node); | ||
47 | } | ||
48 | } | ||
49 | #endif | ||
50 | |||
51 | return bus; | ||
52 | } | ||
53 | |||
54 | extern int pci_routeirq; | ||
55 | static int __init pci_acpi_init(void) | ||
56 | { | ||
57 | struct pci_dev *dev = NULL; | ||
58 | |||
59 | if (pcibios_scanned) | ||
60 | return 0; | ||
61 | |||
62 | if (acpi_noirq) | ||
63 | return 0; | ||
64 | |||
65 | printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); | ||
66 | acpi_irq_penalty_init(); | ||
67 | pcibios_scanned++; | ||
68 | pcibios_enable_irq = acpi_pci_irq_enable; | ||
69 | pcibios_disable_irq = acpi_pci_irq_disable; | ||
70 | |||
71 | if (pci_routeirq) { | ||
72 | /* | ||
73 | * PCI IRQ routing is set up by pci_enable_device(), but we | ||
74 | * also do it here in case there are still broken drivers that | ||
75 | * don't use pci_enable_device(). | ||
76 | */ | ||
77 | printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n"); | ||
78 | for_each_pci_dev(dev) | ||
79 | acpi_pci_irq_enable(dev); | ||
80 | } else | ||
81 | printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n"); | ||
82 | |||
83 | #ifdef CONFIG_X86_IO_APIC | ||
84 | if (acpi_ioapic) | ||
85 | print_IO_APIC(); | ||
86 | #endif | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | subsys_initcall(pci_acpi_init); | ||
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c new file mode 100644 index 000000000000..ebc6f3c66340 --- /dev/null +++ b/arch/x86/pci/common.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Support for PC | ||
3 | * | ||
4 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> | ||
5 | */ | ||
6 | |||
7 | #include <linux/sched.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/ioport.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/dmi.h> | ||
12 | |||
13 | #include <asm/acpi.h> | ||
14 | #include <asm/segment.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <asm/smp.h> | ||
17 | |||
18 | #include "pci.h" | ||
19 | |||
20 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | ||
21 | PCI_PROBE_MMCONF; | ||
22 | |||
23 | static int pci_bf_sort; | ||
24 | int pci_routeirq; | ||
25 | int pcibios_last_bus = -1; | ||
26 | unsigned long pirq_table_addr; | ||
27 | struct pci_bus *pci_root_bus; | ||
28 | struct pci_raw_ops *raw_pci_ops; | ||
29 | |||
30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | ||
31 | { | ||
32 | return raw_pci_ops->read(0, bus->number, devfn, where, size, value); | ||
33 | } | ||
34 | |||
35 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | ||
36 | { | ||
37 | return raw_pci_ops->write(0, bus->number, devfn, where, size, value); | ||
38 | } | ||
39 | |||
40 | struct pci_ops pci_root_ops = { | ||
41 | .read = pci_read, | ||
42 | .write = pci_write, | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * legacy, numa, and acpi all want to call pcibios_scan_root | ||
47 | * from their initcalls. This flag prevents that. | ||
48 | */ | ||
49 | int pcibios_scanned; | ||
50 | |||
51 | /* | ||
52 | * This interrupt-safe spinlock protects all accesses to PCI | ||
53 | * configuration space. | ||
54 | */ | ||
55 | DEFINE_SPINLOCK(pci_config_lock); | ||
56 | |||
57 | /* | ||
58 | * Several buggy motherboards address only 16 devices and mirror | ||
59 | * them to next 16 IDs. We try to detect this `feature' on all | ||
60 | * primary buses (those containing host bridges as they are | ||
61 | * expected to be unique) and remove the ghost devices. | ||
62 | */ | ||
63 | |||
64 | static void __devinit pcibios_fixup_ghosts(struct pci_bus *b) | ||
65 | { | ||
66 | struct list_head *ln, *mn; | ||
67 | struct pci_dev *d, *e; | ||
68 | int mirror = PCI_DEVFN(16,0); | ||
69 | int seen_host_bridge = 0; | ||
70 | int i; | ||
71 | |||
72 | DBG("PCI: Scanning for ghost devices on bus %d\n", b->number); | ||
73 | list_for_each(ln, &b->devices) { | ||
74 | d = pci_dev_b(ln); | ||
75 | if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
76 | seen_host_bridge++; | ||
77 | for (mn=ln->next; mn != &b->devices; mn=mn->next) { | ||
78 | e = pci_dev_b(mn); | ||
79 | if (e->devfn != d->devfn + mirror || | ||
80 | e->vendor != d->vendor || | ||
81 | e->device != d->device || | ||
82 | e->class != d->class) | ||
83 | continue; | ||
84 | for(i=0; i<PCI_NUM_RESOURCES; i++) | ||
85 | if (e->resource[i].start != d->resource[i].start || | ||
86 | e->resource[i].end != d->resource[i].end || | ||
87 | e->resource[i].flags != d->resource[i].flags) | ||
88 | continue; | ||
89 | break; | ||
90 | } | ||
91 | if (mn == &b->devices) | ||
92 | return; | ||
93 | } | ||
94 | if (!seen_host_bridge) | ||
95 | return; | ||
96 | printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number); | ||
97 | |||
98 | ln = &b->devices; | ||
99 | while (ln->next != &b->devices) { | ||
100 | d = pci_dev_b(ln->next); | ||
101 | if (d->devfn >= mirror) { | ||
102 | list_del(&d->global_list); | ||
103 | list_del(&d->bus_list); | ||
104 | kfree(d); | ||
105 | } else | ||
106 | ln = ln->next; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * Called after each bus is probed, but before its children | ||
112 | * are examined. | ||
113 | */ | ||
114 | |||
115 | void __devinit pcibios_fixup_bus(struct pci_bus *b) | ||
116 | { | ||
117 | pcibios_fixup_ghosts(b); | ||
118 | pci_read_bridge_bases(b); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Only use DMI information to set this if nothing was passed | ||
123 | * on the kernel command line (which was parsed earlier). | ||
124 | */ | ||
125 | |||
126 | static int __devinit set_bf_sort(struct dmi_system_id *d) | ||
127 | { | ||
128 | if (pci_bf_sort == pci_bf_sort_default) { | ||
129 | pci_bf_sort = pci_dmi_bf; | ||
130 | printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) | ||
137 | */ | ||
138 | #ifdef __i386__ | ||
139 | static int __devinit assign_all_busses(struct dmi_system_id *d) | ||
140 | { | ||
141 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; | ||
142 | printk(KERN_INFO "%s detected: enabling PCI bus# renumbering" | ||
143 | " (pci=assign-busses)\n", d->ident); | ||
144 | return 0; | ||
145 | } | ||
146 | #endif | ||
147 | |||
148 | static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | ||
149 | #ifdef __i386__ | ||
150 | /* | ||
151 | * Laptops which need pci=assign-busses to see Cardbus cards | ||
152 | */ | ||
153 | { | ||
154 | .callback = assign_all_busses, | ||
155 | .ident = "Samsung X20 Laptop", | ||
156 | .matches = { | ||
157 | DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"), | ||
158 | DMI_MATCH(DMI_PRODUCT_NAME, "SX20S"), | ||
159 | }, | ||
160 | }, | ||
161 | #endif /* __i386__ */ | ||
162 | { | ||
163 | .callback = set_bf_sort, | ||
164 | .ident = "Dell PowerEdge 1950", | ||
165 | .matches = { | ||
166 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
167 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), | ||
168 | }, | ||
169 | }, | ||
170 | { | ||
171 | .callback = set_bf_sort, | ||
172 | .ident = "Dell PowerEdge 1955", | ||
173 | .matches = { | ||
174 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
175 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), | ||
176 | }, | ||
177 | }, | ||
178 | { | ||
179 | .callback = set_bf_sort, | ||
180 | .ident = "Dell PowerEdge 2900", | ||
181 | .matches = { | ||
182 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
183 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), | ||
184 | }, | ||
185 | }, | ||
186 | { | ||
187 | .callback = set_bf_sort, | ||
188 | .ident = "Dell PowerEdge 2950", | ||
189 | .matches = { | ||
190 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
191 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), | ||
192 | }, | ||
193 | }, | ||
194 | { | ||
195 | .callback = set_bf_sort, | ||
196 | .ident = "Dell PowerEdge R900", | ||
197 | .matches = { | ||
198 | DMI_MATCH(DMI_SYS_VENDOR, "Dell"), | ||
199 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"), | ||
200 | }, | ||
201 | }, | ||
202 | { | ||
203 | .callback = set_bf_sort, | ||
204 | .ident = "HP ProLiant BL20p G3", | ||
205 | .matches = { | ||
206 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
207 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"), | ||
208 | }, | ||
209 | }, | ||
210 | { | ||
211 | .callback = set_bf_sort, | ||
212 | .ident = "HP ProLiant BL20p G4", | ||
213 | .matches = { | ||
214 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
215 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"), | ||
216 | }, | ||
217 | }, | ||
218 | { | ||
219 | .callback = set_bf_sort, | ||
220 | .ident = "HP ProLiant BL30p G1", | ||
221 | .matches = { | ||
222 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
223 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"), | ||
224 | }, | ||
225 | }, | ||
226 | { | ||
227 | .callback = set_bf_sort, | ||
228 | .ident = "HP ProLiant BL25p G1", | ||
229 | .matches = { | ||
230 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
231 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"), | ||
232 | }, | ||
233 | }, | ||
234 | { | ||
235 | .callback = set_bf_sort, | ||
236 | .ident = "HP ProLiant BL35p G1", | ||
237 | .matches = { | ||
238 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
239 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"), | ||
240 | }, | ||
241 | }, | ||
242 | { | ||
243 | .callback = set_bf_sort, | ||
244 | .ident = "HP ProLiant BL45p G1", | ||
245 | .matches = { | ||
246 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
247 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"), | ||
248 | }, | ||
249 | }, | ||
250 | { | ||
251 | .callback = set_bf_sort, | ||
252 | .ident = "HP ProLiant BL45p G2", | ||
253 | .matches = { | ||
254 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
255 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"), | ||
256 | }, | ||
257 | }, | ||
258 | { | ||
259 | .callback = set_bf_sort, | ||
260 | .ident = "HP ProLiant BL460c G1", | ||
261 | .matches = { | ||
262 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
263 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"), | ||
264 | }, | ||
265 | }, | ||
266 | { | ||
267 | .callback = set_bf_sort, | ||
268 | .ident = "HP ProLiant BL465c G1", | ||
269 | .matches = { | ||
270 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
271 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"), | ||
272 | }, | ||
273 | }, | ||
274 | { | ||
275 | .callback = set_bf_sort, | ||
276 | .ident = "HP ProLiant BL480c G1", | ||
277 | .matches = { | ||
278 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
279 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"), | ||
280 | }, | ||
281 | }, | ||
282 | { | ||
283 | .callback = set_bf_sort, | ||
284 | .ident = "HP ProLiant BL685c G1", | ||
285 | .matches = { | ||
286 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
287 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), | ||
288 | }, | ||
289 | }, | ||
290 | {} | ||
291 | }; | ||
292 | |||
293 | struct pci_bus * __devinit pcibios_scan_root(int busnum) | ||
294 | { | ||
295 | struct pci_bus *bus = NULL; | ||
296 | struct pci_sysdata *sd; | ||
297 | |||
298 | dmi_check_system(pciprobe_dmi_table); | ||
299 | |||
300 | while ((bus = pci_find_next_bus(bus)) != NULL) { | ||
301 | if (bus->number == busnum) { | ||
302 | /* Already scanned */ | ||
303 | return bus; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | /* Allocate per-root-bus (not per bus) arch-specific data. | ||
308 | * TODO: leak; this memory is never freed. | ||
309 | * It's arguable whether it's worth the trouble to care. | ||
310 | */ | ||
311 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | ||
312 | if (!sd) { | ||
313 | printk(KERN_ERR "PCI: OOM, not probing PCI bus %02x\n", busnum); | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
317 | printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); | ||
318 | |||
319 | return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); | ||
320 | } | ||
321 | |||
322 | extern u8 pci_cache_line_size; | ||
323 | |||
324 | static int __init pcibios_init(void) | ||
325 | { | ||
326 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
327 | |||
328 | if (!raw_pci_ops) { | ||
329 | printk(KERN_WARNING "PCI: System does not support PCI\n"); | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Assume PCI cacheline size of 32 bytes for all x86s except K7/K8 | ||
335 | * and P4. It's also good for 386/486s (which actually have 16) | ||
336 | * as quite a few PCI devices do not support smaller values. | ||
337 | */ | ||
338 | pci_cache_line_size = 32 >> 2; | ||
339 | if (c->x86 >= 6 && c->x86_vendor == X86_VENDOR_AMD) | ||
340 | pci_cache_line_size = 64 >> 2; /* K7 & K8 */ | ||
341 | else if (c->x86 > 6 && c->x86_vendor == X86_VENDOR_INTEL) | ||
342 | pci_cache_line_size = 128 >> 2; /* P4 */ | ||
343 | |||
344 | pcibios_resource_survey(); | ||
345 | |||
346 | if (pci_bf_sort >= pci_force_bf) | ||
347 | pci_sort_breadthfirst(); | ||
348 | #ifdef CONFIG_PCI_BIOS | ||
349 | if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) | ||
350 | pcibios_sort(); | ||
351 | #endif | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | subsys_initcall(pcibios_init); | ||
356 | |||
357 | char * __devinit pcibios_setup(char *str) | ||
358 | { | ||
359 | if (!strcmp(str, "off")) { | ||
360 | pci_probe = 0; | ||
361 | return NULL; | ||
362 | } else if (!strcmp(str, "bfsort")) { | ||
363 | pci_bf_sort = pci_force_bf; | ||
364 | return NULL; | ||
365 | } else if (!strcmp(str, "nobfsort")) { | ||
366 | pci_bf_sort = pci_force_nobf; | ||
367 | return NULL; | ||
368 | } | ||
369 | #ifdef CONFIG_PCI_BIOS | ||
370 | else if (!strcmp(str, "bios")) { | ||
371 | pci_probe = PCI_PROBE_BIOS; | ||
372 | return NULL; | ||
373 | } else if (!strcmp(str, "nobios")) { | ||
374 | pci_probe &= ~PCI_PROBE_BIOS; | ||
375 | return NULL; | ||
376 | } else if (!strcmp(str, "nosort")) { | ||
377 | pci_probe |= PCI_NO_SORT; | ||
378 | return NULL; | ||
379 | } else if (!strcmp(str, "biosirq")) { | ||
380 | pci_probe |= PCI_BIOS_IRQ_SCAN; | ||
381 | return NULL; | ||
382 | } else if (!strncmp(str, "pirqaddr=", 9)) { | ||
383 | pirq_table_addr = simple_strtoul(str+9, NULL, 0); | ||
384 | return NULL; | ||
385 | } | ||
386 | #endif | ||
387 | #ifdef CONFIG_PCI_DIRECT | ||
388 | else if (!strcmp(str, "conf1")) { | ||
389 | pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; | ||
390 | return NULL; | ||
391 | } | ||
392 | else if (!strcmp(str, "conf2")) { | ||
393 | pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; | ||
394 | return NULL; | ||
395 | } | ||
396 | #endif | ||
397 | #ifdef CONFIG_PCI_MMCONFIG | ||
398 | else if (!strcmp(str, "nommconf")) { | ||
399 | pci_probe &= ~PCI_PROBE_MMCONF; | ||
400 | return NULL; | ||
401 | } | ||
402 | #endif | ||
403 | else if (!strcmp(str, "noacpi")) { | ||
404 | acpi_noirq_set(); | ||
405 | return NULL; | ||
406 | } | ||
407 | else if (!strcmp(str, "noearly")) { | ||
408 | pci_probe |= PCI_PROBE_NOEARLY; | ||
409 | return NULL; | ||
410 | } | ||
411 | #ifndef CONFIG_X86_VISWS | ||
412 | else if (!strcmp(str, "usepirqmask")) { | ||
413 | pci_probe |= PCI_USE_PIRQ_MASK; | ||
414 | return NULL; | ||
415 | } else if (!strncmp(str, "irqmask=", 8)) { | ||
416 | pcibios_irq_mask = simple_strtol(str+8, NULL, 0); | ||
417 | return NULL; | ||
418 | } else if (!strncmp(str, "lastbus=", 8)) { | ||
419 | pcibios_last_bus = simple_strtol(str+8, NULL, 0); | ||
420 | return NULL; | ||
421 | } | ||
422 | #endif | ||
423 | else if (!strcmp(str, "rom")) { | ||
424 | pci_probe |= PCI_ASSIGN_ROMS; | ||
425 | return NULL; | ||
426 | } else if (!strcmp(str, "assign-busses")) { | ||
427 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; | ||
428 | return NULL; | ||
429 | } else if (!strcmp(str, "routeirq")) { | ||
430 | pci_routeirq = 1; | ||
431 | return NULL; | ||
432 | } | ||
433 | return str; | ||
434 | } | ||
435 | |||
436 | unsigned int pcibios_assign_all_busses(void) | ||
437 | { | ||
438 | return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; | ||
439 | } | ||
440 | |||
441 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
442 | { | ||
443 | int err; | ||
444 | |||
445 | if ((err = pcibios_enable_resources(dev, mask)) < 0) | ||
446 | return err; | ||
447 | |||
448 | if (!dev->msi_enabled) | ||
449 | return pcibios_enable_irq(dev); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | void pcibios_disable_device (struct pci_dev *dev) | ||
454 | { | ||
455 | if (!dev->msi_enabled && pcibios_disable_irq) | ||
456 | pcibios_disable_irq(dev); | ||
457 | } | ||
458 | |||
459 | struct pci_bus *pci_scan_bus_with_sysdata(int busno) | ||
460 | { | ||
461 | struct pci_bus *bus = NULL; | ||
462 | struct pci_sysdata *sd; | ||
463 | |||
464 | /* | ||
465 | * Allocate per-root-bus (not per bus) arch-specific data. | ||
466 | * TODO: leak; this memory is never freed. | ||
467 | * It's arguable whether it's worth the trouble to care. | ||
468 | */ | ||
469 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | ||
470 | if (!sd) { | ||
471 | printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno); | ||
472 | return NULL; | ||
473 | } | ||
474 | sd->node = -1; | ||
475 | bus = pci_scan_bus(busno, &pci_root_ops, sd); | ||
476 | if (!bus) | ||
477 | kfree(sd); | ||
478 | |||
479 | return bus; | ||
480 | } | ||
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c new file mode 100644 index 000000000000..431c9a51b157 --- /dev/null +++ b/arch/x86/pci/direct.c | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * direct.c - Low-level direct PCI config space access | ||
3 | */ | ||
4 | |||
5 | #include <linux/pci.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/dmi.h> | ||
8 | #include "pci.h" | ||
9 | |||
10 | /* | ||
11 | * Functions for accessing PCI configuration space with type 1 accesses | ||
12 | */ | ||
13 | |||
14 | #define PCI_CONF1_ADDRESS(bus, devfn, reg) \ | ||
15 | (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) | ||
16 | |||
17 | int pci_conf1_read(unsigned int seg, unsigned int bus, | ||
18 | unsigned int devfn, int reg, int len, u32 *value) | ||
19 | { | ||
20 | unsigned long flags; | ||
21 | |||
22 | if ((bus > 255) || (devfn > 255) || (reg > 255)) { | ||
23 | *value = -1; | ||
24 | return -EINVAL; | ||
25 | } | ||
26 | |||
27 | spin_lock_irqsave(&pci_config_lock, flags); | ||
28 | |||
29 | outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); | ||
30 | |||
31 | switch (len) { | ||
32 | case 1: | ||
33 | *value = inb(0xCFC + (reg & 3)); | ||
34 | break; | ||
35 | case 2: | ||
36 | *value = inw(0xCFC + (reg & 2)); | ||
37 | break; | ||
38 | case 4: | ||
39 | *value = inl(0xCFC); | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | int pci_conf1_write(unsigned int seg, unsigned int bus, | ||
49 | unsigned int devfn, int reg, int len, u32 value) | ||
50 | { | ||
51 | unsigned long flags; | ||
52 | |||
53 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | ||
54 | return -EINVAL; | ||
55 | |||
56 | spin_lock_irqsave(&pci_config_lock, flags); | ||
57 | |||
58 | outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); | ||
59 | |||
60 | switch (len) { | ||
61 | case 1: | ||
62 | outb((u8)value, 0xCFC + (reg & 3)); | ||
63 | break; | ||
64 | case 2: | ||
65 | outw((u16)value, 0xCFC + (reg & 2)); | ||
66 | break; | ||
67 | case 4: | ||
68 | outl((u32)value, 0xCFC); | ||
69 | break; | ||
70 | } | ||
71 | |||
72 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | #undef PCI_CONF1_ADDRESS | ||
78 | |||
79 | struct pci_raw_ops pci_direct_conf1 = { | ||
80 | .read = pci_conf1_read, | ||
81 | .write = pci_conf1_write, | ||
82 | }; | ||
83 | |||
84 | |||
85 | /* | ||
86 | * Functions for accessing PCI configuration space with type 2 accesses | ||
87 | */ | ||
88 | |||
89 | #define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg) | ||
90 | |||
91 | static int pci_conf2_read(unsigned int seg, unsigned int bus, | ||
92 | unsigned int devfn, int reg, int len, u32 *value) | ||
93 | { | ||
94 | unsigned long flags; | ||
95 | int dev, fn; | ||
96 | |||
97 | if ((bus > 255) || (devfn > 255) || (reg > 255)) { | ||
98 | *value = -1; | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | dev = PCI_SLOT(devfn); | ||
103 | fn = PCI_FUNC(devfn); | ||
104 | |||
105 | if (dev & 0x10) | ||
106 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
107 | |||
108 | spin_lock_irqsave(&pci_config_lock, flags); | ||
109 | |||
110 | outb((u8)(0xF0 | (fn << 1)), 0xCF8); | ||
111 | outb((u8)bus, 0xCFA); | ||
112 | |||
113 | switch (len) { | ||
114 | case 1: | ||
115 | *value = inb(PCI_CONF2_ADDRESS(dev, reg)); | ||
116 | break; | ||
117 | case 2: | ||
118 | *value = inw(PCI_CONF2_ADDRESS(dev, reg)); | ||
119 | break; | ||
120 | case 4: | ||
121 | *value = inl(PCI_CONF2_ADDRESS(dev, reg)); | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | outb(0, 0xCF8); | ||
126 | |||
127 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int pci_conf2_write(unsigned int seg, unsigned int bus, | ||
133 | unsigned int devfn, int reg, int len, u32 value) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | int dev, fn; | ||
137 | |||
138 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | ||
139 | return -EINVAL; | ||
140 | |||
141 | dev = PCI_SLOT(devfn); | ||
142 | fn = PCI_FUNC(devfn); | ||
143 | |||
144 | if (dev & 0x10) | ||
145 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
146 | |||
147 | spin_lock_irqsave(&pci_config_lock, flags); | ||
148 | |||
149 | outb((u8)(0xF0 | (fn << 1)), 0xCF8); | ||
150 | outb((u8)bus, 0xCFA); | ||
151 | |||
152 | switch (len) { | ||
153 | case 1: | ||
154 | outb((u8)value, PCI_CONF2_ADDRESS(dev, reg)); | ||
155 | break; | ||
156 | case 2: | ||
157 | outw((u16)value, PCI_CONF2_ADDRESS(dev, reg)); | ||
158 | break; | ||
159 | case 4: | ||
160 | outl((u32)value, PCI_CONF2_ADDRESS(dev, reg)); | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | outb(0, 0xCF8); | ||
165 | |||
166 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | #undef PCI_CONF2_ADDRESS | ||
172 | |||
173 | static struct pci_raw_ops pci_direct_conf2 = { | ||
174 | .read = pci_conf2_read, | ||
175 | .write = pci_conf2_write, | ||
176 | }; | ||
177 | |||
178 | |||
179 | /* | ||
180 | * Before we decide to use direct hardware access mechanisms, we try to do some | ||
181 | * trivial checks to ensure it at least _seems_ to be working -- we just test | ||
182 | * whether bus 00 contains a host bridge (this is similar to checking | ||
183 | * techniques used in XFree86, but ours should be more reliable since we | ||
184 | * attempt to make use of direct access hints provided by the PCI BIOS). | ||
185 | * | ||
186 | * This should be close to trivial, but it isn't, because there are buggy | ||
187 | * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID. | ||
188 | */ | ||
189 | static int __init pci_sanity_check(struct pci_raw_ops *o) | ||
190 | { | ||
191 | u32 x = 0; | ||
192 | int devfn; | ||
193 | |||
194 | if (pci_probe & PCI_NO_CHECKS) | ||
195 | return 1; | ||
196 | /* Assume Type 1 works for newer systems. | ||
197 | This handles machines that don't have anything on PCI Bus 0. */ | ||
198 | if (dmi_get_year(DMI_BIOS_DATE) >= 2001) | ||
199 | return 1; | ||
200 | |||
201 | for (devfn = 0; devfn < 0x100; devfn++) { | ||
202 | if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x)) | ||
203 | continue; | ||
204 | if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA) | ||
205 | return 1; | ||
206 | |||
207 | if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x)) | ||
208 | continue; | ||
209 | if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ) | ||
210 | return 1; | ||
211 | } | ||
212 | |||
213 | DBG(KERN_WARNING "PCI: Sanity check failed\n"); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int __init pci_check_type1(void) | ||
218 | { | ||
219 | unsigned long flags; | ||
220 | unsigned int tmp; | ||
221 | int works = 0; | ||
222 | |||
223 | local_irq_save(flags); | ||
224 | |||
225 | outb(0x01, 0xCFB); | ||
226 | tmp = inl(0xCF8); | ||
227 | outl(0x80000000, 0xCF8); | ||
228 | if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) { | ||
229 | works = 1; | ||
230 | } | ||
231 | outl(tmp, 0xCF8); | ||
232 | local_irq_restore(flags); | ||
233 | |||
234 | return works; | ||
235 | } | ||
236 | |||
237 | static int __init pci_check_type2(void) | ||
238 | { | ||
239 | unsigned long flags; | ||
240 | int works = 0; | ||
241 | |||
242 | local_irq_save(flags); | ||
243 | |||
244 | outb(0x00, 0xCFB); | ||
245 | outb(0x00, 0xCF8); | ||
246 | outb(0x00, 0xCFA); | ||
247 | if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && | ||
248 | pci_sanity_check(&pci_direct_conf2)) { | ||
249 | works = 1; | ||
250 | } | ||
251 | |||
252 | local_irq_restore(flags); | ||
253 | |||
254 | return works; | ||
255 | } | ||
256 | |||
257 | void __init pci_direct_init(int type) | ||
258 | { | ||
259 | if (type == 0) | ||
260 | return; | ||
261 | printk(KERN_INFO "PCI: Using configuration type %d\n", type); | ||
262 | if (type == 1) | ||
263 | raw_pci_ops = &pci_direct_conf1; | ||
264 | else | ||
265 | raw_pci_ops = &pci_direct_conf2; | ||
266 | } | ||
267 | |||
268 | int __init pci_direct_probe(void) | ||
269 | { | ||
270 | struct resource *region, *region2; | ||
271 | |||
272 | if ((pci_probe & PCI_PROBE_CONF1) == 0) | ||
273 | goto type2; | ||
274 | region = request_region(0xCF8, 8, "PCI conf1"); | ||
275 | if (!region) | ||
276 | goto type2; | ||
277 | |||
278 | if (pci_check_type1()) | ||
279 | return 1; | ||
280 | release_resource(region); | ||
281 | |||
282 | type2: | ||
283 | if ((pci_probe & PCI_PROBE_CONF2) == 0) | ||
284 | return 0; | ||
285 | region = request_region(0xCF8, 4, "PCI conf2"); | ||
286 | if (!region) | ||
287 | return 0; | ||
288 | region2 = request_region(0xC000, 0x1000, "PCI conf2"); | ||
289 | if (!region2) | ||
290 | goto fail2; | ||
291 | |||
292 | if (pci_check_type2()) { | ||
293 | printk(KERN_INFO "PCI: Using configuration type 2\n"); | ||
294 | raw_pci_ops = &pci_direct_conf2; | ||
295 | return 2; | ||
296 | } | ||
297 | |||
298 | release_resource(region2); | ||
299 | fail2: | ||
300 | release_resource(region); | ||
301 | return 0; | ||
302 | } | ||
diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c new file mode 100644 index 000000000000..42df4b6606df --- /dev/null +++ b/arch/x86/pci/early.c | |||
@@ -0,0 +1,59 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/pci.h> | ||
3 | #include <asm/pci-direct.h> | ||
4 | #include <asm/io.h> | ||
5 | #include "pci.h" | ||
6 | |||
7 | /* Direct PCI access. This is used for PCI accesses in early boot before | ||
8 | the PCI subsystem works. */ | ||
9 | |||
10 | #define PDprintk(x...) | ||
11 | |||
12 | u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) | ||
13 | { | ||
14 | u32 v; | ||
15 | outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); | ||
16 | v = inl(0xcfc); | ||
17 | if (v != 0xffffffff) | ||
18 | PDprintk("%x reading 4 from %x: %x\n", slot, offset, v); | ||
19 | return v; | ||
20 | } | ||
21 | |||
22 | u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset) | ||
23 | { | ||
24 | u8 v; | ||
25 | outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); | ||
26 | v = inb(0xcfc + (offset&3)); | ||
27 | PDprintk("%x reading 1 from %x: %x\n", slot, offset, v); | ||
28 | return v; | ||
29 | } | ||
30 | |||
31 | u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset) | ||
32 | { | ||
33 | u16 v; | ||
34 | outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); | ||
35 | v = inw(0xcfc + (offset&2)); | ||
36 | PDprintk("%x reading 2 from %x: %x\n", slot, offset, v); | ||
37 | return v; | ||
38 | } | ||
39 | |||
40 | void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, | ||
41 | u32 val) | ||
42 | { | ||
43 | PDprintk("%x writing to %x: %x\n", slot, offset, val); | ||
44 | outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); | ||
45 | outl(val, 0xcfc); | ||
46 | } | ||
47 | |||
48 | void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) | ||
49 | { | ||
50 | PDprintk("%x writing to %x: %x\n", slot, offset, val); | ||
51 | outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); | ||
52 | outb(val, 0xcfc); | ||
53 | } | ||
54 | |||
55 | int early_pci_allowed(void) | ||
56 | { | ||
57 | return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) == | ||
58 | PCI_PROBE_CONF1; | ||
59 | } | ||
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c new file mode 100644 index 000000000000..c82cbf4c7226 --- /dev/null +++ b/arch/x86/pci/fixup.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* | ||
2 | * Exceptions for specific devices. Usually work-arounds for fatal design flaws. | ||
3 | */ | ||
4 | |||
5 | #include <linux/delay.h> | ||
6 | #include <linux/dmi.h> | ||
7 | #include <linux/pci.h> | ||
8 | #include <linux/init.h> | ||
9 | #include "pci.h" | ||
10 | |||
11 | |||
12 | static void __devinit pci_fixup_i450nx(struct pci_dev *d) | ||
13 | { | ||
14 | /* | ||
15 | * i450NX -- Find and scan all secondary buses on all PXB's. | ||
16 | */ | ||
17 | int pxb, reg; | ||
18 | u8 busno, suba, subb; | ||
19 | |||
20 | printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d)); | ||
21 | reg = 0xd0; | ||
22 | for(pxb=0; pxb<2; pxb++) { | ||
23 | pci_read_config_byte(d, reg++, &busno); | ||
24 | pci_read_config_byte(d, reg++, &suba); | ||
25 | pci_read_config_byte(d, reg++, &subb); | ||
26 | DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); | ||
27 | if (busno) | ||
28 | pci_scan_bus_with_sysdata(busno); /* Bus A */ | ||
29 | if (suba < subb) | ||
30 | pci_scan_bus_with_sysdata(suba+1); /* Bus B */ | ||
31 | } | ||
32 | pcibios_last_bus = -1; | ||
33 | } | ||
34 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); | ||
35 | |||
36 | static void __devinit pci_fixup_i450gx(struct pci_dev *d) | ||
37 | { | ||
38 | /* | ||
39 | * i450GX and i450KX -- Find and scan all secondary buses. | ||
40 | * (called separately for each PCI bridge found) | ||
41 | */ | ||
42 | u8 busno; | ||
43 | pci_read_config_byte(d, 0x4a, &busno); | ||
44 | printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno); | ||
45 | pci_scan_bus_with_sysdata(busno); | ||
46 | pcibios_last_bus = -1; | ||
47 | } | ||
48 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx); | ||
49 | |||
50 | static void __devinit pci_fixup_umc_ide(struct pci_dev *d) | ||
51 | { | ||
52 | /* | ||
53 | * UM8886BF IDE controller sets region type bits incorrectly, | ||
54 | * therefore they look like memory despite of them being I/O. | ||
55 | */ | ||
56 | int i; | ||
57 | |||
58 | printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d)); | ||
59 | for(i=0; i<4; i++) | ||
60 | d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; | ||
61 | } | ||
62 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide); | ||
63 | |||
64 | static void __devinit pci_fixup_ncr53c810(struct pci_dev *d) | ||
65 | { | ||
66 | /* | ||
67 | * NCR 53C810 returns class code 0 (at least on some systems). | ||
68 | * Fix class to be PCI_CLASS_STORAGE_SCSI | ||
69 | */ | ||
70 | if (!d->class) { | ||
71 | printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d)); | ||
72 | d->class = PCI_CLASS_STORAGE_SCSI << 8; | ||
73 | } | ||
74 | } | ||
75 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); | ||
76 | |||
77 | static void __devinit pci_fixup_latency(struct pci_dev *d) | ||
78 | { | ||
79 | /* | ||
80 | * SiS 5597 and 5598 chipsets require latency timer set to | ||
81 | * at most 32 to avoid lockups. | ||
82 | */ | ||
83 | DBG("PCI: Setting max latency to 32\n"); | ||
84 | pcibios_max_latency = 32; | ||
85 | } | ||
86 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency); | ||
87 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency); | ||
88 | |||
89 | static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d) | ||
90 | { | ||
91 | /* | ||
92 | * PIIX4 ACPI device: hardwired IRQ9 | ||
93 | */ | ||
94 | d->irq = 9; | ||
95 | } | ||
96 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi); | ||
97 | |||
98 | /* | ||
99 | * Addresses issues with problems in the memory write queue timer in | ||
100 | * certain VIA Northbridges. This bugfix is per VIA's specifications, | ||
101 | * except for the KL133/KM133: clearing bit 5 on those Northbridges seems | ||
102 | * to trigger a bug in its integrated ProSavage video card, which | ||
103 | * causes screen corruption. We only clear bits 6 and 7 for that chipset, | ||
104 | * until VIA can provide us with definitive information on why screen | ||
105 | * corruption occurs, and what exactly those bits do. | ||
106 | * | ||
107 | * VIA 8363,8622,8361 Northbridges: | ||
108 | * - bits 5, 6, 7 at offset 0x55 need to be turned off | ||
109 | * VIA 8367 (KT266x) Northbridges: | ||
110 | * - bits 5, 6, 7 at offset 0x95 need to be turned off | ||
111 | * VIA 8363 rev 0x81/0x84 (KL133/KM133) Northbridges: | ||
112 | * - bits 6, 7 at offset 0x55 need to be turned off | ||
113 | */ | ||
114 | |||
115 | #define VIA_8363_KL133_REVISION_ID 0x81 | ||
116 | #define VIA_8363_KM133_REVISION_ID 0x84 | ||
117 | |||
118 | static void pci_fixup_via_northbridge_bug(struct pci_dev *d) | ||
119 | { | ||
120 | u8 v; | ||
121 | int where = 0x55; | ||
122 | int mask = 0x1f; /* clear bits 5, 6, 7 by default */ | ||
123 | |||
124 | if (d->device == PCI_DEVICE_ID_VIA_8367_0) { | ||
125 | /* fix pci bus latency issues resulted by NB bios error | ||
126 | it appears on bug free^Wreduced kt266x's bios forces | ||
127 | NB latency to zero */ | ||
128 | pci_write_config_byte(d, PCI_LATENCY_TIMER, 0); | ||
129 | |||
130 | where = 0x95; /* the memory write queue timer register is | ||
131 | different for the KT266x's: 0x95 not 0x55 */ | ||
132 | } else if (d->device == PCI_DEVICE_ID_VIA_8363_0 && | ||
133 | (d->revision == VIA_8363_KL133_REVISION_ID || | ||
134 | d->revision == VIA_8363_KM133_REVISION_ID)) { | ||
135 | mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5 | ||
136 | causes screen corruption on the KL133/KM133 */ | ||
137 | } | ||
138 | |||
139 | pci_read_config_byte(d, where, &v); | ||
140 | if (v & ~mask) { | ||
141 | printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \ | ||
142 | d->device, d->revision, where, v, mask, v & mask); | ||
143 | v &= mask; | ||
144 | pci_write_config_byte(d, where, v); | ||
145 | } | ||
146 | } | ||
147 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug); | ||
148 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug); | ||
149 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug); | ||
150 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug); | ||
151 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug); | ||
152 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug); | ||
153 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug); | ||
154 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug); | ||
155 | |||
156 | /* | ||
157 | * For some reasons Intel decided that certain parts of their | ||
158 | * 815, 845 and some other chipsets must look like PCI-to-PCI bridges | ||
159 | * while they are obviously not. The 82801 family (AA, AB, BAM/CAM, | ||
160 | * BA/CA/DB and E) PCI bridges are actually HUB-to-PCI ones, according | ||
161 | * to Intel terminology. These devices do forward all addresses from | ||
162 | * system to PCI bus no matter what are their window settings, so they are | ||
163 | * "transparent" (or subtractive decoding) from programmers point of view. | ||
164 | */ | ||
165 | static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev) | ||
166 | { | ||
167 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && | ||
168 | (dev->device & 0xff00) == 0x2400) | ||
169 | dev->transparent = 1; | ||
170 | } | ||
171 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge); | ||
172 | |||
173 | /* | ||
174 | * Fixup for C1 Halt Disconnect problem on nForce2 systems. | ||
175 | * | ||
176 | * From information provided by "Allen Martin" <AMartin@nvidia.com>: | ||
177 | * | ||
178 | * A hang is caused when the CPU generates a very fast CONNECT/HALT cycle | ||
179 | * sequence. Workaround is to set the SYSTEM_IDLE_TIMEOUT to 80 ns. | ||
180 | * This allows the state-machine and timer to return to a proper state within | ||
181 | * 80 ns of the CONNECT and probe appearing together. Since the CPU will not | ||
182 | * issue another HALT within 80 ns of the initial HALT, the failure condition | ||
183 | * is avoided. | ||
184 | */ | ||
185 | static void pci_fixup_nforce2(struct pci_dev *dev) | ||
186 | { | ||
187 | u32 val; | ||
188 | |||
189 | /* | ||
190 | * Chip Old value New value | ||
191 | * C17 0x1F0FFF01 0x1F01FF01 | ||
192 | * C18D 0x9F0FFF01 0x9F01FF01 | ||
193 | * | ||
194 | * Northbridge chip version may be determined by | ||
195 | * reading the PCI revision ID (0xC1 or greater is C18D). | ||
196 | */ | ||
197 | pci_read_config_dword(dev, 0x6c, &val); | ||
198 | |||
199 | /* | ||
200 | * Apply fixup if needed, but don't touch disconnect state | ||
201 | */ | ||
202 | if ((val & 0x00FF0000) != 0x00010000) { | ||
203 | printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n"); | ||
204 | pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000); | ||
205 | } | ||
206 | } | ||
207 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); | ||
208 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); | ||
209 | |||
210 | /* Max PCI Express root ports */ | ||
211 | #define MAX_PCIEROOT 6 | ||
212 | static int quirk_aspm_offset[MAX_PCIEROOT << 3]; | ||
213 | |||
214 | #define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7)) | ||
215 | |||
216 | static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | ||
217 | { | ||
218 | return raw_pci_ops->read(0, bus->number, devfn, where, size, value); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Replace the original pci bus ops for write with a new one that will filter | ||
223 | * the request to insure ASPM cannot be enabled. | ||
224 | */ | ||
225 | static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | ||
226 | { | ||
227 | u8 offset; | ||
228 | |||
229 | offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)]; | ||
230 | |||
231 | if ((offset) && (where == offset)) | ||
232 | value = value & 0xfffffffc; | ||
233 | |||
234 | return raw_pci_ops->write(0, bus->number, devfn, where, size, value); | ||
235 | } | ||
236 | |||
237 | static struct pci_ops quirk_pcie_aspm_ops = { | ||
238 | .read = quirk_pcie_aspm_read, | ||
239 | .write = quirk_pcie_aspm_write, | ||
240 | }; | ||
241 | |||
242 | /* | ||
243 | * Prevents PCI Express ASPM (Active State Power Management) being enabled. | ||
244 | * | ||
245 | * Save the register offset, where the ASPM control bits are located, | ||
246 | * for each PCI Express device that is in the device list of | ||
247 | * the root port in an array for fast indexing. Replace the bus ops | ||
248 | * with the modified one. | ||
249 | */ | ||
250 | static void pcie_rootport_aspm_quirk(struct pci_dev *pdev) | ||
251 | { | ||
252 | int cap_base, i; | ||
253 | struct pci_bus *pbus; | ||
254 | struct pci_dev *dev; | ||
255 | |||
256 | if ((pbus = pdev->subordinate) == NULL) | ||
257 | return; | ||
258 | |||
259 | /* | ||
260 | * Check if the DID of pdev matches one of the six root ports. This | ||
261 | * check is needed in the case this function is called directly by the | ||
262 | * hot-plug driver. | ||
263 | */ | ||
264 | if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) || | ||
265 | (pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1)) | ||
266 | return; | ||
267 | |||
268 | if (list_empty(&pbus->devices)) { | ||
269 | /* | ||
270 | * If no device is attached to the root port at power-up or | ||
271 | * after hot-remove, the pbus->devices is empty and this code | ||
272 | * will set the offsets to zero and the bus ops to parent's bus | ||
273 | * ops, which is unmodified. | ||
274 | */ | ||
275 | for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i) | ||
276 | quirk_aspm_offset[i] = 0; | ||
277 | |||
278 | pbus->ops = pbus->parent->ops; | ||
279 | } else { | ||
280 | /* | ||
281 | * If devices are attached to the root port at power-up or | ||
282 | * after hot-add, the code loops through the device list of | ||
283 | * each root port to save the register offsets and replace the | ||
284 | * bus ops. | ||
285 | */ | ||
286 | list_for_each_entry(dev, &pbus->devices, bus_list) { | ||
287 | /* There are 0 to 8 devices attached to this bus */ | ||
288 | cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
289 | quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10; | ||
290 | } | ||
291 | pbus->ops = &quirk_pcie_aspm_ops; | ||
292 | } | ||
293 | } | ||
294 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk ); | ||
295 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk ); | ||
296 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB, pcie_rootport_aspm_quirk ); | ||
297 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_rootport_aspm_quirk ); | ||
298 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); | ||
299 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); | ||
300 | |||
301 | /* | ||
302 | * Fixup to mark boot BIOS video selected by BIOS before it changes | ||
303 | * | ||
304 | * From information provided by "Jon Smirl" <jonsmirl@gmail.com> | ||
305 | * | ||
306 | * The standard boot ROM sequence for an x86 machine uses the BIOS | ||
307 | * to select an initial video card for boot display. This boot video | ||
308 | * card will have it's BIOS copied to C0000 in system RAM. | ||
309 | * IORESOURCE_ROM_SHADOW is used to associate the boot video | ||
310 | * card with this copy. On laptops this copy has to be used since | ||
311 | * the main ROM may be compressed or combined with another image. | ||
312 | * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW | ||
313 | * is marked here since the boot video device will be the only enabled | ||
314 | * video device at this point. | ||
315 | */ | ||
316 | |||
317 | static void __devinit pci_fixup_video(struct pci_dev *pdev) | ||
318 | { | ||
319 | struct pci_dev *bridge; | ||
320 | struct pci_bus *bus; | ||
321 | u16 config; | ||
322 | |||
323 | if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
324 | return; | ||
325 | |||
326 | /* Is VGA routed to us? */ | ||
327 | bus = pdev->bus; | ||
328 | while (bus) { | ||
329 | bridge = bus->self; | ||
330 | |||
331 | /* | ||
332 | * From information provided by | ||
333 | * "David Miller" <davem@davemloft.net> | ||
334 | * The bridge control register is valid for PCI header | ||
335 | * type BRIDGE, or CARDBUS. Host to PCI controllers use | ||
336 | * PCI header type NORMAL. | ||
337 | */ | ||
338 | if (bridge | ||
339 | &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
340 | ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { | ||
341 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
342 | &config); | ||
343 | if (!(config & PCI_BRIDGE_CTL_VGA)) | ||
344 | return; | ||
345 | } | ||
346 | bus = bus->parent; | ||
347 | } | ||
348 | pci_read_config_word(pdev, PCI_COMMAND, &config); | ||
349 | if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { | ||
350 | pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; | ||
351 | printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); | ||
352 | } | ||
353 | } | ||
354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); | ||
355 | |||
356 | /* | ||
357 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. | ||
358 | * | ||
359 | * We pretend to bring them out of full D3 state, and restore the proper | ||
360 | * IRQ, PCI cache line size, and BARs, otherwise the device won't function | ||
361 | * properly. In some cases, the device will generate an interrupt on | ||
362 | * the wrong IRQ line, causing any devices sharing the line it's | ||
363 | * *supposed* to use to be disabled by the kernel's IRQ debug code. | ||
364 | */ | ||
365 | static u16 toshiba_line_size; | ||
366 | |||
367 | static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = { | ||
368 | { | ||
369 | .ident = "Toshiba PS5 based laptop", | ||
370 | .matches = { | ||
371 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
372 | DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"), | ||
373 | }, | ||
374 | }, | ||
375 | { | ||
376 | .ident = "Toshiba PSM4 based laptop", | ||
377 | .matches = { | ||
378 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
379 | DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"), | ||
380 | }, | ||
381 | }, | ||
382 | { | ||
383 | .ident = "Toshiba A40 based laptop", | ||
384 | .matches = { | ||
385 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
386 | DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"), | ||
387 | }, | ||
388 | }, | ||
389 | { } | ||
390 | }; | ||
391 | |||
392 | static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) | ||
393 | { | ||
394 | if (!dmi_check_system(toshiba_ohci1394_dmi_table)) | ||
395 | return; /* only applies to certain Toshibas (so far) */ | ||
396 | |||
397 | dev->current_state = PCI_D3cold; | ||
398 | pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size); | ||
399 | } | ||
400 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032, | ||
401 | pci_pre_fixup_toshiba_ohci1394); | ||
402 | |||
403 | static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev) | ||
404 | { | ||
405 | if (!dmi_check_system(toshiba_ohci1394_dmi_table)) | ||
406 | return; /* only applies to certain Toshibas (so far) */ | ||
407 | |||
408 | /* Restore config space on Toshiba laptops */ | ||
409 | pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size); | ||
410 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, (u8 *)&dev->irq); | ||
411 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, | ||
412 | pci_resource_start(dev, 0)); | ||
413 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, | ||
414 | pci_resource_start(dev, 1)); | ||
415 | } | ||
416 | DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032, | ||
417 | pci_post_fixup_toshiba_ohci1394); | ||
418 | |||
419 | |||
420 | /* | ||
421 | * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device | ||
422 | * configuration space. | ||
423 | */ | ||
424 | static void pci_early_fixup_cyrix_5530(struct pci_dev *dev) | ||
425 | { | ||
426 | u8 r; | ||
427 | /* clear 'F4 Video Configuration Trap' bit */ | ||
428 | pci_read_config_byte(dev, 0x42, &r); | ||
429 | r &= 0xfd; | ||
430 | pci_write_config_byte(dev, 0x42, r); | ||
431 | } | ||
432 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, | ||
433 | pci_early_fixup_cyrix_5530); | ||
434 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, | ||
435 | pci_early_fixup_cyrix_5530); | ||
436 | |||
437 | /* | ||
438 | * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller: | ||
439 | * prevent update of the BAR0, which doesn't look like a normal BAR. | ||
440 | */ | ||
441 | static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev) | ||
442 | { | ||
443 | dev->resource[0].flags |= IORESOURCE_PCI_FIXED; | ||
444 | } | ||
445 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015, | ||
446 | pci_siemens_interrupt_controller); | ||
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c new file mode 100644 index 000000000000..bcd2f94b732c --- /dev/null +++ b/arch/x86/pci/i386.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Access for i386 machines | ||
3 | * | ||
4 | * Copyright 1993, 1994 Drew Eckhardt | ||
5 | * Visionary Computing | ||
6 | * (Unix and Linux consulting and custom programming) | ||
7 | * Drew@Colorado.EDU | ||
8 | * +1 (303) 786-7975 | ||
9 | * | ||
10 | * Drew's work was sponsored by: | ||
11 | * iX Multiuser Multitasking Magazine | ||
12 | * Hannover, Germany | ||
13 | * hm@ix.de | ||
14 | * | ||
15 | * Copyright 1997--2000 Martin Mares <mj@ucw.cz> | ||
16 | * | ||
17 | * For more information, please consult the following manuals (look at | ||
18 | * http://www.pcisig.com/ for how to get them): | ||
19 | * | ||
20 | * PCI BIOS Specification | ||
21 | * PCI Local Bus Specification | ||
22 | * PCI to PCI Bridge Specification | ||
23 | * PCI System Design Guide | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/errno.h> | ||
33 | |||
34 | #include "pci.h" | ||
35 | |||
36 | /* | ||
37 | * We need to avoid collisions with `mirrored' VGA ports | ||
38 | * and other strange ISA hardware, so we always want the | ||
39 | * addresses to be allocated in the 0x000-0x0ff region | ||
40 | * modulo 0x400. | ||
41 | * | ||
42 | * Why? Because some silly external IO cards only decode | ||
43 | * the low 10 bits of the IO address. The 0x00-0xff region | ||
44 | * is reserved for motherboard devices that decode all 16 | ||
45 | * bits, so it's ok to allocate at, say, 0x2800-0x28ff, | ||
46 | * but we want to try to avoid allocating at 0x2900-0x2bff | ||
47 | * which might have be mirrored at 0x0100-0x03ff.. | ||
48 | */ | ||
49 | void | ||
50 | pcibios_align_resource(void *data, struct resource *res, | ||
51 | resource_size_t size, resource_size_t align) | ||
52 | { | ||
53 | if (res->flags & IORESOURCE_IO) { | ||
54 | resource_size_t start = res->start; | ||
55 | |||
56 | if (start & 0x300) { | ||
57 | start = (start + 0x3ff) & ~0x3ff; | ||
58 | res->start = start; | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | |||
64 | /* | ||
65 | * Handle resources of PCI devices. If the world were perfect, we could | ||
66 | * just allocate all the resource regions and do nothing more. It isn't. | ||
67 | * On the other hand, we cannot just re-allocate all devices, as it would | ||
68 | * require us to know lots of host bridge internals. So we attempt to | ||
69 | * keep as much of the original configuration as possible, but tweak it | ||
70 | * when it's found to be wrong. | ||
71 | * | ||
72 | * Known BIOS problems we have to work around: | ||
73 | * - I/O or memory regions not configured | ||
74 | * - regions configured, but not enabled in the command register | ||
75 | * - bogus I/O addresses above 64K used | ||
76 | * - expansion ROMs left enabled (this may sound harmless, but given | ||
77 | * the fact the PCI specs explicitly allow address decoders to be | ||
78 | * shared between expansion ROMs and other resource regions, it's | ||
79 | * at least dangerous) | ||
80 | * | ||
81 | * Our solution: | ||
82 | * (1) Allocate resources for all buses behind PCI-to-PCI bridges. | ||
83 | * This gives us fixed barriers on where we can allocate. | ||
84 | * (2) Allocate resources for all enabled devices. If there is | ||
85 | * a collision, just mark the resource as unallocated. Also | ||
86 | * disable expansion ROMs during this step. | ||
87 | * (3) Try to allocate resources for disabled devices. If the | ||
88 | * resources were assigned correctly, everything goes well, | ||
89 | * if they weren't, they won't disturb allocation of other | ||
90 | * resources. | ||
91 | * (4) Assign new addresses to resources which were either | ||
92 | * not configured at all or misconfigured. If explicitly | ||
93 | * requested by the user, configure expansion ROM address | ||
94 | * as well. | ||
95 | */ | ||
96 | |||
97 | static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | ||
98 | { | ||
99 | struct pci_bus *bus; | ||
100 | struct pci_dev *dev; | ||
101 | int idx; | ||
102 | struct resource *r, *pr; | ||
103 | |||
104 | /* Depth-First Search on bus tree */ | ||
105 | list_for_each_entry(bus, bus_list, node) { | ||
106 | if ((dev = bus->self)) { | ||
107 | for (idx = PCI_BRIDGE_RESOURCES; | ||
108 | idx < PCI_NUM_RESOURCES; idx++) { | ||
109 | r = &dev->resource[idx]; | ||
110 | if (!r->flags) | ||
111 | continue; | ||
112 | pr = pci_find_parent_resource(dev, r); | ||
113 | if (!r->start || !pr || | ||
114 | request_resource(pr, r) < 0) { | ||
115 | printk(KERN_ERR "PCI: Cannot allocate " | ||
116 | "resource region %d " | ||
117 | "of bridge %s\n", | ||
118 | idx, pci_name(dev)); | ||
119 | /* | ||
120 | * Something is wrong with the region. | ||
121 | * Invalidate the resource to prevent | ||
122 | * child resource allocations in this | ||
123 | * range. | ||
124 | */ | ||
125 | r->flags = 0; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | pcibios_allocate_bus_resources(&bus->children); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | static void __init pcibios_allocate_resources(int pass) | ||
134 | { | ||
135 | struct pci_dev *dev = NULL; | ||
136 | int idx, disabled; | ||
137 | u16 command; | ||
138 | struct resource *r, *pr; | ||
139 | |||
140 | for_each_pci_dev(dev) { | ||
141 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
142 | for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { | ||
143 | r = &dev->resource[idx]; | ||
144 | if (r->parent) /* Already allocated */ | ||
145 | continue; | ||
146 | if (!r->start) /* Address not assigned at all */ | ||
147 | continue; | ||
148 | if (r->flags & IORESOURCE_IO) | ||
149 | disabled = !(command & PCI_COMMAND_IO); | ||
150 | else | ||
151 | disabled = !(command & PCI_COMMAND_MEMORY); | ||
152 | if (pass == disabled) { | ||
153 | DBG("PCI: Resource %08lx-%08lx " | ||
154 | "(f=%lx, d=%d, p=%d)\n", | ||
155 | r->start, r->end, r->flags, disabled, pass); | ||
156 | pr = pci_find_parent_resource(dev, r); | ||
157 | if (!pr || request_resource(pr, r) < 0) { | ||
158 | printk(KERN_ERR "PCI: Cannot allocate " | ||
159 | "resource region %d " | ||
160 | "of device %s\n", | ||
161 | idx, pci_name(dev)); | ||
162 | /* We'll assign a new address later */ | ||
163 | r->end -= r->start; | ||
164 | r->start = 0; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | if (!pass) { | ||
169 | r = &dev->resource[PCI_ROM_RESOURCE]; | ||
170 | if (r->flags & IORESOURCE_ROM_ENABLE) { | ||
171 | /* Turn the ROM off, leave the resource region, | ||
172 | * but keep it unregistered. */ | ||
173 | u32 reg; | ||
174 | DBG("PCI: Switching off ROM of %s\n", | ||
175 | pci_name(dev)); | ||
176 | r->flags &= ~IORESOURCE_ROM_ENABLE; | ||
177 | pci_read_config_dword(dev, | ||
178 | dev->rom_base_reg, ®); | ||
179 | pci_write_config_dword(dev, dev->rom_base_reg, | ||
180 | reg & ~PCI_ROM_ADDRESS_ENABLE); | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | |||
186 | static int __init pcibios_assign_resources(void) | ||
187 | { | ||
188 | struct pci_dev *dev = NULL; | ||
189 | struct resource *r, *pr; | ||
190 | |||
191 | if (!(pci_probe & PCI_ASSIGN_ROMS)) { | ||
192 | /* | ||
193 | * Try to use BIOS settings for ROMs, otherwise let | ||
194 | * pci_assign_unassigned_resources() allocate the new | ||
195 | * addresses. | ||
196 | */ | ||
197 | for_each_pci_dev(dev) { | ||
198 | r = &dev->resource[PCI_ROM_RESOURCE]; | ||
199 | if (!r->flags || !r->start) | ||
200 | continue; | ||
201 | pr = pci_find_parent_resource(dev, r); | ||
202 | if (!pr || request_resource(pr, r) < 0) { | ||
203 | r->end -= r->start; | ||
204 | r->start = 0; | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | pci_assign_unassigned_resources(); | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | void __init pcibios_resource_survey(void) | ||
215 | { | ||
216 | DBG("PCI: Allocating resources\n"); | ||
217 | pcibios_allocate_bus_resources(&pci_root_buses); | ||
218 | pcibios_allocate_resources(0); | ||
219 | pcibios_allocate_resources(1); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * called in fs_initcall (one below subsys_initcall), | ||
224 | * give a chance for motherboard reserve resources | ||
225 | */ | ||
226 | fs_initcall(pcibios_assign_resources); | ||
227 | |||
228 | int pcibios_enable_resources(struct pci_dev *dev, int mask) | ||
229 | { | ||
230 | u16 cmd, old_cmd; | ||
231 | int idx; | ||
232 | struct resource *r; | ||
233 | |||
234 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
235 | old_cmd = cmd; | ||
236 | for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { | ||
237 | /* Only set up the requested stuff */ | ||
238 | if (!(mask & (1 << idx))) | ||
239 | continue; | ||
240 | |||
241 | r = &dev->resource[idx]; | ||
242 | if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) | ||
243 | continue; | ||
244 | if ((idx == PCI_ROM_RESOURCE) && | ||
245 | (!(r->flags & IORESOURCE_ROM_ENABLE))) | ||
246 | continue; | ||
247 | if (!r->start && r->end) { | ||
248 | printk(KERN_ERR "PCI: Device %s not available " | ||
249 | "because of resource %d collisions\n", | ||
250 | pci_name(dev), idx); | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | if (r->flags & IORESOURCE_IO) | ||
254 | cmd |= PCI_COMMAND_IO; | ||
255 | if (r->flags & IORESOURCE_MEM) | ||
256 | cmd |= PCI_COMMAND_MEMORY; | ||
257 | } | ||
258 | if (cmd != old_cmd) { | ||
259 | printk("PCI: Enabling device %s (%04x -> %04x)\n", | ||
260 | pci_name(dev), old_cmd, cmd); | ||
261 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
262 | } | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * If we set up a device for bus mastering, we need to check the latency | ||
268 | * timer as certain crappy BIOSes forget to set it properly. | ||
269 | */ | ||
270 | unsigned int pcibios_max_latency = 255; | ||
271 | |||
272 | void pcibios_set_master(struct pci_dev *dev) | ||
273 | { | ||
274 | u8 lat; | ||
275 | pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); | ||
276 | if (lat < 16) | ||
277 | lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; | ||
278 | else if (lat > pcibios_max_latency) | ||
279 | lat = pcibios_max_latency; | ||
280 | else | ||
281 | return; | ||
282 | printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", | ||
283 | pci_name(dev), lat); | ||
284 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); | ||
285 | } | ||
286 | |||
287 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
288 | enum pci_mmap_state mmap_state, int write_combine) | ||
289 | { | ||
290 | unsigned long prot; | ||
291 | |||
292 | /* I/O space cannot be accessed via normal processor loads and | ||
293 | * stores on this platform. | ||
294 | */ | ||
295 | if (mmap_state == pci_mmap_io) | ||
296 | return -EINVAL; | ||
297 | |||
298 | /* Leave vm_pgoff as-is, the PCI space address is the physical | ||
299 | * address on this platform. | ||
300 | */ | ||
301 | prot = pgprot_val(vma->vm_page_prot); | ||
302 | if (boot_cpu_data.x86 > 3) | ||
303 | prot |= _PAGE_PCD | _PAGE_PWT; | ||
304 | vma->vm_page_prot = __pgprot(prot); | ||
305 | |||
306 | /* Write-combine setting is ignored, it is changed via the mtrr | ||
307 | * interfaces on this platform. | ||
308 | */ | ||
309 | if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
310 | vma->vm_end - vma->vm_start, | ||
311 | vma->vm_page_prot)) | ||
312 | return -EAGAIN; | ||
313 | |||
314 | return 0; | ||
315 | } | ||
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c new file mode 100644 index 000000000000..3de9f9ba2da6 --- /dev/null +++ b/arch/x86/pci/init.c | |||
@@ -0,0 +1,37 @@ | |||
1 | #include <linux/pci.h> | ||
2 | #include <linux/init.h> | ||
3 | #include "pci.h" | ||
4 | |||
5 | /* arch_initcall has too random ordering, so call the initializers | ||
6 | in the right sequence from here. */ | ||
7 | static __init int pci_access_init(void) | ||
8 | { | ||
9 | int type __maybe_unused = 0; | ||
10 | |||
11 | #ifdef CONFIG_PCI_DIRECT | ||
12 | type = pci_direct_probe(); | ||
13 | #endif | ||
14 | #ifdef CONFIG_PCI_MMCONFIG | ||
15 | pci_mmcfg_init(type); | ||
16 | #endif | ||
17 | if (raw_pci_ops) | ||
18 | return 0; | ||
19 | #ifdef CONFIG_PCI_BIOS | ||
20 | pci_pcbios_init(); | ||
21 | #endif | ||
22 | /* | ||
23 | * don't check for raw_pci_ops here because we want pcbios as last | ||
24 | * fallback, yet it's needed to run first to set pcibios_last_bus | ||
25 | * in case legacy PCI probing is used. otherwise detecting peer busses | ||
26 | * fails. | ||
27 | */ | ||
28 | #ifdef CONFIG_PCI_DIRECT | ||
29 | pci_direct_init(type); | ||
30 | #endif | ||
31 | if (!raw_pci_ops) | ||
32 | printk(KERN_ERR | ||
33 | "PCI: Fatal: No config space access function found\n"); | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | arch_initcall(pci_access_init); | ||
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c new file mode 100644 index 000000000000..8434f2323b87 --- /dev/null +++ b/arch/x86/pci/irq.c | |||
@@ -0,0 +1,1173 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Support for PC -- Routing of Interrupts | ||
3 | * | ||
4 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> | ||
5 | */ | ||
6 | |||
7 | #include <linux/types.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/pci.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/dmi.h> | ||
14 | #include <asm/io.h> | ||
15 | #include <asm/smp.h> | ||
16 | #include <asm/io_apic.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/acpi.h> | ||
19 | |||
20 | #include "pci.h" | ||
21 | |||
22 | #define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) | ||
23 | #define PIRQ_VERSION 0x0100 | ||
24 | |||
25 | static int broken_hp_bios_irq9; | ||
26 | static int acer_tm360_irqrouting; | ||
27 | |||
28 | static struct irq_routing_table *pirq_table; | ||
29 | |||
30 | static int pirq_enable_irq(struct pci_dev *dev); | ||
31 | |||
32 | /* | ||
33 | * Never use: 0, 1, 2 (timer, keyboard, and cascade) | ||
34 | * Avoid using: 13, 14 and 15 (FP error and IDE). | ||
35 | * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse) | ||
36 | */ | ||
37 | unsigned int pcibios_irq_mask = 0xfff8; | ||
38 | |||
39 | static int pirq_penalty[16] = { | ||
40 | 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000, | ||
41 | 0, 0, 0, 0, 1000, 100000, 100000, 100000 | ||
42 | }; | ||
43 | |||
44 | struct irq_router { | ||
45 | char *name; | ||
46 | u16 vendor, device; | ||
47 | int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq); | ||
48 | int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new); | ||
49 | }; | ||
50 | |||
51 | struct irq_router_handler { | ||
52 | u16 vendor; | ||
53 | int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device); | ||
54 | }; | ||
55 | |||
56 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; | ||
57 | void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; | ||
58 | |||
59 | /* | ||
60 | * Check passed address for the PCI IRQ Routing Table signature | ||
61 | * and perform checksum verification. | ||
62 | */ | ||
63 | |||
64 | static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr) | ||
65 | { | ||
66 | struct irq_routing_table *rt; | ||
67 | int i; | ||
68 | u8 sum; | ||
69 | |||
70 | rt = (struct irq_routing_table *) addr; | ||
71 | if (rt->signature != PIRQ_SIGNATURE || | ||
72 | rt->version != PIRQ_VERSION || | ||
73 | rt->size % 16 || | ||
74 | rt->size < sizeof(struct irq_routing_table)) | ||
75 | return NULL; | ||
76 | sum = 0; | ||
77 | for (i=0; i < rt->size; i++) | ||
78 | sum += addr[i]; | ||
79 | if (!sum) { | ||
80 | DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt); | ||
81 | return rt; | ||
82 | } | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | |||
87 | |||
88 | /* | ||
89 | * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. | ||
90 | */ | ||
91 | |||
92 | static struct irq_routing_table * __init pirq_find_routing_table(void) | ||
93 | { | ||
94 | u8 *addr; | ||
95 | struct irq_routing_table *rt; | ||
96 | |||
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 | } | ||
103 | for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { | ||
104 | rt = pirq_check_routing_table(addr); | ||
105 | if (rt) | ||
106 | return rt; | ||
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 | |||
117 | static 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)); | ||
125 | for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) { | ||
126 | e = &rt->slots[i]; | ||
127 | #ifdef DEBUG | ||
128 | { | ||
129 | int j; | ||
130 | DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot); | ||
131 | for(j=0; j<4; j++) | ||
132 | DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap); | ||
133 | DBG("\n"); | ||
134 | } | ||
135 | #endif | ||
136 | busmap[e->bus] = 1; | ||
137 | } | ||
138 | for(i = 1; i < 256; i++) { | ||
139 | if (!busmap[i] || pci_find_bus(0, i)) | ||
140 | continue; | ||
141 | if (pci_scan_bus_with_sysdata(i)) | ||
142 | printk(KERN_INFO "PCI: Discovered primary peer " | ||
143 | "bus %02x [IRQ]\n", i); | ||
144 | } | ||
145 | pcibios_last_bus = -1; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Code for querying and setting of IRQ routes on various interrupt routers. | ||
150 | */ | ||
151 | |||
152 | void eisa_set_level_irq(unsigned int irq) | ||
153 | { | ||
154 | unsigned char mask = 1 << (irq & 7); | ||
155 | unsigned int port = 0x4d0 + (irq >> 3); | ||
156 | unsigned char val; | ||
157 | static u16 eisa_irq_mask; | ||
158 | |||
159 | if (irq >= 16 || (1 << irq) & eisa_irq_mask) | ||
160 | return; | ||
161 | |||
162 | eisa_irq_mask |= (1 << irq); | ||
163 | printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq); | ||
164 | val = inb(port); | ||
165 | if (!(val & mask)) { | ||
166 | DBG(KERN_DEBUG " -> edge"); | ||
167 | outb(val | mask, port); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Common IRQ routing practice: nybbles in config space, | ||
173 | * offset by some magic constant. | ||
174 | */ | ||
175 | static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr) | ||
176 | { | ||
177 | u8 x; | ||
178 | unsigned reg = offset + (nr >> 1); | ||
179 | |||
180 | pci_read_config_byte(router, reg, &x); | ||
181 | return (nr & 1) ? (x >> 4) : (x & 0xf); | ||
182 | } | ||
183 | |||
184 | static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val) | ||
185 | { | ||
186 | u8 x; | ||
187 | unsigned reg = offset + (nr >> 1); | ||
188 | |||
189 | pci_read_config_byte(router, reg, &x); | ||
190 | x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val); | ||
191 | pci_write_config_byte(router, reg, x); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * ALI pirq entries are damn ugly, and completely undocumented. | ||
196 | * This has been figured out from pirq tables, and it's not a pretty | ||
197 | * picture. | ||
198 | */ | ||
199 | static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
200 | { | ||
201 | static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; | ||
202 | |||
203 | return irqmap[read_config_nybble(router, 0x48, pirq-1)]; | ||
204 | } | ||
205 | |||
206 | static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
207 | { | ||
208 | static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; | ||
209 | unsigned int val = irqmap[irq]; | ||
210 | |||
211 | if (val) { | ||
212 | write_config_nybble(router, 0x48, pirq-1, val); | ||
213 | return 1; | ||
214 | } | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * The Intel PIIX4 pirq rules are fairly simple: "pirq" is | ||
220 | * just a pointer to the config space. | ||
221 | */ | ||
222 | static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
223 | { | ||
224 | u8 x; | ||
225 | |||
226 | pci_read_config_byte(router, pirq, &x); | ||
227 | return (x < 16) ? x : 0; | ||
228 | } | ||
229 | |||
230 | static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
231 | { | ||
232 | pci_write_config_byte(router, pirq, irq); | ||
233 | return 1; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * The VIA pirq rules are nibble-based, like ALI, | ||
238 | * but without the ugly irq number munging. | ||
239 | * However, PIRQD is in the upper instead of lower 4 bits. | ||
240 | */ | ||
241 | static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
242 | { | ||
243 | return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq); | ||
244 | } | ||
245 | |||
246 | static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
247 | { | ||
248 | write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq); | ||
249 | return 1; | ||
250 | } | ||
251 | |||
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 const unsigned int pirqmap[5] = { 3, 2, 5, 1, 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 const unsigned int pirqmap[5] = { 3, 2, 5, 1, 1 }; | ||
266 | write_config_nybble(router, 0x55, pirqmap[pirq-1], irq); | ||
267 | return 1; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * ITE 8330G pirq rules are nibble-based | ||
272 | * FIXME: pirqmap may be { 1, 0, 3, 2 }, | ||
273 | * 2+3 are both mapped to irq 9 on my system | ||
274 | */ | ||
275 | static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
276 | { | ||
277 | static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; | ||
278 | return read_config_nybble(router,0x43, pirqmap[pirq-1]); | ||
279 | } | ||
280 | |||
281 | static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
282 | { | ||
283 | static const unsigned char pirqmap[4] = { 1, 0, 2, 3 }; | ||
284 | write_config_nybble(router, 0x43, pirqmap[pirq-1], irq); | ||
285 | return 1; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * OPTI: high four bits are nibble pointer.. | ||
290 | * I wonder what the low bits do? | ||
291 | */ | ||
292 | static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
293 | { | ||
294 | return read_config_nybble(router, 0xb8, pirq >> 4); | ||
295 | } | ||
296 | |||
297 | static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
298 | { | ||
299 | write_config_nybble(router, 0xb8, pirq >> 4, irq); | ||
300 | return 1; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Cyrix: nibble offset 0x5C | ||
305 | * 0x5C bits 7:4 is INTB bits 3:0 is INTA | ||
306 | * 0x5D bits 7:4 is INTD bits 3:0 is INTC | ||
307 | */ | ||
308 | static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
309 | { | ||
310 | return read_config_nybble(router, 0x5C, (pirq-1)^1); | ||
311 | } | ||
312 | |||
313 | static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
314 | { | ||
315 | write_config_nybble(router, 0x5C, (pirq-1)^1, irq); | ||
316 | return 1; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * PIRQ routing for SiS 85C503 router used in several SiS chipsets. | ||
321 | * We have to deal with the following issues here: | ||
322 | * - vendors have different ideas about the meaning of link values | ||
323 | * - some onboard devices (integrated in the chipset) have special | ||
324 | * links and are thus routed differently (i.e. not via PCI INTA-INTD) | ||
325 | * - different revision of the router have a different layout for | ||
326 | * the routing registers, particularly for the onchip devices | ||
327 | * | ||
328 | * For all routing registers the common thing is we have one byte | ||
329 | * per routeable link which is defined as: | ||
330 | * bit 7 IRQ mapping enabled (0) or disabled (1) | ||
331 | * bits [6:4] reserved (sometimes used for onchip devices) | ||
332 | * bits [3:0] IRQ to map to | ||
333 | * allowed: 3-7, 9-12, 14-15 | ||
334 | * reserved: 0, 1, 2, 8, 13 | ||
335 | * | ||
336 | * The config-space registers located at 0x41/0x42/0x43/0x44 are | ||
337 | * always used to route the normal PCI INT A/B/C/D respectively. | ||
338 | * Apparently there are systems implementing PCI routing table using | ||
339 | * link values 0x01-0x04 and others using 0x41-0x44 for PCI INTA..D. | ||
340 | * We try our best to handle both link mappings. | ||
341 | * | ||
342 | * Currently (2003-05-21) it appears most SiS chipsets follow the | ||
343 | * definition of routing registers from the SiS-5595 southbridge. | ||
344 | * According to the SiS 5595 datasheets the revision id's of the | ||
345 | * router (ISA-bridge) should be 0x01 or 0xb0. | ||
346 | * | ||
347 | * Furthermore we've also seen lspci dumps with revision 0x00 and 0xb1. | ||
348 | * Looks like these are used in a number of SiS 5xx/6xx/7xx chipsets. | ||
349 | * They seem to work with the current routing code. However there is | ||
350 | * some concern because of the two USB-OHCI HCs (original SiS 5595 | ||
351 | * had only one). YMMV. | ||
352 | * | ||
353 | * Onchip routing for router rev-id 0x01/0xb0 and probably 0x00/0xb1: | ||
354 | * | ||
355 | * 0x61: IDEIRQ: | ||
356 | * bits [6:5] must be written 01 | ||
357 | * bit 4 channel-select primary (0), secondary (1) | ||
358 | * | ||
359 | * 0x62: USBIRQ: | ||
360 | * bit 6 OHCI function disabled (0), enabled (1) | ||
361 | * | ||
362 | * 0x6a: ACPI/SCI IRQ: bits 4-6 reserved | ||
363 | * | ||
364 | * 0x7e: Data Acq. Module IRQ - bits 4-6 reserved | ||
365 | * | ||
366 | * We support USBIRQ (in addition to INTA-INTD) and keep the | ||
367 | * IDE, ACPI and DAQ routing untouched as set by the BIOS. | ||
368 | * | ||
369 | * Currently the only reported exception is the new SiS 65x chipset | ||
370 | * which includes the SiS 69x southbridge. Here we have the 85C503 | ||
371 | * router revision 0x04 and there are changes in the register layout | ||
372 | * mostly related to the different USB HCs with USB 2.0 support. | ||
373 | * | ||
374 | * Onchip routing for router rev-id 0x04 (try-and-error observation) | ||
375 | * | ||
376 | * 0x60/0x61/0x62/0x63: 1xEHCI and 3xOHCI (companion) USB-HCs | ||
377 | * bit 6-4 are probably unused, not like 5595 | ||
378 | */ | ||
379 | |||
380 | #define PIRQ_SIS_IRQ_MASK 0x0f | ||
381 | #define PIRQ_SIS_IRQ_DISABLE 0x80 | ||
382 | #define PIRQ_SIS_USB_ENABLE 0x40 | ||
383 | |||
384 | static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
385 | { | ||
386 | u8 x; | ||
387 | int reg; | ||
388 | |||
389 | reg = pirq; | ||
390 | if (reg >= 0x01 && reg <= 0x04) | ||
391 | reg += 0x40; | ||
392 | pci_read_config_byte(router, reg, &x); | ||
393 | return (x & PIRQ_SIS_IRQ_DISABLE) ? 0 : (x & PIRQ_SIS_IRQ_MASK); | ||
394 | } | ||
395 | |||
396 | static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
397 | { | ||
398 | u8 x; | ||
399 | int reg; | ||
400 | |||
401 | reg = pirq; | ||
402 | if (reg >= 0x01 && reg <= 0x04) | ||
403 | reg += 0x40; | ||
404 | pci_read_config_byte(router, reg, &x); | ||
405 | x &= ~(PIRQ_SIS_IRQ_MASK | PIRQ_SIS_IRQ_DISABLE); | ||
406 | x |= irq ? irq: PIRQ_SIS_IRQ_DISABLE; | ||
407 | pci_write_config_byte(router, reg, x); | ||
408 | return 1; | ||
409 | } | ||
410 | |||
411 | |||
412 | /* | ||
413 | * VLSI: nibble offset 0x74 - educated guess due to routing table and | ||
414 | * config space of VLSI 82C534 PCI-bridge/router (1004:0102) | ||
415 | * Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard | ||
416 | * devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6 | ||
417 | * for the busbridge to the docking station. | ||
418 | */ | ||
419 | |||
420 | static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
421 | { | ||
422 | if (pirq > 8) { | ||
423 | printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq); | ||
424 | return 0; | ||
425 | } | ||
426 | return read_config_nybble(router, 0x74, pirq-1); | ||
427 | } | ||
428 | |||
429 | static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
430 | { | ||
431 | if (pirq > 8) { | ||
432 | printk(KERN_INFO "VLSI router pirq escape (%d)\n", pirq); | ||
433 | return 0; | ||
434 | } | ||
435 | write_config_nybble(router, 0x74, pirq-1, irq); | ||
436 | return 1; | ||
437 | } | ||
438 | |||
439 | /* | ||
440 | * ServerWorks: PCI interrupts mapped to system IRQ lines through Index | ||
441 | * and Redirect I/O registers (0x0c00 and 0x0c01). The Index register | ||
442 | * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a. The Redirect | ||
443 | * register is a straight binary coding of desired PIC IRQ (low nibble). | ||
444 | * | ||
445 | * The 'link' value in the PIRQ table is already in the correct format | ||
446 | * for the Index register. There are some special index values: | ||
447 | * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1, | ||
448 | * and 0x03 for SMBus. | ||
449 | */ | ||
450 | static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
451 | { | ||
452 | outb_p(pirq, 0xc00); | ||
453 | return inb(0xc01) & 0xf; | ||
454 | } | ||
455 | |||
456 | static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
457 | { | ||
458 | outb_p(pirq, 0xc00); | ||
459 | outb_p(irq, 0xc01); | ||
460 | return 1; | ||
461 | } | ||
462 | |||
463 | /* Support for AMD756 PCI IRQ Routing | ||
464 | * Jhon H. Caicedo <jhcaiced@osso.org.co> | ||
465 | * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced) | ||
466 | * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced) | ||
467 | * The AMD756 pirq rules are nibble-based | ||
468 | * offset 0x56 0-3 PIRQA 4-7 PIRQB | ||
469 | * offset 0x57 0-3 PIRQC 4-7 PIRQD | ||
470 | */ | ||
471 | static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
472 | { | ||
473 | u8 irq; | ||
474 | irq = 0; | ||
475 | if (pirq <= 4) | ||
476 | { | ||
477 | irq = read_config_nybble(router, 0x56, pirq - 1); | ||
478 | } | ||
479 | printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", | ||
480 | dev->vendor, dev->device, pirq, irq); | ||
481 | return irq; | ||
482 | } | ||
483 | |||
484 | static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
485 | { | ||
486 | printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", | ||
487 | dev->vendor, dev->device, pirq, irq); | ||
488 | if (pirq <= 4) | ||
489 | { | ||
490 | write_config_nybble(router, 0x56, pirq - 1, irq); | ||
491 | } | ||
492 | return 1; | ||
493 | } | ||
494 | |||
495 | #ifdef CONFIG_PCI_BIOS | ||
496 | |||
497 | static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | ||
498 | { | ||
499 | struct pci_dev *bridge; | ||
500 | int pin = pci_get_interrupt_pin(dev, &bridge); | ||
501 | return pcibios_set_irq_routing(bridge, pin, irq); | ||
502 | } | ||
503 | |||
504 | #endif | ||
505 | |||
506 | static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
507 | { | ||
508 | static struct pci_device_id __initdata pirq_440gx[] = { | ||
509 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, | ||
510 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, | ||
511 | { }, | ||
512 | }; | ||
513 | |||
514 | /* 440GX has a proprietary PIRQ router -- don't use it */ | ||
515 | if (pci_dev_present(pirq_440gx)) | ||
516 | return 0; | ||
517 | |||
518 | switch(device) | ||
519 | { | ||
520 | case PCI_DEVICE_ID_INTEL_82371FB_0: | ||
521 | case PCI_DEVICE_ID_INTEL_82371SB_0: | ||
522 | case PCI_DEVICE_ID_INTEL_82371AB_0: | ||
523 | case PCI_DEVICE_ID_INTEL_82371MX: | ||
524 | case PCI_DEVICE_ID_INTEL_82443MX_0: | ||
525 | case PCI_DEVICE_ID_INTEL_82801AA_0: | ||
526 | case PCI_DEVICE_ID_INTEL_82801AB_0: | ||
527 | case PCI_DEVICE_ID_INTEL_82801BA_0: | ||
528 | case PCI_DEVICE_ID_INTEL_82801BA_10: | ||
529 | case PCI_DEVICE_ID_INTEL_82801CA_0: | ||
530 | case PCI_DEVICE_ID_INTEL_82801CA_12: | ||
531 | case PCI_DEVICE_ID_INTEL_82801DB_0: | ||
532 | case PCI_DEVICE_ID_INTEL_82801E_0: | ||
533 | case PCI_DEVICE_ID_INTEL_82801EB_0: | ||
534 | case PCI_DEVICE_ID_INTEL_ESB_1: | ||
535 | case PCI_DEVICE_ID_INTEL_ICH6_0: | ||
536 | case PCI_DEVICE_ID_INTEL_ICH6_1: | ||
537 | case PCI_DEVICE_ID_INTEL_ICH7_0: | ||
538 | case PCI_DEVICE_ID_INTEL_ICH7_1: | ||
539 | case PCI_DEVICE_ID_INTEL_ICH7_30: | ||
540 | case PCI_DEVICE_ID_INTEL_ICH7_31: | ||
541 | case PCI_DEVICE_ID_INTEL_ESB2_0: | ||
542 | case PCI_DEVICE_ID_INTEL_ICH8_0: | ||
543 | case PCI_DEVICE_ID_INTEL_ICH8_1: | ||
544 | case PCI_DEVICE_ID_INTEL_ICH8_2: | ||
545 | case PCI_DEVICE_ID_INTEL_ICH8_3: | ||
546 | case PCI_DEVICE_ID_INTEL_ICH8_4: | ||
547 | case PCI_DEVICE_ID_INTEL_ICH9_0: | ||
548 | case PCI_DEVICE_ID_INTEL_ICH9_1: | ||
549 | case PCI_DEVICE_ID_INTEL_ICH9_2: | ||
550 | case PCI_DEVICE_ID_INTEL_ICH9_3: | ||
551 | case PCI_DEVICE_ID_INTEL_ICH9_4: | ||
552 | case PCI_DEVICE_ID_INTEL_ICH9_5: | ||
553 | case PCI_DEVICE_ID_INTEL_TOLAPAI_0: | ||
554 | r->name = "PIIX/ICH"; | ||
555 | r->get = pirq_piix_get; | ||
556 | r->set = pirq_piix_set; | ||
557 | return 1; | ||
558 | } | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static __init int via_router_probe(struct irq_router *r, | ||
563 | struct pci_dev *router, u16 device) | ||
564 | { | ||
565 | /* FIXME: We should move some of the quirk fixup stuff here */ | ||
566 | |||
567 | /* | ||
568 | * work arounds for some buggy BIOSes | ||
569 | */ | ||
570 | if (device == PCI_DEVICE_ID_VIA_82C586_0) { | ||
571 | switch(router->device) { | ||
572 | case PCI_DEVICE_ID_VIA_82C686: | ||
573 | /* | ||
574 | * Asus k7m bios wrongly reports 82C686A | ||
575 | * as 586-compatible | ||
576 | */ | ||
577 | device = PCI_DEVICE_ID_VIA_82C686; | ||
578 | break; | ||
579 | case PCI_DEVICE_ID_VIA_8235: | ||
580 | /** | ||
581 | * Asus a7v-x bios wrongly reports 8235 | ||
582 | * as 586-compatible | ||
583 | */ | ||
584 | device = PCI_DEVICE_ID_VIA_8235; | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | switch(device) { | ||
590 | case PCI_DEVICE_ID_VIA_82C586_0: | ||
591 | r->name = "VIA"; | ||
592 | r->get = pirq_via586_get; | ||
593 | r->set = pirq_via586_set; | ||
594 | return 1; | ||
595 | case PCI_DEVICE_ID_VIA_82C596: | ||
596 | case PCI_DEVICE_ID_VIA_82C686: | ||
597 | case PCI_DEVICE_ID_VIA_8231: | ||
598 | case PCI_DEVICE_ID_VIA_8233A: | ||
599 | case PCI_DEVICE_ID_VIA_8235: | ||
600 | case PCI_DEVICE_ID_VIA_8237: | ||
601 | /* FIXME: add new ones for 8233/5 */ | ||
602 | r->name = "VIA"; | ||
603 | r->get = pirq_via_get; | ||
604 | r->set = pirq_via_set; | ||
605 | return 1; | ||
606 | } | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static __init int vlsi_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
611 | { | ||
612 | switch(device) | ||
613 | { | ||
614 | case PCI_DEVICE_ID_VLSI_82C534: | ||
615 | r->name = "VLSI 82C534"; | ||
616 | r->get = pirq_vlsi_get; | ||
617 | r->set = pirq_vlsi_set; | ||
618 | return 1; | ||
619 | } | ||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | |||
624 | static __init int serverworks_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
625 | { | ||
626 | switch(device) | ||
627 | { | ||
628 | case PCI_DEVICE_ID_SERVERWORKS_OSB4: | ||
629 | case PCI_DEVICE_ID_SERVERWORKS_CSB5: | ||
630 | r->name = "ServerWorks"; | ||
631 | r->get = pirq_serverworks_get; | ||
632 | r->set = pirq_serverworks_set; | ||
633 | return 1; | ||
634 | } | ||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static __init int sis_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
639 | { | ||
640 | if (device != PCI_DEVICE_ID_SI_503) | ||
641 | return 0; | ||
642 | |||
643 | r->name = "SIS"; | ||
644 | r->get = pirq_sis_get; | ||
645 | r->set = pirq_sis_set; | ||
646 | return 1; | ||
647 | } | ||
648 | |||
649 | static __init int cyrix_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
650 | { | ||
651 | switch(device) | ||
652 | { | ||
653 | case PCI_DEVICE_ID_CYRIX_5520: | ||
654 | r->name = "NatSemi"; | ||
655 | r->get = pirq_cyrix_get; | ||
656 | r->set = pirq_cyrix_set; | ||
657 | return 1; | ||
658 | } | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static __init int opti_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
663 | { | ||
664 | switch(device) | ||
665 | { | ||
666 | case PCI_DEVICE_ID_OPTI_82C700: | ||
667 | r->name = "OPTI"; | ||
668 | r->get = pirq_opti_get; | ||
669 | r->set = pirq_opti_set; | ||
670 | return 1; | ||
671 | } | ||
672 | return 0; | ||
673 | } | ||
674 | |||
675 | static __init int ite_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
676 | { | ||
677 | switch(device) | ||
678 | { | ||
679 | case PCI_DEVICE_ID_ITE_IT8330G_0: | ||
680 | r->name = "ITE"; | ||
681 | r->get = pirq_ite_get; | ||
682 | r->set = pirq_ite_set; | ||
683 | return 1; | ||
684 | } | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
689 | { | ||
690 | switch(device) | ||
691 | { | ||
692 | case PCI_DEVICE_ID_AL_M1533: | ||
693 | case PCI_DEVICE_ID_AL_M1563: | ||
694 | printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n"); | ||
695 | r->name = "ALI"; | ||
696 | r->get = pirq_ali_get; | ||
697 | r->set = pirq_ali_set; | ||
698 | return 1; | ||
699 | } | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
704 | { | ||
705 | switch(device) | ||
706 | { | ||
707 | case PCI_DEVICE_ID_AMD_VIPER_740B: | ||
708 | r->name = "AMD756"; | ||
709 | break; | ||
710 | case PCI_DEVICE_ID_AMD_VIPER_7413: | ||
711 | r->name = "AMD766"; | ||
712 | break; | ||
713 | case PCI_DEVICE_ID_AMD_VIPER_7443: | ||
714 | r->name = "AMD768"; | ||
715 | break; | ||
716 | default: | ||
717 | return 0; | ||
718 | } | ||
719 | r->get = pirq_amd756_get; | ||
720 | r->set = pirq_amd756_set; | ||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | static __initdata struct irq_router_handler pirq_routers[] = { | ||
725 | { PCI_VENDOR_ID_INTEL, intel_router_probe }, | ||
726 | { PCI_VENDOR_ID_AL, ali_router_probe }, | ||
727 | { PCI_VENDOR_ID_ITE, ite_router_probe }, | ||
728 | { PCI_VENDOR_ID_VIA, via_router_probe }, | ||
729 | { PCI_VENDOR_ID_OPTI, opti_router_probe }, | ||
730 | { PCI_VENDOR_ID_SI, sis_router_probe }, | ||
731 | { PCI_VENDOR_ID_CYRIX, cyrix_router_probe }, | ||
732 | { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, | ||
733 | { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, | ||
734 | { PCI_VENDOR_ID_AMD, amd_router_probe }, | ||
735 | /* Someone with docs needs to add the ATI Radeon IGP */ | ||
736 | { 0, NULL } | ||
737 | }; | ||
738 | static struct irq_router pirq_router; | ||
739 | static struct pci_dev *pirq_router_dev; | ||
740 | |||
741 | |||
742 | /* | ||
743 | * FIXME: should we have an option to say "generic for | ||
744 | * chipset" ? | ||
745 | */ | ||
746 | |||
747 | static void __init pirq_find_router(struct irq_router *r) | ||
748 | { | ||
749 | struct irq_routing_table *rt = pirq_table; | ||
750 | struct irq_router_handler *h; | ||
751 | |||
752 | #ifdef CONFIG_PCI_BIOS | ||
753 | if (!rt->signature) { | ||
754 | printk(KERN_INFO "PCI: Using BIOS for IRQ routing\n"); | ||
755 | r->set = pirq_bios_set; | ||
756 | r->name = "BIOS"; | ||
757 | return; | ||
758 | } | ||
759 | #endif | ||
760 | |||
761 | /* Default unless a driver reloads it */ | ||
762 | r->name = "default"; | ||
763 | r->get = NULL; | ||
764 | r->set = NULL; | ||
765 | |||
766 | DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n", | ||
767 | rt->rtr_vendor, rt->rtr_device); | ||
768 | |||
769 | pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn); | ||
770 | if (!pirq_router_dev) { | ||
771 | DBG(KERN_DEBUG "PCI: Interrupt router not found at " | ||
772 | "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); | ||
773 | return; | ||
774 | } | ||
775 | |||
776 | for( h = pirq_routers; h->vendor; h++) { | ||
777 | /* First look for a router match */ | ||
778 | if (rt->rtr_vendor == h->vendor && h->probe(r, pirq_router_dev, rt->rtr_device)) | ||
779 | break; | ||
780 | /* Fall back to a device match */ | ||
781 | if (pirq_router_dev->vendor == h->vendor && h->probe(r, pirq_router_dev, pirq_router_dev->device)) | ||
782 | break; | ||
783 | } | ||
784 | printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n", | ||
785 | pirq_router.name, | ||
786 | pirq_router_dev->vendor, | ||
787 | pirq_router_dev->device, | ||
788 | pci_name(pirq_router_dev)); | ||
789 | |||
790 | /* The device remains referenced for the kernel lifetime */ | ||
791 | } | ||
792 | |||
793 | static struct irq_info *pirq_get_info(struct pci_dev *dev) | ||
794 | { | ||
795 | struct irq_routing_table *rt = pirq_table; | ||
796 | int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); | ||
797 | struct irq_info *info; | ||
798 | |||
799 | for (info = rt->slots; entries--; info++) | ||
800 | if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) | ||
801 | return info; | ||
802 | return NULL; | ||
803 | } | ||
804 | |||
805 | static int pcibios_lookup_irq(struct pci_dev *dev, int assign) | ||
806 | { | ||
807 | u8 pin; | ||
808 | struct irq_info *info; | ||
809 | int i, pirq, newirq; | ||
810 | int irq = 0; | ||
811 | u32 mask; | ||
812 | struct irq_router *r = &pirq_router; | ||
813 | struct pci_dev *dev2 = NULL; | ||
814 | char *msg = NULL; | ||
815 | |||
816 | /* Find IRQ pin */ | ||
817 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
818 | if (!pin) { | ||
819 | DBG(KERN_DEBUG " -> no interrupt pin\n"); | ||
820 | return 0; | ||
821 | } | ||
822 | pin = pin - 1; | ||
823 | |||
824 | /* Find IRQ routing entry */ | ||
825 | |||
826 | if (!pirq_table) | ||
827 | return 0; | ||
828 | |||
829 | DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin); | ||
830 | info = pirq_get_info(dev); | ||
831 | if (!info) { | ||
832 | DBG(" -> not found in routing table\n" KERN_DEBUG); | ||
833 | return 0; | ||
834 | } | ||
835 | pirq = info->irq[pin].link; | ||
836 | mask = info->irq[pin].bitmap; | ||
837 | if (!pirq) { | ||
838 | DBG(" -> not routed\n" KERN_DEBUG); | ||
839 | return 0; | ||
840 | } | ||
841 | DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); | ||
842 | mask &= pcibios_irq_mask; | ||
843 | |||
844 | /* Work around broken HP Pavilion Notebooks which assign USB to | ||
845 | IRQ 9 even though it is actually wired to IRQ 11 */ | ||
846 | |||
847 | if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) { | ||
848 | dev->irq = 11; | ||
849 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); | ||
850 | r->set(pirq_router_dev, dev, pirq, 11); | ||
851 | } | ||
852 | |||
853 | /* same for Acer Travelmate 360, but with CB and irq 11 -> 10 */ | ||
854 | if (acer_tm360_irqrouting && dev->irq == 11 && dev->vendor == PCI_VENDOR_ID_O2) { | ||
855 | pirq = 0x68; | ||
856 | mask = 0x400; | ||
857 | dev->irq = r->get(pirq_router_dev, dev, pirq); | ||
858 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * Find the best IRQ to assign: use the one | ||
863 | * reported by the device if possible. | ||
864 | */ | ||
865 | newirq = dev->irq; | ||
866 | if (newirq && !((1 << newirq) & mask)) { | ||
867 | if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0; | ||
868 | else printk("\n" KERN_WARNING | ||
869 | "PCI: IRQ %i for device %s doesn't match PIRQ mask " | ||
870 | "- try pci=usepirqmask\n" KERN_DEBUG, newirq, | ||
871 | pci_name(dev)); | ||
872 | } | ||
873 | if (!newirq && assign) { | ||
874 | for (i = 0; i < 16; i++) { | ||
875 | if (!(mask & (1 << i))) | ||
876 | continue; | ||
877 | if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED)) | ||
878 | newirq = i; | ||
879 | } | ||
880 | } | ||
881 | DBG(" -> newirq=%d", newirq); | ||
882 | |||
883 | /* Check if it is hardcoded */ | ||
884 | if ((pirq & 0xf0) == 0xf0) { | ||
885 | irq = pirq & 0xf; | ||
886 | DBG(" -> hardcoded IRQ %d\n", irq); | ||
887 | msg = "Hardcoded"; | ||
888 | } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \ | ||
889 | ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) { | ||
890 | DBG(" -> got IRQ %d\n", irq); | ||
891 | msg = "Found"; | ||
892 | eisa_set_level_irq(irq); | ||
893 | } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { | ||
894 | DBG(" -> assigning IRQ %d", newirq); | ||
895 | if (r->set(pirq_router_dev, dev, pirq, newirq)) { | ||
896 | eisa_set_level_irq(newirq); | ||
897 | DBG(" ... OK\n"); | ||
898 | msg = "Assigned"; | ||
899 | irq = newirq; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | if (!irq) { | ||
904 | DBG(" ... failed\n"); | ||
905 | if (newirq && mask == (1 << newirq)) { | ||
906 | msg = "Guessed"; | ||
907 | irq = newirq; | ||
908 | } else | ||
909 | return 0; | ||
910 | } | ||
911 | printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, pci_name(dev)); | ||
912 | |||
913 | /* Update IRQ for all devices with the same pirq value */ | ||
914 | while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) { | ||
915 | pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); | ||
916 | if (!pin) | ||
917 | continue; | ||
918 | pin--; | ||
919 | info = pirq_get_info(dev2); | ||
920 | if (!info) | ||
921 | continue; | ||
922 | if (info->irq[pin].link == pirq) { | ||
923 | /* We refuse to override the dev->irq information. Give a warning! */ | ||
924 | if ( dev2->irq && dev2->irq != irq && \ | ||
925 | (!(pci_probe & PCI_USE_PIRQ_MASK) || \ | ||
926 | ((1 << dev2->irq) & mask)) ) { | ||
927 | #ifndef CONFIG_PCI_MSI | ||
928 | printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n", | ||
929 | pci_name(dev2), dev2->irq, irq); | ||
930 | #endif | ||
931 | continue; | ||
932 | } | ||
933 | dev2->irq = irq; | ||
934 | pirq_penalty[irq]++; | ||
935 | if (dev != dev2) | ||
936 | printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, pci_name(dev2)); | ||
937 | } | ||
938 | } | ||
939 | return 1; | ||
940 | } | ||
941 | |||
942 | static void __init pcibios_fixup_irqs(void) | ||
943 | { | ||
944 | struct pci_dev *dev = NULL; | ||
945 | u8 pin; | ||
946 | |||
947 | DBG(KERN_DEBUG "PCI: IRQ fixup\n"); | ||
948 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
949 | /* | ||
950 | * If the BIOS has set an out of range IRQ number, just ignore it. | ||
951 | * Also keep track of which IRQ's are already in use. | ||
952 | */ | ||
953 | if (dev->irq >= 16) { | ||
954 | DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq); | ||
955 | dev->irq = 0; | ||
956 | } | ||
957 | /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */ | ||
958 | if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000) | ||
959 | pirq_penalty[dev->irq] = 0; | ||
960 | pirq_penalty[dev->irq]++; | ||
961 | } | ||
962 | |||
963 | dev = NULL; | ||
964 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
965 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
966 | #ifdef CONFIG_X86_IO_APIC | ||
967 | /* | ||
968 | * Recalculate IRQ numbers if we use the I/O APIC. | ||
969 | */ | ||
970 | if (io_apic_assign_pci_irqs) | ||
971 | { | ||
972 | int irq; | ||
973 | |||
974 | if (pin) { | ||
975 | pin--; /* interrupt pins are numbered starting from 1 */ | ||
976 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); | ||
977 | /* | ||
978 | * Busses behind bridges are typically not listed in the MP-table. | ||
979 | * In this case we have to look up the IRQ based on the parent bus, | ||
980 | * parent slot, and pin number. The SMP code detects such bridged | ||
981 | * busses itself so we should get into this branch reliably. | ||
982 | */ | ||
983 | if (irq < 0 && dev->bus->parent) { /* go back to the bridge */ | ||
984 | struct pci_dev * bridge = dev->bus->self; | ||
985 | |||
986 | pin = (pin + PCI_SLOT(dev->devfn)) % 4; | ||
987 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, | ||
988 | PCI_SLOT(bridge->devfn), pin); | ||
989 | if (irq >= 0) | ||
990 | printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n", | ||
991 | pci_name(bridge), 'A' + pin, irq); | ||
992 | } | ||
993 | if (irq >= 0) { | ||
994 | printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", | ||
995 | pci_name(dev), 'A' + pin, irq); | ||
996 | dev->irq = irq; | ||
997 | } | ||
998 | } | ||
999 | } | ||
1000 | #endif | ||
1001 | /* | ||
1002 | * Still no IRQ? Try to lookup one... | ||
1003 | */ | ||
1004 | if (pin && !dev->irq) | ||
1005 | pcibios_lookup_irq(dev, 0); | ||
1006 | } | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
1010 | * Work around broken HP Pavilion Notebooks which assign USB to | ||
1011 | * IRQ 9 even though it is actually wired to IRQ 11 | ||
1012 | */ | ||
1013 | static int __init fix_broken_hp_bios_irq9(struct dmi_system_id *d) | ||
1014 | { | ||
1015 | if (!broken_hp_bios_irq9) { | ||
1016 | broken_hp_bios_irq9 = 1; | ||
1017 | printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); | ||
1018 | } | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | /* | ||
1023 | * Work around broken Acer TravelMate 360 Notebooks which assign | ||
1024 | * Cardbus to IRQ 11 even though it is actually wired to IRQ 10 | ||
1025 | */ | ||
1026 | static int __init fix_acer_tm360_irqrouting(struct dmi_system_id *d) | ||
1027 | { | ||
1028 | if (!acer_tm360_irqrouting) { | ||
1029 | acer_tm360_irqrouting = 1; | ||
1030 | printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident); | ||
1031 | } | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static struct dmi_system_id __initdata pciirq_dmi_table[] = { | ||
1036 | { | ||
1037 | .callback = fix_broken_hp_bios_irq9, | ||
1038 | .ident = "HP Pavilion N5400 Series Laptop", | ||
1039 | .matches = { | ||
1040 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1041 | DMI_MATCH(DMI_BIOS_VERSION, "GE.M1.03"), | ||
1042 | DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), | ||
1043 | DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"), | ||
1044 | }, | ||
1045 | }, | ||
1046 | { | ||
1047 | .callback = fix_acer_tm360_irqrouting, | ||
1048 | .ident = "Acer TravelMate 36x Laptop", | ||
1049 | .matches = { | ||
1050 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
1051 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), | ||
1052 | }, | ||
1053 | }, | ||
1054 | { } | ||
1055 | }; | ||
1056 | |||
1057 | static int __init pcibios_irq_init(void) | ||
1058 | { | ||
1059 | DBG(KERN_DEBUG "PCI: IRQ init\n"); | ||
1060 | |||
1061 | if (pcibios_enable_irq || raw_pci_ops == NULL) | ||
1062 | return 0; | ||
1063 | |||
1064 | dmi_check_system(pciirq_dmi_table); | ||
1065 | |||
1066 | pirq_table = pirq_find_routing_table(); | ||
1067 | |||
1068 | #ifdef CONFIG_PCI_BIOS | ||
1069 | if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) | ||
1070 | pirq_table = pcibios_get_irq_routing_table(); | ||
1071 | #endif | ||
1072 | if (pirq_table) { | ||
1073 | pirq_peer_trick(); | ||
1074 | pirq_find_router(&pirq_router); | ||
1075 | if (pirq_table->exclusive_irqs) { | ||
1076 | int i; | ||
1077 | for (i=0; i<16; i++) | ||
1078 | if (!(pirq_table->exclusive_irqs & (1 << i))) | ||
1079 | pirq_penalty[i] += 100; | ||
1080 | } | ||
1081 | /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */ | ||
1082 | if (io_apic_assign_pci_irqs) | ||
1083 | pirq_table = NULL; | ||
1084 | } | ||
1085 | |||
1086 | pcibios_enable_irq = pirq_enable_irq; | ||
1087 | |||
1088 | pcibios_fixup_irqs(); | ||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | subsys_initcall(pcibios_irq_init); | ||
1093 | |||
1094 | |||
1095 | static void pirq_penalize_isa_irq(int irq, int active) | ||
1096 | { | ||
1097 | /* | ||
1098 | * If any ISAPnP device reports an IRQ in its list of possible | ||
1099 | * IRQ's, we try to avoid assigning it to PCI devices. | ||
1100 | */ | ||
1101 | if (irq < 16) { | ||
1102 | if (active) | ||
1103 | pirq_penalty[irq] += 1000; | ||
1104 | else | ||
1105 | pirq_penalty[irq] += 100; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | void pcibios_penalize_isa_irq(int irq, int active) | ||
1110 | { | ||
1111 | #ifdef CONFIG_ACPI | ||
1112 | if (!acpi_noirq) | ||
1113 | acpi_penalize_isa_irq(irq, active); | ||
1114 | else | ||
1115 | #endif | ||
1116 | pirq_penalize_isa_irq(irq, active); | ||
1117 | } | ||
1118 | |||
1119 | static int pirq_enable_irq(struct pci_dev *dev) | ||
1120 | { | ||
1121 | u8 pin; | ||
1122 | struct pci_dev *temp_dev; | ||
1123 | |||
1124 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
1125 | if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { | ||
1126 | char *msg = ""; | ||
1127 | |||
1128 | pin--; /* interrupt pins are numbered starting from 1 */ | ||
1129 | |||
1130 | if (io_apic_assign_pci_irqs) { | ||
1131 | int irq; | ||
1132 | |||
1133 | irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin); | ||
1134 | /* | ||
1135 | * Busses behind bridges are typically not listed in the MP-table. | ||
1136 | * In this case we have to look up the IRQ based on the parent bus, | ||
1137 | * parent slot, and pin number. The SMP code detects such bridged | ||
1138 | * busses itself so we should get into this branch reliably. | ||
1139 | */ | ||
1140 | temp_dev = dev; | ||
1141 | while (irq < 0 && dev->bus->parent) { /* go back to the bridge */ | ||
1142 | struct pci_dev * bridge = dev->bus->self; | ||
1143 | |||
1144 | pin = (pin + PCI_SLOT(dev->devfn)) % 4; | ||
1145 | irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, | ||
1146 | PCI_SLOT(bridge->devfn), pin); | ||
1147 | if (irq >= 0) | ||
1148 | printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n", | ||
1149 | pci_name(bridge), 'A' + pin, irq); | ||
1150 | dev = bridge; | ||
1151 | } | ||
1152 | dev = temp_dev; | ||
1153 | if (irq >= 0) { | ||
1154 | printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n", | ||
1155 | pci_name(dev), 'A' + pin, irq); | ||
1156 | dev->irq = irq; | ||
1157 | return 0; | ||
1158 | } else | ||
1159 | msg = " Probably buggy MP table."; | ||
1160 | } else if (pci_probe & PCI_BIOS_IRQ_SCAN) | ||
1161 | msg = ""; | ||
1162 | else | ||
1163 | msg = " Please try using pci=biosirq."; | ||
1164 | |||
1165 | /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ | ||
1166 | if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) | ||
1167 | return 0; | ||
1168 | |||
1169 | printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", | ||
1170 | 'A' + pin, pci_name(dev), msg); | ||
1171 | } | ||
1172 | return 0; | ||
1173 | } | ||
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c new file mode 100644 index 000000000000..5565d7016b75 --- /dev/null +++ b/arch/x86/pci/legacy.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * legacy.c - traditional, old school PCI bus probing | ||
3 | */ | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/pci.h> | ||
6 | #include "pci.h" | ||
7 | |||
8 | /* | ||
9 | * Discover remaining PCI buses in case there are peer host bridges. | ||
10 | * We use the number of last PCI bus provided by the PCI BIOS. | ||
11 | */ | ||
12 | static void __devinit pcibios_fixup_peer_bridges(void) | ||
13 | { | ||
14 | int n, devfn; | ||
15 | |||
16 | if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) | ||
17 | return; | ||
18 | DBG("PCI: Peer bridge fixup\n"); | ||
19 | |||
20 | for (n=0; n <= pcibios_last_bus; n++) { | ||
21 | u32 l; | ||
22 | if (pci_find_bus(0, n)) | ||
23 | continue; | ||
24 | for (devfn = 0; devfn < 256; devfn += 8) { | ||
25 | if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) && | ||
26 | l != 0x0000 && l != 0xffff) { | ||
27 | DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l); | ||
28 | printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); | ||
29 | pci_scan_bus_with_sysdata(n); | ||
30 | break; | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static int __init pci_legacy_init(void) | ||
37 | { | ||
38 | if (!raw_pci_ops) { | ||
39 | printk("PCI: System does not support PCI\n"); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | if (pcibios_scanned++) | ||
44 | return 0; | ||
45 | |||
46 | printk("PCI: Probing PCI hardware\n"); | ||
47 | pci_root_bus = pcibios_scan_root(0); | ||
48 | if (pci_root_bus) | ||
49 | pci_bus_add_devices(pci_root_bus); | ||
50 | |||
51 | pcibios_fixup_peer_bridges(); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | subsys_initcall(pci_legacy_init); | ||
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c new file mode 100644 index 000000000000..4df637e34f81 --- /dev/null +++ b/arch/x86/pci/mmconfig-shared.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * mmconfig-shared.c - Low-level direct PCI config space access via | ||
3 | * MMCONFIG - common code between i386 and x86-64. | ||
4 | * | ||
5 | * This code does: | ||
6 | * - known chipset handling | ||
7 | * - ACPI decoding and validation | ||
8 | * | ||
9 | * Per-architecture code takes care of the mappings and accesses | ||
10 | * themselves. | ||
11 | */ | ||
12 | |||
13 | #include <linux/pci.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/acpi.h> | ||
16 | #include <linux/bitmap.h> | ||
17 | #include <asm/e820.h> | ||
18 | |||
19 | #include "pci.h" | ||
20 | |||
21 | /* aperture is up to 256MB but BIOS may reserve less */ | ||
22 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
23 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
24 | |||
25 | DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS); | ||
26 | |||
27 | /* Indicate if the mmcfg resources have been placed into the resource table. */ | ||
28 | static int __initdata pci_mmcfg_resources_inserted; | ||
29 | |||
30 | /* K8 systems have some devices (typically in the builtin northbridge) | ||
31 | that are only accessible using type1 | ||
32 | Normally this can be expressed in the MCFG by not listing them | ||
33 | and assigning suitable _SEGs, but this isn't implemented in some BIOS. | ||
34 | Instead try to discover all devices on bus 0 that are unreachable using MM | ||
35 | and fallback for them. */ | ||
36 | static void __init unreachable_devices(void) | ||
37 | { | ||
38 | int i, bus; | ||
39 | /* Use the max bus number from ACPI here? */ | ||
40 | for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) { | ||
41 | for (i = 0; i < 32; i++) { | ||
42 | unsigned int devfn = PCI_DEVFN(i, 0); | ||
43 | u32 val1, val2; | ||
44 | |||
45 | pci_conf1_read(0, bus, devfn, 0, 4, &val1); | ||
46 | if (val1 == 0xffffffff) | ||
47 | continue; | ||
48 | |||
49 | if (pci_mmcfg_arch_reachable(0, bus, devfn)) { | ||
50 | raw_pci_ops->read(0, bus, devfn, 0, 4, &val2); | ||
51 | if (val1 == val2) | ||
52 | continue; | ||
53 | } | ||
54 | set_bit(i + 32 * bus, pci_mmcfg_fallback_slots); | ||
55 | printk(KERN_NOTICE "PCI: No mmconfig possible on device" | ||
56 | " %02x:%02x\n", bus, i); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static const char __init *pci_mmcfg_e7520(void) | ||
62 | { | ||
63 | u32 win; | ||
64 | pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win); | ||
65 | |||
66 | win = win & 0xf000; | ||
67 | if(win == 0x0000 || win == 0xf000) | ||
68 | pci_mmcfg_config_num = 0; | ||
69 | else { | ||
70 | pci_mmcfg_config_num = 1; | ||
71 | pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); | ||
72 | if (!pci_mmcfg_config) | ||
73 | return NULL; | ||
74 | pci_mmcfg_config[0].address = win << 16; | ||
75 | pci_mmcfg_config[0].pci_segment = 0; | ||
76 | pci_mmcfg_config[0].start_bus_number = 0; | ||
77 | pci_mmcfg_config[0].end_bus_number = 255; | ||
78 | } | ||
79 | |||
80 | return "Intel Corporation E7520 Memory Controller Hub"; | ||
81 | } | ||
82 | |||
83 | static const char __init *pci_mmcfg_intel_945(void) | ||
84 | { | ||
85 | u32 pciexbar, mask = 0, len = 0; | ||
86 | |||
87 | pci_mmcfg_config_num = 1; | ||
88 | |||
89 | pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar); | ||
90 | |||
91 | /* Enable bit */ | ||
92 | if (!(pciexbar & 1)) | ||
93 | pci_mmcfg_config_num = 0; | ||
94 | |||
95 | /* Size bits */ | ||
96 | switch ((pciexbar >> 1) & 3) { | ||
97 | case 0: | ||
98 | mask = 0xf0000000U; | ||
99 | len = 0x10000000U; | ||
100 | break; | ||
101 | case 1: | ||
102 | mask = 0xf8000000U; | ||
103 | len = 0x08000000U; | ||
104 | break; | ||
105 | case 2: | ||
106 | mask = 0xfc000000U; | ||
107 | len = 0x04000000U; | ||
108 | break; | ||
109 | default: | ||
110 | pci_mmcfg_config_num = 0; | ||
111 | } | ||
112 | |||
113 | /* Errata #2, things break when not aligned on a 256Mb boundary */ | ||
114 | /* Can only happen in 64M/128M mode */ | ||
115 | |||
116 | if ((pciexbar & mask) & 0x0fffffffU) | ||
117 | pci_mmcfg_config_num = 0; | ||
118 | |||
119 | /* Don't hit the APIC registers and their friends */ | ||
120 | if ((pciexbar & mask) >= 0xf0000000U) | ||
121 | pci_mmcfg_config_num = 0; | ||
122 | |||
123 | if (pci_mmcfg_config_num) { | ||
124 | pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); | ||
125 | if (!pci_mmcfg_config) | ||
126 | return NULL; | ||
127 | pci_mmcfg_config[0].address = pciexbar & mask; | ||
128 | pci_mmcfg_config[0].pci_segment = 0; | ||
129 | pci_mmcfg_config[0].start_bus_number = 0; | ||
130 | pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1; | ||
131 | } | ||
132 | |||
133 | return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; | ||
134 | } | ||
135 | |||
136 | struct pci_mmcfg_hostbridge_probe { | ||
137 | u32 vendor; | ||
138 | u32 device; | ||
139 | const char *(*probe)(void); | ||
140 | }; | ||
141 | |||
142 | static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { | ||
143 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, | ||
144 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, | ||
145 | }; | ||
146 | |||
147 | static int __init pci_mmcfg_check_hostbridge(void) | ||
148 | { | ||
149 | u32 l; | ||
150 | u16 vendor, device; | ||
151 | int i; | ||
152 | const char *name; | ||
153 | |||
154 | pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l); | ||
155 | vendor = l & 0xffff; | ||
156 | device = (l >> 16) & 0xffff; | ||
157 | |||
158 | pci_mmcfg_config_num = 0; | ||
159 | pci_mmcfg_config = NULL; | ||
160 | name = NULL; | ||
161 | |||
162 | for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { | ||
163 | if (pci_mmcfg_probes[i].vendor == vendor && | ||
164 | pci_mmcfg_probes[i].device == device) | ||
165 | name = pci_mmcfg_probes[i].probe(); | ||
166 | } | ||
167 | |||
168 | if (name) { | ||
169 | printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n", | ||
170 | name, pci_mmcfg_config_num ? "with" : "without"); | ||
171 | } | ||
172 | |||
173 | return name != NULL; | ||
174 | } | ||
175 | |||
176 | static void __init pci_mmcfg_insert_resources(unsigned long resource_flags) | ||
177 | { | ||
178 | #define PCI_MMCFG_RESOURCE_NAME_LEN 19 | ||
179 | int i; | ||
180 | struct resource *res; | ||
181 | char *names; | ||
182 | unsigned num_buses; | ||
183 | |||
184 | res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), | ||
185 | pci_mmcfg_config_num, GFP_KERNEL); | ||
186 | if (!res) { | ||
187 | printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | names = (void *)&res[pci_mmcfg_config_num]; | ||
192 | for (i = 0; i < pci_mmcfg_config_num; i++, res++) { | ||
193 | struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i]; | ||
194 | num_buses = cfg->end_bus_number - cfg->start_bus_number + 1; | ||
195 | res->name = names; | ||
196 | snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", | ||
197 | cfg->pci_segment); | ||
198 | res->start = cfg->address; | ||
199 | res->end = res->start + (num_buses << 20) - 1; | ||
200 | res->flags = IORESOURCE_MEM | resource_flags; | ||
201 | insert_resource(&iomem_resource, res); | ||
202 | names += PCI_MMCFG_RESOURCE_NAME_LEN; | ||
203 | } | ||
204 | |||
205 | /* Mark that the resources have been inserted. */ | ||
206 | pci_mmcfg_resources_inserted = 1; | ||
207 | } | ||
208 | |||
209 | static void __init pci_mmcfg_reject_broken(int type) | ||
210 | { | ||
211 | typeof(pci_mmcfg_config[0]) *cfg; | ||
212 | |||
213 | if ((pci_mmcfg_config_num == 0) || | ||
214 | (pci_mmcfg_config == NULL) || | ||
215 | (pci_mmcfg_config[0].address == 0)) | ||
216 | return; | ||
217 | |||
218 | cfg = &pci_mmcfg_config[0]; | ||
219 | |||
220 | /* | ||
221 | * Handle more broken MCFG tables on Asus etc. | ||
222 | * They only contain a single entry for bus 0-0. | ||
223 | */ | ||
224 | if (pci_mmcfg_config_num == 1 && | ||
225 | cfg->pci_segment == 0 && | ||
226 | (cfg->start_bus_number | cfg->end_bus_number) == 0) { | ||
227 | printk(KERN_ERR "PCI: start and end of bus number is 0. " | ||
228 | "Rejected as broken MCFG.\n"); | ||
229 | goto reject; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Only do this check when type 1 works. If it doesn't work | ||
234 | * assume we run on a Mac and always use MCFG | ||
235 | */ | ||
236 | if (type == 1 && !e820_all_mapped(cfg->address, | ||
237 | cfg->address + MMCONFIG_APER_MIN, | ||
238 | E820_RESERVED)) { | ||
239 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" | ||
240 | " E820-reserved\n", cfg->address); | ||
241 | goto reject; | ||
242 | } | ||
243 | return; | ||
244 | |||
245 | reject: | ||
246 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | ||
247 | kfree(pci_mmcfg_config); | ||
248 | pci_mmcfg_config = NULL; | ||
249 | pci_mmcfg_config_num = 0; | ||
250 | } | ||
251 | |||
252 | void __init pci_mmcfg_init(int type) | ||
253 | { | ||
254 | int known_bridge = 0; | ||
255 | |||
256 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | ||
257 | return; | ||
258 | |||
259 | if (type == 1 && pci_mmcfg_check_hostbridge()) | ||
260 | known_bridge = 1; | ||
261 | |||
262 | if (!known_bridge) { | ||
263 | acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); | ||
264 | pci_mmcfg_reject_broken(type); | ||
265 | } | ||
266 | |||
267 | if ((pci_mmcfg_config_num == 0) || | ||
268 | (pci_mmcfg_config == NULL) || | ||
269 | (pci_mmcfg_config[0].address == 0)) | ||
270 | return; | ||
271 | |||
272 | if (pci_mmcfg_arch_init()) { | ||
273 | if (type == 1) | ||
274 | unreachable_devices(); | ||
275 | if (known_bridge) | ||
276 | pci_mmcfg_insert_resources(IORESOURCE_BUSY); | ||
277 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | ||
278 | } else { | ||
279 | /* | ||
280 | * Signal not to attempt to insert mmcfg resources because | ||
281 | * the architecture mmcfg setup could not initialize. | ||
282 | */ | ||
283 | pci_mmcfg_resources_inserted = 1; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | static int __init pci_mmcfg_late_insert_resources(void) | ||
288 | { | ||
289 | /* | ||
290 | * If resources are already inserted or we are not using MMCONFIG, | ||
291 | * don't insert the resources. | ||
292 | */ | ||
293 | if ((pci_mmcfg_resources_inserted == 1) || | ||
294 | (pci_probe & PCI_PROBE_MMCONF) == 0 || | ||
295 | (pci_mmcfg_config_num == 0) || | ||
296 | (pci_mmcfg_config == NULL) || | ||
297 | (pci_mmcfg_config[0].address == 0)) | ||
298 | return 1; | ||
299 | |||
300 | /* | ||
301 | * Attempt to insert the mmcfg resources but not with the busy flag | ||
302 | * marked so it won't cause request errors when __request_region is | ||
303 | * called. | ||
304 | */ | ||
305 | pci_mmcfg_insert_resources(0); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Perform MMCONFIG resource insertion after PCI initialization to allow for | ||
312 | * misprogrammed MCFG tables that state larger sizes but actually conflict | ||
313 | * with other system resources. | ||
314 | */ | ||
315 | late_initcall(pci_mmcfg_late_insert_resources); | ||
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c new file mode 100644 index 000000000000..1bf5816d34c8 --- /dev/null +++ b/arch/x86/pci/mmconfig_32.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx> | ||
3 | * Copyright (C) 2004 Intel Corp. | ||
4 | * | ||
5 | * This code is released under the GNU General Public License version 2. | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * mmconfig.c - Low-level direct PCI config space access via MMCONFIG | ||
10 | */ | ||
11 | |||
12 | #include <linux/pci.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/acpi.h> | ||
15 | #include <asm/e820.h> | ||
16 | #include "pci.h" | ||
17 | |||
18 | /* Assume systems with more busses have correct MCFG */ | ||
19 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | ||
20 | |||
21 | /* The base address of the last MMCONFIG device accessed */ | ||
22 | static u32 mmcfg_last_accessed_device; | ||
23 | static int mmcfg_last_accessed_cpu; | ||
24 | |||
25 | /* | ||
26 | * Functions for accessing PCI configuration space with MMCONFIG accesses | ||
27 | */ | ||
28 | static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) | ||
29 | { | ||
30 | struct acpi_mcfg_allocation *cfg; | ||
31 | int cfg_num; | ||
32 | |||
33 | if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS && | ||
34 | test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots)) | ||
35 | return 0; | ||
36 | |||
37 | for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { | ||
38 | cfg = &pci_mmcfg_config[cfg_num]; | ||
39 | if (cfg->pci_segment == seg && | ||
40 | (cfg->start_bus_number <= bus) && | ||
41 | (cfg->end_bus_number >= bus)) | ||
42 | return cfg->address; | ||
43 | } | ||
44 | |||
45 | /* Fall back to type 0 */ | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * This is always called under pci_config_lock | ||
51 | */ | ||
52 | static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) | ||
53 | { | ||
54 | u32 dev_base = base | (bus << 20) | (devfn << 12); | ||
55 | int cpu = smp_processor_id(); | ||
56 | if (dev_base != mmcfg_last_accessed_device || | ||
57 | cpu != mmcfg_last_accessed_cpu) { | ||
58 | mmcfg_last_accessed_device = dev_base; | ||
59 | mmcfg_last_accessed_cpu = cpu; | ||
60 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | ||
65 | unsigned int devfn, int reg, int len, u32 *value) | ||
66 | { | ||
67 | unsigned long flags; | ||
68 | u32 base; | ||
69 | |||
70 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) { | ||
71 | *value = -1; | ||
72 | return -EINVAL; | ||
73 | } | ||
74 | |||
75 | base = get_base_addr(seg, bus, devfn); | ||
76 | if (!base) | ||
77 | return pci_conf1_read(seg,bus,devfn,reg,len,value); | ||
78 | |||
79 | spin_lock_irqsave(&pci_config_lock, flags); | ||
80 | |||
81 | pci_exp_set_dev_base(base, bus, devfn); | ||
82 | |||
83 | switch (len) { | ||
84 | case 1: | ||
85 | *value = mmio_config_readb(mmcfg_virt_addr + reg); | ||
86 | break; | ||
87 | case 2: | ||
88 | *value = mmio_config_readw(mmcfg_virt_addr + reg); | ||
89 | break; | ||
90 | case 4: | ||
91 | *value = mmio_config_readl(mmcfg_virt_addr + reg); | ||
92 | break; | ||
93 | } | ||
94 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | ||
100 | unsigned int devfn, int reg, int len, u32 value) | ||
101 | { | ||
102 | unsigned long flags; | ||
103 | u32 base; | ||
104 | |||
105 | if ((bus > 255) || (devfn > 255) || (reg > 4095)) | ||
106 | return -EINVAL; | ||
107 | |||
108 | base = get_base_addr(seg, bus, devfn); | ||
109 | if (!base) | ||
110 | return pci_conf1_write(seg,bus,devfn,reg,len,value); | ||
111 | |||
112 | spin_lock_irqsave(&pci_config_lock, flags); | ||
113 | |||
114 | pci_exp_set_dev_base(base, bus, devfn); | ||
115 | |||
116 | switch (len) { | ||
117 | case 1: | ||
118 | mmio_config_writeb(mmcfg_virt_addr + reg, value); | ||
119 | break; | ||
120 | case 2: | ||
121 | mmio_config_writew(mmcfg_virt_addr + reg, value); | ||
122 | break; | ||
123 | case 4: | ||
124 | mmio_config_writel(mmcfg_virt_addr + reg, value); | ||
125 | break; | ||
126 | } | ||
127 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static struct pci_raw_ops pci_mmcfg = { | ||
133 | .read = pci_mmcfg_read, | ||
134 | .write = pci_mmcfg_write, | ||
135 | }; | ||
136 | |||
137 | int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, | ||
138 | unsigned int devfn) | ||
139 | { | ||
140 | return get_base_addr(seg, bus, devfn) != 0; | ||
141 | } | ||
142 | |||
143 | int __init pci_mmcfg_arch_init(void) | ||
144 | { | ||
145 | printk(KERN_INFO "PCI: Using MMCONFIG\n"); | ||
146 | raw_pci_ops = &pci_mmcfg; | ||
147 | return 1; | ||
148 | } | ||
diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c new file mode 100644 index 000000000000..f5f165f69e0c --- /dev/null +++ b/arch/x86/pci/numa.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * numa.c - Low-level PCI access for NUMA-Q machines | ||
3 | */ | ||
4 | |||
5 | #include <linux/pci.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/nodemask.h> | ||
8 | #include "pci.h" | ||
9 | |||
10 | #define BUS2QUAD(global) (mp_bus_id_to_node[global]) | ||
11 | #define BUS2LOCAL(global) (mp_bus_id_to_local[global]) | ||
12 | #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local]) | ||
13 | |||
14 | #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \ | ||
15 | (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3)) | ||
16 | |||
17 | static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, | ||
18 | unsigned int devfn, int reg, int len, u32 *value) | ||
19 | { | ||
20 | unsigned long flags; | ||
21 | |||
22 | if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | ||
23 | return -EINVAL; | ||
24 | |||
25 | spin_lock_irqsave(&pci_config_lock, flags); | ||
26 | |||
27 | outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus)); | ||
28 | |||
29 | switch (len) { | ||
30 | case 1: | ||
31 | *value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus)); | ||
32 | break; | ||
33 | case 2: | ||
34 | *value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus)); | ||
35 | break; | ||
36 | case 4: | ||
37 | *value = inl_quad(0xCFC, BUS2QUAD(bus)); | ||
38 | break; | ||
39 | } | ||
40 | |||
41 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, | ||
47 | unsigned int devfn, int reg, int len, u32 value) | ||
48 | { | ||
49 | unsigned long flags; | ||
50 | |||
51 | if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) | ||
52 | return -EINVAL; | ||
53 | |||
54 | spin_lock_irqsave(&pci_config_lock, flags); | ||
55 | |||
56 | outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus)); | ||
57 | |||
58 | switch (len) { | ||
59 | case 1: | ||
60 | outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus)); | ||
61 | break; | ||
62 | case 2: | ||
63 | outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus)); | ||
64 | break; | ||
65 | case 4: | ||
66 | outl_quad((u32)value, 0xCFC, BUS2QUAD(bus)); | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | #undef PCI_CONF1_MQ_ADDRESS | ||
76 | |||
77 | static struct pci_raw_ops pci_direct_conf1_mq = { | ||
78 | .read = pci_conf1_mq_read, | ||
79 | .write = pci_conf1_mq_write | ||
80 | }; | ||
81 | |||
82 | |||
83 | static void __devinit pci_fixup_i450nx(struct pci_dev *d) | ||
84 | { | ||
85 | /* | ||
86 | * i450NX -- Find and scan all secondary buses on all PXB's. | ||
87 | */ | ||
88 | int pxb, reg; | ||
89 | u8 busno, suba, subb; | ||
90 | int quad = BUS2QUAD(d->bus->number); | ||
91 | |||
92 | printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d)); | ||
93 | reg = 0xd0; | ||
94 | for(pxb=0; pxb<2; pxb++) { | ||
95 | pci_read_config_byte(d, reg++, &busno); | ||
96 | pci_read_config_byte(d, reg++, &suba); | ||
97 | pci_read_config_byte(d, reg++, &subb); | ||
98 | DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); | ||
99 | if (busno) { | ||
100 | /* Bus A */ | ||
101 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno)); | ||
102 | } | ||
103 | if (suba < subb) { | ||
104 | /* Bus B */ | ||
105 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1)); | ||
106 | } | ||
107 | } | ||
108 | pcibios_last_bus = -1; | ||
109 | } | ||
110 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx); | ||
111 | |||
112 | static int __init pci_numa_init(void) | ||
113 | { | ||
114 | int quad; | ||
115 | |||
116 | raw_pci_ops = &pci_direct_conf1_mq; | ||
117 | |||
118 | if (pcibios_scanned++) | ||
119 | return 0; | ||
120 | |||
121 | pci_root_bus = pcibios_scan_root(0); | ||
122 | if (pci_root_bus) | ||
123 | pci_bus_add_devices(pci_root_bus); | ||
124 | if (num_online_nodes() > 1) | ||
125 | for_each_online_node(quad) { | ||
126 | if (quad == 0) | ||
127 | continue; | ||
128 | printk("Scanning PCI bus %d for quad %d\n", | ||
129 | QUADLOCAL2BUS(quad,0), quad); | ||
130 | pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0)); | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | subsys_initcall(pci_numa_init); | ||
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c new file mode 100644 index 000000000000..10ac8c316c46 --- /dev/null +++ b/arch/x86/pci/pcbios.c | |||
@@ -0,0 +1,492 @@ | |||
1 | /* | ||
2 | * BIOS32 and PCI BIOS handling. | ||
3 | */ | ||
4 | |||
5 | #include <linux/pci.h> | ||
6 | #include <linux/init.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/uaccess.h> | ||
9 | #include "pci.h" | ||
10 | #include "pci-functions.h" | ||
11 | |||
12 | |||
13 | /* BIOS32 signature: "_32_" */ | ||
14 | #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) | ||
15 | |||
16 | /* PCI signature: "PCI " */ | ||
17 | #define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) | ||
18 | |||
19 | /* PCI service signature: "$PCI" */ | ||
20 | #define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) | ||
21 | |||
22 | /* PCI BIOS hardware mechanism flags */ | ||
23 | #define PCIBIOS_HW_TYPE1 0x01 | ||
24 | #define PCIBIOS_HW_TYPE2 0x02 | ||
25 | #define PCIBIOS_HW_TYPE1_SPEC 0x10 | ||
26 | #define PCIBIOS_HW_TYPE2_SPEC 0x20 | ||
27 | |||
28 | /* | ||
29 | * This is the standard structure used to identify the entry point | ||
30 | * to the BIOS32 Service Directory, as documented in | ||
31 | * Standard BIOS 32-bit Service Directory Proposal | ||
32 | * Revision 0.4 May 24, 1993 | ||
33 | * Phoenix Technologies Ltd. | ||
34 | * Norwood, MA | ||
35 | * and the PCI BIOS specification. | ||
36 | */ | ||
37 | |||
38 | union bios32 { | ||
39 | struct { | ||
40 | unsigned long signature; /* _32_ */ | ||
41 | unsigned long entry; /* 32 bit physical address */ | ||
42 | unsigned char revision; /* Revision level, 0 */ | ||
43 | unsigned char length; /* Length in paragraphs should be 01 */ | ||
44 | unsigned char checksum; /* All bytes must add up to zero */ | ||
45 | unsigned char reserved[5]; /* Must be zero */ | ||
46 | } fields; | ||
47 | char chars[16]; | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * Physical address of the service directory. I don't know if we're | ||
52 | * allowed to have more than one of these or not, so just in case | ||
53 | * we'll make pcibios_present() take a memory start parameter and store | ||
54 | * the array there. | ||
55 | */ | ||
56 | |||
57 | static struct { | ||
58 | unsigned long address; | ||
59 | unsigned short segment; | ||
60 | } bios32_indirect = { 0, __KERNEL_CS }; | ||
61 | |||
62 | /* | ||
63 | * Returns the entry point for the given service, NULL on error | ||
64 | */ | ||
65 | |||
66 | static unsigned long bios32_service(unsigned long service) | ||
67 | { | ||
68 | unsigned char return_code; /* %al */ | ||
69 | unsigned long address; /* %ebx */ | ||
70 | unsigned long length; /* %ecx */ | ||
71 | unsigned long entry; /* %edx */ | ||
72 | unsigned long flags; | ||
73 | |||
74 | local_irq_save(flags); | ||
75 | __asm__("lcall *(%%edi); cld" | ||
76 | : "=a" (return_code), | ||
77 | "=b" (address), | ||
78 | "=c" (length), | ||
79 | "=d" (entry) | ||
80 | : "0" (service), | ||
81 | "1" (0), | ||
82 | "D" (&bios32_indirect)); | ||
83 | local_irq_restore(flags); | ||
84 | |||
85 | switch (return_code) { | ||
86 | case 0: | ||
87 | return address + entry; | ||
88 | case 0x80: /* Not present */ | ||
89 | printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); | ||
90 | return 0; | ||
91 | default: /* Shouldn't happen */ | ||
92 | printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", | ||
93 | service, return_code); | ||
94 | return 0; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static struct { | ||
99 | unsigned long address; | ||
100 | unsigned short segment; | ||
101 | } pci_indirect = { 0, __KERNEL_CS }; | ||
102 | |||
103 | static int pci_bios_present; | ||
104 | |||
105 | static int __devinit check_pcibios(void) | ||
106 | { | ||
107 | u32 signature, eax, ebx, ecx; | ||
108 | u8 status, major_ver, minor_ver, hw_mech; | ||
109 | unsigned long flags, pcibios_entry; | ||
110 | |||
111 | if ((pcibios_entry = bios32_service(PCI_SERVICE))) { | ||
112 | pci_indirect.address = pcibios_entry + PAGE_OFFSET; | ||
113 | |||
114 | local_irq_save(flags); | ||
115 | __asm__( | ||
116 | "lcall *(%%edi); cld\n\t" | ||
117 | "jc 1f\n\t" | ||
118 | "xor %%ah, %%ah\n" | ||
119 | "1:" | ||
120 | : "=d" (signature), | ||
121 | "=a" (eax), | ||
122 | "=b" (ebx), | ||
123 | "=c" (ecx) | ||
124 | : "1" (PCIBIOS_PCI_BIOS_PRESENT), | ||
125 | "D" (&pci_indirect) | ||
126 | : "memory"); | ||
127 | local_irq_restore(flags); | ||
128 | |||
129 | status = (eax >> 8) & 0xff; | ||
130 | hw_mech = eax & 0xff; | ||
131 | major_ver = (ebx >> 8) & 0xff; | ||
132 | minor_ver = ebx & 0xff; | ||
133 | if (pcibios_last_bus < 0) | ||
134 | pcibios_last_bus = ecx & 0xff; | ||
135 | DBG("PCI: BIOS probe returned s=%02x hw=%02x ver=%02x.%02x l=%02x\n", | ||
136 | status, hw_mech, major_ver, minor_ver, pcibios_last_bus); | ||
137 | if (status || signature != PCI_SIGNATURE) { | ||
138 | printk (KERN_ERR "PCI: BIOS BUG #%x[%08x] found\n", | ||
139 | status, signature); | ||
140 | return 0; | ||
141 | } | ||
142 | printk(KERN_INFO "PCI: PCI BIOS revision %x.%02x entry at 0x%lx, last bus=%d\n", | ||
143 | major_ver, minor_ver, pcibios_entry, pcibios_last_bus); | ||
144 | #ifdef CONFIG_PCI_DIRECT | ||
145 | if (!(hw_mech & PCIBIOS_HW_TYPE1)) | ||
146 | pci_probe &= ~PCI_PROBE_CONF1; | ||
147 | if (!(hw_mech & PCIBIOS_HW_TYPE2)) | ||
148 | pci_probe &= ~PCI_PROBE_CONF2; | ||
149 | #endif | ||
150 | return 1; | ||
151 | } | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id, | ||
156 | unsigned short index, unsigned char *bus, unsigned char *device_fn) | ||
157 | { | ||
158 | unsigned short bx; | ||
159 | unsigned short ret; | ||
160 | |||
161 | __asm__("lcall *(%%edi); cld\n\t" | ||
162 | "jc 1f\n\t" | ||
163 | "xor %%ah, %%ah\n" | ||
164 | "1:" | ||
165 | : "=b" (bx), | ||
166 | "=a" (ret) | ||
167 | : "1" (PCIBIOS_FIND_PCI_DEVICE), | ||
168 | "c" (device_id), | ||
169 | "d" (vendor), | ||
170 | "S" ((int) index), | ||
171 | "D" (&pci_indirect)); | ||
172 | *bus = (bx >> 8) & 0xff; | ||
173 | *device_fn = bx & 0xff; | ||
174 | return (int) (ret & 0xff00) >> 8; | ||
175 | } | ||
176 | |||
177 | static int pci_bios_read(unsigned int seg, unsigned int bus, | ||
178 | unsigned int devfn, int reg, int len, u32 *value) | ||
179 | { | ||
180 | unsigned long result = 0; | ||
181 | unsigned long flags; | ||
182 | unsigned long bx = (bus << 8) | devfn; | ||
183 | |||
184 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) | ||
185 | return -EINVAL; | ||
186 | |||
187 | spin_lock_irqsave(&pci_config_lock, flags); | ||
188 | |||
189 | switch (len) { | ||
190 | case 1: | ||
191 | __asm__("lcall *(%%esi); cld\n\t" | ||
192 | "jc 1f\n\t" | ||
193 | "xor %%ah, %%ah\n" | ||
194 | "1:" | ||
195 | : "=c" (*value), | ||
196 | "=a" (result) | ||
197 | : "1" (PCIBIOS_READ_CONFIG_BYTE), | ||
198 | "b" (bx), | ||
199 | "D" ((long)reg), | ||
200 | "S" (&pci_indirect)); | ||
201 | break; | ||
202 | case 2: | ||
203 | __asm__("lcall *(%%esi); cld\n\t" | ||
204 | "jc 1f\n\t" | ||
205 | "xor %%ah, %%ah\n" | ||
206 | "1:" | ||
207 | : "=c" (*value), | ||
208 | "=a" (result) | ||
209 | : "1" (PCIBIOS_READ_CONFIG_WORD), | ||
210 | "b" (bx), | ||
211 | "D" ((long)reg), | ||
212 | "S" (&pci_indirect)); | ||
213 | break; | ||
214 | case 4: | ||
215 | __asm__("lcall *(%%esi); cld\n\t" | ||
216 | "jc 1f\n\t" | ||
217 | "xor %%ah, %%ah\n" | ||
218 | "1:" | ||
219 | : "=c" (*value), | ||
220 | "=a" (result) | ||
221 | : "1" (PCIBIOS_READ_CONFIG_DWORD), | ||
222 | "b" (bx), | ||
223 | "D" ((long)reg), | ||
224 | "S" (&pci_indirect)); | ||
225 | break; | ||
226 | } | ||
227 | |||
228 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
229 | |||
230 | return (int)((result & 0xff00) >> 8); | ||
231 | } | ||
232 | |||
233 | static int pci_bios_write(unsigned int seg, unsigned int bus, | ||
234 | unsigned int devfn, int reg, int len, u32 value) | ||
235 | { | ||
236 | unsigned long result = 0; | ||
237 | unsigned long flags; | ||
238 | unsigned long bx = (bus << 8) | devfn; | ||
239 | |||
240 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | ||
241 | return -EINVAL; | ||
242 | |||
243 | spin_lock_irqsave(&pci_config_lock, flags); | ||
244 | |||
245 | switch (len) { | ||
246 | case 1: | ||
247 | __asm__("lcall *(%%esi); cld\n\t" | ||
248 | "jc 1f\n\t" | ||
249 | "xor %%ah, %%ah\n" | ||
250 | "1:" | ||
251 | : "=a" (result) | ||
252 | : "0" (PCIBIOS_WRITE_CONFIG_BYTE), | ||
253 | "c" (value), | ||
254 | "b" (bx), | ||
255 | "D" ((long)reg), | ||
256 | "S" (&pci_indirect)); | ||
257 | break; | ||
258 | case 2: | ||
259 | __asm__("lcall *(%%esi); cld\n\t" | ||
260 | "jc 1f\n\t" | ||
261 | "xor %%ah, %%ah\n" | ||
262 | "1:" | ||
263 | : "=a" (result) | ||
264 | : "0" (PCIBIOS_WRITE_CONFIG_WORD), | ||
265 | "c" (value), | ||
266 | "b" (bx), | ||
267 | "D" ((long)reg), | ||
268 | "S" (&pci_indirect)); | ||
269 | break; | ||
270 | case 4: | ||
271 | __asm__("lcall *(%%esi); cld\n\t" | ||
272 | "jc 1f\n\t" | ||
273 | "xor %%ah, %%ah\n" | ||
274 | "1:" | ||
275 | : "=a" (result) | ||
276 | : "0" (PCIBIOS_WRITE_CONFIG_DWORD), | ||
277 | "c" (value), | ||
278 | "b" (bx), | ||
279 | "D" ((long)reg), | ||
280 | "S" (&pci_indirect)); | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | spin_unlock_irqrestore(&pci_config_lock, flags); | ||
285 | |||
286 | return (int)((result & 0xff00) >> 8); | ||
287 | } | ||
288 | |||
289 | |||
290 | /* | ||
291 | * Function table for BIOS32 access | ||
292 | */ | ||
293 | |||
294 | static struct pci_raw_ops pci_bios_access = { | ||
295 | .read = pci_bios_read, | ||
296 | .write = pci_bios_write | ||
297 | }; | ||
298 | |||
299 | /* | ||
300 | * Try to find PCI BIOS. | ||
301 | */ | ||
302 | |||
303 | static struct pci_raw_ops * __devinit pci_find_bios(void) | ||
304 | { | ||
305 | union bios32 *check; | ||
306 | unsigned char sum; | ||
307 | int i, length; | ||
308 | |||
309 | /* | ||
310 | * Follow the standard procedure for locating the BIOS32 Service | ||
311 | * directory by scanning the permissible address range from | ||
312 | * 0xe0000 through 0xfffff for a valid BIOS32 structure. | ||
313 | */ | ||
314 | |||
315 | for (check = (union bios32 *) __va(0xe0000); | ||
316 | check <= (union bios32 *) __va(0xffff0); | ||
317 | ++check) { | ||
318 | long sig; | ||
319 | if (probe_kernel_address(&check->fields.signature, sig)) | ||
320 | continue; | ||
321 | |||
322 | if (check->fields.signature != BIOS32_SIGNATURE) | ||
323 | continue; | ||
324 | length = check->fields.length * 16; | ||
325 | if (!length) | ||
326 | continue; | ||
327 | sum = 0; | ||
328 | for (i = 0; i < length ; ++i) | ||
329 | sum += check->chars[i]; | ||
330 | if (sum != 0) | ||
331 | continue; | ||
332 | if (check->fields.revision != 0) { | ||
333 | printk("PCI: unsupported BIOS32 revision %d at 0x%p\n", | ||
334 | check->fields.revision, check); | ||
335 | continue; | ||
336 | } | ||
337 | DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check); | ||
338 | if (check->fields.entry >= 0x100000) { | ||
339 | printk("PCI: BIOS32 entry (0x%p) in high memory, " | ||
340 | "cannot use.\n", check); | ||
341 | return NULL; | ||
342 | } else { | ||
343 | unsigned long bios32_entry = check->fields.entry; | ||
344 | DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", | ||
345 | bios32_entry); | ||
346 | bios32_indirect.address = bios32_entry + PAGE_OFFSET; | ||
347 | if (check_pcibios()) | ||
348 | return &pci_bios_access; | ||
349 | } | ||
350 | break; /* Hopefully more than one BIOS32 cannot happen... */ | ||
351 | } | ||
352 | |||
353 | return NULL; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Sort the device list according to PCI BIOS. Nasty hack, but since some | ||
358 | * fool forgot to define the `correct' device order in the PCI BIOS specs | ||
359 | * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels | ||
360 | * which used BIOS ordering, we are bound to do this... | ||
361 | */ | ||
362 | |||
363 | void __devinit pcibios_sort(void) | ||
364 | { | ||
365 | LIST_HEAD(sorted_devices); | ||
366 | struct list_head *ln; | ||
367 | struct pci_dev *dev, *d; | ||
368 | int idx, found; | ||
369 | unsigned char bus, devfn; | ||
370 | |||
371 | DBG("PCI: Sorting device list...\n"); | ||
372 | while (!list_empty(&pci_devices)) { | ||
373 | ln = pci_devices.next; | ||
374 | dev = pci_dev_g(ln); | ||
375 | idx = found = 0; | ||
376 | while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) { | ||
377 | idx++; | ||
378 | list_for_each(ln, &pci_devices) { | ||
379 | d = pci_dev_g(ln); | ||
380 | if (d->bus->number == bus && d->devfn == devfn) { | ||
381 | list_move_tail(&d->global_list, &sorted_devices); | ||
382 | if (d == dev) | ||
383 | found = 1; | ||
384 | break; | ||
385 | } | ||
386 | } | ||
387 | if (ln == &pci_devices) { | ||
388 | printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn); | ||
389 | /* | ||
390 | * We must not continue scanning as several buggy BIOSes | ||
391 | * return garbage after the last device. Grr. | ||
392 | */ | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | if (!found) { | ||
397 | printk(KERN_WARNING "PCI: Device %s not found by BIOS\n", | ||
398 | pci_name(dev)); | ||
399 | list_move_tail(&dev->global_list, &sorted_devices); | ||
400 | } | ||
401 | } | ||
402 | list_splice(&sorted_devices, &pci_devices); | ||
403 | } | ||
404 | |||
405 | /* | ||
406 | * BIOS Functions for IRQ Routing | ||
407 | */ | ||
408 | |||
409 | struct irq_routing_options { | ||
410 | u16 size; | ||
411 | struct irq_info *table; | ||
412 | u16 segment; | ||
413 | } __attribute__((packed)); | ||
414 | |||
415 | struct irq_routing_table * pcibios_get_irq_routing_table(void) | ||
416 | { | ||
417 | struct irq_routing_options opt; | ||
418 | struct irq_routing_table *rt = NULL; | ||
419 | int ret, map; | ||
420 | unsigned long page; | ||
421 | |||
422 | if (!pci_bios_present) | ||
423 | return NULL; | ||
424 | page = __get_free_page(GFP_KERNEL); | ||
425 | if (!page) | ||
426 | return NULL; | ||
427 | opt.table = (struct irq_info *) page; | ||
428 | opt.size = PAGE_SIZE; | ||
429 | opt.segment = __KERNEL_DS; | ||
430 | |||
431 | DBG("PCI: Fetching IRQ routing table... "); | ||
432 | __asm__("push %%es\n\t" | ||
433 | "push %%ds\n\t" | ||
434 | "pop %%es\n\t" | ||
435 | "lcall *(%%esi); cld\n\t" | ||
436 | "pop %%es\n\t" | ||
437 | "jc 1f\n\t" | ||
438 | "xor %%ah, %%ah\n" | ||
439 | "1:" | ||
440 | : "=a" (ret), | ||
441 | "=b" (map), | ||
442 | "=m" (opt) | ||
443 | : "0" (PCIBIOS_GET_ROUTING_OPTIONS), | ||
444 | "1" (0), | ||
445 | "D" ((long) &opt), | ||
446 | "S" (&pci_indirect), | ||
447 | "m" (opt) | ||
448 | : "memory"); | ||
449 | DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map); | ||
450 | if (ret & 0xff00) | ||
451 | printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", (ret >> 8) & 0xff); | ||
452 | else if (opt.size) { | ||
453 | rt = kmalloc(sizeof(struct irq_routing_table) + opt.size, GFP_KERNEL); | ||
454 | if (rt) { | ||
455 | memset(rt, 0, sizeof(struct irq_routing_table)); | ||
456 | rt->size = opt.size + sizeof(struct irq_routing_table); | ||
457 | rt->exclusive_irqs = map; | ||
458 | memcpy(rt->slots, (void *) page, opt.size); | ||
459 | printk(KERN_INFO "PCI: Using BIOS Interrupt Routing Table\n"); | ||
460 | } | ||
461 | } | ||
462 | free_page(page); | ||
463 | return rt; | ||
464 | } | ||
465 | EXPORT_SYMBOL(pcibios_get_irq_routing_table); | ||
466 | |||
467 | int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) | ||
468 | { | ||
469 | int ret; | ||
470 | |||
471 | __asm__("lcall *(%%esi); cld\n\t" | ||
472 | "jc 1f\n\t" | ||
473 | "xor %%ah, %%ah\n" | ||
474 | "1:" | ||
475 | : "=a" (ret) | ||
476 | : "0" (PCIBIOS_SET_PCI_HW_INT), | ||
477 | "b" ((dev->bus->number << 8) | dev->devfn), | ||
478 | "c" ((irq << 8) | (pin + 10)), | ||
479 | "S" (&pci_indirect)); | ||
480 | return !(ret & 0xff00); | ||
481 | } | ||
482 | EXPORT_SYMBOL(pcibios_set_irq_routing); | ||
483 | |||
484 | void __init pci_pcbios_init(void) | ||
485 | { | ||
486 | if ((pci_probe & PCI_PROBE_BIOS) | ||
487 | && ((raw_pci_ops = pci_find_bios()))) { | ||
488 | pci_probe |= PCI_BIOS_SORT; | ||
489 | pci_bios_present = 1; | ||
490 | } | ||
491 | } | ||
492 | |||
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h new file mode 100644 index 000000000000..8c66f275756f --- /dev/null +++ b/arch/x86/pci/pci.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Access for i386 machines. | ||
3 | * | ||
4 | * (c) 1999 Martin Mares <mj@ucw.cz> | ||
5 | */ | ||
6 | |||
7 | #undef DEBUG | ||
8 | |||
9 | #ifdef DEBUG | ||
10 | #define DBG(x...) printk(x) | ||
11 | #else | ||
12 | #define DBG(x...) | ||
13 | #endif | ||
14 | |||
15 | #define PCI_PROBE_BIOS 0x0001 | ||
16 | #define PCI_PROBE_CONF1 0x0002 | ||
17 | #define PCI_PROBE_CONF2 0x0004 | ||
18 | #define PCI_PROBE_MMCONF 0x0008 | ||
19 | #define PCI_PROBE_MASK 0x000f | ||
20 | #define PCI_PROBE_NOEARLY 0x0010 | ||
21 | |||
22 | #define PCI_NO_SORT 0x0100 | ||
23 | #define PCI_BIOS_SORT 0x0200 | ||
24 | #define PCI_NO_CHECKS 0x0400 | ||
25 | #define PCI_USE_PIRQ_MASK 0x0800 | ||
26 | #define PCI_ASSIGN_ROMS 0x1000 | ||
27 | #define PCI_BIOS_IRQ_SCAN 0x2000 | ||
28 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 | ||
29 | |||
30 | extern unsigned int pci_probe; | ||
31 | extern unsigned long pirq_table_addr; | ||
32 | |||
33 | enum pci_bf_sort_state { | ||
34 | pci_bf_sort_default, | ||
35 | pci_force_nobf, | ||
36 | pci_force_bf, | ||
37 | pci_dmi_bf, | ||
38 | }; | ||
39 | |||
40 | /* pci-i386.c */ | ||
41 | |||
42 | extern unsigned int pcibios_max_latency; | ||
43 | |||
44 | void pcibios_resource_survey(void); | ||
45 | int pcibios_enable_resources(struct pci_dev *, int); | ||
46 | |||
47 | /* pci-pc.c */ | ||
48 | |||
49 | extern int pcibios_last_bus; | ||
50 | extern struct pci_bus *pci_root_bus; | ||
51 | extern struct pci_ops pci_root_ops; | ||
52 | |||
53 | /* pci-irq.c */ | ||
54 | |||
55 | struct irq_info { | ||
56 | u8 bus, devfn; /* Bus, device and function */ | ||
57 | struct { | ||
58 | u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ | ||
59 | u16 bitmap; /* Available IRQs */ | ||
60 | } __attribute__((packed)) irq[4]; | ||
61 | u8 slot; /* Slot number, 0=onboard */ | ||
62 | u8 rfu; | ||
63 | } __attribute__((packed)); | ||
64 | |||
65 | struct irq_routing_table { | ||
66 | u32 signature; /* PIRQ_SIGNATURE should be here */ | ||
67 | u16 version; /* PIRQ_VERSION */ | ||
68 | u16 size; /* Table size in bytes */ | ||
69 | u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ | ||
70 | u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ | ||
71 | u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ | ||
72 | u32 miniport_data; /* Crap */ | ||
73 | u8 rfu[11]; | ||
74 | u8 checksum; /* Modulo 256 checksum must give zero */ | ||
75 | struct irq_info slots[0]; | ||
76 | } __attribute__((packed)); | ||
77 | |||
78 | extern unsigned int pcibios_irq_mask; | ||
79 | |||
80 | extern int pcibios_scanned; | ||
81 | extern spinlock_t pci_config_lock; | ||
82 | |||
83 | extern int (*pcibios_enable_irq)(struct pci_dev *dev); | ||
84 | extern void (*pcibios_disable_irq)(struct pci_dev *dev); | ||
85 | |||
86 | extern int pci_conf1_write(unsigned int seg, unsigned int bus, | ||
87 | unsigned int devfn, int reg, int len, u32 value); | ||
88 | extern int pci_conf1_read(unsigned int seg, unsigned int bus, | ||
89 | unsigned int devfn, int reg, int len, u32 *value); | ||
90 | |||
91 | extern int pci_direct_probe(void); | ||
92 | extern void pci_direct_init(int type); | ||
93 | extern void pci_pcbios_init(void); | ||
94 | extern void pci_mmcfg_init(int type); | ||
95 | extern void pcibios_sort(void); | ||
96 | |||
97 | /* pci-mmconfig.c */ | ||
98 | |||
99 | /* Verify the first 16 busses. We assume that systems with more busses | ||
100 | get MCFG right. */ | ||
101 | #define PCI_MMCFG_MAX_CHECK_BUS 16 | ||
102 | extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS); | ||
103 | |||
104 | extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, | ||
105 | unsigned int devfn); | ||
106 | extern int __init pci_mmcfg_arch_init(void); | ||
107 | |||
108 | /* | ||
109 | * AMD Fam10h CPUs are buggy, and cannot access MMIO config space | ||
110 | * on their northbrige except through the * %eax register. As such, you MUST | ||
111 | * NOT use normal IOMEM accesses, you need to only use the magic mmio-config | ||
112 | * accessor functions. | ||
113 | * In fact just use pci_config_*, nothing else please. | ||
114 | */ | ||
115 | static inline unsigned char mmio_config_readb(void __iomem *pos) | ||
116 | { | ||
117 | u8 val; | ||
118 | asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos)); | ||
119 | return val; | ||
120 | } | ||
121 | |||
122 | static inline unsigned short mmio_config_readw(void __iomem *pos) | ||
123 | { | ||
124 | u16 val; | ||
125 | asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos)); | ||
126 | return val; | ||
127 | } | ||
128 | |||
129 | static inline unsigned int mmio_config_readl(void __iomem *pos) | ||
130 | { | ||
131 | u32 val; | ||
132 | asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos)); | ||
133 | return val; | ||
134 | } | ||
135 | |||
136 | static inline void mmio_config_writeb(void __iomem *pos, u8 val) | ||
137 | { | ||
138 | asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
139 | } | ||
140 | |||
141 | static inline void mmio_config_writew(void __iomem *pos, u16 val) | ||
142 | { | ||
143 | asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
144 | } | ||
145 | |||
146 | static inline void mmio_config_writel(void __iomem *pos, u32 val) | ||
147 | { | ||
148 | asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory"); | ||
149 | } | ||
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c new file mode 100644 index 000000000000..8ecb1c722594 --- /dev/null +++ b/arch/x86/pci/visws.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Low-Level PCI Support for SGI Visual Workstation | ||
3 | * | ||
4 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> | ||
5 | */ | ||
6 | |||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include "cobalt.h" | ||
12 | #include "lithium.h" | ||
13 | |||
14 | #include "pci.h" | ||
15 | |||
16 | |||
17 | extern struct pci_raw_ops pci_direct_conf1; | ||
18 | |||
19 | static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } | ||
20 | static void pci_visws_disable_irq(struct pci_dev *dev) { } | ||
21 | |||
22 | int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; | ||
23 | void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq; | ||
24 | |||
25 | void __init pcibios_penalize_isa_irq(int irq, int active) {} | ||
26 | |||
27 | |||
28 | unsigned int pci_bus0, pci_bus1; | ||
29 | |||
30 | static inline u8 bridge_swizzle(u8 pin, u8 slot) | ||
31 | { | ||
32 | return (((pin - 1) + slot) % 4) + 1; | ||
33 | } | ||
34 | |||
35 | static u8 __init visws_swizzle(struct pci_dev *dev, u8 *pinp) | ||
36 | { | ||
37 | u8 pin = *pinp; | ||
38 | |||
39 | while (dev->bus->self) { /* Move up the chain of bridges. */ | ||
40 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
41 | dev = dev->bus->self; | ||
42 | } | ||
43 | *pinp = pin; | ||
44 | |||
45 | return PCI_SLOT(dev->devfn); | ||
46 | } | ||
47 | |||
48 | static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
49 | { | ||
50 | int irq, bus = dev->bus->number; | ||
51 | |||
52 | pin--; | ||
53 | |||
54 | /* Nothing useful at PIIX4 pin 1 */ | ||
55 | if (bus == pci_bus0 && slot == 4 && pin == 0) | ||
56 | return -1; | ||
57 | |||
58 | /* PIIX4 USB is on Bus 0, Slot 4, Line 3 */ | ||
59 | if (bus == pci_bus0 && slot == 4 && pin == 3) { | ||
60 | irq = CO_IRQ(CO_APIC_PIIX4_USB); | ||
61 | goto out; | ||
62 | } | ||
63 | |||
64 | /* First pin spread down 1 APIC entry per slot */ | ||
65 | if (pin == 0) { | ||
66 | irq = CO_IRQ((bus == pci_bus0 ? CO_APIC_PCIB_BASE0 : | ||
67 | CO_APIC_PCIA_BASE0) + slot); | ||
68 | goto out; | ||
69 | } | ||
70 | |||
71 | /* lines 1,2,3 from any slot is shared in this twirly pattern */ | ||
72 | if (bus == pci_bus1) { | ||
73 | /* lines 1-3 from devices 0 1 rotate over 2 apic entries */ | ||
74 | irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((slot + (pin - 1)) % 2)); | ||
75 | } else { /* bus == pci_bus0 */ | ||
76 | /* lines 1-3 from devices 0-3 rotate over 3 apic entries */ | ||
77 | if (slot == 0) | ||
78 | slot = 3; /* same pattern */ | ||
79 | irq = CO_IRQ(CO_APIC_PCIA_BASE123 + ((3 - slot) + (pin - 1) % 3)); | ||
80 | } | ||
81 | out: | ||
82 | printk(KERN_DEBUG "PCI: Bus %d Slot %d Line %d -> IRQ %d\n", bus, slot, pin, irq); | ||
83 | return irq; | ||
84 | } | ||
85 | |||
86 | void __init pcibios_update_irq(struct pci_dev *dev, int irq) | ||
87 | { | ||
88 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
89 | } | ||
90 | |||
91 | static int __init pcibios_init(void) | ||
92 | { | ||
93 | /* The VISWS supports configuration access type 1 only */ | ||
94 | pci_probe = (pci_probe | PCI_PROBE_CONF1) & | ||
95 | ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2); | ||
96 | |||
97 | pci_bus0 = li_pcib_read16(LI_PCI_BUSNUM) & 0xff; | ||
98 | pci_bus1 = li_pcia_read16(LI_PCI_BUSNUM) & 0xff; | ||
99 | |||
100 | printk(KERN_INFO "PCI: Lithium bridge A bus: %u, " | ||
101 | "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0); | ||
102 | |||
103 | raw_pci_ops = &pci_direct_conf1; | ||
104 | pci_scan_bus_with_sysdata(pci_bus0); | ||
105 | pci_scan_bus_with_sysdata(pci_bus1); | ||
106 | pci_fixup_irqs(visws_swizzle, visws_map_irq); | ||
107 | pcibios_resource_survey(); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | subsys_initcall(pcibios_init); | ||