[BACK]Return to irq.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / kern

Diff for /prex-old/sys/kern/irq.c between version 1.1.1.1 and 1.1.1.1.2.1

version 1.1.1.1, 2008/06/03 10:38:46 version 1.1.1.1.2.1, 2008/08/13 17:12:31
Line 67 
Line 67 
 #include <irq.h>  #include <irq.h>
   
 /* forward declarations */  /* forward declarations */
 static void irq_thread(u_long);  static void     irq_thread(void *);
   
 static struct irq *irq_table[NIRQS];    /* IRQ descriptor table */  static struct irq       *irq_table[NIRQS];      /* IRQ descriptor table */
 static volatile int nr_irq_locks;       /* lock count for interrupt */  static volatile int     nr_irq_locks;           /* lock counter */
 static volatile int saved_irq_state;    /* IRQ state saved by irq_lock() */  static volatile int     saved_irq_state;        /* state saved by irq_lock() */
   
 /*  /*
  * irq_attach - attach ISR and IST to the specified interrupt.   * irq_attach - attach ISR and IST to the specified interrupt.
  * @vector: interrupt vector number  
  * @prio:   interrupt priority level.  
  * @shared: true if it allows the IRQ sharing.  
  * @isr:    pointer to the interrupt service routine.  
  * @ist:    pointer to the interrupt service thread. NULL for no ist.  
  *   *
  * irq_attach() returns irq handle which is needed for irq_detach().   * Returns irq handle, or NULL on failure.  The interrupt of
  * Or, it returns -1 if it failed.   * attached irq will be unmasked (enabled) in this routine.
  * The interrupt of attached irq will be unmasked (enabled) in this  
  * routine.  
  *  
  * TODO: Interrupt sharing is not supported, for now.   * TODO: Interrupt sharing is not supported, for now.
  */   */
 int  irq_t
 irq_attach(int vector, int prio, int shared, int (*isr)(int),  irq_attach(int vector, int prio, int shared, int (*isr)(int), void (*ist)(int))
            void (*ist)(int))  
 {  {
         struct irq *irq;          struct irq *irq;
         thread_t th;  
         int mode;          int mode;
   
         ASSERT(irq_level == 0);          ASSERT(irq_level == 0);
Line 102 
Line 92 
         sched_lock();          sched_lock();
         if ((irq = kmem_alloc(sizeof(struct irq))) == NULL) {          if ((irq = kmem_alloc(sizeof(struct irq))) == NULL) {
                 sched_unlock();                  sched_unlock();
                 return -1;                  return NULL;
         }          }
         memset(irq, 0, sizeof(struct irq));          memset(irq, 0, sizeof(struct irq));
         irq->vector = vector;          irq->vector = vector;
Line 113 
Line 103 
                 /*                  /*
                  * Create a new thread for IST.                   * Create a new thread for IST.
                  */                   */
                 th = kernel_thread(ISTPRIO(prio), irq_thread, (u_long)irq);                  irq->thread = kthread_create(&irq_thread, irq, ISTPRIO(prio));
                 if (th == NULL)                  if (irq->thread == NULL) {
                         panic("irq_attach");                          kmem_free(irq);
                 irq->thread = th;                          sched_unlock();
                 event_init(&irq->ist_event, "interrupt");                          return NULL;
                   }
                   event_init(&irq->istevt, "interrupt");
         }          }
         irq_table[vector] = irq;          irq_table[vector] = irq;
         mode = shared ? IMODE_LEVEL : IMODE_EDGE;  
   
         irq_lock();          irq_lock();
           mode = shared ? IMODE_LEVEL : IMODE_EDGE;
         interrupt_setup(vector, mode);          interrupt_setup(vector, mode);
         interrupt_unmask(vector, prio);          interrupt_unmask(vector, prio);
         irq_unlock();          irq_unlock();
   
         sched_unlock();          sched_unlock();
         printk("IRQ%d attached priority=%d\n", vector, prio);          DPRINTF(("IRQ%d attached priority=%d\n", vector, prio));
         return (int)irq;          return irq;
 }  }
   
 /*  /*
  * Detach an interrupt handler from the interrupt chain.   * Detach an interrupt handler from the interrupt chain.
  * The detached interrupt will be masked off if nobody attaches   * The detached interrupt will be masked off if nobody
  * to it, anymore.   * attaches to it, anymore.
  */   */
 void  void
 irq_detach(int handle)  irq_detach(irq_t irq)
 {  {
         struct irq *irq = (struct irq *)handle;  
   
         ASSERT(irq_level == 0);          ASSERT(irq_level == 0);
         ASSERT(irq);          ASSERT(irq);
         ASSERT(irq->vector < NIRQS);          ASSERT(irq->vector < NIRQS);
Line 152 
Line 141 
   
         irq_table[irq->vector] = NULL;          irq_table[irq->vector] = NULL;
         if (irq->thread != NULL)          if (irq->thread != NULL)
                 thread_kill(irq->thread);                  kthread_terminate(irq->thread);
   
         kmem_free(irq);          kmem_free(irq);
 }  }
   
