/* 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)
*/
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];
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 *
*==========================================================================*/
/* 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 */
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);
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))
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 */
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;
}
}
}
/*==========================================================================*
* 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);
/* 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 */
_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,
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.
*/
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)
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);
}
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);
}