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> 1847a650f2SMatthew Minter #include "pci.h" 191da177e4SLinus Torvalds 2047a650f2SMatthew Minter void pci_assign_irq(struct pci_dev *dev) 211da177e4SLinus Torvalds { 2247a650f2SMatthew Minter u8 pin; 2347a650f2SMatthew Minter u8 slot = -1; 24691cd0c2SAndreas Block int irq = 0; 2547a650f2SMatthew Minter struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus); 2647a650f2SMatthew Minter 2747a650f2SMatthew Minter if (!(hbrg->map_irq)) { 2847a650f2SMatthew Minter dev_dbg(&dev->dev, "runtime IRQ mapping not provided by arch\n"); 2947a650f2SMatthew Minter return; 3047a650f2SMatthew Minter } 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 4347a650f2SMatthew Minter if (pin) { 441da177e4SLinus Torvalds /* Follow the chain of bridges, swizzling as we go. */ 4547a650f2SMatthew Minter if (hbrg->swizzle_irq) 4647a650f2SMatthew Minter slot = (*(hbrg->swizzle_irq))(dev, &pin); 471da177e4SLinus Torvalds 4847a650f2SMatthew Minter /* 4947a650f2SMatthew Minter * If a swizzling function is not used map_irq must 5047a650f2SMatthew Minter * ignore slot 5147a650f2SMatthew Minter */ 5247a650f2SMatthew Minter irq = (*(hbrg->map_irq))(dev, slot, pin); 531da177e4SLinus Torvalds if (irq == -1) 541da177e4SLinus Torvalds irq = 0; 55691cd0c2SAndreas Block } 561da177e4SLinus Torvalds dev->irq = irq; 571da177e4SLinus Torvalds 5847a650f2SMatthew Minter dev_dbg(&dev->dev, "assign IRQ: got %d\n", dev->irq); 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds /* Always tell the device, so the driver knows what is 611da177e4SLinus Torvalds the real IRQ to use; the device does not use it. */ 62*606799ccSBjorn Helgaas pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); 631da177e4SLinus Torvalds } 64