void via1_irq(int irq, void *dev_id, struct pt_regs *regs) { int irq_bit, i; unsigned char events, mask; mask = via1[vIER] & 0x7F; if (!(events = via1[vIFR] & mask)) return; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via1[vIER] = irq_bit; mac_do_irq_list(VIA1_SOURCE_BASE + i, regs); via1[vIFR] = irq_bit; via1[vIER] = irq_bit | 0x80; } #if 0 /* freakin' pmu is doing weird stuff */ if (!oss_present) { /* This (still) seems to be necessary to get IDE working. However, if you enable VBL interrupts, you're screwed... */ /* FIXME: should we check the SLOTIRQ bit before pulling this stunt? */ /* No, it won't be set. that's why we're doing this. */ via_irq_disable(IRQ_MAC_NUBUS); via_irq_clear(IRQ_MAC_NUBUS); mac_do_irq_list(IRQ_MAC_NUBUS, regs); via_irq_enable(IRQ_MAC_NUBUS); } #endif }
void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs) { volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2; unsigned char reg; unsigned long flags; /* Read RR3 from the chip. Always do this on channel A */ /* This must be an atomic operation so disable irqs. */ local_irq_save(flags); *scc = 3; reg = *scc; local_irq_restore(flags); /* Now dispatch. Bits 0-2 are for channel B and */ /* bits 3-5 are for channel A. We can safely */ /* ignore the remaining bits here. */ /* */ /* Note that we're ignoring scc_mask for now. */ /* If we actually mask the ints then we tend to */ /* get hammered by very persistent SCC irqs, */ /* and since they're autovector interrupts they */ /* pretty much kill the system. */ if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs); if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs); }
void oss_irq(int irq, void *dev_id, struct pt_regs *regs) { int events; events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI); if (!events) return; #ifdef DEBUG_IRQS if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { printk("oss_irq: irq %d events = 0x%04X\n", irq, (int) oss->irq_pending); } #endif /* FIXME: how do you clear a pending IRQ? */ if (events & OSS_IP_SOUND) { /* FIXME: call sound handler */ oss->irq_pending &= ~OSS_IP_SOUND; } else if (events & OSS_IP_SCSI) { oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED; mac_do_irq_list(IRQ_MAC_SCSI, regs); oss->irq_pending &= ~OSS_IP_SCSI; oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI; } else { /* FIXME: error check here? */ } }
void psc_irq(int irq, void *dev_id, struct pt_regs *regs) { int pIFR = pIFRbase + ((int) dev_id); int pIER = pIERbase + ((int) dev_id); int base_irq; int irq_bit,i; unsigned char events; irq -= VEC_SPUR; base_irq = irq << 3; #ifdef DEBUG_IRQS printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n", irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER)); #endif events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF; if (!events) return; for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) { if (events & irq_bit) { psc_write_byte(pIER, irq_bit); mac_do_irq_list(base_irq + i, regs); psc_write_byte(pIFR, irq_bit); psc_write_byte(pIER, irq_bit | 0x80); } } }
void via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs) { int irq_bit, i; unsigned char events; if (!(events = ~via2[gBufA] & nubus_active)) return; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { if (events & irq_bit) { via_irq_disable(NUBUS_SOURCE_BASE + i); mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs); via_irq_enable(NUBUS_SOURCE_BASE + i); } } }
void via2_irq(int irq, void *dev_id, struct pt_regs *regs) { int irq_bit, i; unsigned char events, mask; mask = via2[gIER] & 0x7F; if (!(events = via2[gIFR] & mask)) return; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via2[gIER] = irq_bit; mac_do_irq_list(VIA2_SOURCE_BASE + i, regs); via2[gIFR] = irq_bit | rbv_clear; via2[gIER] = irq_bit | 0x80; } }
void oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs) { int events, irq_bit, i; events = oss->irq_pending & OSS_IP_NUBUS; if (!events) return; #ifdef DEBUG_NUBUS_INT if (console_loglevel > 7) { printk("oss_nubus_irq: events = 0x%04X\n", events); } #endif /* There are only six slots on the OSS, not seven */ for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) { if (events & irq_bit) { oss->irq_level[i] = OSS_IRQLEV_DISABLED; mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs); oss->irq_pending &= ~irq_bit; oss->irq_level[i] = OSS_IRQLEV_NUBUS; } } }