diff --git a/kernel/i8259.c b/kernel/i8259.c index 51bada0ae..9a82d55db 100755 --- a/kernel/i8259.c +++ b/kernel/i8259.c @@ -1,5 +1,6 @@ /* This file contains routines for initializing the 8259 interrupt controller: * put_irq_handler: register an interrupt handler + * rm_irq_handler: deregister an interrupt handler * intr_handle: handle a hardware interrupt * intr_init: initialize the interrupt controller(s) */ @@ -94,7 +95,7 @@ irq_handler_t handler; int id; irq_hook_t **line; - if ((unsigned) irq >= NR_IRQ_VECTORS) + if (irq < 0 || irq >= NR_IRQ_VECTORS) panic("invalid call to put_irq_handler", irq); line = &irq_handlers[irq]; @@ -115,6 +116,34 @@ irq_handler_t handler; irq_use |= 1 << irq; } +/*=========================================================================* + * rm_irq_handler * + *=========================================================================*/ +PUBLIC int rm_irq_handler(irq, id) +int irq; +int id; +{ +/* Unregister an interrupt handler. */ + irq_hook_t **line; + + if (irq < 0 || irq >= NR_IRQ_VECTORS) { + return EINVAL; + } + + line = &irq_handlers[irq]; + while (*line != NULL) { + if((*line)->id == id) { + (*line) = (*line)->next; + if(!irq_handlers[irq]) + irq_use &= ~(1 << irq); + return OK; + } + line = &(*line)->next; + } + + return ENOENT; +} + /*==========================================================================* * intr_handle * *==========================================================================*/ diff --git a/kernel/main.c b/kernel/main.c index 08ea09a35..1b956b3d0 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -29,7 +29,7 @@ /* Prototype declarations for PRIVATE functions. */ FORWARD _PROTOTYPE( void announce, (void)); -FORWARD _PROTOTYPE( void shutdown, (struct timer *tp)); +FORWARD _PROTOTYPE( void shutdown, (int how)); #define STOP_TICKS (5*HZ) /* time allowed to stop */ @@ -243,7 +243,7 @@ int how; /* 0 = halt, 1 = reboot, 2 = panic!, ... */ tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */ if (skip_stop_sequence) { /* set in exception() */ kprintf("\nAn exception occured; skipping stop sequence.\n", NO_ARG); - shutdown(&shutdown_timer); /* TTY isn't scheduled */ + shutdown(how); /* TTY isn't scheduled */ } else { kprintf("\nNotifying system services about MINIX shutdown.\n", NO_ARG); kprintf("Known bug: hitting a key before done will hang the monitor.\n", NO_ARG); @@ -268,7 +268,7 @@ timer_t *tp; static struct proc *p = NIL_PROC; /* next process to stop */ static char *types[] = {"task","system","driver","server","user"}; - /* See if the last process' shutdown was successfull. Else, force exit. */ + /* See if the last process' shutdown was successful. Else, force exit. */ if (p != NIL_PROC) { kprintf("[%s]\n", isalivep(p) ? karg("FAILED") : karg("OK")); if (isalivep(p)) @@ -285,6 +285,7 @@ timer_t *tp; if (p == NIL_PROC) p = BEG_PROC_ADDR; while (TRUE) { if (isalivep(p) && p->p_type == level) { /* found a process */ + int w; kprintf("- Stopping %s ", karg(p->p_name)); kprintf("%s ... ", karg(types[p->p_type])); shutdown_process = p; /* directly continue if exited */ @@ -297,8 +298,9 @@ timer_t *tp; p = BEG_PROC_ADDR; level = level - 1; if (level == P_TASK) { /* done; tasks must remain alive */ - set_timer(tp, get_uptime()+HZ, shutdown); /* shutdown MINIX */ - return; /* user can inspect output */ + shutdown(tmr_arg(tp)->ta_int); + /* no return */ + return; } } } @@ -307,15 +309,13 @@ timer_t *tp; /*==========================================================================* * shutdown * *==========================================================================*/ -PRIVATE void shutdown(tp) -timer_t *tp; +PRIVATE void shutdown(int how) { /* This function is called from prepare_shutdown or stop_sequence to bring * down MINIX. How to shutdown is in the argument: RBT_REBOOT, RBT_HALT, * RBT_RESET. */ static u16_t magic = STOP_MEM_CHECK; - int how = tmr_arg(tp)->ta_int; /* Now mask all interrupts, including the clock, and stop the clock. */ outb(INT_CTLMASK, ~0); diff --git a/kernel/proto.h b/kernel/proto.h index ceb6b6a20..a36489720 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -37,7 +37,7 @@ _PROTOTYPE( void kprintf, (const char *fmt, karg_t arg) ); /* main.c */ _PROTOTYPE( void main, (void) ); -_PROTOTYPE( void prepare_shutdown, (int how) ); +_PROTOTYPE( void prepare_shutdown, (int) ); _PROTOTYPE( void stop_sequence, (struct timer *tp) ); /* misc.c */ @@ -83,6 +83,7 @@ _PROTOTYPE( void intr_init, (int mine) ); _PROTOTYPE( void intr_handle, (irq_hook_t *hook) ); _PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq, irq_handler_t handler) ); +_PROTOTYPE( int rm_irq_handler, (int irq, int id) ); /* klib*.s */ _PROTOTYPE( void int86, (void) ); _PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset, diff --git a/kernel/system.c b/kernel/system.c index 58b293b1d..6a43bbf26 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -236,7 +236,7 @@ int proc_nr; /* slot of process to clean up */ PUBLIC int generic_handler(hook) irq_hook_t *hook; { -/* This function handles hardware interrupt in a simpel and generic way. All +/* This function handles hardware interrupt in a simple and generic way. All * interrupts are transformed into messages to a driver. The IRQ line will be * reenabled if the policy says so. */ diff --git a/kernel/system/irqctl.c b/kernel/system/irqctl.c index 81261363b..3cf2edb14 100644 --- a/kernel/system/irqctl.c +++ b/kernel/system/irqctl.c @@ -24,15 +24,18 @@ register message *m_ptr; /* pointer to request message */ int irq_vec; int irq_hook_id; int proc_nr; + int r = OK; irq_hook_t *hook_ptr; + irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID; + irq_vec = (unsigned) m_ptr->IRQ_VECTOR; + /* See what is requested and take needed actions. */ switch(m_ptr->IRQ_REQUEST) { /* Enable or disable IRQs. This is straightforward. */ case IRQ_ENABLE: case IRQ_DISABLE: - irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID; if (irq_hook_id >= NR_IRQ_HOOKS) return(EINVAL); if (irq_hooks[irq_hook_id].proc_nr != m_ptr->m_source) return(EPERM); if (m_ptr->IRQ_REQUEST == IRQ_ENABLE) @@ -48,8 +51,7 @@ register message *m_ptr; /* pointer to request message */ case IRQ_SETPOLICY: /* Check if IRQ line is acceptable. */ - irq_vec = (unsigned) m_ptr->IRQ_VECTOR; - if ((unsigned) irq_vec >= NR_IRQ_VECTORS) { + if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) { kprintf("ST: irq line %d is not acceptable!\n", irq_vec); return(EINVAL); } @@ -73,9 +75,22 @@ register message *m_ptr; /* pointer to request message */ m_ptr->IRQ_HOOK_ID = irq_hook_id; break; + case IRQ_RMPOLICY: + if(irq_hook_id < 0 || irq_hook_id >= NR_IRQ_HOOKS || + irq_hooks[irq_hook_id].proc_nr == NONE) { + r = EINVAL; + } else { + if(m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) { + r = EPERM; + } else { + r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id); + } + } + break; + default: - return(EINVAL); /* invalid IRQ_REQUEST */ + r = EINVAL; /* invalid IRQ_REQUEST */ } - return(OK); + return(r); }