2005-04-17 02:20:36 +04:00
/*
* drivers / pci / setup - irq . c
*
* Extruded from code written by
* Dave Rusling ( david . rusling @ reo . mts . dec . com )
* David Mosberger ( davidm @ cs . arizona . edu )
* David Miller ( davem @ redhat . com )
*
* Support routines for initializing a PCI subsystem .
*/
# include <linux/kernel.h>
# include <linux/pci.h>
# include <linux/errno.h>
# include <linux/ioport.h>
# include <linux/cache.h>
2012-09-17 15:22:54 +04:00
void __weak pcibios_update_irq ( struct pci_dev * dev , int irq )
{
dev_dbg ( & dev - > dev , " assigning IRQ %02d \n " , irq ) ;
pci_write_config_byte ( dev , PCI_INTERRUPT_LINE , irq ) ;
}
2005-04-17 02:20:36 +04:00
2014-04-19 04:13:49 +04:00
static void pdev_fixup_irq ( struct pci_dev * dev ,
u8 ( * swizzle ) ( struct pci_dev * , u8 * ) ,
int ( * map_irq ) ( const struct pci_dev * , u8 , u8 ) )
2005-04-17 02:20:36 +04:00
{
u8 pin , slot ;
2007-02-06 03:36:07 +03:00
int irq = 0 ;
2005-04-17 02:20:36 +04:00
/* If this device is not on the primary bus, we need to figure out
which interrupt pin it will come in on . We know which slot it
will come in on ' cos that slot is where the bridge is . Each
time the interrupt line passes through a PCI - PCI bridge we must
apply the swizzle function . */
pci_read_config_byte ( dev , PCI_INTERRUPT_PIN , & pin ) ;
2007-02-06 03:36:07 +03:00
/* Cope with illegal. */
if ( pin > 4 )
2005-04-17 02:20:36 +04:00
pin = 1 ;
2007-02-06 03:36:07 +03:00
if ( pin ! = 0 ) {
/* Follow the chain of bridges, swizzling as we go. */
slot = ( * swizzle ) ( dev , & pin ) ;
2005-04-17 02:20:36 +04:00
2007-02-06 03:36:07 +03:00
irq = ( * map_irq ) ( dev , slot , pin ) ;
if ( irq = = - 1 )
irq = 0 ;
}
2005-04-17 02:20:36 +04:00
dev - > irq = irq ;
2008-06-13 20:52:11 +04:00
dev_dbg ( & dev - > dev , " fixup irq: got %d \n " , dev - > irq ) ;
2005-04-17 02:20:36 +04:00
/* Always tell the device, so the driver knows what is
the real IRQ to use ; the device does not use it . */
pcibios_update_irq ( dev , irq ) ;
}
2014-04-19 04:13:49 +04:00
void pci_fixup_irqs ( u8 ( * swizzle ) ( struct pci_dev * , u8 * ) ,
int ( * map_irq ) ( const struct pci_dev * , u8 , u8 ) )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * dev = NULL ;
2014-04-19 04:13:49 +04:00
2010-07-03 20:04:39 +04:00
for_each_pci_dev ( dev )
2005-04-17 02:20:36 +04:00
pdev_fixup_irq ( dev , swizzle , map_irq ) ;
}
2015-04-08 21:21:33 +03:00
EXPORT_SYMBOL_GPL ( pci_fixup_irqs ) ;