root/arch/sparc/kernel/irq.c

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

DEFINITIONS

This source file includes following definitions.
  1. sun4c_disable_irq
  2. sun4m_disable_irq
  3. disable_irq
  4. sun4c_enable_irq
  5. sun4m_enable_irq
  6. enable_irq
  7. get_irq_list
  8. free_irq
  9. unexpected_irq
  10. handler_irq
  11. do_IRQ
  12. do_fast_IRQ
  13. request_fast_irq
  14. request_irq
  15. probe_irq_on
  16. probe_irq_off
  17. sun4c_init_IRQ
  18. sun4m_init_IRQ
  19. init_IRQ

   1 /*  $Id: irq.c,v 1.29 1995/11/25 00:58:08 davem Exp $
   2  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
   3  *                            Sparc the IRQ's are basically 'cast in stone'
   4  *                            and you are supposed to probe the prom's device
   5  *                            node trees to find out who's got which IRQ.
   6  *
   7  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   8  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
   9  *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@jamica.lab.ipmce.su)
  10  */
  11 
  12 #include <linux/ptrace.h>
  13 #include <linux/errno.h>
  14 #include <linux/linkage.h>
  15 #include <linux/kernel_stat.h>
  16 #include <linux/signal.h>
  17 #include <linux/sched.h>
  18 #include <linux/interrupt.h>
  19 
  20 #include <asm/ptrace.h>
  21 #include <asm/processor.h>
  22 #include <asm/system.h>
  23 #include <asm/psr.h>
  24 #include <asm/vaddrs.h>
  25 #include <asm/timer.h>
  26 #include <asm/openprom.h>
  27 #include <asm/oplib.h>
  28 #include <asm/traps.h>
  29 #include <asm/irq.h>
  30 #include <asm/io.h>
  31 
  32 /* Pointer to the interrupt enable byte */
  33 unsigned char *interrupt_enable = 0;
  34 struct sun4m_intregs *sun4m_interrupts;
  35 
  36 void
  37 sun4c_disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         unsigned long flags;
  40         unsigned char current_mask, new_mask;
  41 
  42         if(sparc_cpu_model != sun4c)
  43                 return;
  44         save_flags(flags); cli();
  45         current_mask = *interrupt_enable;
  46         switch(irq_nr) {
  47         case 1:
  48                 new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
  49                 break;
  50         case 8:
  51                 new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
  52                 break;
  53         case 10:
  54                 new_mask = ((current_mask) & (~(SUN4C_INT_E10)));
  55                 break;
  56         case 14:
  57                 new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
  58                 break;
  59         default:
  60                 restore_flags(flags);
  61                 return;
  62         };
  63   
  64         *interrupt_enable = new_mask;
  65         restore_flags(flags);
  66 }
  67 
  68 void
  69 sun4m_disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71         printk("IRQ routines not yet written for the sun4m\n");
  72         panic("disable_irq: Unsupported arch.");
  73 }
  74 
  75 void
  76 disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         switch(sparc_cpu_model) {
  79         case sun4c:
  80                 sun4c_disable_irq(irq_nr);
  81                 break;
  82         case sun4m:
  83                 sun4m_disable_irq(irq_nr);
  84         default:
  85                 panic("disable_irq: Unsupported arch.");
  86         }
  87 }
  88 
  89 void
  90 sun4c_enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         unsigned long flags;
  93         unsigned char current_mask, new_mask;
  94 
  95         if(sparc_cpu_model != sun4c)
  96                 return;
  97         save_flags(flags); cli();
  98         current_mask = *interrupt_enable;
  99         switch(irq_nr) {
 100         case 1:
 101                 new_mask = ((current_mask) | SUN4C_INT_E1);
 102                 break;
 103         case 8:
 104                 new_mask = ((current_mask) | SUN4C_INT_E8);
 105                 break;
 106         case 10:
 107                 new_mask = ((current_mask) | SUN4C_INT_E10);
 108                 break;
 109         case 14:
 110                 new_mask = ((current_mask) | SUN4C_INT_E14);
 111                 break;
 112         default:
 113                 restore_flags(flags);
 114                 return;
 115         };
 116 
 117         *interrupt_enable = new_mask;
 118         restore_flags(flags);
 119 }
 120 
 121 void
 122 sun4m_enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         printk("IRQ routines not written for the sun4m yet.\n");
 125         panic("IRQ unsupported arch.");
 126 }
 127 
 128 void
 129 enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         switch(sparc_cpu_model) {
 132         case sun4c:
 133                 sun4c_enable_irq(irq_nr);
 134                 break;
 135         case sun4m:
 136                 sun4m_enable_irq(irq_nr);
 137                 break;
 138         default:
 139                 panic("IRQ unsupported arch.");
 140         }
 141 }
 142 
 143 /*
 144  * Initial irq handlers.
 145  */
 146 struct irqaction {
 147         void (*handler)(int, struct pt_regs *);
 148         unsigned long flags;
 149         unsigned long mask;
 150         const char *name;
 151 };
 152 
 153 static struct irqaction irq_action[16] = {
 154   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 155   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 156   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 157   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 158   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 159   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 160   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
 161   { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
 162 };
 163 
 164 
 165 int
 166 get_irq_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         int i, len = 0;
 169         struct irqaction * action = irq_action;
 170 
 171         for (i = 0 ; i < 16 ; i++, action++) {
 172                 if (!action->handler)
 173                         continue;
 174                 len += sprintf(buf+len, "%2d: %8d %c %s\n",
 175                                i, kstat.interrupts[i],
 176                                (action->flags & SA_INTERRUPT) ? '+' : ' ',
 177                                action->name);
 178         }
 179         return len;
 180 }
 181 
 182 void
 183 free_irq(unsigned int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         struct irqaction * action = irq + irq_action;
 186         unsigned long flags;
 187 
 188         if (irq > 14) {  /* 14 irq levels on the sparc */
 189                 printk("Trying to free bogus IRQ %d\n", irq);
 190                 return;
 191         }
 192         if (!action->handler) {
 193                 printk("Trying to free free IRQ%d\n", irq);
 194                 return;
 195         }
 196         save_flags(flags); cli();
 197         disable_irq(irq);
 198         action->handler = NULL;
 199         action->flags = 0;
 200         action->mask = 0;
 201         action->name = NULL;
 202         restore_flags(flags);
 203 }
 204 
 205 void
 206 unexpected_irq(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208         int i;
 209 
 210         printk("IO device interrupt, irq = %d\n", irq);
 211         printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 
 212                     regs->npc, regs->u_regs[14]);
 213         printk("Expecting: ");
 214         for (i = 0; i < 16; i++)
 215                 if (irq_action[i].handler)
 216                         prom_printf("[%s:%d:0x%x] ", irq_action[i].name, (int) i,
 217                                (unsigned int) irq_action[i].handler);
 218         printk("AIEEE\n");
 219         panic("bogus interrupt received");
 220 }
 221 
 222 void
 223 handler_irq(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 224 {
 225         struct irqaction * action = irq_action + irq;
 226 
 227         kstat.interrupts[irq]++;
 228         if (!action->handler)
 229                 unexpected_irq(irq, regs);
 230         else
 231                 action->handler(irq, regs);
 232 }
 233 
 234 /*
 235  * do_IRQ handles IRQ's that have been installed without the
 236  * SA_INTERRUPT flag: it uses the full signal-handling return
 237  * and runs with other interrupts enabled. All relatively slow
 238  * IRQ's should use this format: notably the keyboard/timer
 239  * routines.
 240  */
 241 asmlinkage void
 242 do_IRQ(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 243 {
 244         struct irqaction *action = irq + irq_action;
 245 
 246         kstat.interrupts[irq]++;
 247         action->handler(irq, regs);
 248         return;
 249 }
 250 
 251 /*
 252  * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
 253  * stuff - the handler is also running with interrupts disabled unless
 254  * it explicitly enables them later.
 255  */
 256 asmlinkage void
 257 do_fast_IRQ(int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         kstat.interrupts[irq]++;
 260         printk("Got FAST_IRQ number %04lx\n", (long unsigned int) irq);
 261         return;
 262 }
 263 
 264 int
 265 request_fast_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
     /* [previous][next][first][last][top][bottom][index][help] */
 266                  unsigned long irqflags, const char *devname)
 267 {
 268         struct irqaction *action;
 269         unsigned long flags;
 270 
 271         if(irq > 14)
 272                 return -EINVAL;
 273         action = irq + irq_action;
 274         if(action->handler)
 275                 return -EBUSY;
 276         if(!handler)
 277                 return -EINVAL;
 278 
 279         save_flags(flags); cli();
 280 
 281         /* Dork with trap table if we get this far. */
 282         sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one =
 283                 SPARC_BRANCH((unsigned long) handler,
 284                              (unsigned long) &sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one);
 285         sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_two = SPARC_RD_PSR_L0;
 286         sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_three = SPARC_NOP;
 287         sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_four = SPARC_NOP;
 288 
 289         action->handler = handler;
 290         action->flags = irqflags;
 291         action->mask = 0;
 292         action->name = devname;
 293 
 294         restore_flags(flags);
 295         return 0;
 296 }
 297 
 298 extern void probe_clock(void);
 299                 
 300 int
 301 request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
     /* [previous][next][first][last][top][bottom][index][help] */
 302             unsigned long irqflags, const char * devname)
 303 {
 304         struct irqaction *action;
 305         unsigned long flags;
 306 
 307         if(irq > 14)
 308                 return -EINVAL;
 309 
 310         action = irq + irq_action;
 311         if(action->handler)
 312                 return -EBUSY;
 313         if(!handler)
 314                 return -EINVAL;
 315 
 316         save_flags(flags); cli();
 317         action->handler = handler;
 318         action->flags = irqflags;
 319         action->mask = 0;
 320         action->name = devname;
 321         enable_irq(irq);
 322         if(irq == 10)
 323                 probe_clock();
 324         restore_flags(flags);
 325         return 0;
 326 }
 327 
 328 /* We really don't need these at all on the Sparc.  We only have
 329  * stubs here because they are exported to modules.
 330  */
 331 unsigned long probe_irq_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333   return 0;
 334 }
 335 
 336 int probe_irq_off(unsigned long mask)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338   return 0;
 339 }
 340 
 341 void
 342 sun4c_init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344         struct linux_prom_registers int_regs[2];
 345         int ie_node;
 346 
 347         ie_node = prom_searchsiblings (prom_getchild(prom_root_node),
 348                                        "interrupt-enable");
 349         if(ie_node == 0)
 350                 panic("Cannot find /interrupt-enable node");
 351         /* Depending on the "address" property is bad news... */
 352         prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs));
 353         sparc_alloc_io(int_regs[0].phys_addr, (void *) INTREG_VADDR,
 354                        int_regs[0].reg_size, "sun4c_interrupts",
 355                        int_regs[0].which_io, 0x0);
 356 
 357         interrupt_enable = (char *) INTREG_VADDR;
 358 
 359         /* Default value, accept interrupts, but no one is actually active */
 360         *interrupt_enable = (SUN4C_INT_ENABLE);
 361         sti(); /* Turn irq's on full-blast. */
 362 }
 363 
 364 void
 365 sun4m_init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 366 {
 367         int ie_node;
 368 
 369         struct linux_prom_registers int_regs[PROMREG_MAX];
 370         int num_regs;
 371 
 372         cli();
 373 
 374         if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
 375            (ie_node = prom_getchild (ie_node)) == 0 ||
 376            (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0)
 377                 panic("Cannot find /obio/interrupt node\n");
 378         num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
 379                                     sizeof(int_regs));
 380         num_regs = (num_regs/sizeof(struct linux_prom_registers));
 381 
 382         /* Apply the obio ranges to these registers. */
 383         prom_apply_obio_ranges(int_regs, num_regs);
 384 
 385         /* Map the interrupt registers for all possible cpus. */
 386         sparc_alloc_io(int_regs[0].phys_addr, (void *) INTREG_VADDR,
 387                        PAGE_SIZE*NCPUS, "interrupts_percpu",
 388                        int_regs[0].which_io, 0x0);
 389 
 390         /* Map the system interrupt control registers. */
 391         sparc_alloc_io(int_regs[num_regs-1].phys_addr,
 392                        (void *) INTREG_VADDR+(NCPUS*PAGE_SIZE),
 393                        int_regs[num_regs-1].reg_size, "interrupts_system",
 394                        int_regs[num_regs-1].which_io, 0x0);
 395 
 396         sun4m_interrupts = (struct sun4m_intregs *) INTREG_VADDR;
 397         sti();
 398 }
 399 
 400 void
 401 init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 402 {
 403         switch(sparc_cpu_model) {
 404         case sun4c:
 405                 sun4c_init_IRQ();
 406                 break;
 407         case sun4m:
 408                 sun4m_init_IRQ();
 409                 break;
 410         default:
 411                 panic("Cannot initialize IRQ's on this Sun machine...");
 412                 break;
 413         };
 414 }

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