Included NewOS change 1642 (argument checking)

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1182 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-09-26 01:01:54 +00:00
parent 5f20abf004
commit 71c882e5f5
+110 -96
View File
@@ -1,186 +1,200 @@
/* /*
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. ** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
*/ */
#include <kernel.h> #include <kernel.h>
#include <int.h> #include <int.h>
#include <debug.h> #include <debug.h>
#include <memheap.h> #include <memheap.h>
#include <smp.h> #include <smp.h>
#include <arch/int.h> #include <arch/int.h>
#include <errno.h> #include <errno.h>
#include <stage2.h> #include <stage2.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#define NUM_IO_VECTORS 256 #define NUM_IO_VECTORS 256
struct io_handler { struct io_handler {
struct io_handler *next; struct io_handler *next;
struct io_handler *prev; struct io_handler *prev;
interrupt_handler func; interrupt_handler func;
void* data; void *data;
}; };
struct io_vector { struct io_vector {
struct io_handler handler_list; struct io_handler handler_list;
spinlock_t vector_lock; spinlock_t vector_lock;
}; };
static struct io_vector *io_vectors = NULL; static struct io_vector *io_vectors = NULL;
int
int_init(kernel_args *ka)
{
dprintf("init_int_handlers: entry\n");
return arch_int_init(ka); int
} int_init(kernel_args *ka)
{
dprintf("init_int_handlers: entry\n");
return arch_int_init(ka);
}
int int
int_init2(kernel_args *ka) int_init2(kernel_args *ka)
{ {
io_vectors = (struct io_vector *)kmalloc(sizeof(struct io_vector) * NUM_IO_VECTORS); io_vectors = (struct io_vector *)kmalloc(sizeof(struct io_vector) * NUM_IO_VECTORS);
if (io_vectors == NULL) if (io_vectors == NULL)
panic("int_init2: could not create io vector table!\n"); panic("int_init2: could not create io vector table!\n");
memset(io_vectors, 0, sizeof(struct io_vector) * NUM_IO_VECTORS); memset(io_vectors, 0, sizeof(struct io_vector) * NUM_IO_VECTORS);
return arch_int_init2(ka); return arch_int_init2(ka);
} }
/* install_interrupt_handler
* This function is used internally to install a handler on the given vector. /** This function is used internally to install a handler on the given vector.
* NB this does NOT take an IRQ, but a system interrupt value. * NB this does NOT take an IRQ, but a system interrupt value.
* As this is intended for system use this function doe NOT call * As this is intended for system use this function does NOT call
* arch_int_enable_io_interrupt() as it only works for IRQ values * arch_int_enable_io_interrupt() as it only works for IRQ values
*/ */
long install_interrupt_handler(long vector, interrupt_handler handler,
void* data) long
install_interrupt_handler(long vector, interrupt_handler handler, void *data)
{ {
struct io_handler *io = NULL; struct io_handler *io = NULL;
int state; int state;
if (vector < 0 || vector >= NUM_IO_VECTORS)
return B_BAD_VALUE;
/* find the chain of handlers for this irq. /* find the chain of handlers for this irq.
* NB there can be multiple handlers for the same IRQ, especially for * NB there can be multiple handlers for the same IRQ, especially for
* PCI drivers. Where we have multiple handlers we will call each in turn * PCI drivers. Where we have multiple handlers we will call each in turn
* until one returns a value other than B_UNHANDLED_INTERRUPT. * until one returns a value other than B_UNHANDLED_INTERRUPT.
*/ */
io = (struct io_handler *)kmalloc(sizeof(struct io_handler)); io = (struct io_handler *)kmalloc(sizeof(struct io_handler));
if (io == NULL) if (io == NULL)
return ENOMEM; return ENOMEM;
io->func = handler; io->func = handler;
io->data = data; io->data = data;
/* Make sure our list is init'd or bad things will happen */ /* Make sure our list is init'd or bad things will happen */
if (io_vectors[vector].handler_list.next == NULL) { if (io_vectors[vector].handler_list.next == NULL) {
io_vectors[vector].handler_list.next = &io_vectors[vector].handler_list; io_vectors[vector].handler_list.next = &io_vectors[vector].handler_list;
io_vectors[vector].handler_list.prev = &io_vectors[vector].handler_list; io_vectors[vector].handler_list.prev = &io_vectors[vector].handler_list;
} }
/* Disable the interrupts, get the spinlock for this irq only /* Disable the interrupts, get the spinlock for this irq only
* and then insert the handler */ * and then insert the handler */
state = disable_interrupts(); state = disable_interrupts();
acquire_spinlock(&io_vectors[vector].vector_lock); acquire_spinlock(&io_vectors[vector].vector_lock);
insque(io, &io_vectors[vector].handler_list); insque(io, &io_vectors[vector].handler_list);
release_spinlock(&io_vectors[vector].vector_lock);
restore_interrupts(state); release_spinlock(&io_vectors[vector].vector_lock);
restore_interrupts(state);
return 0; return 0;
} }
/* install_io_interrupt_handler
* install a handler to be called when an interrupt is triggered /** install a handler to be called when an interrupt is triggered
* for the given irq with data as the argument * for the given irq with data as the argument
*/ */
long install_io_interrupt_handler(long irq, interrupt_handler handler,
void* data, ulong flags) long
{ install_io_interrupt_handler(long irq, interrupt_handler handler, void *data, ulong flags)
{
long vector = irq + 0x20; long vector = irq + 0x20;
long rv = install_interrupt_handler(vector, handler, data); long rv = install_interrupt_handler(vector, handler, data);
if (rv != 0) if (rv != 0)
return rv; return rv;
/* If we were passed the bit-flag B_NO_ENABLE_COUNTER then /* If we were passed the bit-flag B_NO_ENABLE_COUNTER then
* we're being asked to not alter whether the interrupt is set * we're being asked to not alter whether the interrupt is set
* regardless of setting. * regardless of setting.
*/ */
if ((flags & B_NO_ENABLE_COUNTER) == 0) if ((flags & B_NO_ENABLE_COUNTER) == 0)
arch_int_enable_io_interrupt(irq); arch_int_enable_io_interrupt(irq);
return 0; return 0;
} }
/* remove_interrupt_handler
* read notes for install_interrupt_handler /** read notes for install_interrupt_handler */
*/
long remove_interrupt_handler(long vector, interrupt_handler handler, long
void* data) remove_interrupt_handler(long vector, interrupt_handler handler, void *data)
{ {
struct io_handler *io = NULL; struct io_handler *io = NULL;
long rv = EINVAL; long rv = EINVAL;
int state;
if (vector < 0 || vector >= NUM_IO_VECTORS)
return B_BAD_VALUE;
/* lock the structures down so it is not modified while we search */ /* lock the structures down so it is not modified while we search */
int state = disable_interrupts(); state = disable_interrupts();
acquire_spinlock(&io_vectors[vector].vector_lock); acquire_spinlock(&io_vectors[vector].vector_lock);
/* loop through the available handlers and try to find a match. /* loop through the available handlers and try to find a match.
* We go forward through the list but this means we start with the * We go forward through the list but this means we start with the
* most recently added handlers. * most recently added handlers.
*/ */
for (io = io_vectors[vector].handler_list.next; for (io = io_vectors[vector].handler_list.next;
io != &io_vectors[vector].handler_list; io != &io_vectors[vector].handler_list;
io = io->next) { io = io->next) {
/* we have to match both function and data */ /* we have to match both function and data */
if (io->func == handler && io->data == data) { if (io->func == handler && io->data == data) {
remque(io); remque(io);
kfree(io); kfree(io);
rv = 0; rv = 0;
break; break;
} }
} }
/* to finish we need to release our locks and return /* to finish we need to release our locks and return
* the value rv * the value rv
*/ */
release_spinlock(&io_vectors[vector].vector_lock); release_spinlock(&io_vectors[vector].vector_lock);
restore_interrupts(state); restore_interrupts(state);
return rv; return rv;
} }
/* remove_io_interrupt_handler
* remove an interrupt handler previously inserted /** remove an interrupt handler previously inserted */
*/
long remove_io_interrupt_handler(long irq, interrupt_handler handler, long
void* data) remove_io_interrupt_handler(long irq, interrupt_handler handler, void *data)
{ {
long vector = irq + 0x20; long vector = irq + 0x20;
long rv = remove_interrupt_handler(vector, handler, data); long rv = remove_interrupt_handler(vector, handler, data);
if (rv < 0) if (rv < 0)
return rv; return rv;
/* Check if we need to disable interrupts... */ /* Check if we need to disable interrupts... */
if (io_vectors[vector].handler_list.next != &io_vectors[vector].handler_list) if (io_vectors[vector].handler_list.next != &io_vectors[vector].handler_list)
arch_int_disable_io_interrupt(irq); arch_int_disable_io_interrupt(irq);
return 0; return 0;
} }
/* int_io_interrupt_handler
* actually process an interrupt via the handlers registered for that /** actually process an interrupt via the handlers registered for that
* vector (irq) * vector (irq)
*/ */
int int_io_interrupt_handler(int vector)
int
int_io_interrupt_handler(int vector)
{ {
int ret = B_UNHANDLED_INTERRUPT; int ret = B_UNHANDLED_INTERRUPT;
acquire_spinlock(&io_vectors[vector].vector_lock); acquire_spinlock(&io_vectors[vector].vector_lock);
if (io_vectors[vector].handler_list.next == &io_vectors[vector].handler_list) { if (io_vectors[vector].handler_list.next == &io_vectors[vector].handler_list) {
dprintf("unhandled io interrupt %d\n", vector); dprintf("unhandled io interrupt %d\n", vector);
} else { } else {