/* * Recalculate the interrupt masks from scratch. * We could code special registry and deregistry versions of this function that * would be faster, but the code would be nastier, and we don't expect this to * happen very much anyway. */ void intr_calculatemasks(void) { int irq, level; struct intrq *iq; struct intrhand *ih; /* First, figure out which levels each IRQ uses. */ for (irq = 0; irq < ICU_LEN; irq++) { int levels = 0; iq = &isa_intrq[irq]; for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; ih = TAILQ_NEXT(ih, ih_list)) levels |= (1U << ih->ih_ipl); iq->iq_levels = levels; } /* Then figure out which IRQs use each level. */ for (level = 0; level < NIPL; level++) { int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (isa_intrq[irq].iq_levels & (1U << level)) irqs |= (1U << irq); imask[level] = irqs; } imask[IPL_SCHED] |= imask[IPL_VM]; imask[IPL_HIGH] |= imask[IPL_SCHED]; /* And eventually calculate the complete masks. */ for (irq = 0; irq < ICU_LEN; irq++) { int irqs = 1 << irq; iq = &isa_intrq[irq]; for (ih = TAILQ_FIRST(&iq->iq_list); ih != NULL; ih = TAILQ_NEXT(ih, ih_list)) irqs |= imask[ih->ih_ipl]; iq->iq_mask = irqs; } /* Lastly, determine which IRQs are actually in use. */ { int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (!TAILQ_EMPTY(&isa_intrq[irq].iq_list)) irqs |= (1U << irq); if (irqs >= 0x100) /* any IRQs >= 8 in use */ irqs |= 1 << IRQ_SLAVE; imen = ~irqs; SET_ICUS(); } #if 0 printf("type\tmask\tlevel\thand\n"); for (irq = 0; irq < ICU_LEN; irq++) { printf("%x\t%04x\t%x\t%p\n", intrtype[irq], intrmask[irq], intrlevel[irq], intrhand[irq]); } for (level = 0; level < IPL_LEVELS; ++level) printf("%d: %08x\n", level, imask[level]); #endif }
/* * Recalculate the interrupt masks from scratch. * We could code special registry and deregistry versions of this function that * would be faster, but the code would be nastier, and we don't expect this to * happen very much anyway. */ void intr_calculatemasks(void) { int irq, level, unusedirqs; struct intrhand *q; /* First, figure out which levels each IRQ uses. */ unusedirqs = 0xffff; for (irq = 0; irq < ICU_LEN; irq++) { int levels = 0; for (q = intrhand[irq]; q; q = q->ih_next) levels |= 1 << IPL(q->ih_level); intrlevel[irq] = levels; if (levels) unusedirqs &= ~(1 << irq); } /* Then figure out which IRQs use each level. */ for (level = 0; level < NIPL; level++) { int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (intrlevel[irq] & (1 << level)) irqs |= 1 << irq; imask[level] = irqs | unusedirqs; } /* * Initialize soft interrupt masks to block themselves. */ IMASK(IPL_SOFTAST) |= 1 << SIR_AST; IMASK(IPL_SOFTCLOCK) |= 1 << SIR_CLOCK; IMASK(IPL_SOFTNET) |= 1 << SIR_NET; IMASK(IPL_SOFTTTY) |= 1 << SIR_TTY; /* * Enforce a hierarchy that gives slow devices a better chance at not * dropping data. */ for (level = 0; level < NIPL - 1; level++) imask[level + 1] |= imask[level]; /* And eventually calculate the complete masks. */ for (irq = 0; irq < ICU_LEN; irq++) { int irqs = 1 << irq; int minlevel = IPL_NONE; int maxlevel = IPL_NONE; if (intrhand[irq] == NULL) { maxlevel = IPL_HIGH; irqs = IMASK(IPL_HIGH); } else { for (q = intrhand[irq]; q; q = q->ih_next) { irqs |= IMASK(q->ih_level); if (minlevel == IPL_NONE || q->ih_level < minlevel) minlevel = q->ih_level; if (q->ih_level > maxlevel) maxlevel = q->ih_level; } } if (irqs != IMASK(maxlevel)) panic("irq %d level %x mask mismatch: %x vs %x", irq, maxlevel, irqs, IMASK(maxlevel)); intrmask[irq] = irqs; iminlevel[irq] = minlevel; imaxlevel[irq] = maxlevel; #if 0 printf("irq %d: level %x, mask 0x%x (%x)\n", irq, imaxlevel[irq], intrmask[irq], IMASK(imaxlevel[irq])); #endif } /* Lastly, determine which IRQs are actually in use. */ { int irqs = 0; for (irq = 0; irq < ICU_LEN; irq++) if (intrhand[irq]) irqs |= 1 << irq; if (irqs >= 0x100) /* any IRQs >= 8 in use */ irqs |= 1 << IRQ_SLAVE; imen = ~irqs; SET_ICUS(); } /* For speed of splx, provide the inverse of the interrupt masks. */ for (irq = 0; irq < ICU_LEN; irq++) iunmask[irq] = ~imask[irq]; }