home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / sparc / kernel / irq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-20  |  7.5 KB  |  336 lines

  1. /*  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  2.  *                            Sparc the IRQ's are basically 'cast in stone'
  3.  *                            and you are supposed to probe the prom's device
  4.  *                            node trees to find out who's got which IRQ.
  5.  *
  6.  *  Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  7.  *
  8.  */
  9.  
  10. /*
  11.  * IRQ's are in fact implemented a bit like signal handlers for the kernel.
  12.  * The same sigaction struct is used, and with similar semantics (ie there
  13.  * is a SA_INTERRUPT flag etc). Naturally it's not a 1:1 relation, but there
  14.  * are similarities.
  15.  *
  16.  * sa_handler(int irq_NR) is the default function called (0 if no).
  17.  * sa_mask is horribly ugly (I won't even mention it)
  18.  * sa_flags contains various info: SA_INTERRUPT etc
  19.  * sa_restorer is the unused
  20.  */
  21.  
  22. #include <linux/config.h>
  23. #include <linux/ptrace.h>
  24. #include <linux/errno.h>
  25. #include <linux/linkage.h>
  26. #include <linux/kernel_stat.h>
  27. #include <linux/signal.h>
  28. #include <linux/sched.h>
  29. #include <linux/interrupt.h>
  30. #include <asm/ptrace.h>
  31. #include <asm/system.h>
  32. #include <asm/psr.h>
  33. #include <asm/vaddrs.h>
  34. #include <asm/clock.h>
  35. #include <asm/openprom.h>
  36.  
  37. #define DEBUG_IRQ
  38.  
  39. void disable_irq(unsigned int irq_nr)
  40. {
  41.   unsigned long flags;
  42.   unsigned char *int_reg;
  43.   
  44.   save_flags(flags);
  45.   cli();
  46.  
  47.   /* We have mapped the irq enable register in head.S and all we
  48.    * have to do here is frob the bits.
  49.    */
  50.  
  51.   int_reg = (unsigned char *) IRQ_ENA_ADR;
  52.  
  53.   switch(irq_nr)
  54.     {
  55.     case 1:
  56.       *int_reg = ((*int_reg) & (~(0x02)));
  57.       break;
  58.     case 4:
  59.       *int_reg = ((*int_reg) & (~(0x04)));
  60.       break;
  61.     case 6:
  62.       *int_reg = ((*int_reg) & (~(0x08)));
  63.       break;      
  64.     case 8:
  65.       *int_reg = ((*int_reg) & (~(0x10)));
  66.       break;      
  67.     case 10:
  68.       *int_reg = ((*int_reg) & (~(0x20)));
  69.       break;      
  70.     case 14:
  71.       *int_reg = ((*int_reg) & (~(0x80)));
  72.       break;      
  73.     default:
  74.       printk("AIEEE, Illegal interrupt disable requested irq=%d\n", 
  75.          (int) irq_nr);
  76.       break;
  77.     };
  78.   
  79.   restore_flags(flags);
  80.   return;
  81. }
  82.  
  83. void enable_irq(unsigned int irq_nr)
  84. {
  85.   unsigned long flags;
  86.   unsigned char *int_reg;
  87.   
  88.   save_flags(flags);
  89.   cli();
  90.  
  91.   /* We have mapped the irq enable register in head.S and all we
  92.    * have to do here is frob the bits.
  93.    */
  94.  
  95.   int_reg = (unsigned char *) IRQ_ENA_ADR;
  96.   
  97. #ifdef DEBUG_IRQ
  98.   printk(" --- Enabling IRQ level %d ---\n", irq_nr);
  99. #endif
  100.  
  101.   switch(irq_nr)
  102.     {
  103.     case 1:
  104.       *int_reg = ((*int_reg) | 0x02);
  105.       break;
  106.     case 4:
  107.       *int_reg = ((*int_reg) | 0x04);
  108.       break;
  109.     case 6:
  110.       *int_reg = ((*int_reg) | 0x08);
  111.       break;      
  112.     case 8:
  113.       *int_reg = ((*int_reg) | 0x10);
  114.       break;      
  115.     case 10:
  116.       *int_reg = ((*int_reg) | 0x20);
  117.       break;      
  118.     case 14:
  119.       *int_reg = ((*int_reg) | 0x80);
  120.       break;      
  121.     default:
  122.       printk("AIEEE, Illegal interrupt enable requested irq=%d\n", 
  123.          (int) irq_nr);
  124.       break;
  125.     };
  126.  
  127.   restore_flags(flags);
  128.  
  129.   return;
  130. }
  131.  
  132. /*
  133.  * Initial irq handlers.
  134.  */
  135. struct irqaction {
  136.   void (*handler)(int, struct pt_regs *);
  137.   unsigned long flags;
  138.   unsigned long mask;
  139.   const char *name;
  140. };
  141.  
  142. static struct irqaction irq_action[16] = {
  143.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  144.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  145.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  146.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  147.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  148.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  149.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  150.   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
  151. };
  152.  
  153.  
  154. int get_irq_list(char *buf)
  155. {
  156.   int i, len = 0;
  157.   struct irqaction * action = irq_action;
  158.   
  159.   for (i = 0 ; i < 16 ; i++, action++) {
  160.     if (!action->handler)
  161.       continue;
  162.     len += sprintf(buf+len, "%2d: %8d %c %s\n",
  163.            i, kstat.interrupts[i],
  164.            (action->flags & SA_INTERRUPT) ? '+' : ' ',
  165.            action->name);
  166.   }
  167.   return len;
  168. }
  169.  
  170. void free_irq(unsigned int irq)
  171. {
  172.         struct irqaction * action = irq + irq_action;
  173.         unsigned long flags;
  174.  
  175.         if (irq > 14) {  /* 14 irq levels on the sparc */
  176.                 printk("Trying to free IRQ %d\n", irq);
  177.                 return;
  178.         }
  179.         if (!action->handler) {
  180.                 printk("Trying to free free IRQ%d\n", irq);
  181.                 return;
  182.         }
  183.         save_flags(flags);
  184.         cli();
  185.         disable_irq(irq);
  186.         action->handler = NULL;
  187.         action->flags = 0;
  188.         action->mask = 0;
  189.         action->name = NULL;
  190.         restore_flags(flags);
  191. }
  192.  
  193. #if 0
  194. static void handle_nmi(struct pt_regs * regs)
  195. {
  196.   printk("NMI, probably due to bus-parity error.\n");
  197.   printk("PC=%08lx, SP=%08lx\n", regs->pc, regs->sp);
  198. }
  199. #endif
  200.  
  201. void unexpected_irq(int irq, struct pt_regs * regs)
  202. {
  203.         int i;
  204.  
  205.         printk("IO device interrupt, irq = %d\n", irq);
  206.         printk("PC = %08lx NPC = %08lx SP=%08lx\n", regs->pc, 
  207.            regs->npc, regs->sp);
  208.         printk("Expecting: ");
  209.         for (i = 0; i < 16; i++)
  210.                 if (irq_action[i].handler)
  211.                         printk("[%s:%d] ", irq_action[i].name, i);
  212.         printk("AIEEE\n");
  213. }
  214.  
  215. static inline void handler_irq(int irq, struct pt_regs * regs)
  216. {
  217.   struct irqaction * action = irq + irq_action;
  218.  
  219.   if (!action->handler) {
  220.     unexpected_irq(irq, regs);
  221.     return;
  222.   }
  223.   action->handler(irq, regs);
  224. }
  225.  
  226. /*
  227.  * do_IRQ handles IRQ's that have been installed without the
  228.  * SA_INTERRUPT flag: it uses the full signal-handling return
  229.  * and runs with other interrupts enabled. All relatively slow
  230.  * IRQ's should use this format: notably the keyboard/timer
  231.  * routines.
  232.  */
  233. asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
  234. {
  235.   struct irqaction *action = irq + irq_action;
  236.  
  237.   kstat.interrupts[irq]++;
  238.   action->handler(irq, regs);
  239.   return;
  240. }
  241.  
  242. /*
  243.  * Since we need to special things to clear up the clock chip around
  244.  * the do_timer() call we have a special version of do_IRQ for the
  245.  * level 14 interrupt which does these things.
  246.  */
  247.  
  248. asmlinkage void do_sparc_timer(int irq, struct pt_regs * regs)
  249. {
  250.   struct irqaction *action = irq + irq_action;
  251.   register volatile int clear;
  252.  
  253.   kstat.interrupts[irq]++;
  254.  
  255.   /* I do the following already in the entry code, better safe than
  256.    * sorry for now. Reading the limit register clears the interrupt.
  257.    */
  258.   clear = TIMER_STRUCT->timer_limit14;
  259.  
  260.   action->handler(irq, regs);
  261.   return;
  262. }
  263.  
  264. /*
  265.  * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
  266.  * stuff - the handler is also running with interrupts disabled unless
  267.  * it explicitly enables them later.
  268.  */
  269. asmlinkage void do_fast_IRQ(int irq)
  270. {
  271.   kstat.interrupts[irq]++;
  272.   printk("Got FAST_IRQ number %04lx\n", (long unsigned int) irq);
  273.   return;
  274. }
  275.  
  276. extern int first_descent;
  277. extern void probe_clock(int);
  278.         
  279. int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
  280.     unsigned long irqflags, const char * devname)
  281. {
  282.   struct irqaction *action;
  283.   unsigned long flags;
  284.  
  285.   if(irq > 14)  /* Only levels 1-14 are valid on the Sparc. */
  286.     return -EINVAL;
  287.  
  288.   if(irq == 0)  /* sched_init() requesting the timer IRQ */
  289.     {
  290.       irq = 14;
  291.       probe_clock(first_descent);
  292.     }
  293.  
  294.   action = irq + irq_action;
  295.  
  296.   if(action->handler)
  297.     return -EBUSY;
  298.  
  299.   if(!handler)
  300.     return -EINVAL;
  301.  
  302.   save_flags(flags);
  303.  
  304.   cli();
  305.  
  306.   action->handler = handler;
  307.   action->flags = irqflags;
  308.   action->mask = 0;
  309.   action->name = devname;
  310.  
  311.   enable_irq(irq);
  312.  
  313.   restore_flags(flags);
  314.  
  315.   return 0;
  316. }
  317.  
  318. unsigned int probe_irq_on (void)
  319. {
  320.   unsigned int irqs = 0;
  321.  
  322.   return irqs;
  323. }
  324.  
  325. int probe_irq_off (unsigned int irqs)
  326. {
  327.   unsigned int i = 0;
  328.  
  329.   return i;
  330. }
  331.  
  332. void init_IRQ(void)
  333. {
  334.   return;
  335. }
  336.