home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / m68k / ints.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-09  |  4.2 KB  |  210 lines

  1. /*
  2.  * ints.c -- 680x0 Linux general interrupt handling code
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file README.legal in the main directory of this archive
  6.  * for more details.
  7.  */
  8.  
  9. #include <asm/system.h>
  10.  
  11. #include <linux/types.h>
  12. #include <linux/config.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/sched.h>
  15.  
  16. /*
  17.  * ++roman: The number of possible interrupts is 7 only if there are no
  18.  * non-autovec ints. But e.g. the Atari uses a lot of them. So I defined
  19.  * a constant NUM_INT_SOURCES in interrupt.h that gives the total number of
  20.  * possible interrputs. A constant FIRST_NONAUTO_VEC is defined also.
  21.  */
  22.  
  23. /* list is accessed 0-6 for IRQs 1-7 */
  24. static isr_node_t *isr_list[NUM_INT_SOURCES];
  25.  
  26. /* The number of spurious interrupts */
  27. volatile unsigned long num_spurious;
  28.  
  29. volatile unsigned long intr_count = 0;
  30. unsigned long bh_active = 0;
  31. unsigned long bh_mask = 0xFFFFFFFF;
  32. struct bh_struct bh_base[32]; 
  33.  
  34. /*
  35.  * void init_INTS(void)
  36.  *
  37.  * Parameters:    None
  38.  *
  39.  * Returns:    Nothing
  40.  *
  41.  * This function should be called during kernel startup to initialize
  42.  * the IRQ handling routines.
  43.  */
  44.  
  45. void init_INTS(void)
  46. {
  47.     int i;
  48.  
  49.     /* initialize the ISR list pointers */
  50.     for (i = 0; i < NUM_INT_SOURCES; i++)
  51.     isr_list[i] = NULL;
  52.     
  53.     num_spurious = 0;
  54.     
  55.     /* intialize the bottom half routines. */
  56.     for (i = 0; i < 32; i++) {
  57.         bh_base[i].routine = NULL;
  58.         bh_base[i].data = NULL;
  59.     }
  60.     bh_active = 0;
  61.     intr_count = 0;
  62.  
  63.     mach_init_INTS ();
  64.  
  65.     /* enable CPU interrupts */
  66.     sti();
  67. }
  68.  
  69. /*
  70.  * do_bottom_half() runs at normal kernel priority: all interrupts
  71.  * enabled.  do_bottom_half() is atomic with respect to itself: a
  72.  * bottom_half handler need not be re-entrant.
  73.  */
  74. asmlinkage void do_bottom_half(void)
  75. {
  76.     unsigned long active;
  77.     unsigned long mask, left;
  78.     struct bh_struct *bh;
  79.  
  80.     bh = bh_base;
  81.     active = bh_active & bh_mask;
  82.     
  83.     for (mask = 1, left = ~0 ; left & active ; bh++,mask += mask,left += left) {
  84.         if (mask & active) {
  85.             void (*fn)(void *);
  86.             bh_active &= ~mask;
  87.             fn = bh->routine;
  88.             if (!fn)
  89.                 goto bad_bh;
  90.             fn(bh->data);
  91.         }
  92.     }
  93.     return;
  94. bad_bh:
  95.     printk ("irq.c:bad bottom half entry\n");
  96. }
  97.  
  98. void insert_isr (isr_node_t **listp, isr_node_t *node)
  99. {
  100.     unsigned long spl;
  101.     isr_node_t *cur, *last = NULL;
  102.  
  103.     save_flags(spl);
  104.     cli();
  105.  
  106.     cur = *listp;
  107.  
  108.     if (!cur || cur->pri > node->pri) {
  109.     if (cur)
  110.         node->next = cur;
  111.     *listp = node;
  112.     restore_flags (spl);
  113.     return;
  114.     }
  115.  
  116.     while (cur->next && cur->pri <= node->pri)
  117.     {
  118.     last = cur;
  119.     cur = cur->next;
  120.     }
  121.  
  122.     if (!cur->next) {
  123.     cur->next = node;
  124.     } else {
  125.     node->next = cur;
  126.     last->next = node;
  127.     }
  128.  
  129.     restore_flags(spl);
  130. }
  131.  
  132. isr_node_t *new_isr_node(void)
  133. {
  134.     isr_node_t *np;
  135.  
  136.     static isr_node_t nodes[32];
  137.     static int curnode = 0;
  138.  
  139.     np = &nodes[curnode++];
  140.     if (curnode >= sizeof(nodes)/sizeof(nodes[0]))
  141.     panic ("new_isr_node: out of nodes");
  142.  
  143.     return np;
  144. }
  145.  
  146. int add_isr (unsigned long source, isrfunc isr, int pri, void *data)
  147. {
  148.     isr_node_t *p;
  149.  
  150.     if (source & IRQ_MACHSPEC)
  151.     {
  152.     return mach_add_isr (source, isr, pri, data);
  153.     }
  154.  
  155.     if (source < IRQ1 || source > NUM_INT_SOURCES)
  156.     panic ("add_isr: Incorrect IRQ source");
  157.  
  158.     p = new_isr_node();
  159.     p->isr = isr;
  160.     p->pri = pri;
  161.     p->data = data;
  162.     p->next = NULL;
  163.  
  164.     insert_isr (&isr_list[source-1], p);
  165.  
  166.     return 1;
  167. }
  168.  
  169. void call_isr_list(isr_node_t *p, struct intframe *fp)
  170. {
  171.     while (p) {
  172.     p->isr (fp, p->data);
  173.     p = p->next;
  174.     }
  175. }
  176.  
  177. #define    DEBUG_LOST_INT_DECR
  178.  
  179. asmlinkage void process_int(int level, struct intframe *fp)
  180. {
  181. #ifdef DEBUG_LOST_INT_DECR
  182.     int cnt = intr_count;
  183.     static int last_spur = 0;
  184. #endif
  185.     
  186. #if NUM_INT_SOURCES > 7
  187.     /* Possibility for non-autovec ints! */
  188.     if (level < 8)
  189.         /* autovector int */
  190.         call_isr_list (isr_list[level-1], fp);
  191.     else
  192.         /* non-autovec */
  193.         call_isr_list (isr_list[level-FIRST_NONAUTO_VEC+24+7], fp);
  194. #else
  195.     call_isr_list (isr_list[level-1], fp);
  196. #endif
  197.  
  198. #ifdef DEBUG_LOST_INT_DECR
  199.     if (cnt != intr_count) {
  200.         printk( "intr_count=%d != old_cnt=%d; resetted\n", (int)intr_count, cnt );
  201.         intr_count = cnt;
  202.     }
  203.     if (num_spurious != last_spur) {
  204.         printk( "num_spurious is now %lu\n", num_spurious );
  205.         last_spur = num_spurious;
  206.     }
  207. #endif
  208. }
  209.  
  210.