/*
       *	Low-Level PCI Support for PC -- Routing of Interrupts
       *
       *	(c) 1999--2000 Martin Mares <mj@suse.cz>
       */
      
      #include <linux/config.h>
      #include <linux/types.h>
      #include <linux/kernel.h>
      #include <linux/pci.h>
      #include <linux/init.h>
      #include <linux/malloc.h>
      #include <linux/interrupt.h>
      #include <linux/irq.h>
      
      #include <asm/io.h>
      #include <asm/smp.h>
      #include <asm/io_apic.h>
      
      #include "pci-i386.h"
      
      #define PIRQ_SIGNATURE	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
      #define PIRQ_VERSION 0x0100
      
      static struct irq_routing_table *pirq_table;
      
      /*
       * Never use: 0, 1, 2 (timer, keyboard, and cascade)
       * Avoid using: 13, 14 and 15 (FP error and IDE).
       * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
       */
      unsigned int pcibios_irq_mask = 0xfff8;
      
      static int pirq_penalty[16] = {
      	1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
      	0, 0, 0, 0, 1000, 100000, 100000, 100000
      };
      
      struct irq_router {
      	char *name;
      	u16 vendor, device;
      	int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
      	int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
      };
      
      /*
       *  Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
       */
      
  50  static struct irq_routing_table * __init pirq_find_routing_table(void)
      {
      	u8 *addr;
      	struct irq_routing_table *rt;
      	int i;
      	u8 sum;
      
  57  	for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
      		rt = (struct irq_routing_table *) addr;
      		if (rt->signature != PIRQ_SIGNATURE ||
      		    rt->version != PIRQ_VERSION ||
      		    rt->size % 16 ||
  62  		    rt->size < sizeof(struct irq_routing_table))
  63  			continue;
      		sum = 0;
  65  		for(i=0; i<rt->size; i++)
      			sum += addr[i];
  67  		if (!sum) {
      			DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
  69  			return rt;
      		}
      	}
  72  	return NULL;
      }
      
      /*
       *  If we have a IRQ routing table, use it to search for peer host
       *  bridges.  It's a gross hack, but since there are no other known
       *  ways how to get a list of buses, we have to go this way.
       */
      
  81  static void __init pirq_peer_trick(void)
      {
      	struct irq_routing_table *rt = pirq_table;
      	u8 busmap[256];
      	int i;
      	struct irq_info *e;
      
      	memset(busmap, 0, sizeof(busmap));
  89  	for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
      		e = &rt->slots[i];
      #ifdef DEBUG
      		{
      			int j;
      			DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
      			for(j=0; j<4; j++)
      				DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
      			DBG("\n");
      		}
      #endif
      		busmap[e->bus] = 1;
      	}
 102  	for(i=1; i<256; i++)
      		/*
      		 *  It might be a secondary bus, but in this case its parent is already
      		 *  known (ascending bus order) and therefore pci_scan_bus returns immediately.
      		 */
 107  		if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
      			printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
      	pcibios_last_bus = -1;
      }
      
      /*
       *  Code for querying and setting of IRQ routes on various interrupt routers.
       */
      
 116  static void eisa_set_level_irq(unsigned int irq)
      {
      	unsigned char mask = 1 << (irq & 7);
      	unsigned int port = 0x4d0 + (irq >> 3);
      	unsigned char val = inb(port);
      
 122  	if (!(val & mask)) {
      		DBG(" -> edge");
      		outb(val | mask, port);
      	}
      }
      
      /*
       * Common IRQ routing practice: nybbles in config space,
       * offset by some magic constant.
       */
 132  static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
      {
      	u8 x;
      	unsigned reg = offset + (nr >> 1);
      
      	pci_read_config_byte(router, reg, &x);
 138  	return (nr & 1) ? (x >> 4) : (x & 0xf);
      }
      
 141  static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
      {
      	u8 x;
      	unsigned reg = offset + (nr >> 1);
      
      	pci_read_config_byte(router, reg, &x);
      	x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
      	pci_write_config_byte(router, reg, x);
      }
      
      /*
       * ALI pirq entries are damn ugly, and completely undocumented.
       * This has been figured out from pirq tables, and it's not a pretty
       * picture.
       */
 156  static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
      	static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
      
 160  	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
      }
      
 163  static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
      	unsigned int val = irqmap[irq];
      		
 168  	if (val) {
      		write_config_nybble(router, 0x48, pirq-1, val);
 170  		return 1;
      	}
 172  	return 0;
      }
      
      /*
       * The Intel PIIX4 pirq rules are fairly simple: "pirq" is
       * just a pointer to the config space.
       */
 179  static int pirq_piix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
      	u8 x;
      
      	pci_read_config_byte(router, pirq, &x);
 184  	return (x < 16) ? x : 0;
      }
      
 187  static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	pci_write_config_byte(router, pirq, irq);
 190  	return 1;
      }
      
      /*
       * The VIA pirq rules are nibble-based, like ALI,
       * but without the ugly irq number munging.
       */
 197  static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
 199  	return read_config_nybble(router, 0x55, pirq);
      }
      
 202  static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	write_config_nybble(router, 0x55, pirq, irq);
 205  	return 1;
      }
      
      /*
       * OPTI: high four bits are nibble pointer..
       * I wonder what the low bits do?
       */
 212  static int pirq_opti_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
 214  	return read_config_nybble(router, 0xb8, pirq >> 4);
      }
      
 217  static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	write_config_nybble(router, 0xb8, pirq >> 4, irq);
 220  	return 1;
      }
      
      /*
       * Cyrix: nibble offset 0x5C
       */
 226  static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
 228  	return read_config_nybble(router, 0x5C, pirq-1);
      }
      
 231  static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	write_config_nybble(router, 0x5C, pirq-1, irq);
 234  	return 1;
      }
      
 237  static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
      	u8 x;
      	int reg = 0x41 + (pirq - 'A') ;
      
      	pci_read_config_byte(router, reg, &x);
 243  	return (x & 0x80) ? 0 : (x & 0x0f);
      }
      
 246  static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	u8 x;
      	int reg = 0x41 + (pirq - 'A') ;
      
      	pci_read_config_byte(router, reg, &x);
      	x = (pirq & 0x20) ? 0 : (irq & 0x0f);
      	pci_write_config_byte(router, reg, x);
      
 255  	return 1;
      }
      
      /*
       * VLSI: nibble offset 0x74 - educated guess due to routing table and
       *       config space of VLSI 82C534 PCI-bridge/router (1004:0102)
       *       Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
       *       devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
       *       for the busbridge to the docking station.
       */
      
 266  static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
 268  	if (pirq > 8) {
      		printk("VLSI router pirq escape (%d)\n", pirq);
 270  		return 0;
      	}
 272  	return read_config_nybble(router, 0x74, pirq-1);
      }
      
 275  static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
 277  	if (pirq > 8) {
      		printk("VLSI router pirq escape (%d)\n", pirq);
 279  		return 0;
      	}
      	write_config_nybble(router, 0x74, pirq-1, irq);
 282  	return 1;
      }
      
      /*
       * ServerWorks: PCI interrupts mapped to system IRQ lines through Index
       * and Redirect I/O registers (0x0c00 and 0x0c01).  The Index register
       * format is (PCIIRQ## | 0x10), e.g.: PCIIRQ10=0x1a.  The Redirect
       * register is a straight binary coding of desired PIC IRQ (low nibble).
       *
       * The 'link' value in the PIRQ table is already in the correct format
       * for the Index register.  There are some special index values:
       * 0x00 for ACPI (SCI), 0x01 for USB, 0x02 for IDE0, 0x04 for IDE1,
       * and 0x03 for SMBus.
       */
 296  static int pirq_serverworks_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
      {
      	outb_p(pirq, 0xc00);
 299  	return inb(0xc01) & 0xf;
      }
      
 302  static int pirq_serverworks_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	outb_p(pirq, 0xc00);
      	outb_p(irq, 0xc01);
 306  	return 1;
      }
      
      #ifdef CONFIG_PCI_BIOS
      
 311  static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
      {
      	struct pci_dev *bridge;
      	int pin = pci_get_interrupt_pin(dev, &bridge);
 315  	return pcibios_set_irq_routing(bridge, pin, irq);
      }
      
      static struct irq_router pirq_bios_router =
      	{ "BIOS", 0, 0, NULL, pirq_bios_set };
      
      #endif
      
      static struct irq_router pirq_routers[] = {
      	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
      	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
      	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
      	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
      	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
      
      	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
      
      	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
      	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
      	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
      
      	{ "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
      
      	{ "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
      	{ "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
      	{ "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
      	{ "ServerWorks", PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4,
      	  pirq_serverworks_get, pirq_serverworks_set },
      
      	{ "default", 0, 0, NULL, NULL }
      };
      
      static struct irq_router *pirq_router;
      static struct pci_dev *pirq_router_dev;
      
 350  static void __init pirq_find_router(void)
      {
      	struct irq_routing_table *rt = pirq_table;
      	struct irq_router *r;
      
      #ifdef CONFIG_PCI_BIOS
 356  	if (!rt->signature) {
      		printk("PCI: Using BIOS for IRQ routing\n");
      		pirq_router = &pirq_bios_router;
 359  		return;
      	}
      #endif
      	/* fall back to default router if nothing else found */
      	pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1;
      
      	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
 366  	if (!pirq_router_dev) {
      		DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
 368  		return;
      	}
      
 371  	for(r=pirq_routers; r->vendor; r++) {
      		/* Exact match against router table entry? Use it! */
 373  		if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) {
      			pirq_router = r;
 375  			break;
      		}
      		/* Match against router device entry? Use it as a fallback */
 378  		if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) {
      			pirq_router = r;
      		}
      	}
      	printk("PCI: Using IRQ router %s [%04x/%04x] at %s\n",
      		pirq_router->name,
      		pirq_router_dev->vendor,
      		pirq_router_dev->device,
      		pirq_router_dev->slot_name);
      }
      
 389  static struct irq_info *pirq_get_info(struct pci_dev *dev)
      {
      	struct irq_routing_table *rt = pirq_table;
      	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
      	struct irq_info *info;
      
 395  	for (info = rt->slots; entries--; info++)
 396  		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
 397  			return info;
 398  	return NULL;
      }
      
 401  static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
      {
      }
      
 405  static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
      {
      	u8 pin;
      	struct irq_info *info;
      	int i, pirq, newirq;
      	int irq = 0;
      	u32 mask;
      	struct irq_router *r = pirq_router;
      	struct pci_dev *dev2;
      	char *msg = NULL;
      
 416  	if (!pirq_table)
 417  		return 0;
      
      	/* Find IRQ routing entry */
      	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 421  	if (!pin) {
      		DBG(" -> no interrupt pin\n");
 423  		return 0;
      	}
      	pin = pin - 1;
      	
      	DBG("IRQ for %s:%d", dev->slot_name, pin);
      	info = pirq_get_info(dev);
 429  	if (!info) {
      		DBG(" -> not found in routing table\n");
 431  		return 0;
      	}
      	pirq = info->irq[pin].link;
      	mask = info->irq[pin].bitmap;
 435  	if (!pirq) {
      		DBG(" -> not routed\n");
 437  		return 0;
      	}
      	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
      	mask &= pcibios_irq_mask;
      
      	/*
      	 * Find the best IRQ to assign: use the one
      	 * reported by the device if possible.
      	 */
      	newirq = dev->irq;
 447  	if (!newirq && assign) {
 448  		for (i = 0; i < 16; i++) {
 449  			if (!(mask & (1 << i)))
 450  				continue;
      			if (pirq_penalty[i] < pirq_penalty[newirq] &&
 452  			    !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
      				free_irq(i, dev);
      				newirq = i;
      			}
      		}
      	}
      	DBG(" -> newirq=%d", newirq);
      
      	/* Check if it is hardcoded */
 461  	if ((pirq & 0xf0) == 0xf0) {
      		irq = pirq & 0xf;
      		DBG(" -> hardcoded IRQ %d\n", irq);
      		msg = "Hardcoded";
 465  		if (dev->irq && dev->irq != irq) {
      			printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
 467  			return 0;
      		}
 469  	} else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
      		DBG(" -> got IRQ %d\n", irq);
      		msg = "Found";
      		/* We refuse to override the dev->irq information. Give a warning! */
 473  	    	if (dev->irq && dev->irq != irq) {
      	    		printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
 475  	    		return 0;
      	    	}
 477  	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
      		DBG(" -> assigning IRQ %d", newirq);
 479  		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
      			eisa_set_level_irq(newirq);
      			DBG(" ... OK\n");
      			msg = "Assigned";
      			irq = newirq;
      		}
      	}
      
 487  	if (!irq) {
      		DBG(" ... failed\n");
 489  		if (newirq && mask == (1 << newirq)) {
      			msg = "Guessed";
      			irq = newirq;
 492  		} else
 493  			return 0;
      	}
      	printk("PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
      
      	/* Update IRQ for all devices with the same pirq value */
 498  	pci_for_each_dev(dev2) {
      		pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
      		if (!pin)
      			continue;
      		pin--;
      		info = pirq_get_info(dev2);
      		if (!info)
      			continue;
      		if (info->irq[pin].link == pirq) {
      			dev2->irq = irq;
      			pirq_penalty[irq]++;
      			if (dev != dev2)
      				printk("PCI: The same IRQ used for device %s\n", dev2->slot_name);
      		}
      	}
 513  	return 1;
      }
      
 516  void __init pcibios_irq_init(void)
      {
      	DBG("PCI: IRQ init\n");
      	pirq_table = pirq_find_routing_table();
      #ifdef CONFIG_PCI_BIOS
 521  	if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
      		pirq_table = pcibios_get_irq_routing_table();
      #endif
 524  	if (pirq_table) {
      		pirq_peer_trick();
      		pirq_find_router();
 527  		if (pirq_table->exclusive_irqs) {
      			int i;
 529  			for (i=0; i<16; i++)
 530  				if (!(pirq_table->exclusive_irqs & (1 << i)))
      					pirq_penalty[i] += 100;
      		}
      		/* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
 534  		if (io_apic_assign_pci_irqs)
      			pirq_table = NULL;
      	}
      }
      
 539  void __init pcibios_fixup_irqs(void)
      {
      	struct pci_dev *dev;
      	u8 pin;
      
      	DBG("PCI: IRQ fixup\n");
 545  	pci_for_each_dev(dev) {
      		/*
      		 * If the BIOS has set an out of range IRQ number, just ignore it.
      		 * Also keep track of which IRQ's are already in use.
      		 */
      		if (dev->irq >= 16) {
      			DBG("%s: ignoring bogus IRQ %d\n", dev->slot_name, dev->irq);
      			dev->irq = 0;
      		}
      		/* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
      		if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
      			pirq_penalty[dev->irq] = 0;
      		pirq_penalty[dev->irq]++;
      	}
      
 560  	pci_for_each_dev(dev) {
      		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
      #ifdef CONFIG_X86_IO_APIC
      		/*
      		 * Recalculate IRQ numbers if we use the I/O APIC.
      		 */
      		if (io_apic_assign_pci_irqs)
      		{
      			int irq;
      
      			if (pin) {
      				pin--;		/* interrupt pins are numbered starting from 1 */
      				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
      /*
       * Will be removed completely if things work out well with fuzzy parsing
       */
      #if 0
      				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
      					struct pci_dev * bridge = dev->bus->self;
      
      					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
      					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
      							PCI_SLOT(bridge->devfn), pin);
      					if (irq >= 0)
      						printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", 
      							bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
      				}
      #endif
      				if (irq >= 0) {
      					printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
      						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
      					dev->irq = irq;
      				}
      			}
      		}
      #endif
      		/*
      		 * Still no IRQ? Try to lookup one...
      		 */
      		if (pin && !dev->irq)
      			pcibios_lookup_irq(dev, 0);
      	}
      }
      
 604  void pcibios_penalize_isa_irq(int irq)
      {
      	/*
      	 *  If any ISAPnP device reports an IRQ in its list of possible
      	 *  IRQ's, we try to avoid assigning it to PCI devices.
      	 */
      	pirq_penalty[irq] += 100;
      }
      
 613  void pcibios_enable_irq(struct pci_dev *dev)
      {
      	u8 pin;
      	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 617  	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
      		char *msg;
 619  		if (io_apic_assign_pci_irqs)
      			msg = " Probably buggy MP table.";
 621  		else if (pci_probe & PCI_BIOS_IRQ_SCAN)
      			msg = "";
 623  		else
      			msg = " Please try using pci=biosirq.";
      		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
      		       'A' + pin - 1, dev->slot_name, msg);
      	}
      }