2 * Low-Level PCI Support for PC -- Routing of Interrupts
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
7 #include <linux/config.h>
8 #include <linux/types.h>
9 #include <linux/kernel.h>
10 #include <linux/pci.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/interrupt.h>
14 #include <linux/irq.h>
17 #include <asm/io_apic.h>
18 #include <asm/hw_irq.h>
19 #include <linux/acpi.h>
23 #include <asm-xen/xen-public/xen.h>
24 #include <asm-xen/xen-public/physdev.h>
26 static int pirq_enable_irq(struct pci_dev *dev);
29 * Never use: 0, 1, 2 (timer, keyboard, and cascade)
30 * Avoid using: 13, 14 and 15 (FP error and IDE).
31 * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
33 unsigned int pcibios_irq_mask = 0xfff8;
35 static int pirq_penalty[16] = {
36 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
37 0, 0, 0, 0, 1000, 100000, 100000, 100000
40 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
42 static int pirq_enable_irq(struct pci_dev *);
44 static int __init pcibios_irq_init(void)
49 DBG("PCI: IRQ init\n");
51 if (pcibios_enable_irq || raw_pci_ops == NULL)
54 op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES;
55 if (HYPERVISOR_physdev_op(&op) != 0) {
56 printk(KERN_WARNING "PCI: System does not support PCI\n");
60 printk(KERN_INFO "PCI: Probing PCI hardware\n");
61 for (bus = 0; bus < 256; bus++)
62 if (test_bit(bus, (unsigned long *)
63 &op.u.pci_probe_root_buses.busmask[0]))
64 (void)pcibios_scan_root(bus);
66 pcibios_enable_irq = pirq_enable_irq;
71 subsys_initcall(pcibios_irq_init);
74 static void pirq_penalize_isa_irq(int irq)
77 * If any ISAPnP device reports an IRQ in its list of possible
78 * IRQ's, we try to avoid assigning it to PCI devices.
81 pirq_penalty[irq] += 100;
84 void pcibios_penalize_isa_irq(int irq)
86 #ifdef CONFIG_ACPI_PCI
88 acpi_penalize_isa_irq(irq);
91 pirq_penalize_isa_irq(irq);
94 static int pirq_enable_irq(struct pci_dev *dev)
100 /* Inform Xen that we are going to use this device. */
101 op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE;
102 op.u.pci_initialise_device.bus = dev->bus->number;
103 op.u.pci_initialise_device.dev = PCI_SLOT(dev->devfn);
104 op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn);
105 if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
108 /* Now we can bind to the very final IRQ line. */
109 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin);
112 /* Sanity-check that an interrupt-producing device is routed
114 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
117 printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n",
118 dev->irq, pci_name(dev));
120 printk(KERN_WARNING "PCI: No IRQ known for interrupt "
121 "pin %c of device %s.\n", 'A' + pin - 1,
128 int pci_vector_resources(int last, int nr_released)
130 int count = nr_released;
133 int offset = (last % 8);
135 while (next < FIRST_SYSTEM_VECTOR) {
138 if (next == IA32_SYSCALL_VECTOR)
141 if (next == SYSCALL_VECTOR)
145 if (next >= FIRST_SYSTEM_VECTOR) {
147 next = FIRST_DEVICE_VECTOR + offset;