예제 #1
0
/*
 * 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);
	
}
예제 #3
0
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);
}
예제 #4
0
파일: intr.c 프로젝트: ryo/netbsd-src
/*
 * 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);
	}
}
예제 #5
0
/*
 * 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;
}
예제 #7
0
파일: intr.c 프로젝트: ryo/netbsd-src
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);
}