| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
|  | 13 | #include <linux/init.h> | 
|  | 14 | #include <linux/kernel.h> | 
|  | 15 | #include <linux/pci.h> | 
|  | 16 | #include <linux/errno.h> | 
|  | 17 | #include <linux/ioport.h> | 
|  | 18 | #include <linux/cache.h> | 
|  | 19 |  | 
|  | 20 |  | 
|  | 21 | static void __init | 
|  | 22 | pdev_fixup_irq(struct pci_dev *dev, | 
|  | 23 | u8 (*swizzle)(struct pci_dev *, u8 *), | 
|  | 24 | int (*map_irq)(struct pci_dev *, u8, u8)) | 
|  | 25 | { | 
|  | 26 | u8 pin, slot; | 
| Andreas Block | 691cd0c | 2007-02-05 16:36:07 -0800 | [diff] [blame] | 27 | int irq = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 28 |  | 
|  | 29 | /* If this device is not on the primary bus, we need to figure out | 
|  | 30 | which interrupt pin it will come in on.   We know which slot it | 
|  | 31 | will come in on 'cos that slot is where the bridge is.   Each | 
|  | 32 | time the interrupt line passes through a PCI-PCI bridge we must | 
|  | 33 | apply the swizzle function.  */ | 
|  | 34 |  | 
|  | 35 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | 
| Andreas Block | 691cd0c | 2007-02-05 16:36:07 -0800 | [diff] [blame] | 36 | /* Cope with illegal. */ | 
|  | 37 | if (pin > 4) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 | pin = 1; | 
|  | 39 |  | 
| Andreas Block | 691cd0c | 2007-02-05 16:36:07 -0800 | [diff] [blame] | 40 | if (pin != 0) { | 
|  | 41 | /* Follow the chain of bridges, swizzling as we go.  */ | 
|  | 42 | slot = (*swizzle)(dev, &pin); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 43 |  | 
| Andreas Block | 691cd0c | 2007-02-05 16:36:07 -0800 | [diff] [blame] | 44 | irq = (*map_irq)(dev, slot, pin); | 
|  | 45 | if (irq == -1) | 
|  | 46 | irq = 0; | 
|  | 47 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 48 | dev->irq = irq; | 
|  | 49 |  | 
|  | 50 | pr_debug("PCI: fixup irq: (%s) got %d\n", | 
|  | 51 | dev->dev.kobj.name, dev->irq); | 
|  | 52 |  | 
|  | 53 | /* Always tell the device, so the driver knows what is | 
|  | 54 | the real IRQ to use; the device does not use it. */ | 
|  | 55 | pcibios_update_irq(dev, irq); | 
|  | 56 | } | 
|  | 57 |  | 
|  | 58 | void __init | 
|  | 59 | pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), | 
|  | 60 | int (*map_irq)(struct pci_dev *, u8, u8)) | 
|  | 61 | { | 
|  | 62 | struct pci_dev *dev = NULL; | 
|  | 63 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 
|  | 64 | pdev_fixup_irq(dev, swizzle, map_irq); | 
|  | 65 | } | 
|  | 66 | } |