| 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 |  | 
| Bjorn Helgaas | 80ccba1 | 2008-06-13 10:52:11 -0600 | [diff] [blame] | 50 | 	dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 |  | 
 | 52 | 	/* Always tell the device, so the driver knows what is | 
 | 53 | 	   the real IRQ to use; the device does not use it. */ | 
 | 54 | 	pcibios_update_irq(dev, irq); | 
 | 55 | } | 
 | 56 |  | 
 | 57 | void __init | 
 | 58 | pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), | 
 | 59 | 	       int (*map_irq)(struct pci_dev *, u8, u8)) | 
 | 60 | { | 
 | 61 | 	struct pci_dev *dev = NULL; | 
 | 62 | 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 
 | 63 | 		pdev_fixup_irq(dev, swizzle, map_irq); | 
 | 64 | 	} | 
 | 65 | } |