Merge branch 'akpm' (patches from Andrew)
[linux-2.6-block.git] / drivers / pci / setup-irq.c
CommitLineData
1da177e4
LT
1/*
2 * drivers/pci/setup-irq.c
3 *
4 * Extruded from code written by
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 * David Miller (davem@redhat.com)
8 *
9 * Support routines for initializing a PCI subsystem.
10 */
11
12
1da177e4
LT
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/errno.h>
16#include <linux/ioport.h>
17#include <linux/cache.h>
18
8885b7b6
TR
19void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
20{
21 dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq);
22 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
23}
1da177e4 24
3c78bc61
RD
25static void pdev_fixup_irq(struct pci_dev *dev,
26 u8 (*swizzle)(struct pci_dev *, u8 *),
27 int (*map_irq)(const struct pci_dev *, u8, u8))
1da177e4
LT
28{
29 u8 pin, slot;
691cd0c2 30 int irq = 0;
1da177e4
LT
31
32 /* If this device is not on the primary bus, we need to figure out
33 which interrupt pin it will come in on. We know which slot it
34 will come in on 'cos that slot is where the bridge is. Each
35 time the interrupt line passes through a PCI-PCI bridge we must
36 apply the swizzle function. */
37
38 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
691cd0c2
AB
39 /* Cope with illegal. */
40 if (pin > 4)
1da177e4
LT
41 pin = 1;
42
691cd0c2
AB
43 if (pin != 0) {
44 /* Follow the chain of bridges, swizzling as we go. */
45 slot = (*swizzle)(dev, &pin);
1da177e4 46
691cd0c2
AB
47 irq = (*map_irq)(dev, slot, pin);
48 if (irq == -1)
49 irq = 0;
50 }
1da177e4
LT
51 dev->irq = irq;
52
80ccba11 53 dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
1da177e4
LT
54
55 /* Always tell the device, so the driver knows what is
56 the real IRQ to use; the device does not use it. */
57 pcibios_update_irq(dev, irq);
58}
59
3c78bc61
RD
60void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
61 int (*map_irq)(const struct pci_dev *, u8, u8))
1da177e4
LT
62{
63 struct pci_dev *dev = NULL;
3c78bc61 64
4e344b1c 65 for_each_pci_dev(dev)
1da177e4 66 pdev_fixup_irq(dev, swizzle, map_irq);
1da177e4 67}
e6b29dea 68EXPORT_SYMBOL_GPL(pci_fixup_irqs);