static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) { int irq, bits; for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) { int i = irq >> 5; bits = ld_le32(&pmac_irq_hw[i]->flag) | ppc_lost_interrupts[i]; if (bits == 0) continue; irq -= cntlzw(bits); break; } /* The previous version of this code allowed for this case, we * don't. Put this here to check for it. * -- Cort */ if ( irq_desc[irq].ctl != &gatwick_pic ) printk("gatwick irq not from gatwick pic\n"); else ppc_irq_dispatch_handler( regs, irq ); }
static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm) { int irq; ++Pci_Interrupt_Count; //PPCDBG(PPCDBG_BUSWALK,"PCI: XmPciLpEvent.c: intReceived\n"); switch (eventParm->hvLpEvent.xSubtype) { case XmPciLpEvent_SlotInterrupt: irq = eventParm->hvLpEvent.xCorrelationToken; /* Dispatch the interrupt handlers for this irq */ ppc_irq_dispatch_handler(regsParm, irq); HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, eventParm->eventData.slotInterrupt.subBusNumber, eventParm->eventData.slotInterrupt.deviceId); break; /* Ignore error recovery events for now */ case XmPciLpEvent_BusCreated: printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber); break; case XmPciLpEvent_BusFailed: printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber); break; case XmPciLpEvent_BusRecovered: printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber); break; case XmPciLpEvent_NodeFailed: printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId); break; case XmPciLpEvent_NodeRecovered: printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", eventParm->eventData.nodeRecovered.busNumber, eventParm->eventData.nodeRecovered.subBusNumber, eventParm->eventData.nodeRecovered.deviceId); break; default: printk(KERN_ERR "XmPciLpEvent.c: unrecognized event subtype 0x%x\n", eventParm->hvLpEvent.xSubtype); break; }; }
void pmac_do_IRQ(struct pt_regs *regs, int cpu, int isfake) { int irq; unsigned long bits = 0; #ifdef __SMP__ /* IPI's are a hack on the powersurge -- Cort */ if ( cpu != 0 ) { if (!isfake) { #ifdef CONFIG_XMON static int xmon_2nd; if (xmon_2nd) xmon(regs); #endif pmac_smp_message_recv(); goto out; } /* could be here due to a do_fake_interrupt call but we don't mess with the controller from the second cpu -- Cort */ goto out; } { unsigned int loops = MAXCOUNT; while (test_bit(0, &global_irq_lock)) { if (smp_processor_id() == global_irq_holder) { printk("uh oh, interrupt while we hold global irq lock!\n"); #ifdef CONFIG_XMON xmon(0); #endif break; } if (loops-- == 0) { printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder); #ifdef CONFIG_XMON xmon(0); #endif } } } #endif /* __SMP__ */ /* Yeah, I know, this could be a separate do_IRQ function */ if (has_openpic) { irq = openpic_irq(0); if (irq == OPENPIC_VEC_SPURIOUS) { /* Spurious interrupts should never be ack'ed */ ppc_spurious_interrupts++; } else { /* Can this happen ? (comes from CHRP code) */ if (irq < 0) { printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", irq, regs->nip); ppc_spurious_interrupts++; } else { if (!irq_desc[irq].level) openpic_eoi(0); ppc_irq_dispatch_handler( regs, irq ); if (irq_desc[irq].level) openpic_eoi(0); } } return; } for (irq = max_real_irqs - 1; irq > 0; irq -= 32) { int i = irq >> 5; bits = ld_le32(&pmac_irq_hw[i]->flag) | ppc_lost_interrupts[i]; if (bits == 0) continue; irq -= cntlzw(bits); break; } if (irq < 0) { printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", irq, regs->nip); ppc_spurious_interrupts++; } else { ppc_irq_dispatch_handler( regs, irq ); } #ifdef CONFIG_SMP out: #endif /* CONFIG_SMP */ } /* This routine will fix some missing interrupt values in the device tree * on the gatwick mac-io controller used by some PowerBooks */ static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) { struct device_node *node; int count; memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); node = gw->child; count = 0; while(node) { /* Fix SCC */ if (strcasecmp(node->name, "escc") == 0) if (node->child) { if (node->child->n_intrs < 3) { node->child->intrs = &gatwick_int_pool[count]; count += 3; } node->child->n_intrs = 3; node->child->intrs[0].line = 15+irq_base; node->child->intrs[1].line = 4+irq_base; node->child->intrs[2].line = 5+irq_base; printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", node->child->intrs[0].line, node->child->intrs[1].line, node->child->intrs[2].line); } /* Fix media-bay & left SWIM */ if (strcasecmp(node->name, "media-bay") == 0) { struct device_node* ya_node; if (node->n_intrs == 0) node->intrs = &gatwick_int_pool[count++]; node->n_intrs = 1; node->intrs[0].line = 29+irq_base; printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", node->intrs[0].line); ya_node = node->child; while(ya_node) { if (strcasecmp(ya_node->name, "floppy") == 0) { if (ya_node->n_intrs < 2) { ya_node->intrs = &gatwick_int_pool[count]; count += 2; } ya_node->n_intrs = 2; ya_node->intrs[0].line = 19+irq_base; ya_node->intrs[1].line = 1+irq_base; printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", ya_node->intrs[0].line, ya_node->intrs[1].line); } if (strcasecmp(ya_node->name, "ata4") == 0) { if (ya_node->n_intrs < 2) { ya_node->intrs = &gatwick_int_pool[count]; count += 2; } ya_node->n_intrs = 2; ya_node->intrs[0].line = 14+irq_base; ya_node->intrs[1].line = 3+irq_base; printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", ya_node->intrs[0].line, ya_node->intrs[1].line); } ya_node = ya_node->sibling; } } node = node->sibling; } if (count > 10) { printk("WARNING !! Gatwick interrupt pool overflow\n"); printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); printk(" requested = %d\n", count); } } /* * The PowerBook 3400/2400/3500 can have a combo ethernet/modem * card which includes an ohare chip that acts as a second interrupt * controller. If we find this second ohare, set it up and fix the * interrupt value in the device tree for the ethernet chip. */ static void __init enable_second_ohare(void) { unsigned char bus, devfn; unsigned short cmd; unsigned long addr; int second_irq; struct device_node *irqctrler = find_devices("pci106b,7"); struct device_node *ether; if (irqctrler == NULL || irqctrler->n_addrs <= 0) return; addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); max_irqs = 64; if (pci_device_loc(irqctrler, &bus, &devfn) == 0) { pmac_pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; cmd &= ~PCI_COMMAND_IO; pmac_pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); } second_irq = irqctrler->intrs[0].line; printk(KERN_INFO "irq: secondary controller on irq %d\n", second_irq); request_irq(second_irq, gatwick_action, SA_INTERRUPT, "interrupt cascade", 0 ); /* Fix interrupt for the modem/ethernet combo controller. The number in the device tree (27) is bogus (correct for the ethernet-only board but not the combo ethernet/modem board). The real interrupt is 28 on the second controller -> 28+32 = 60. */ ether = find_devices("pci1011,14"); if (ether && ether->n_intrs > 0) { ether->intrs[0].line = 60; printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", ether->intrs[0].line); } }