in iosapic.c [706:798]
int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
{
struct iosapic_info *isi = isi_obj;
struct irt_entry *irte = NULL; /* only used if PAT PDC */
struct vector_info *vi;
int isi_line; /* line used by device */
if (!isi) {
printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
pci_name(pcidev));
return -1;
}
#ifdef CONFIG_SUPERIO
/*
* HACK ALERT! (non-compliant PCI device support)
*
* All SuckyIO interrupts are routed through the PIC's on function 1.
* But SuckyIO OHCI USB controller gets an IRT entry anyway because
* it advertises INT D for INT_PIN. Use that IRT entry to get the
* SuckyIO interrupt routing for PICs on function 1 (*BLEECCHH*).
*/
if (is_superio_device(pcidev)) {
/* We must call superio_fixup_irq() to register the pdev */
pcidev->irq = superio_fixup_irq(pcidev);
/* Don't return if need to program the IOSAPIC's IRT... */
if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
return pcidev->irq;
}
#endif /* CONFIG_SUPERIO */
/* lookup IRT entry for isi/slot/pin set */
irte = iosapic_xlate_pin(isi, pcidev);
if (!irte) {
printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
pci_name(pcidev));
return -1;
}
DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
irte,
irte->entry_type,
irte->entry_length,
irte->polarity_trigger,
irte->src_bus_irq_devno,
irte->src_bus_id,
irte->src_seg_id,
irte->dest_iosapic_intin,
(u32) irte->dest_iosapic_addr);
isi_line = irte->dest_iosapic_intin;
/* get vector info for this input line */
vi = isi->isi_vector + isi_line;
DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
/* If this IRQ line has already been setup, skip it */
if (vi->irte)
goto out;
vi->irte = irte;
/*
* Allocate processor IRQ
*
* XXX/FIXME The txn_alloc_irq() code and related code should be
* moved to enable_irq(). That way we only allocate processor IRQ
* bits for devices that actually have drivers claiming them.
* Right now we assign an IRQ to every PCI device present,
* regardless of whether it's used or not.
*/
vi->txn_irq = txn_alloc_irq(8);
if (vi->txn_irq < 0)
panic("I/O sapic: couldn't get TXN IRQ\n");
/* enable_irq() will use txn_* to program IRdT */
vi->txn_addr = txn_alloc_addr(vi->txn_irq);
vi->txn_data = txn_alloc_data(vi->txn_irq);
vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
vi->eoi_data = cpu_to_le32(vi->txn_data);
cpu_claim_irq(vi->txn_irq, &iosapic_interrupt_type, vi);
out:
pcidev->irq = vi->txn_irq;
DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn),
pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
return pcidev->irq;
}