/* * Deregister an interrupt handler. */ void sa11x0_intr_disestablish(sa11x0_chipset_tag_t ic, void *arg) { struct irqhandler *ih = arg; int irq = ih->ih_irq; int saved_cpsr; struct irqhandler **p, *q; #if DIAGNOSTIC if (irq < 0 || irq >= ICU_LEN) panic("intr_disestablish: bogus irq"); #endif /* * Remove the handler from the chain. * This is O(n^2), too. */ for (p = &irqhandlers[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next) ; if (q) *p = q->ih_next; else panic("intr_disestablish: handler not registered"); free(ih, M_DEVBUF); intr_calculatemasks(); saved_cpsr = SetCPSR(I32_bit, I32_bit); set_spl_masks(); irq_setmasks(); SetCPSR(I32_bit, saved_cpsr & I32_bit); }
/* * isa_intr_init() * * Initialise the ISA ICU and attach an ISA interrupt handler to the * ISA interrupt line on the footbridge. */ void isa_intr_init(void) { struct intrq *iq; int i; /* * should get the parent here, but initialisation order being so * strange I need to check if it's available */ for (i = 0; i < ICU_LEN; i++) { iq = &isa_intrq[i]; TAILQ_INIT(&iq->iq_list); snprintf(iq->iq_name, sizeof(iq->iq_name), "irq %d", i); evcnt_attach_dynamic(&iq->iq_ev, EVCNT_TYPE_INTR, NULL, "isa", iq->iq_name); } isa_icu_init(); intr_calculatemasks(); /* something to break the build in an informative way */ #ifndef ISA_FOOTBRIDGE_IRQ #warning Before using isa with footbridge you must define ISA_FOOTBRIDGE_IRQ #endif footbridge_intr_claim(ISA_FOOTBRIDGE_IRQ, IPL_BIO, "isabus", isa_irqdispatch, NULL); }
void * sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg) { int saved_cpsr; struct irqhandler **p, *q, *ih; static struct irqhandler fakehand = {fakeintr}; /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) panic("sa11x0_intr_establish: can't malloc handler info"); if (irq < 0 || irq >= ICU_LEN || type == IST_NONE) panic("intr_establish: bogus irq or type"); /* All interrupts are level intrs. */ /* * Figure out where to put the handler. * This is O(N^2), but we want to preserve the order, and N is * generally small. */ for (p = &irqhandlers[irq]; (q = *p) != NULL; p = &q->ih_next) ; /* * Actually install a fake handler momentarily, since we might be doing * this with interrupts enabled and don't want the real routine called * until masking is set up. */ fakehand.ih_level = level; *p = &fakehand; intr_calculatemasks(); /* * Poke the real handler in now. */ ih->ih_func = ih_fun; ih->ih_arg = ih_arg; ih->ih_count = 0; ih->ih_next = NULL; ih->ih_level = level; ih->ih_irq = irq; ih->ih_name = NULL; /* XXX */ *p = ih; saved_cpsr = SetCPSR(I32_bit, I32_bit); set_spl_masks(); irq_setmasks(); SetCPSR(I32_bit, saved_cpsr & I32_bit); #ifdef DEBUG dumpirqhandlers(); #endif return (ih); }
/* * Deregister an interrupt handler. */ void intr_disestablish(void *arg) { struct intrhand * const ih = arg; const int virq = ih->ih_virq; struct intr_source * const is = &intrsources[virq]; struct intrhand **p, **q; int maxipl = IPL_NONE; if (!PIC_VIRQ_LEGAL_P(virq)) panic("intr_disestablish: bogus virq %d", virq); /* * Remove the handler from the chain. * This is O(n^2), too. */ for (p = &is->is_hand, q = NULL; (*p) != NULL; p = &(*p)->ih_next) { struct intrhand * const tmp_ih = *p; if (tmp_ih == ih) { q = p; } else { maxipl = max(maxipl, tmp_ih->ih_ipl); } } if (q) *q = ih->ih_next; else panic("intr_disestablish: handler not registered"); kmem_intr_free((void *)ih, sizeof(*ih)); /* * Reset the IPL for this source now that we've removed a handler. */ is->is_ipl = maxipl; intr_calculatemasks(); if (is->is_hand == NULL) { is->is_type = IST_NONE; evcnt_detach(&is->is_ev); /* * Make the virutal IRQ available again. */ virq_map[virq] = 0; virq_mask |= PIC_VIRQ_TO_MASK(virq); } }
/* * Called from boot code to establish ppp interfaces. */ void pppattach() { register struct ppp_softc *sc; register int i = 0; for (sc = ppp_softc; i < NPPP; sc++) { sc->sc_if.if_name = "ppp"; sc->sc_if.if_unit = i++; sc->sc_if.if_mtu = PPP_MTU; sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; sc->sc_if.if_type = IFT_PPP; sc->sc_if.if_hdrlen = PPP_HDRLEN; sc->sc_if.if_ioctl = pppsioctl; sc->sc_if.if_output = pppoutput; sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; sc->sc_inq.ifq_maxlen = IFQ_MAXLEN; sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN; sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN; if_attach(&sc->sc_if); #if NBPFILTER > 0 bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN); #endif } #if NetBSD1_0 && defined(i386) /* * XXX kludge to fix the bug in the i386 interrupt handling code, * where software interrupts could be taken while hardware * interrupts were blocked. */ if ((imask[IPL_TTY] & (1 << SIR_NET)) == 0) { imask[IPL_TTY] |= (1 << SIR_NET); intr_calculatemasks(); } #endif }
/* * Deregister an interrupt handler. */ void isa_intr_disestablish(isa_chipset_tag_t ic, void *arg) { struct intrhand *ih = arg; struct intrq *iq = &isa_intrq[ih->ih_irq]; int irq = ih->ih_irq; u_int oldirqstate; if (!LEGAL_IRQ(irq)) panic("intr_disestablish: bogus irq"); oldirqstate = disable_interrupts(I32_bit); TAILQ_REMOVE(&iq->iq_list, ih, ih_list); intr_calculatemasks(); restore_interrupts(oldirqstate); free(ih, M_DEVBUF); if (TAILQ_EMPTY(&(iq->iq_list))) iq->iq_ist = IST_NONE; }
void * intr_establish_xname(int hwirq, int type, int ipl, int (*ih_fun)(void *), void *ih_arg, const char *xname) { struct intrhand **p, *q, *ih; struct pic_ops *pic; static struct intrhand fakehand; int maxipl = ipl; if (maxipl == IPL_NONE) maxipl = IPL_HIGH; if (hwirq >= max_base) { panic("%s: bogus IRQ %d, max is %d", __func__, hwirq, max_base - 1); } pic = find_pic_by_hwirq(hwirq); if (pic == NULL) { panic("%s: cannot find a pic for IRQ %d", __func__, hwirq); } const int virq = mapirq(hwirq); /* no point in sleeping unless someone can free memory. */ ih = kmem_intr_alloc(sizeof(*ih), cold ? KM_NOSLEEP : KM_SLEEP); if (ih == NULL) panic("intr_establish: can't allocate handler info"); if (!PIC_VIRQ_LEGAL_P(virq) || type == IST_NONE) panic("intr_establish: bogus irq (%d) or type (%d)", hwirq, type); struct intr_source * const is = &intrsources[virq]; switch (is->is_type) { case IST_NONE: is->is_type = type; break; case IST_EDGE_FALLING: case IST_EDGE_RISING: case IST_LEVEL_LOW: case IST_LEVEL_HIGH: if (type == is->is_type) break; /* FALLTHROUGH */ case IST_PULSE: if (type != IST_NONE) panic("intr_establish: can't share %s with %s", intr_typename(is->is_type), intr_typename(type)); break; } if (is->is_hand == NULL) { snprintf(is->is_source, sizeof(is->is_source), "irq %d", is->is_hwirq); evcnt_attach_dynamic(&is->is_ev, EVCNT_TYPE_INTR, NULL, pic->pic_name, is->is_source); } /* * Figure out where to put the handler. * This is O(N^2), but we want to preserve the order, and N is * generally small. */ for (p = &is->is_hand; (q = *p) != NULL; p = &q->ih_next) { maxipl = max(maxipl, q->ih_ipl); } /* * Actually install a fake handler momentarily, since we might be doing * this with interrupts enabled and don't want the real routine called * until masking is set up. */ fakehand.ih_ipl = ipl; fakehand.ih_fun = fakeintr; *p = &fakehand; /* * Poke the real handler in now. */ ih->ih_fun = ih_fun; ih->ih_arg = ih_arg; ih->ih_next = NULL; ih->ih_ipl = ipl; ih->ih_virq = virq; strlcpy(ih->ih_xname, xname != NULL ? xname : "unknown", sizeof(ih->ih_xname)); *p = ih; if (pic->pic_establish_irq != NULL) pic->pic_establish_irq(pic, hwirq - pic->pic_intrbase, is->is_type, maxipl); /* * Remember the highest IPL used by this handler. */ is->is_ipl = maxipl; /* * now that the handler is established we're actually ready to * calculate the masks */ intr_calculatemasks(); return ih; }
/* * Set up an interrupt handler to start being called. * XXX PRONE TO RACE CONDITIONS, UGLY, 'INTERESTING' INSERTION ALGORITHM. */ void * isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg) { struct intrq *iq; struct intrhand *ih; u_int oldirqstate; #if 0 printf("isa_intr_establish(%d, %d, %d)\n", irq, type, level); #endif /* no point in sleeping unless someone can free memory. */ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); if (ih == NULL) return (NULL); if (!LEGAL_IRQ(irq) || type == IST_NONE) panic("intr_establish: bogus irq or type"); iq = &isa_intrq[irq]; switch (iq->iq_ist) { case IST_NONE: iq->iq_ist = type; #if 0 printf("Setting irq %d to type %d - ", irq, type); #endif if (irq < 8) { outb(0x4d0, (inb(0x4d0) & ~(1 << irq)) | ((type == IST_LEVEL) ? (1 << irq) : 0)); /* printf("%02x\n", inb(0x4d0));*/ } else { outb(0x4d1, (inb(0x4d1) & ~(1 << irq)) | ((type == IST_LEVEL) ? (1 << irq) : 0)); /* printf("%02x\n", inb(0x4d1));*/ } break; case IST_EDGE: case IST_LEVEL: if (iq->iq_ist == type) break; case IST_PULSE: if (type != IST_NONE) panic("intr_establish: can't share %s with %s", isa_intr_typename(iq->iq_ist), isa_intr_typename(type)); break; } ih->ih_func = ih_fun; ih->ih_arg = ih_arg; ih->ih_ipl = level; ih->ih_irq = irq; /* do not stop us */ oldirqstate = disable_interrupts(I32_bit); TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list); intr_calculatemasks(); restore_interrupts(oldirqstate); return (ih); }