Line 160 
Line 150 
  * Lock IRQ.   * Lock IRQ.
  *   *
  * All H/W interrupts are masked off.   * All H/W interrupts are masked off.
  * Caller is no need to save the interrupt state before irq_lock()   * Caller is no need to save the interrupt state before
  * because it is automatically restored in irq_unlock() when no one   * irq_lock() because it is automatically restored in
  * is locking the IRQ anymore.   * irq_unlock() when no one is locking the IRQ anymore.
  */   */
 void  void
 irq_lock(void)  irq_lock(void)
Line 173 
Line 163 
         interrupt_disable();          interrupt_disable();
         if (++nr_irq_locks == 1)          if (++nr_irq_locks == 1)
                 saved_irq_state = s;                  saved_irq_state = s;
   
           ASSERT(nr_irq_locks != 0);
 }  }
   
 /*  /*
  * Unlock IRQ.   * Unlock IRQ.
  *   *
  * If lock count becomes 0, the interrupt is restored to original   * If lock count becomes 0, the interrupt is restored to
  * state at first irq_lock() call.   * original state at first irq_lock() call.
  */   */
 void  void
 irq_unlock(void)  irq_unlock(void)
Line 195 
Line 187 
  * This is a common dispatcher to all interrupt threads.   * This is a common dispatcher to all interrupt threads.
  */   */
 static void  static void
 irq_thread(u_long arg)  irq_thread(void *arg)
 {  {
         int vec;          int vec;
         void (*func)(int);          void (*func)(int);
Line 209 
Line 201 
   
         for (;;) {          for (;;) {
                 interrupt_disable();                  interrupt_disable();
                 if (irq->ist_request <= 0) {                  if (irq->istreq <= 0) {
                         /*                          /*
                          * Since the interrupt is disabled above, an                           * Since the interrupt is disabled above,
                          * interrupt for this vector keeps pending until                           * an interrupt for this vector keeps
                          * this thread enters sleep state. Thus, we don't                           * pending until this thread enters sleep
                          * lose any IST requests even if the interrupt                           * state. Thus, we don't lose any IST
                          * is fired here.                           * requests even if the interrupt is fired
                            * here.
                          */                           */
                         sched_sleep(&irq->ist_event);                          sched_sleep(&irq->istevt);
                 }                  }
                 irq->ist_request--;                  irq->istreq--;
                 ASSERT(irq->ist_request >= 0);                  ASSERT(irq->istreq >= 0);
                 interrupt_enable();                  interrupt_enable();
   
                 /* Call IST */                  /*
                 (func)(vec);                   * Call IST
                    */
                   (*func)(vec);
         }          }
         /* NOTREACHED */          /* NOTREACHED */
 }  }
Line 232 
Line 227 
 /*  /*
  * Interrupt handler.   * Interrupt handler.
  *   *
  * This routine will call the corresponding ISR for the requested   * This routine will call the corresponding ISR for the
  * interrupt vector. This routine is called from the code in the   * requested interrupt vector. This routine is called from
  * architecture dependent layer. We assumes the scheduler is already   * the code in the architecture dependent layer. We
  * locked by caller.   * assumes the scheduler is already locked by caller.
  */   */
 void  void
 irq_handler(int vector)  irq_handler(int vector)
Line 248 
Line 243 
                 return;         /* Ignore stray interrupt */                  return;         /* Ignore stray interrupt */
         ASSERT(irq->isr);          ASSERT(irq->isr);
   
         /* Call ISR */          /*
         rc = (irq->isr)(vector);           * Call ISR
            */
           rc = (*irq->isr)(vector);
   
         if (rc == INT_CONTINUE) {          if (rc == INT_CONTINUE) {
                 /* Kick IST */                  /*
                    * Kick IST
                    */
                 ASSERT(irq->ist);                  ASSERT(irq->ist);
                 irq->ist_request++;                  irq->istreq++;
                 sched_wakeup(&irq->ist_event);                  sched_wakeup(&irq->istevt);
                   ASSERT(irq->istreq != 0);
         }          }
         irq->count++;  
 }  }
   
 #if defined(DEBUG) && defined(CONFIG_KDUMP)  
 void  void
 irq_dump(void)  
 {  
         int vector;  
         struct irq *irq;  
   
         printk("IRQ dump:\n");  
         printk(" vector isr      ist      prio     count\n");  
         printk(" ------ -------- -------- -------- --------\n");  
   
         for (vector = 0; vector < NIRQS; vector++) {  
                 irq = irq_table[vector];  
                 if (irq) {  
                         printk("   %4d %08x %08x      %3d %8d\n",  
                                vector, irq->isr, irq->ist,  
                                (irq->thread ? irq->thread->prio : 0),  
                                irq->count);  
                 }  
         }  
 }  
 #endif  
   
 void  
 irq_init(void)  irq_init(void)
 {  {
         /*  
          * Start interrupt processing.          /* Start interrupt processing. */
          */  
         interrupt_enable();          interrupt_enable();
 }  }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.2.1

CVSweb