]> Zhao Yanbai Git Server - minix.git/commitdiff
. added rm_irq_handler which un-links an irq handler from the linked
authorBen Gras <ben@minix3.org>
Thu, 12 May 2005 16:06:37 +0000 (16:06 +0000)
committerBen Gras <ben@minix3.org>
Thu, 12 May 2005 16:06:37 +0000 (16:06 +0000)
   list of handlers, callable by irqctl system call
 . workaround for hanging keyboard bug after shutdown.. if key is pressed
   during or after shutdown procedure, keyboard stops working. It looks like
   irq 1 gets stuck high if no keyboard reading is done (e.g. because the
   irq is masked or tty driver has exited). Workaround is to leave irqs
   enabled until the last second, and call shutdown() immediately after the
   last driver has stopped (tty task). This way the chance of an unserviced
   interrupt occuring is negligible.

kernel/i8259.c
kernel/main.c
kernel/proto.h
kernel/system.c
kernel/system/irqctl.c

index 51bada0ae719d3afe96fcb8432a79bedc94b561a..9a82d55dbb843197e9d2f61be749d89ef24ad095 100755 (executable)
@@ -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                                 *
  *==========================================================================*/
index 08ea09a358e539b929fad78a0770597ee702279b..1b956b3d0f4f33c8098dcace5e064c31889a4004 100755 (executable)
@@ -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); 
index ceb6b6a20f9fb67844e339f338a40929137c60d0..a364897203512b12156afeb81b377c2ee528e113 100755 (executable)
@@ -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,
index 58b293b1d153a41f0c16d512c890b63a24f6a3e5..6a43bbf26ef2c807495f3e32eb5c68f46b8cef92 100755 (executable)
@@ -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.
  */
index 81261363bbc1ad3ae7edf2cc4818076ed5bace4a..3cf2edb14744320f868d4c56e4633fae161e7ff1 100644 (file)
@@ -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);
 }