Esempio n. 1
0
/* Deregister an interrupt handler. */
void
isa_intr_disestablish(isa_chipset_tag_t ic, void *arg)
{
	struct intrhand *ih = arg;

	if (!LEGAL_IRQ(ih->ih_pin))
		panic("intr_disestablish: bogus irq");

	intr_disestablish(ih);
}
Esempio n. 2
0
/*
 * Just check to see if an IRQ is available/can be shared.
 * 0 = interrupt not available
 * 1 = interrupt shareable
 * 2 = interrupt all to ourself
 */
int
isa_intr_check(isa_chipset_tag_t ic, int irq, int type)
{
	if (!LEGAL_IRQ(irq) || type == IST_NONE)
		return (0);

	switch (intrtype[irq]) {
	case IST_NONE:
		return (2);
		break;
	case IST_LEVEL:
		if (type != intrtype[irq])
			return (0);
		return (1);
		break;
	case IST_EDGE:
	case IST_PULSE:
		if (type != IST_NONE)
			return (0);
	}
	return (1);
}
/*
 * 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;
}
Esempio n. 4
0
int
isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq)
{
	int i, bestirq, count;
	int tmp;
	struct intrhand **p, *q;

	if (type == IST_NONE)
		panic("intr_alloc: bogus type");

	bestirq = -1;
	count = -1;

	/* some interrupts should never be dynamically allocated */
	mask &= 0xdef8;

	/*
	 * XXX some interrupts will be used later (6 for fdc, 12 for pms).
	 * the right answer is to do "breadth-first" searching of devices.
	 */
	mask &= 0xefbf;

	for (i = 0; i < ICU_LEN; i++) {
		if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
			continue;

		switch(intrtype[i]) {
		case IST_NONE:
			/*
			 * if nothing's using the irq, just return it
			 */
			*irq = i;
			return (0);

		case IST_EDGE:
		case IST_LEVEL:
			if (type != intrtype[i])
				continue;
			/*
			 * if the irq is shareable, count the number of other
			 * handlers, and if it's smaller than the last irq like
			 * this, remember it
			 *
			 * XXX We should probably also consider the
			 * interrupt level and stick IPL_TTY with other
			 * IPL_TTY, etc.
			 */
			for (p = &intrhand[i], tmp = 0; (q = *p) != NULL;
			     p = &q->ih_next, tmp++)
				;
			if ((bestirq == -1) || (count > tmp)) {
				bestirq = i;
				count = tmp;
			}
			break;

		case IST_PULSE:
			/* this just isn't shareable */
			continue;
		}
	}

	if (bestirq == -1)
		return (1);

	*irq = bestirq;

	return (0);
}
/*
 * 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);
}
Esempio n. 6
0
int
isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq)
{
	int i, tmp, bestirq, count;
	struct intrhand **p, *q;
	struct intrsource *isp;
	struct cpu_info *ci;

	if (type == IST_NONE)
		panic("intr_alloc: bogus type");

	ci = &cpu_info_primary;

	bestirq = -1;
	count = -1;

	/* some interrupts should never be dynamically allocated */
	mask &= 0xdef8;

	/*
	 * XXX some interrupts will be used later (6 for fdc, 12 for pms).
	 * the right answer is to do "breadth-first" searching of devices.
	 */
	mask &= 0xefbf;

	mutex_enter(&cpu_lock);

	for (i = 0; i < NUM_LEGACY_IRQS; i++) {
		if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
			continue;
		isp = ci->ci_isources[i];
		if (isp == NULL) {
			/* if nothing's using the irq, just return it */
			*irq = i;
			mutex_exit(&cpu_lock);
			return 0;
		}

		switch(isp->is_type) {
		case IST_EDGE:
		case IST_LEVEL:
			if (type != isp->is_type)
				continue;
			/*
			 * if the irq is shareable, count the number of other
			 * handlers, and if it's smaller than the last irq like
			 * this, remember it
			 *
			 * XXX We should probably also consider the
			 * interrupt level and stick IPL_TTY with other
			 * IPL_TTY, etc.
			 */
			for (p = &isp->is_handlers, tmp = 0; (q = *p) != NULL;
			     p = &q->ih_next, tmp++)
				;
			if ((bestirq == -1) || (count > tmp)) {
				bestirq = i;
				count = tmp;
			}
			break;
		case IST_PULSE:
			/* this just isn't shareable */
			continue;
		}
	}

	mutex_exit(&cpu_lock);

	if (bestirq == -1)
		return 1;

	*irq = bestirq;

	return 0;
}