root/arch/alpha/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. request_irq
  5. free_irq
  6. handle_irq
  7. device_interrupt
  8. machine_check
  9. do_entInt
  10. init_IRQ

   1 /*
   2  *      linux/arch/alpha/kernel/irq.c
   3  *
   4  *      Copyright (C) 1995 Linus Torvalds
   5  *
   6  * This file contains the code used by various IRQ handling routines:
   7  * asking for different IRQ's should be done through these routines
   8  * instead of just grabbing them. Thus setups with different IRQ numbers
   9  * shouldn't result in any weird surprises, and installing new handlers
  10  * should be easier.
  11  */
  12 
  13 #include <linux/ptrace.h>
  14 #include <linux/errno.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/system.h>
  21 #include <asm/io.h>
  22 #include <asm/irq.h>
  23 #include <asm/bitops.h>
  24 
  25 static unsigned char cache_21 = 0xff;
  26 static unsigned char cache_A1 = 0xff;
  27 
  28 void disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30         unsigned long flags;
  31         unsigned char mask;
  32 
  33         mask = 1 << (irq_nr & 7);
  34         save_flags(flags);
  35         if (irq_nr < 8) {
  36                 cli();
  37                 cache_21 |= mask;
  38                 outb(cache_21,0x21);
  39                 restore_flags(flags);
  40                 return;
  41         }
  42         cli();
  43         cache_A1 |= mask;
  44         outb(cache_A1,0xA1);
  45         restore_flags(flags);
  46 }
  47 
  48 void enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  49 {
  50         unsigned long flags;
  51         unsigned char mask;
  52 
  53         mask = ~(1 << (irq_nr & 7));
  54         save_flags(flags);
  55         if (irq_nr < 8) {
  56                 cli();
  57                 cache_21 &= mask;
  58                 outb(cache_21,0x21);
  59                 restore_flags(flags);
  60                 return;
  61         }
  62         cli();
  63         cache_A1 &= mask;
  64         outb(cache_A1,0xA1);
  65         restore_flags(flags);
  66 }
  67 
  68 /*
  69  * Initial irq handlers.
  70  */
  71 struct irqaction {
  72         void (*handler)(int, struct pt_regs *);
  73         unsigned long flags;
  74         unsigned long mask;
  75         const char *name;
  76 };
  77 
  78 static struct irqaction irq_action[16] = {
  79         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  80         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  81         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  82         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  83         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  84         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  85         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
  86         { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
  87 };
  88 
  89 int get_irq_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         int i, len = 0;
  92         struct irqaction * action = irq_action;
  93 
  94         for (i = 0 ; i < 16 ; i++, action++) {
  95                 if (!action->handler)
  96                         continue;
  97                 len += sprintf(buf+len, "%2d: %8d %c %s\n",
  98                         i, kstat.interrupts[i],
  99                         (action->flags & SA_INTERRUPT) ? '+' : ' ',
 100                         action->name);
 101         }
 102         return len;
 103 }
 104 
 105 int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
     /* [previous][next][first][last][top][bottom][index][help] */
 106         unsigned long irqflags, const char * devname)
 107 {
 108         struct irqaction * action;
 109         unsigned long flags;
 110 
 111         if (irq > 15)
 112                 return -EINVAL;
 113         action = irq + irq_action;
 114         if (action->handler)
 115                 return -EBUSY;
 116         if (!handler)
 117                 return -EINVAL;
 118         save_flags(flags);
 119         cli();
 120         action->handler = handler;
 121         action->flags = irqflags;
 122         action->mask = 0;
 123         action->name = devname;
 124         if (irq < 8) {
 125                 cache_21 &= ~(1<<irq);
 126                 outb(cache_21,0x21);
 127         } else {
 128                 cache_21 &= ~(1<<2);
 129                 cache_A1 &= ~(1<<(irq-8));
 130                 outb(cache_21,0x21);
 131                 outb(cache_A1,0xA1);
 132         }
 133         restore_flags(flags);
 134         return 0;
 135 }
 136 
 137 void free_irq(unsigned int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139         halt();
 140 }
 141 
 142 static void handle_irq(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         struct irqaction * action = irq + irq_action;
 145 
 146         kstat.interrupts[irq]++;
 147         if (action->handler)
 148                 action->handler(irq, regs);
 149 }
 150 
 151 /*
 152  * I don't have any good documentation on the EISA hardware interrupt
 153  * stuff: I don't know the mapping between the interrupt vector and the
 154  * EISA interrupt number.
 155  *
 156  * It *seems* to be 0x8X0 for EISA interrupt X, and 0x9X0 for the
 157  * local motherboard interrupts..
 158  *
 159  *      0x660 - NMI?
 160  *
 161  *      0x800 - ??? I've gotten this, but EISA irq0 shouldn't happen
 162  *              as the timer is not on the EISA bus
 163  *
 164  *      0x860 - ??? floppy disk (EISA irq6)
 165  *
 166  *      0x900 - ??? I get this at autoprobing when the EISA serial
 167  *              lines com3/com4 don't exist. It keeps coming after
 168  *              that..
 169  *
 170  *      0x980 - keyboard
 171  *      0x990 - mouse
 172  *
 173  * We'll see..
 174  */
 175 static void device_interrupt(unsigned long vector, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177         int i;
 178         static int nr = 0;
 179 
 180         if (vector == 0x980 && irq_action[1].handler) {
 181                 handle_irq(1, regs);
 182                 return;
 183         }
 184 
 185         if (nr > 3)
 186                 return;
 187         nr++;
 188         printk("IO device interrupt, vector = %lx\n", vector);
 189         printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
 190         printk("Expecting: ");
 191         for (i = 0; i < 16; i++)
 192                 if (irq_action[i].handler)
 193                         printk("[%s:%d] ", irq_action[i].name, i);
 194         printk("\n");
 195         printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
 196                 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
 197         printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
 198 }
 199 
 200 static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202         printk("Machine check\n");
 203 }
 204 
 205 asmlinkage void do_entInt(unsigned long type, unsigned long vector,
     /* [previous][next][first][last][top][bottom][index][help] */
 206         unsigned long la_ptr, struct pt_regs *regs)
 207 {
 208         switch (type) {
 209                 case 0:
 210                         printk("Interprocessor interrupt? You must be kidding\n");
 211                         break;
 212                 case 1:
 213                         /* timer interrupt.. */
 214                         handle_irq(0, regs);
 215                         return;
 216                 case 2:
 217                         machine_check(vector, la_ptr, regs);
 218                         break;
 219                 case 3:
 220                         device_interrupt(vector, regs);
 221                         return;
 222                 case 4:
 223                         printk("Performance counter interrupt\n");
 224                         break;;
 225                 default:
 226                         printk("Hardware intr %ld %lx? Huh?\n", type, vector);
 227         }
 228         printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
 229 }
 230 
 231 extern asmlinkage void entInt(void);
 232 
 233 void init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         wrent(entInt, 0);
 236 }

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