root/arch/i386/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. get_smp_prof_list
  5. do_IRQ
  6. do_fast_IRQ
  7. request_irq
  8. free_irq
  9. math_error_irq
  10. no_action
  11. probe_irq_on
  12. probe_irq_off
  13. init_IRQ

   1 /*
   2  *      linux/arch/i386/kernel/irq.c
   3  *
   4  *      Copyright (C) 1992 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 /*
  14  * IRQ's are in fact implemented a bit like signal handlers for the kernel.
  15  * Naturally it's not a 1:1 relation, but there are similarities.
  16  */
  17 
  18 #include <linux/ptrace.h>
  19 #include <linux/errno.h>
  20 #include <linux/kernel_stat.h>
  21 #include <linux/signal.h>
  22 #include <linux/sched.h>
  23 #include <linux/ioport.h>
  24 #include <linux/interrupt.h>
  25 #include <linux/timex.h>
  26 #include <linux/malloc.h>
  27 #include <linux/random.h>
  28 
  29 #include <asm/system.h>
  30 #include <asm/io.h>
  31 #include <asm/irq.h>
  32 #include <asm/bitops.h>
  33 #include <asm/smp.h>
  34 
  35 #define CR0_NE 32
  36 #define TIMER_IRQ 0                     /* Keep this in sync with time.c */
  37 
  38 static unsigned char cache_21 = 0xff;
  39 static unsigned char cache_A1 = 0xff;
  40 
  41 #ifdef __SMP_PROF__
  42 static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
  43 #endif
  44 
  45 void disable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47         unsigned long flags;
  48         unsigned char mask;
  49 
  50         mask = 1 << (irq_nr & 7);
  51         save_flags(flags);
  52         if (irq_nr < 8) {
  53                 cli();
  54                 cache_21 |= mask;
  55                 outb(cache_21,0x21);
  56                 restore_flags(flags);
  57                 return;
  58         }
  59         cli();
  60         cache_A1 |= mask;
  61         outb(cache_A1,0xA1);
  62         restore_flags(flags);
  63 }
  64 
  65 void enable_irq(unsigned int irq_nr)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         unsigned long flags;
  68         unsigned char mask;
  69 
  70         mask = ~(1 << (irq_nr & 7));
  71         save_flags(flags);
  72         if (irq_nr < 8) {
  73                 cli();
  74                 cache_21 &= mask;
  75                 outb(cache_21,0x21);
  76                 restore_flags(flags);
  77                 return;
  78         }
  79         cli();
  80         cache_A1 &= mask;
  81         outb(cache_A1,0xA1);
  82         restore_flags(flags);
  83 }
  84 
  85 /*
  86  * This builds up the IRQ handler stubs using some ugly macros in irq.h
  87  *
  88  * These macros create the low-level assembly IRQ routines that do all
  89  * the operations that are needed to keep the AT interrupt-controller
  90  * happy. They are also written to be fast - and to disable interrupts
  91  * as little as humanly possible.
  92  *
  93  * NOTE! These macros expand to three different handlers for each line: one
  94  * complete handler that does all the fancy stuff (including signal handling),
  95  * and one fast handler that is meant for simple IRQ's that want to be
  96  * atomic. The specific handler is chosen depending on the SA_INTERRUPT
  97  * flag when installing a handler. Finally, one "bad interrupt" handler, that
  98  * is used when no handler is present.
  99  */
 100 BUILD_IRQ(FIRST,0,0x01)
 101 BUILD_IRQ(FIRST,1,0x02)
 102 BUILD_IRQ(FIRST,2,0x04)
 103 BUILD_IRQ(FIRST,3,0x08)
 104 BUILD_IRQ(FIRST,4,0x10)
 105 BUILD_IRQ(FIRST,5,0x20)
 106 BUILD_IRQ(FIRST,6,0x40)
 107 BUILD_IRQ(FIRST,7,0x80)
 108 BUILD_IRQ(SECOND,8,0x01)
 109 BUILD_IRQ(SECOND,9,0x02)
 110 BUILD_IRQ(SECOND,10,0x04)
 111 BUILD_IRQ(SECOND,11,0x08)
 112 BUILD_IRQ(SECOND,12,0x10)
 113 #ifdef __SMP__
 114 BUILD_MSGIRQ(SECOND,13,0x20)
 115 #else
 116 BUILD_IRQ(SECOND,13,0x20)
 117 #endif
 118 BUILD_IRQ(SECOND,14,0x40)
 119 BUILD_IRQ(SECOND,15,0x80)
 120 #ifdef __SMP__
 121 BUILD_RESCHEDIRQ(16)
 122 #endif
 123 
 124 /*
 125  * Pointers to the low-level handlers: first the general ones, then the
 126  * fast ones, then the bad ones.
 127  */
 128 static void (*interrupt[17])(void) = {
 129         IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
 130         IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
 131         IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
 132         IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt      
 133 #ifdef __SMP__  
 134         ,IRQ16_interrupt
 135 #endif
 136 };
 137 
 138 static void (*fast_interrupt[16])(void) = {
 139         fast_IRQ0_interrupt, fast_IRQ1_interrupt,
 140         fast_IRQ2_interrupt, fast_IRQ3_interrupt,
 141         fast_IRQ4_interrupt, fast_IRQ5_interrupt,
 142         fast_IRQ6_interrupt, fast_IRQ7_interrupt,
 143         fast_IRQ8_interrupt, fast_IRQ9_interrupt,
 144         fast_IRQ10_interrupt, fast_IRQ11_interrupt,
 145         fast_IRQ12_interrupt, fast_IRQ13_interrupt,
 146         fast_IRQ14_interrupt, fast_IRQ15_interrupt
 147 };
 148 
 149 static void (*bad_interrupt[16])(void) = {
 150         bad_IRQ0_interrupt, bad_IRQ1_interrupt,
 151         bad_IRQ2_interrupt, bad_IRQ3_interrupt,
 152         bad_IRQ4_interrupt, bad_IRQ5_interrupt,
 153         bad_IRQ6_interrupt, bad_IRQ7_interrupt,
 154         bad_IRQ8_interrupt, bad_IRQ9_interrupt,
 155         bad_IRQ10_interrupt, bad_IRQ11_interrupt,
 156         bad_IRQ12_interrupt, bad_IRQ13_interrupt,
 157         bad_IRQ14_interrupt, bad_IRQ15_interrupt
 158 };
 159 
 160 /*
 161  * Initial irq handlers.
 162  */
 163 static struct irqaction timer_irq   = { NULL, 0, 0, NULL, NULL, NULL};
 164 static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
 165 static struct irqaction math_irq    = { NULL, 0, 0, NULL, NULL, NULL};
 166 
 167 static struct irqaction *irq_action[16] = {
 168           NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
 169           NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
 170 };
 171 
 172 int get_irq_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         int i, len = 0;
 175         struct irqaction * action;
 176 
 177         for (i = 0 ; i < 16 ; i++) {
 178                 action = *(i + irq_action);
 179                 if (!action) 
 180                         continue;
 181                 len += sprintf(buf+len, "%2d: %8d %c %s",
 182                         i, kstat.interrupts[i],
 183                         (action->flags & SA_INTERRUPT) ? '+' : ' ',
 184                         action->name);
 185                 for (action=action->next; action; action = action->next) {
 186                         len += sprintf(buf+len, ",%s %s",
 187                                 (action->flags & SA_INTERRUPT) ? " +" : "",
 188                                 action->name);
 189                 }
 190                 len += sprintf(buf+len, "\n");
 191         }
 192 /*
 193  *      Linus - should you add NMI counts here ?????
 194  */
 195 #ifdef __SMP_PROF__
 196         len+=sprintf(buf+len, "IPI: %8lu received\n",
 197                 ipi_count);
 198 #endif          
 199         return len;
 200 }
 201 
 202 #ifdef __SMP_PROF__
 203 
 204 int get_smp_prof_list(char *buf) {
     /* [previous][next][first][last][top][bottom][index][help] */
 205         int i,j, len = 0;
 206         struct irqaction * action;
 207         unsigned long sum_spins = 0;
 208         unsigned long sum_spins_syscall = 0;
 209         unsigned long sum_spins_sys_idle = 0;
 210         unsigned long sum_smp_idle_count = 0;
 211 
 212         for (i=0;i<=smp_num_cpus;i++) {
 213           sum_spins+=smp_spins[i];
 214           sum_spins_syscall+=smp_spins_syscall[i];
 215           sum_spins_sys_idle+=smp_spins_sys_idle[i];
 216           sum_smp_idle_count+=smp_idle_count[i];
 217         }
 218 
 219         len += sprintf(buf+len,"CPUS: %10i \n", 
 220                 0==smp_num_cpus?1:smp_num_cpus);
 221         len += sprintf(buf+len,"            SUM ");
 222         for (i=0;i<smp_num_cpus;i++)
 223           len += sprintf(buf+len,"        P%1d ",i);
 224         len += sprintf(buf+len,"\n");
 225         for (i = 0 ; i < NR_IRQS ; i++) {
 226                 action = *(i + irq_action);
 227                 if (!action->handler)
 228                         continue;
 229                 len += sprintf(buf+len, "%3d: %10d ",
 230                         i, kstat.interrupts[i]);
 231                 for (j=0;j<smp_num_cpus;j++)
 232                   len+=sprintf(buf+len, "%10d ",int_count[j][i]);
 233                 len += sprintf(buf+len, "%c %s\n",
 234                         (action->flags & SA_INTERRUPT) ? '+' : ' ',
 235                         action->name);
 236                 for (action=action->next; action; action = action->next) {
 237                         len += sprintf(buf+len, ",%s %s",
 238                                 (action->flags & SA_INTERRUPT) ? " +" : "",
 239                                 action->name);
 240                 }
 241         }
 242         len+=sprintf(buf+len, "LCK: %10lu",
 243                 sum_spins);
 244         for (i=0;i<smp_num_cpus;i++)
 245           len+=sprintf(buf+len," %10lu",smp_spins[i]);
 246         len +=sprintf(buf+len,"   spins from int\n");
 247 
 248         len+=sprintf(buf+len, "LCK: %10lu",
 249                 sum_spins_syscall);
 250         for (i=0;i<smp_num_cpus;i++)
 251           len+=sprintf(buf+len," %10lu",smp_spins_syscall[i]);
 252         len +=sprintf(buf+len,"   spins from syscall\n");
 253 
 254         len+=sprintf(buf+len, "LCK: %10lu",
 255                 sum_spins_sys_idle);
 256         for (i=0;i<smp_num_cpus;i++)
 257           len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[i]);
 258         len +=sprintf(buf+len,"   spins from sysidle\n");
 259         len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
 260         for (i=0;i<smp_num_cpus;i++)
 261           len+=sprintf(buf+len," %10lu",smp_idle_count[i]);
 262         len +=sprintf(buf+len,"   idle ticks\n");
 263 
 264         len+=sprintf(buf+len, "IPI: %10lu   received\n",
 265                 ipi_count);
 266 
 267         return len;
 268 }
 269 #endif 
 270 
 271 
 272 
 273 /*
 274  * do_IRQ handles IRQ's that have been installed without the
 275  * SA_INTERRUPT flag: it uses the full signal-handling return
 276  * and runs with other interrupts enabled. All relatively slow
 277  * IRQ's should use this format: notably the keyboard/timer
 278  * routines.
 279  */
 280 asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282         struct irqaction * action = *(irq + irq_action);
 283 
 284 #ifdef __SMP__
 285         if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
 286                 panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
 287 #endif
 288 
 289         kstat.interrupts[irq]++;
 290 #ifdef __SMP_PROF__
 291         int_count[smp_processor_id()][irq]++;
 292 #endif
 293         while (action) {
 294             if (action->flags & SA_SAMPLE_RANDOM) {
 295                 add_interrupt_randomness(irq);
 296             }
 297             action->handler(irq, action->dev_id, regs);
 298             action = action->next;
 299         }
 300 }
 301 
 302 /*
 303  * do_fast_IRQ handles IRQ's that don't need the fancy interrupt return
 304  * stuff - the handler is also running with interrupts disabled unless
 305  * it explicitly enables them later.
 306  */
 307 asmlinkage void do_fast_IRQ(int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309         struct irqaction * action = *(irq + irq_action);
 310 #ifdef __SMP__
 311         /* IRQ 13 is allowed - thats an invalidate */
 312         if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
 313                 panic("fast_IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
 314 #endif
 315 
 316         kstat.interrupts[irq]++;
 317 #ifdef __SMP_PROF__
 318         int_count[smp_processor_id()][irq]++;
 319 #endif
 320         while (action) {
 321             if (action->flags & SA_SAMPLE_RANDOM)
 322                 add_interrupt_randomness(irq);
 323             action->handler(irq, action->dev_id, NULL);
 324             action = action->next;
 325         }
 326 }
 327 
 328 #define SA_PROBE SA_ONESHOT
 329 
 330 int request_irq(unsigned int irq, 
     /* [previous][next][first][last][top][bottom][index][help] */
 331                 void (*handler)(int, void *, struct pt_regs *),
 332                 unsigned long irqflags, 
 333                 const char * devname,
 334                 void *dev_id)
 335 {
 336         struct irqaction * action, *tmp = NULL;
 337         unsigned long flags;
 338 
 339         if (irq > 15)
 340             return -EINVAL;
 341         if (!handler)
 342             return -EINVAL;
 343         action = *(irq + irq_action);
 344         if (action) {
 345             if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
 346                 for (tmp = action; tmp->next; tmp = tmp->next);
 347             } else {
 348                 return -EBUSY;
 349             }
 350             if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
 351               printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
 352               return -EBUSY;
 353             }   
 354         }
 355         if (irqflags & SA_SAMPLE_RANDOM)
 356                 rand_initialize_irq(irq);
 357         save_flags(flags);
 358         cli();
 359         if (irq == 2)
 360             action = &cascade_irq;
 361         else if (irq == 13)
 362           action = &math_irq;
 363         else if (irq == TIMER_IRQ)
 364           action = &timer_irq;
 365         else
 366           action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 367 
 368         if (!action) { 
 369             restore_flags(flags);
 370             return -ENOMEM;
 371         }
 372 
 373         action->handler = handler;
 374         action->flags = irqflags;
 375         action->mask = 0;
 376         action->name = devname;
 377         action->next = NULL;
 378         action->dev_id = dev_id;
 379 
 380         if (tmp) {
 381             tmp->next = action;
 382         } else {
 383             *(irq + irq_action) = action;
 384             if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */
 385                 if (action->flags & SA_INTERRUPT)
 386                   set_intr_gate(0x20+irq,fast_interrupt[irq]);
 387                 else
 388                   set_intr_gate(0x20+irq,interrupt[irq]);
 389             }
 390             if (irq < 8) {
 391                 cache_21 &= ~(1<<irq);
 392                 outb(cache_21,0x21);
 393             } else {
 394                 cache_21 &= ~(1<<2);
 395                 cache_A1 &= ~(1<<(irq-8));
 396                 outb(cache_21,0x21);
 397                 outb(cache_A1,0xA1);
 398             }
 399         }
 400 
 401         restore_flags(flags);
 402         return 0;
 403 }
 404                 
 405 void free_irq(unsigned int irq, void *dev_id)
     /* [previous][next][first][last][top][bottom][index][help] */
 406 {
 407         struct irqaction * action = *(irq + irq_action);
 408         struct irqaction * tmp = NULL;
 409         unsigned long flags;
 410 
 411         if (irq > 15) {
 412                 printk("Trying to free IRQ%d\n",irq);
 413                 return;
 414         }
 415         if (!action->handler) {
 416                 printk("Trying to free free IRQ%d\n",irq);
 417                 return;
 418         }
 419         if (dev_id) {
 420             for (; action; action = action->next) {
 421                 if (action->dev_id == dev_id) break;
 422                 tmp = action;
 423             }
 424             if (!action) {
 425                 printk("Trying to free free shared IRQ%d\n",irq);
 426                 return;
 427             }
 428         } else if (action->flags & SA_SHIRQ) {
 429             printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
 430             return;
 431         }
 432         save_flags(flags);
 433         cli();
 434         if (action && tmp) {
 435             tmp->next = action->next;
 436         } else {
 437             *(irq + irq_action) = action->next;
 438         }
 439 
 440         if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
 441           memset(action, 0, sizeof(struct irqaction));
 442         else 
 443           kfree_s(action, sizeof(struct irqaction));
 444         
 445         if (!(*(irq + irq_action))) {
 446             if (irq < 8) {
 447                 cache_21 |= 1 << irq;
 448                 outb(cache_21,0x21);
 449             } else {
 450                 cache_A1 |= 1 << (irq-8);
 451                 outb(cache_A1,0xA1);
 452             }
 453             set_intr_gate(0x20+irq,bad_interrupt[irq]);
 454         }
 455 
 456         restore_flags(flags);
 457 }
 458 
 459 #ifndef __SMP__
 460 
 461 /*
 462  * Note that on a 486, we don't want to do a SIGFPE on a irq13
 463  * as the irq is unreliable, and exception 16 works correctly
 464  * (ie as explained in the intel literature). On a 386, you
 465  * can't use exception 16 due to bad IBM design, so we have to
 466  * rely on the less exact irq13.
 467  *
 468  * Careful.. Not only is IRQ13 unreliable, but it is also
 469  * leads to races. IBM designers who came up with it should
 470  * be shot.
 471  */
 472  
 473 
 474 static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476         outb(0,0xF0);
 477         if (ignore_irq13 || !hard_math)
 478                 return;
 479         math_error();
 480 }
 481 
 482 #endif
 483 
 484 static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
     /* [previous][next][first][last][top][bottom][index][help] */
 485 
 486 unsigned long probe_irq_on (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 487 {
 488         unsigned int i, irqs = 0, irqmask;
 489         unsigned long delay;
 490 
 491         /* first, snaffle up any unassigned irqs */
 492         for (i = 15; i > 0; i--) {
 493                 if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
 494                         enable_irq(i);
 495                         irqs |= (1 << i);
 496                 }
 497         }
 498 
 499         /* wait for spurious interrupts to mask themselves out again */
 500         for (delay = jiffies + 2; delay > jiffies; );   /* min 10ms delay */
 501 
 502         /* now filter out any obviously spurious interrupts */
 503         irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
 504         for (i = 15; i > 0; i--) {
 505                 if (irqs & (1 << i) & irqmask) {
 506                         irqs ^= (1 << i);
 507                         free_irq(i, NULL);
 508                 }
 509         }
 510 #ifdef DEBUG
 511         printk("probe_irq_on:  irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
 512 #endif
 513         return irqs;
 514 }
 515 
 516 int probe_irq_off (unsigned long irqs)
     /* [previous][next][first][last][top][bottom][index][help] */
 517 {
 518         unsigned int i, irqmask;
 519 
 520         irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
 521         for (i = 15; i > 0; i--) {
 522                 if (irqs & (1 << i)) {
 523                         free_irq(i, NULL);
 524                 }
 525         }
 526 #ifdef DEBUG
 527         printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
 528 #endif
 529         irqs &= irqmask;
 530         if (!irqs)
 531                 return 0;
 532         i = ffz(~irqs);
 533         if (irqs != (irqs & (1 << i)))
 534                 i = -i;
 535         return i;
 536 }
 537 
 538 void init_IRQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540         int i;
 541         static unsigned char smptrap=0;
 542         if(smptrap)
 543                 return;
 544         smptrap=1;
 545 
 546         /* set the clock to 100 Hz */
 547         outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
 548         outb_p(LATCH & 0xff , 0x40);    /* LSB */
 549         outb(LATCH >> 8 , 0x40);        /* MSB */
 550         for (i = 0; i < 16 ; i++)
 551                 set_intr_gate(0x20+i,bad_interrupt[i]);
 552         /* This bit is a hack because we don't send timer messages to all processors yet */
 553         /* It has to here .. it doesnt work if you put it down the bottom - assembler explodes 8) */
 554 #ifdef __SMP__  
 555         set_intr_gate(0x20+i, interrupt[i]);    /* IRQ '16' - IPI for rescheduling */
 556 #endif  
 557         if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
 558                 printk("Unable to get IRQ2 for cascade.\n");
 559 #ifndef __SMP__         
 560         if (request_irq(13, math_error_irq, 0, "math error", NULL))
 561                 printk("Unable to get IRQ13 for math-error handler.\n");
 562 #else
 563         if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI", NULL))
 564                 printk("Unable to get IRQ13 for IPI.\n");
 565 #endif                          
 566         request_region(0x20,0x20,"pic1");
 567         request_region(0xa0,0x20,"pic2");
 568 } 

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