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. ack_irq
  5. mask_irq
  6. unmask_irq
  7. request_irq
  8. free_irq
  9. handle_nmi
  10. unexpected_irq
  11. handle_irq
  12. device_interrupt
  13. isa_device_interrupt
  14. cabriolet_and_eb66p_device_interrupt
  15. eb66_and_eb64p_device_interrupt
  16. srm_device_interrupt
  17. probe_irq_on
  18. probe_irq_off
  19. machine_check
  20. do_entInt
  21. 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/config.h>
  14 #include <linux/ptrace.h>
  15 #include <linux/errno.h>
  16 #include <linux/kernel_stat.h>
  17 #include <linux/signal.h>
  18 #include <linux/sched.h>
  19 #include <linux/interrupt.h>
  20 #include <linux/malloc.h>
  21 #include <linux/random.h>
  22 
  23 #include <asm/system.h>
  24 #include <asm/io.h>
  25 #include <asm/irq.h>
  26 #include <asm/bitops.h>
  27 #include <asm/dma.h>
  28 
  29 extern void timer_interrupt(struct pt_regs * regs);
  30 
  31 static unsigned char cache_21 = 0xff;
  32 static unsigned char cache_A1 = 0xff;
  33 
  34 #if NR_IRQS == 33
  35   static unsigned char cache_804 = 0xef;
  36   static unsigned char cache_805 = 0xff;
  37   static unsigned char cache_806 = 0xff;
  38 #elif NR_IRQS == 32
  39   static unsigned char cache_26 = 0xdf;
  40   static unsigned char cache_27 = 0xff;
  41 #endif
  42 
  43 void disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  44 {
  45         unsigned long flags;
  46         unsigned char mask;
  47 
  48         save_flags(flags);
  49         cli();
  50         mask = 1 << (irq_nr & 7);
  51 
  52         if (irq_nr < 8) {
  53                 cache_21 |= mask;
  54                 outb(cache_21,0x21);
  55         } else if (irq_nr < 16) {
  56                 cache_A1 |= mask;
  57                 outb(cache_A1,0xA1);
  58 #if NR_IRQS == 33
  59         } else if (irq_nr < 24) {
  60                 cache_804 |= mask;
  61                 outb(cache_804, 0x804);
  62         } else if (irq_nr < 32) {
  63                 cache_805 |= mask;
  64                 outb(cache_805, 0x805);
  65         } else {
  66                 cache_806 |= mask;
  67                 outb(cache_806, 0x806);
  68 #elif NR_IRQS == 32 
  69         } else if (irq_nr < 24) {
  70                 cache_26 |= mask;
  71                 outb(cache_26, 0x26);
  72         } else {
  73                 cache_27 |= mask;
  74                 outb(cache_27, 0x27);
  75 #endif
  76         }
  77         restore_flags(flags);
  78 }
  79 
  80 void enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         unsigned long flags;
  83         unsigned char mask;
  84 
  85         mask = ~(1 << (irq_nr & 7));
  86         save_flags(flags);
  87         cli();
  88 
  89         if (irq_nr < 8) {
  90                 cache_21 &= mask;
  91                 outb(cache_21,0x21);
  92         } else if (irq_nr < 16) {
  93                 cache_A1 &= mask;
  94                 outb(cache_A1,0xA1);
  95 #if NR_IRQS == 33
  96         } else if (irq_nr < 24) {
  97                 cache_804 &= mask;
  98                 outb(cache_804, 0x804);
  99         } else if (irq_nr < 32) {
 100                 cache_805 &= mask;
 101                 outb(cache_805, 0x805);
 102         } else {
 103                 cache_806 &= mask;
 104                 outb(cache_806, 0x806);
 105 #elif NR_IRQS == 32
 106         } else if (irq_nr < 24) {
 107                 cache_26 &= mask;
 108                 outb(cache_26, 0x26);
 109         } else {
 110                 cache_27 &= mask;
 111                 outb(cache_27, 0x27);
 112 #endif
 113         }
 114         restore_flags(flags);
 115 }
 116 
 117 /*
 118  * Initial irq handlers.
 119  */
 120 static struct irqaction *irq_action[NR_IRQS];
 121 
 122 int get_irq_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         int i, len = 0;
 125         struct irqaction * action;
 126 
 127         for (i = 0 ; i < NR_IRQS ; i++) {
 128                 action = *(i + irq_action);
 129                 if (!action) 
 130                         continue;
 131                 len += sprintf(buf+len, "%2d: %8d %c %s",
 132                         i, kstat.interrupts[i],
 133                         (action->flags & SA_INTERRUPT) ? '+' : ' ',
 134                         action->name);
 135                 for (action=action->next; action; action = action->next) {
 136                         len += sprintf(buf+len, ",%s %s",
 137                                 (action->flags & SA_INTERRUPT) ? " +" : "",
 138                                 action->name);
 139                 }
 140                 len += sprintf(buf+len, "\n");
 141         }
 142         return len;
 143 }
 144 
 145 static inline void ack_irq(int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         if (irq < 16) {
 148                 /* ACK the interrupt making it the lowest priority */
 149                 /*  First the slave .. */
 150                 if (irq > 7) {
 151                         outb(0xE0 | (irq - 8), 0xa0);
 152                         irq = 2;
 153                 }
 154                 /* .. then the master */
 155                 outb(0xE0 | irq, 0x20);
 156         }
 157 }
 158 
 159 static inline void mask_irq(int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         unsigned char mask;
 162 
 163         mask = 1 << (irq & 7);
 164         if (irq < 8) {
 165                 cache_21 |= mask;
 166                 outb(cache_21, 0x21);
 167         } else if (irq < 16) {
 168                 cache_A1 |= mask;
 169                 outb(cache_A1, 0xA1);
 170 #if NR_IRQS == 33
 171         } else if (irq < 24) {
 172                 cache_804 |= mask;
 173                 outb(cache_804, 0x804);
 174         } else if (irq < 32) {
 175                 cache_805 |= mask;
 176                 outb(cache_805, 0x805);
 177         } else {
 178                 cache_806 |= mask;
 179                 outb(cache_806, 0x806);
 180 #elif NR_IRQS == 32
 181         } else if (irq < 24) {
 182                 cache_26 |= mask;
 183                 outb(cache_26, 0x26);
 184         } else {
 185                 cache_27 |= mask;
 186                 outb(cache_27, 0x27);
 187 #endif
 188         }
 189 }
 190 
 191 static inline void unmask_irq(unsigned long irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193         unsigned char mask = ~(1 << (irq & 7));
 194 
 195         if (irq < 8) {
 196                 cache_21 &= mask;
 197                 outb(cache_21, 0x21);
 198         } else if (irq < 16) {
 199                 cache_A1 &= mask;
 200                 outb(cache_A1, 0xA1);
 201 #if NR_IRQS == 33
 202         } else if (irq < 24) {
 203                 cache_804 &= mask;
 204                 outb(cache_804, 0x804);
 205         } else if (irq < 32) {
 206                 cache_805 &= mask;
 207                 outb(cache_805, 0x805);
 208         } else {
 209                 cache_806 &= mask;
 210                 outb(cache_806, 0x806);
 211 #elif NR_IRQS == 32
 212         } else if (irq < 24) {
 213                 cache_26 &= mask;
 214                 outb(cache_26, 0x26);
 215         } else {
 216                 cache_27 &= mask;
 217                 outb(cache_27, 0x27);
 218 #endif
 219         }
 220 }
 221 
 222 int request_irq(unsigned int irq, 
     /* [previous][next][first][last][top][bottom][index][help] */
 223                 void (*handler)(int, void *, struct pt_regs *),
 224                 unsigned long irqflags, 
 225                 const char * devname,
 226                 void *dev_id)
 227 {
 228         struct irqaction *action, *tmp = NULL;
 229         unsigned long flags;
 230 
 231         if (irq >= NR_IRQS)
 232                 return -EINVAL;
 233         /* don't accept requests for irq #0 */
 234         if (!irq)
 235                 return -EINVAL;
 236         if (!handler)
 237             return -EINVAL;
 238         action = *(irq + irq_action);
 239         if (action) {
 240             if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
 241                 for (tmp = action; tmp->next; tmp = tmp->next);
 242             } else {
 243                 return -EBUSY;
 244             }
 245             if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
 246               printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
 247               return -EBUSY;
 248             }   
 249         }
 250         save_flags(flags);
 251         cli();
 252         action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 253         if (!action) { 
 254             restore_flags(flags);
 255             return -ENOMEM;
 256         }
 257         
 258         action->handler = handler;
 259         action->flags = irqflags;
 260         action->mask = 0;
 261         action->name = devname;
 262         action->next = NULL;
 263         action->dev_id = dev_id;
 264 
 265         if (tmp) {
 266             tmp->next = action;
 267         } else {
 268             *(irq + irq_action) = action;
 269             enable_irq(irq);
 270             if (irq >= 8 && irq < 16) {
 271                 enable_irq(2);  /* ensure cascade is enabled too */
 272             }
 273         }
 274 
 275         restore_flags(flags);
 276         return 0;
 277 }
 278 
 279 void free_irq(unsigned int irq, void *dev_id)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281         struct irqaction * action = *(irq + irq_action);
 282         struct irqaction * tmp = NULL;
 283         unsigned long flags;
 284 
 285         if (irq >= NR_IRQS) {
 286                 printk("Trying to free IRQ%d\n", irq);
 287                 return;
 288         }
 289         if (!action->handler) {
 290                 printk("Trying to free free IRQ%d\n", irq);
 291                 return;
 292         }
 293         if (dev_id) {
 294             for (; action; action = action->next) {
 295                 if (action->dev_id == dev_id) break;
 296                 tmp = action;
 297             }
 298             if (!action) {
 299                 printk("Trying to free free shared IRQ%d\n",irq);
 300                 return;
 301             }
 302         } else if (action->flags & SA_SHIRQ) {
 303             printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
 304             return;
 305         }
 306         save_flags(flags);
 307         cli();
 308         if (action && tmp) {
 309             tmp->next = action->next;
 310         } else {
 311             *(irq + irq_action) = action->next;
 312         }
 313         kfree_s(action, sizeof(struct irqaction));
 314 
 315         if (!(*(irq + irq_action))) {
 316             mask_irq(irq);
 317         }
 318 
 319         restore_flags(flags);
 320 }
 321 
 322 static inline void handle_nmi(struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324         printk("Whee.. NMI received. Probable hardware error\n");
 325         printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
 326 }
 327 
 328 static void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 329 {
 330         struct irqaction *action;
 331         int i;
 332 
 333         printk("IO device interrupt, irq = %d\n", irq);
 334         printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
 335         printk("Expecting: ");
 336         for (i = 0; i < 16; i++)
 337                 if ((action = *(i + irq_action)))
 338                         while (action->handler) {
 339                                 printk("[%s:%d] ", action->name, i);
 340                                 action = action->next;
 341                         }
 342         printk("\n");
 343 #if defined(CONFIG_ALPHA_JENSEN)
 344         printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
 345                 inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
 346         outb(0x0c, 0x3fc);
 347         outb(0x0c, 0x2fc);
 348         outb(0,0x61);
 349         outb(0,0x461);
 350 #endif
 351 }
 352 
 353 static inline void handle_irq(int irq, void *dev_id, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 354 {
 355         struct irqaction * action = *(irq + irq_action);
 356 
 357         kstat.interrupts[irq]++;
 358         if (!action) {
 359             unexpected_irq(irq, action->dev_id, regs);
 360             return;
 361         }
 362         while (action) {
 363             action->handler(irq, action->dev_id, regs);
 364             action = action->next;
 365         }
 366 }
 367 
 368 static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370         struct irqaction * action;
 371 
 372         if ((unsigned) irq > NR_IRQS) {
 373                 printk("device_interrupt: unexpected interrupt %d\n", irq);
 374                 return;
 375         }
 376 
 377         kstat.interrupts[irq]++;
 378         action = *(irq_action + irq);
 379         if (action->flags & SA_SAMPLE_RANDOM)
 380                 add_interrupt_randomness(irq);
 381         /* quick interrupts get executed with no extra overhead */
 382         if (action->flags & SA_INTERRUPT) {
 383                 while (action) {
 384                         action->handler(irq, action->dev_id, regs);
 385                         action = action->next;
 386                 }
 387                 ack_irq(ack);
 388                 return;
 389         }
 390         /*
 391          * For normal interrupts, we mask it out, and then ACK it.
 392          * This way another (more timing-critical) interrupt can
 393          * come through while we're doing this one.
 394          *
 395          * Note! A irq without a handler gets masked and acked, but
 396          * never unmasked. The autoirq stuff depends on this (it looks
 397          * at the masks before and after doing the probing).
 398          */
 399         mask_irq(ack);
 400         ack_irq(ack);
 401         if (!action)
 402                 return;
 403         while (action) {
 404             action->handler(irq, action->dev_id, regs);
 405             action = action->next;
 406         }
 407         unmask_irq(ack);
 408 }
 409 
 410 /*
 411  * Handle ISA interrupt via the PICs.
 412  */
 413 static inline void isa_device_interrupt(unsigned long vector,
     /* [previous][next][first][last][top][bottom][index][help] */
 414                                         struct pt_regs * regs)
 415 {
 416 #if defined(CONFIG_ALPHA_APECS)
 417 #       define IACK_SC  APECS_IACK_SC
 418 #elif defined(CONFIG_ALPHA_LCA)
 419 #       define IACK_SC  LCA_IACK_SC
 420 #elif defined(CONFIG_ALPHA_ALCOR)
 421 #       define IACK_SC  ALCOR_IACK_SC
 422 #else
 423         /*
 424          * This is bogus but necessary to get it to compile
 425          * on all platforms.  If you try to use this on any
 426          * other than the intended platforms, you'll notice
 427          * real fast...
 428          */
 429 #       define IACK_SC  1L
 430 #endif
 431         int j;
 432 
 433 #if 1
 434         /*
 435          * Generate a PCI interrupt acknowledge cycle.  The PIC will
 436          * respond with the interrupt vector of the highest priority
 437          * interrupt that is pending.  The PALcode sets up the
 438          * interrupts vectors such that irq level L generates vector
 439          * L.
 440          */
 441         j = *(volatile int *) IACK_SC;
 442         j &= 0xff;
 443         if (j == 7) {
 444             if (!(inb(0x20) & 0x80)) {
 445                 /* it's only a passive release... */
 446                 return;
 447             }
 448         }
 449         device_interrupt(j, j, regs);
 450 #else
 451         unsigned long pic;
 452 
 453         /*
 454          * It seems to me that the probability of two or more *device*
 455          * interrupts occuring at almost exactly the same time is
 456          * pretty low.  So why pay the price of checking for
 457          * additional interrupts here if the common case can be
 458          * handled so much easier?
 459          */
 460         /* 
 461          *  The first read of gives you *all* interrupting lines.
 462          *  Therefore, read the mask register and and out those lines
 463          *  not enabled.  Note that some documentation has 21 and a1 
 464          *  write only.  This is not true.
 465          */
 466         pic = inb(0x20) | (inb(0xA0) << 8);     /* read isr */
 467         pic &= ~((cache_A1 << 8) | cache_21);   /* apply mask */
 468         pic &= 0xFFFB;                          /* mask out cascade */
 469 
 470         while (pic) {
 471                 j = ffz(~pic);
 472                 pic &= pic - 1;
 473                 device_interrupt(j, j, regs);
 474         }
 475 #endif
 476 }
 477 
 478 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
     /* [previous][next][first][last][top][bottom][index][help] */
 479                                                         struct pt_regs * regs)
 480 {
 481         unsigned long pld;
 482         unsigned int i;
 483         unsigned long flags;
 484 
 485         save_flags(flags);
 486         cli();
 487 
 488         /* read the interrupt summary registers */
 489         pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
 490 
 491 #if 0
 492         printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
 493 #endif
 494 
 495         /*
 496          * Now for every possible bit set, work through them and call
 497          * the appropriate interrupt handler.
 498          */
 499         while (pld) {
 500                 i = ffz(~pld);
 501                 pld &= pld - 1; /* clear least bit set */
 502                 if (i == 4) {
 503                         isa_device_interrupt(vector, regs);
 504                 } else {
 505                         device_interrupt(16 + i, 16 + i, regs);
 506                 }
 507         }
 508         restore_flags(flags);
 509 }
 510 
 511 static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
     /* [previous][next][first][last][top][bottom][index][help] */
 512                                                    struct pt_regs * regs)
 513 {
 514         unsigned long pld;
 515         unsigned int i;
 516         unsigned long flags;
 517 
 518         save_flags(flags);
 519         cli();
 520 
 521         /* read the interrupt summary registers */
 522         pld = inb(0x26) | (inb(0x27) << 8);
 523         /*
 524          * Now, for every possible bit set, work through
 525          * them and call the appropriate interrupt handler.
 526          */
 527         while (pld) {
 528                 i = ffz(~pld);
 529                 pld &= pld - 1; /* clear least bit set */
 530 
 531                 if (i == 5) {
 532                         isa_device_interrupt(vector, regs);
 533                 } else {
 534                         device_interrupt(16 + i, 16 + i, regs);
 535                 }
 536         }
 537         restore_flags(flags);
 538 }
 539 
 540 /*
 541  * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
 542  * 0x9X0 for the local motherboard interrupts..
 543  *
 544  *      0x660 - NMI
 545  *
 546  *      0x800 - IRQ0  interval timer (not used, as we use the RTC timer)
 547  *      0x810 - IRQ1  line printer (duh..)
 548  *      0x860 - IRQ6  floppy disk
 549  *      0x8E0 - IRQ14 SCSI controller
 550  *
 551  *      0x900 - COM1
 552  *      0x920 - COM2
 553  *      0x980 - keyboard
 554  *      0x990 - mouse
 555  *
 556  * PCI-based systems are more sane: they don't have the local
 557  * interrupts at all, and have only normal PCI interrupts from
 558  * devices.  Happily it's easy enough to do a sane mapping from the
 559  * Jensen..  Note that this means that we may have to do a hardware
 560  * "ack" to a different interrupt than we report to the rest of the
 561  * world.
 562  */
 563 static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 564 {
 565         int irq, ack;
 566         unsigned long flags;
 567 
 568         save_flags(flags);
 569         cli();
 570 
 571 
 572         ack = irq = (vector - 0x800) >> 4;
 573 
 574 #ifdef CONFIG_ALPHA_JENSEN
 575         switch (vector) {
 576               case 0x660: handle_nmi(regs); return;
 577                 /* local device interrupts: */
 578               case 0x900: handle_irq(4, regs); return;  /* com1 -> irq 4 */
 579               case 0x920: handle_irq(3, regs); return;  /* com2 -> irq 3 */
 580               case 0x980: handle_irq(1, regs); return;  /* kbd -> irq 1 */
 581               case 0x990: handle_irq(9, regs); return;  /* mouse -> irq 9 */
 582               default:
 583                 if (vector > 0x900) {
 584                         printk("Unknown local interrupt %lx\n", vector);
 585                 }
 586         }
 587         /* irq1 is supposed to be the keyboard, silly Jensen (is this really needed??) */
 588         if (irq == 1)
 589                 irq = 7;
 590 #endif /* CONFIG_ALPHA_JENSEN */
 591 
 592         device_interrupt(irq, ack, regs);
 593 
 594         restore_flags(flags) ;
 595 }
 596 
 597 #if NR_IRQS > 64
 598 #  error Number of irqs limited to 64 due to interrupt-probing.
 599 #endif
 600 
 601 /*
 602  * Start listening for interrupts..
 603  */
 604 unsigned long probe_irq_on(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 605 {
 606         struct irqaction * action;
 607         unsigned long irqs = 0, irqmask;
 608         unsigned long delay;
 609         unsigned int i;
 610 
 611         for (i = NR_IRQS - 1; i > 0; i--) {
 612                 action = *(i + irq_action);
 613                 if (!action->handler) {
 614                         enable_irq(i);
 615                         irqs |= (1 << i);
 616                 }
 617         }
 618 
 619         /* wait for spurious interrupts to mask themselves out again */
 620         for (delay = jiffies + HZ/10; delay > jiffies; )
 621                 /* about 100 ms delay */;
 622         
 623         /* now filter out any obviously spurious interrupts */
 624         irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
 625 #if NR_IRQS == 33
 626         irqmask |= ((((unsigned long)cache_804)<<16) |
 627                     (((unsigned long)cache_805)<<24) |
 628                     (((unsigned long)cache_806)<<24));
 629 #elif NR_IRQS == 32
 630         irqmask |= ((((unsigned long)cache_26)<<16) |
 631                     (((unsigned long)cache_27)<<24));
 632 #endif
 633         irqs &= ~irqmask;
 634         return irqs;
 635 }
 636 
 637 /*
 638  * Get the result of the IRQ probe.. A negative result means that
 639  * we have several candidates (but we return the lowest-numbered
 640  * one).
 641  */
 642 int probe_irq_off(unsigned long irqs)
     /* [previous][next][first][last][top][bottom][index][help] */
 643 {
 644         unsigned long irqmask;
 645         int i;
 646         
 647         irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
 648 #if NR_IRQS == 33
 649         irqmask |= ((((unsigned long)cache_804)<<16) |
 650                     (((unsigned long)cache_805)<<24) |
 651                     (((unsigned long)cache_806)<<24));
 652 #elif NR_IRQS == 32
 653         irqmask |= ((((unsigned long)cache_26)<<16) |
 654                     (((unsigned long)cache_27)<<24));
 655 #endif
 656         irqs &= irqmask & ~1;   /* always mask out irq 0---it's the unused timer */
 657 #ifdef CONFIG_ALPHA_P2K
 658         irqs &= ~(1 << 8);      /* mask out irq 8 since that's the unused RTC input to PIC */
 659 #endif
 660         if (!irqs)
 661                 return 0;
 662         i = ffz(~irqs);
 663         if (irqs != (1UL << i))
 664                 i = -i;
 665         return i;
 666 }
 667 
 668 static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 669 {
 670 #if defined(CONFIG_ALPHA_LCA)
 671         extern void lca_machine_check (unsigned long vector, unsigned long la,
 672                                        struct pt_regs *regs);
 673         lca_machine_check(vector, la, regs);
 674 #elif defined(CONFIG_ALPHA_APECS)
 675         extern void apecs_machine_check(unsigned long vector, unsigned long la,
 676                                         struct pt_regs * regs);
 677         apecs_machine_check(vector, la, regs);
 678 #elif defined(CONFIG_ALPHA_ALCOR)
 679         extern void alcor_machine_check(unsigned long vector, unsigned long la,
 680                                         struct pt_regs * regs);
 681         alcor_machine_check(vector, la, regs);
 682 #else
 683         printk("Machine check\n");
 684 #endif
 685 }
 686 
 687 asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
     /* [previous][next][first][last][top][bottom][index][help] */
 688         unsigned long a3, unsigned long a4, unsigned long a5,
 689         struct pt_regs regs)
 690 {
 691         switch (type) {
 692                 case 0:
 693                         printk("Interprocessor interrupt? You must be kidding\n");
 694                         break;
 695                 case 1:
 696                         timer_interrupt(&regs);
 697                         return;
 698                 case 2:
 699                         machine_check(vector, la_ptr, &regs);
 700                         return;
 701                 case 3:
 702 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \
 703     defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM)
 704                         srm_device_interrupt(vector, &regs);
 705 #elif NR_IRQS == 33
 706                         cabriolet_and_eb66p_device_interrupt(vector, &regs);
 707 #elif NR_IRQS == 32
 708                         eb66_and_eb64p_device_interrupt(vector, &regs);
 709 #elif NR_IRQS == 16
 710                         isa_device_interrupt(vector, &regs);
 711 #endif
 712                         return;
 713                 case 4:
 714                         printk("Performance counter interrupt\n");
 715                         break;;
 716                 default:
 717                         printk("Hardware intr %ld %lx? Huh?\n", type, vector);
 718         }
 719         printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
 720 }
 721 
 722 extern asmlinkage void entInt(void);
 723 
 724 void init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 725 {
 726         wrent(entInt, 0);
 727         dma_outb(0, DMA1_RESET_REG);
 728         dma_outb(0, DMA2_RESET_REG);
 729         dma_outb(0, DMA1_CLR_MASK_REG);
 730         dma_outb(0, DMA2_CLR_MASK_REG);
 731 #if NR_IRQS == 33
 732         outb(cache_804, 0x804);
 733         outb(cache_805, 0x805);
 734         outb(cache_806, 0x806);
 735 #elif NR_IRQS == 32
 736         outb(cache_26, 0x26);
 737         outb(cache_27, 0x27);
 738 #endif
 739 }

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