[BACK]Return to kern_irq.c CVS log [TXT][DIR] Up to [local] / funnyos / kern

File: [local] / funnyos / kern / kern_irq.c (download)

Revision 1.2, Sun Nov 4 23:18:46 2007 UTC (16 years, 6 months ago) by init
Branch: MAIN
Changes since 1.1: +3 -1 lines

correctly initialize irqtable in intr_establish

/*
 * $Id: kern_irq.c,v 1.2 2007/11/04 23:18:46 init Exp $
 */
#include <sys/types.h>
#include <sys/device.h>
#include <sys/mem.h>

#include <sys/kern_irq.h>
#include <libkern/printf.h>

/*
 * System interrupt vectors to be used by (some) interrupt controller unit.
 */

struct intr_vector *irqtable = NULL;


void
intr_establish(uint8_t intrno, struct device *device, void (*intrfunc)(struct device *))
{
	/*
	 * Add interrupt vector to irqtable.
	 */
	struct intr_vector *ivp;

	ivp = irqtable;

	if (ivp == NULL) {
		/* first element in list */

		/* allocate space for this (first) vector */
		ivp = kmalloc(sizeof(struct intr_vector));

		if (ivp == NULL)
			panic("failed to allocate initial space for interrupt table\n");

		ivp->iv_intrno = intrno;
		ivp->iv_device = device;
		ivp->iv_intrfunc = intrfunc;
		ivp->iv_next = NULL;

		irqtable = ivp;
	}
	else {
		/* walk through the list */
		do {
			/* check if this interrupt line already binded */
			if (ivp->iv_intrno == intrno)
				panic("failed to establish interrupt (intrno %d already set by other device)\n", intrno);

			/* become next element */
			ivp = ivp->iv_next;
		} while(ivp != NULL);

		/* allocate space */
		ivp = kmalloc(sizeof(struct intr_vector));

		if (ivp == NULL)
			panic("failed to allocate space for interrupt vector\n");

		ivp->iv_intrno = intrno;
		ivp->iv_device = device;
		ivp->iv_intrfunc = intrfunc;
		ivp->iv_next = NULL;
	}

}


void
intr_disestablish(uint8_t intrno)
{
	/*
	 * Delete interrupt vector from vectors irqtable.
	 */
	/* TODO when kfree() will be implemented */
}


void
intr_execute(uint8_t intrno)
{
	/*
	 * Find intrno in irqtable and call interrupt handler of driver associated with this line.
	 * Pass struct device * into that handler to disguise between driver instances.
	 */
	struct intr_vector *ivp;

	ivp = irqtable;

	if (ivp == NULL)
		/* none vectors are configured yet */
		panic("failed to execute intr handler (irqtable is not configured yet)\n");

	/* look for our handler */
	while(ivp != NULL) {
		if (ivp->iv_intrno == intrno) {
			/* jump off */
			ivp->iv_intrfunc(ivp->iv_device);
			return;
		}

		ivp = ivp->iv_next;
	}
	/*
	 * Search stopped on NULL.
	 */
	/* XXX really panic here? */
	panic("failed to execute intr handler for intr %d (irqtable record not found)\n", intrno);

}