11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * drivers/pci/setup-irq.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Extruded from code written by 51da177e4SLinus Torvalds * Dave Rusling (david.rusling@reo.mts.dec.com) 61da177e4SLinus Torvalds * David Mosberger (davidm@cs.arizona.edu) 71da177e4SLinus Torvalds * David Miller (davem@redhat.com) 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Support routines for initializing a PCI subsystem. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include <linux/kernel.h> 141da177e4SLinus Torvalds #include <linux/pci.h> 151da177e4SLinus Torvalds #include <linux/errno.h> 161da177e4SLinus Torvalds #include <linux/ioport.h> 171da177e4SLinus Torvalds #include <linux/cache.h> 181da177e4SLinus Torvalds 198885b7b6SThierry Reding void __weak pcibios_update_irq(struct pci_dev *dev, int irq) 208885b7b6SThierry Reding { 218885b7b6SThierry Reding dev_dbg(&dev->dev, "assigning IRQ %02d\n", irq); 228885b7b6SThierry Reding pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 238885b7b6SThierry Reding } 241da177e4SLinus Torvalds 25*3c78bc61SRyan Desfosses static void pdev_fixup_irq(struct pci_dev *dev, 261da177e4SLinus Torvalds u8 (*swizzle)(struct pci_dev *, u8 *), 27d5341942SRalf Baechle int (*map_irq)(const struct pci_dev *, u8, u8)) 281da177e4SLinus Torvalds { 291da177e4SLinus Torvalds u8 pin, slot; 30691cd0c2SAndreas Block int irq = 0; 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds /* If this device is not on the primary bus, we need to figure out 331da177e4SLinus Torvalds which interrupt pin it will come in on. We know which slot it 341da177e4SLinus Torvalds will come in on 'cos that slot is where the bridge is. Each 351da177e4SLinus Torvalds time the interrupt line passes through a PCI-PCI bridge we must 361da177e4SLinus Torvalds apply the swizzle function. */ 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 39691cd0c2SAndreas Block /* Cope with illegal. */ 40691cd0c2SAndreas Block if (pin > 4) 411da177e4SLinus Torvalds pin = 1; 421da177e4SLinus Torvalds 43691cd0c2SAndreas Block if (pin != 0) { 441da177e4SLinus Torvalds /* Follow the chain of bridges, swizzling as we go. */ 451da177e4SLinus Torvalds slot = (*swizzle)(dev, &pin); 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds irq = (*map_irq)(dev, slot, pin); 481da177e4SLinus Torvalds if (irq == -1) 491da177e4SLinus Torvalds irq = 0; 50691cd0c2SAndreas Block } 511da177e4SLinus Torvalds dev->irq = irq; 521da177e4SLinus Torvalds 5380ccba11SBjorn Helgaas dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq); 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds /* Always tell the device, so the driver knows what is 561da177e4SLinus Torvalds the real IRQ to use; the device does not use it. */ 571da177e4SLinus Torvalds pcibios_update_irq(dev, irq); 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds 60*3c78bc61SRyan Desfosses void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), 61d5341942SRalf Baechle int (*map_irq)(const struct pci_dev *, u8, u8)) 621da177e4SLinus Torvalds { 631da177e4SLinus Torvalds struct pci_dev *dev = NULL; 64*3c78bc61SRyan Desfosses 654e344b1cSKulikov Vasiliy for_each_pci_dev(dev) 661da177e4SLinus Torvalds pdev_fixup_irq(dev, swizzle, map_irq); 671da177e4SLinus Torvalds } 68