root/arch/sparc/kernel/irq.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. disable_irq
  2. enable_irq
  3. get_irq_list
  4. free_irq
  5. handle_nmi
  6. unexpected_irq
  7. handler_irq
  8. do_IRQ
  9. do_sparc_timer
  10. do_fast_IRQ
  11. request_irq
  12. probe_irq_on
  13. probe_irq_off
  14. init_IRQ

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 *),
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 319 {
 320   unsigned int irqs = 0;
 321 
 322   return irqs;
 323 }
 324 
 325 int probe_irq_off (unsigned int irqs)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327   unsigned int i = 0;
 328 
 329   return i;
 330 }
 331 
 332 void init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334   return;
 335 }

/* [previous][next][first][last][top][bottom][index][help] */