-
-static irqreturn_t
-iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct vector_info *vi = (struct vector_info *)dev_id;
- extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
- int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline;
-
- DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
- irq, vi->irqline, vi->eoi_addr);
-
-/* FIXME: Need to mask/unmask? processor IRQ is already masked... */
- do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs);
-
- /*
- ** PCI only supports level triggered in order to share IRQ lines.
- ** I/O SAPIC must always issue EOI.
- */
- IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
-
- return IRQ_HANDLED;
-}
-
-
-int
-iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
-{
- struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
- struct irt_entry *irte = NULL; /* only used if PAT PDC */
- struct vector_info *vi;
- int isi_line; /* line used by device */
- int tmp;
-
- if (NULL == 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 (NULL == 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;
- pcidev->irq = isi->isi_region->data.irqbase + isi_line;
-
- /* get vector info for this input line */
- ASSERT(NULL != isi->isi_vector);
- 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)
- return pcidev->irq;
-
- vi->irte = irte;
-
- /* Allocate processor IRQ */
- vi->txn_irq = txn_alloc_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.
-*/
- 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, 8);
- ASSERT(vi->txn_data < 256); /* matches 8 above */
-
- tmp = request_irq(vi->txn_irq, iosapic_interrupt, 0,
- vi->name, vi);
- ASSERT(tmp == 0);
-
- vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
- vi->eoi_data = cpu_to_le32(vi->irqline);
-
- ASSERT(NULL != isi->isi_region);
-
- DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
- PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->irq),
- pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
-
- return pcidev->irq;
-}
-
-
-static void
-iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)