root/arch/i386/kernel/irq.c

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

DEFINITIONS

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

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