[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.3, Sun Dec 16 23:24:59 2007 UTC (16 years, 3 months ago) by nbrk
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +10 -6 lines

fix linked list logic (irqtable) to correct link more than one element.

/*
 * $Id: kern_irq.c,v 1.3 2007/12/16 23:24:59 nbrk 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, *previvp;

	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 */
		while(ivp->iv_next != NULL) {
			if (ivp->iv_intrno == intrno)
				panic("failed to establish interrupt (intrno %d already set by other device)\n", intrno);

			ivp = ivp->iv_next;
		}
		/* found last entry */
		previvp = ivp;
		ivp = ivp->iv_next;

		/* 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;

		/* link previous entry */
		previvp->iv_next = ivp;
	}

}


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);

}