void amiga_enable_irq(unsigned int irq) { if (irq >= AMI_IRQS) { printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); return; } if (--ami_ablecount[irq]) return; /* No action for auto-vector interrupts */ if (irq >= IRQ_AMIGA_AUTO){ printk("%s: Trying to enable auto-vector IRQ %i\n", __FUNCTION__, irq - IRQ_AMIGA_AUTO); return; } if (irq >= IRQ_AMIGA_CIAB) { cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB))); cia_able_irq(&ciab_base, CIA_ICR_SETCLR | (1 << (irq - IRQ_AMIGA_CIAB))); return; } if (irq >= IRQ_AMIGA_CIAA) { cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA))); cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | (1 << (irq - IRQ_AMIGA_CIAA))); return; } /* enable the interrupt */ custom.intena = IF_SETCLR | ami_intena_vals[irq]; }
void amiga_enable_irq(unsigned int irq) { if (irq >= AMI_IRQS) { printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); return; } ami_ablecount[irq]--; if (ami_ablecount[irq]<0) ami_ablecount[irq]=0; else if (ami_ablecount[irq]) return; /* No action for auto-vector interrupts */ if (irq >= IRQ_AMIGA_AUTO){ printk("%s: Trying to enable auto-vector IRQ %i\n", __FUNCTION__, irq - IRQ_AMIGA_AUTO); return; } if (irq >= IRQ_AMIGA_CIAA) { cia_set_irq(irq, 0); cia_able_irq(irq, 1); return; } /* enable the interrupt */ amiga_custom.intena = IF_SETCLR | ami_intena_vals[irq]; }
/* This is always executed with interrupts disabled. */ static unsigned long amiga_gettimeoffset (void) { unsigned short hi, lo, hi2; unsigned long ticks, offset = 0; /* read CIA B timer A current value */ hi = ciab.tahi; lo = ciab.talo; hi2 = ciab.tahi; if (hi != hi2) { lo = ciab.talo; hi = hi2; } ticks = hi << 8 | lo; if (ticks > jiffy_ticks / 2) /* check for pending interrupt */ if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA) offset = 10000; ticks = jiffy_ticks - ticks; ticks = (10000 * ticks) / jiffy_ticks; return ticks + offset; }
int cia_request_irq(struct ciabase *base, unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { unsigned char mask; base->irq_list[irq].handler = handler; base->irq_list[irq].flags = flags; base->irq_list[irq].dev_id = dev_id; base->irq_list[irq].devname = devname; /* enable the interrupt */ mask = 1 << irq; cia_set_irq(base, mask); cia_able_irq(base, CIA_ICR_SETCLR | mask); return 0; }
void __init cia_init_IRQ(struct ciabase *base) { int i; /* init isr handlers */ for (i = 0; i < CIA_IRQS; i++) { base->irq_list[i].handler = NULL; base->irq_list[i].flags = 0; } /* clear any pending interrupt and turn off all interrupts */ cia_set_irq(base, CIA_ICR_ALL); cia_able_irq(base, CIA_ICR_ALL); /* install CIA handler */ request_irq(base->handler_irq, cia_handler, 0, base->name, base); custom.intena = IF_SETCLR | base->int_mask; }
static void cia_handler(int irq, void *dev_id, struct pt_regs *fp) { struct ciabase *base = (struct ciabase *)dev_id; int mach_irq, i; unsigned char ints; mach_irq = base->cia_irq; irq = SYS_IRQS + mach_irq; ints = cia_set_irq(base, CIA_ICR_ALL); custom.intreq = base->int_mask; for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) { if (ints & 1) { kstat.irqs[0][irq]++; base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp); } ints >>= 1; } amiga_do_irq_list(base->server_irq, fp); }