|
|
1.1 root 1: /*
2: * Linux IRQ management.
3: * Copyright (C) 1995 Shantanu Goel.
4: *
5: * This program is free software; you can redistribute it and/or modify
6: * it under the terms of the GNU General Public License as published by
7: * the Free Software Foundation; either version 2, or (at your option)
8: * any later version.
9: *
10: * This program is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: * GNU General Public License for more details.
14: *
15: * You should have received a copy of the GNU General Public License
16: * along with this program; if not, write to the Free Software
17: * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18: */
19:
20: /*
21: * linux/arch/i386/kernel/irq.c
22: *
23: * Copyright (C) 1992 Linus Torvalds
24: */
25:
26: #include <sys/types.h>
27: #include <mach/mach_types.h>
28: #include <mach/vm_param.h>
29: #include <kern/assert.h>
30:
31: #include <i386/spl.h>
32: #include <i386/pic.h>
33: #include <i386/pit.h>
34:
35: #define MACH_INCLUDE
36: #include <linux/mm.h>
37: #include <linux/interrupt.h>
38: #include <linux/ptrace.h>
39: #include <linux/delay.h>
40: #include <linux/kernel_stat.h>
41: #include <linux/malloc.h>
42: #include <linux/ioport.h>
43:
44: #include <asm/system.h>
45: #include <asm/bitops.h>
46: #include <asm/irq.h>
47: #include <asm/io.h>
1.1.1.2 ! root 48: #include <asm/hardirq.h>
1.1 root 49:
1.1.1.2 ! root 50: #include <linux/dev/glue/glue.h>
! 51: #include <machine/machspl.h>
! 52:
! 53: #if 0
! 54: /* XXX: This is the way it's done in linux 2.2. GNU Mach currently uses intr_count. It should be made using local_{bh/irq}_count instead (through hardirq_enter/exit) for SMP support. */
! 55: unsigned int local_bh_count[NR_CPUS];
! 56: unsigned int local_irq_count[NR_CPUS];
! 57: #endif
1.1 root 58:
59: /*
60: * XXX Move this into more suitable place...
61: * Set if the machine has an EISA bus.
62: */
63: int EISA_bus = 0;
64:
65: /*
66: * Priority at which a Linux handler should be called.
67: * This is used at the time of an IRQ allocation. It is
68: * set by emulation routines for each class of device.
69: */
70: spl_t linux_intr_pri;
71:
72: /*
73: * Flag indicating an interrupt is being handled.
74: */
1.1.1.2 ! root 75: unsigned int intr_count = 0;
1.1 root 76:
77: /*
78: * List of Linux interrupt handlers.
79: */
80: struct linux_action
81: {
82: void (*handler) (int, void *, struct pt_regs *);
83: void *dev_id;
84: struct linux_action *next;
85: unsigned long flags;
86: };
87:
88: static struct linux_action *irq_action[16] =
89: {
90: NULL, NULL, NULL, NULL,
91: NULL, NULL, NULL, NULL,
92: NULL, NULL, NULL, NULL,
93: NULL, NULL, NULL, NULL
94: };
95:
96: /*
97: * Generic interrupt handler for Linux devices.
98: * Set up a fake `struct pt_regs' then call the real handler.
99: */
1.1.1.2 ! root 100: static void
1.1 root 101: linux_intr (int irq)
102: {
103: struct pt_regs regs;
104: struct linux_action *action = *(irq_action + irq);
1.1.1.2 ! root 105: unsigned long flags;
1.1 root 106:
107: kstat.interrupts[irq]++;
108: intr_count++;
109:
1.1.1.2 ! root 110: save_flags (flags);
! 111: if (action && (action->flags & SA_INTERRUPT))
! 112: cli ();
! 113:
1.1 root 114: while (action)
115: {
116: action->handler (irq, action->dev_id, ®s);
117: action = action->next;
118: }
119:
1.1.1.2 ! root 120: restore_flags (flags);
1.1 root 121:
1.1.1.2 ! root 122: intr_count--;
1.1 root 123: }
124:
125: /*
126: * Mask an IRQ.
127: */
128: static inline void
129: mask_irq (unsigned int irq_nr)
130: {
131: int i;
132:
133: for (i = 0; i < intpri[irq_nr]; i++)
134: pic_mask[i] |= 1 << irq_nr;
135:
136: if (curr_pic_mask != pic_mask[curr_ipl])
137: {
138: curr_pic_mask = pic_mask[curr_ipl];
139: if (irq_nr < 8)
140: outb (curr_pic_mask & 0xff, PIC_MASTER_OCW);
141: else
142: outb (curr_pic_mask >> 8, PIC_SLAVE_OCW);
143: }
144: }
145:
146: /*
147: * Unmask an IRQ.
148: */
149: static inline void
150: unmask_irq (unsigned int irq_nr)
151: {
152: int mask, i;
153:
154: mask = 1 << irq_nr;
155: if (irq_nr >= 8)
156: mask |= 1 << 2;
157:
158: for (i = 0; i < intpri[irq_nr]; i++)
159: pic_mask[i] &= ~mask;
160:
161: if (curr_pic_mask != pic_mask[curr_ipl])
162: {
163: curr_pic_mask = pic_mask[curr_ipl];
164: if (irq_nr < 8)
165: outb (curr_pic_mask & 0xff, PIC_MASTER_OCW);
166: else
167: outb (curr_pic_mask >> 8, PIC_SLAVE_OCW);
168: }
169: }
170:
171: void
172: disable_irq (unsigned int irq_nr)
173: {
174: unsigned long flags;
175:
176: assert (irq_nr < NR_IRQS);
177:
178: save_flags (flags);
179: cli ();
180: mask_irq (irq_nr);
181: restore_flags (flags);
182: }
183:
184: void
185: enable_irq (unsigned int irq_nr)
186: {
187: unsigned long flags;
188:
189: assert (irq_nr < NR_IRQS);
190:
191: save_flags (flags);
192: cli ();
193: unmask_irq (irq_nr);
194: restore_flags (flags);
195: }
196:
197: /*
198: * Default interrupt handler for Linux.
199: */
1.1.1.2 ! root 200: void
1.1 root 201: linux_bad_intr (int irq)
202: {
203: mask_irq (irq);
204: }
205:
206: static int
207: setup_x86_irq (int irq, struct linux_action *new)
208: {
209: int shared = 0;
210: struct linux_action *old, **p;
211: unsigned long flags;
212:
213: p = irq_action + irq;
214: if ((old = *p) != NULL)
215: {
216: /* Can't share interrupts unless both agree to */
217: if (!(old->flags & new->flags & SA_SHIRQ))
1.1.1.2 ! root 218: return (-EBUSY);
1.1 root 219:
220: /* Can't share interrupts unless both are same type */
221: if ((old->flags ^ new->flags) & SA_INTERRUPT)
1.1.1.2 ! root 222: return (-EBUSY);
! 223:
! 224: /* Can't share at different levels */
! 225: if (intpri[irq] && linux_intr_pri != intpri[irq])
! 226: return (-EBUSY);
1.1 root 227:
228: /* add new interrupt at end of irq queue */
229: do
230: {
231: p = &old->next;
232: old = *p;
233: }
234: while (old);
235: shared = 1;
236: }
237:
238: save_flags (flags);
239: cli ();
240: *p = new;
241:
242: if (!shared)
243: {
244: ivect[irq] = linux_intr;
245: iunit[irq] = irq;
246: intpri[irq] = linux_intr_pri;
247: unmask_irq (irq);
248: }
249: restore_flags (flags);
250: return 0;
251: }
252:
253: /*
254: * Attach a handler to an IRQ.
255: */
256: int
257: request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *),
258: unsigned long flags, const char *device, void *dev_id)
259: {
260: struct linux_action *action;
261: int retval;
262:
263: assert (irq < 16);
264:
265: if (!handler)
1.1.1.2 ! root 266: return -EINVAL;
1.1 root 267:
268: /*
269: * Hmm... Should I use `kalloc()' ?
270: * By OKUJI Yoshinori.
271: */
272: action = (struct linux_action *)
273: linux_kmalloc (sizeof (struct linux_action), GFP_KERNEL);
274: if (action == NULL)
1.1.1.2 ! root 275: return -ENOMEM;
1.1 root 276:
277: action->handler = handler;
278: action->next = NULL;
279: action->dev_id = dev_id;
280: action->flags = flags;
281:
282: retval = setup_x86_irq (irq, action);
283: if (retval)
284: linux_kfree (action);
285:
286: return retval;
287: }
288:
289: /*
290: * Deallocate an irq.
291: */
292: void
293: free_irq (unsigned int irq, void *dev_id)
294: {
295: struct linux_action *action, **p;
296: unsigned long flags;
297:
298: if (irq > 15)
299: panic ("free_irq: bad irq number");
300:
301: for (p = irq_action + irq; (action = *p) != NULL; p = &action->next)
302: {
303: if (action->dev_id != dev_id)
304: continue;
305:
306: save_flags (flags);
307: cli ();
308: *p = action->next;
309: if (!irq_action[irq])
310: {
311: mask_irq (irq);
312: ivect[irq] = linux_bad_intr;
313: iunit[irq] = irq;
314: intpri[irq] = SPL0;
315: }
316: restore_flags (flags);
317: linux_kfree (action);
318: return;
319: }
320:
321: panic ("free_irq: bad irq number");
322: }
323:
324: /*
325: * Set for an irq probe.
326: */
327: unsigned long
328: probe_irq_on (void)
329: {
330: unsigned i, irqs = 0;
331: unsigned long delay;
332:
333: assert (curr_ipl == 0);
334:
335: /*
336: * Allocate all available IRQs.
337: */
338: for (i = 15; i > 0; i--)
339: {
340: if (!irq_action[i] && ivect[i] == linux_bad_intr)
341: {
342: intpri[i] = linux_intr_pri;
343: enable_irq (i);
344: irqs |= 1 << i;
345: }
346: }
347:
348: /*
349: * Wait for spurious interrupts to mask themselves out.
350: */
351: for (delay = jiffies + HZ / 10; delay > jiffies;)
352: ;
353:
354: return (irqs & ~curr_pic_mask);
355: }
356:
357: /*
358: * Return the result of an irq probe.
359: */
360: int
361: probe_irq_off (unsigned long irqs)
362: {
363: unsigned int i;
364:
365: assert (curr_ipl == 0);
366:
367: irqs &= curr_pic_mask;
368:
369: /*
370: * Disable unnecessary IRQs.
371: */
372: for (i = 15; i > 0; i--)
373: {
374: if (!irq_action[i] && ivect[i] == linux_bad_intr)
375: {
376: disable_irq (i);
377: intpri[i] = SPL0;
378: }
379: }
380:
381: /*
382: * Return IRQ number.
383: */
384: if (!irqs)
385: return 0;
386: i = ffz (~irqs);
387: if (irqs != (irqs & (1 << i)))
388: i = -i;
389: return i;
390: }
391:
392: /*
393: * Reserve IRQs used by Mach drivers.
394: * Must be called before Linux IRQ detection, after Mach IRQ detection.
395: */
396: static void
397: reserve_mach_irqs (void)
398: {
399: unsigned int i;
400:
401: for (i = 0; i < 16; i++)
402: {
403: if (ivect[i] != prtnull && ivect[i] != intnull)
404: /* Set non-NULL value. */
405: irq_action[i] = (struct linux_action *) -1;
406: }
407: }
408:
1.1.1.2 ! root 409: #ifdef __SMP__
! 410: unsigned char global_irq_holder = NO_PROC_ID;
! 411: unsigned volatile int global_irq_lock;
! 412: atomic_t global_irq_count;
! 413:
! 414: atomic_t global_bh_count;
! 415: atomic_t global_bh_lock;
! 416:
! 417: /*
! 418: * "global_cli()" is a special case, in that it can hold the
! 419: * interrupts disabled for a longish time, and also because
! 420: * we may be doing TLB invalidates when holding the global
! 421: * IRQ lock for historical reasons. Thus we may need to check
! 422: * SMP invalidate events specially by hand here (but not in
! 423: * any normal spinlocks)
! 424: */
! 425: #if 0
! 426: /* XXX: check how Mach handles this */
! 427: static inline void check_smp_invalidate(int cpu)
! 428: {
! 429: if (test_bit(cpu, &smp_invalidate_needed)) {
! 430: clear_bit(cpu, &smp_invalidate_needed);
! 431: local_flush_tlb();
! 432: }
! 433: }
! 434: #endif
! 435:
! 436: static void show(char * str)
! 437: {
! 438: int i;
! 439: unsigned long *stack;
! 440: int cpu = smp_processor_id();
! 441:
! 442: printk("\n%s, CPU %d:\n", str, cpu);
! 443: printk("irq: %d [%d %d]\n",
! 444: atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
! 445: printk("bh: %d [%d %d]\n",
! 446: atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
! 447: stack = (unsigned long *) &stack;
! 448: for (i = 40; i ; i--) {
! 449: unsigned long x = *++stack;
! 450: //if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) {
! 451: printk("<[%08lx]> ", x);
! 452: //}
! 453: }
! 454: }
! 455:
! 456: #define MAXCOUNT 100000000
! 457:
! 458: static inline void wait_on_bh(void)
! 459: {
! 460: int count = MAXCOUNT;
! 461: do {
! 462: if (!--count) {
! 463: show("wait_on_bh");
! 464: count = ~0;
! 465: }
! 466: /* nothing .. wait for the other bh's to go away */
! 467: } while (atomic_read(&global_bh_count) != 0);
! 468: }
! 469:
! 470: /*
! 471: * I had a lockup scenario where a tight loop doing
! 472: * spin_unlock()/spin_lock() on CPU#1 was racing with
! 473: * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
! 474: * apparently the spin_unlock() information did not make it
! 475: * through to CPU#0 ... nasty, is this by design, do we have to limit
! 476: * 'memory update oscillation frequency' artificially like here?
! 477: *
! 478: * Such 'high frequency update' races can be avoided by careful design, but
! 479: * some of our major constructs like spinlocks use similar techniques,
! 480: * it would be nice to clarify this issue. Set this define to 0 if you
! 481: * want to check whether your system freezes. I suspect the delay done
! 482: * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
! 483: * i thought that such things are guaranteed by design, since we use
! 484: * the 'LOCK' prefix.
! 485: */
! 486: #define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 1
! 487:
! 488: #if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
! 489: # define SYNC_OTHER_CORES(x) udelay(x+1)
! 490: #else
! 491: /*
! 492: * We have to allow irqs to arrive between __sti and __cli
! 493: */
! 494: # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
! 495: #endif
! 496:
! 497: static inline void wait_on_irq(int cpu)
! 498: {
! 499: int count = MAXCOUNT;
! 500:
! 501: for (;;) {
! 502:
! 503: /*
! 504: * Wait until all interrupts are gone. Wait
! 505: * for bottom half handlers unless we're
! 506: * already executing in one..
! 507: */
! 508: if (!atomic_read(&global_irq_count)) {
! 509: if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
! 510: break;
! 511: }
! 512:
! 513: /* Duh, we have to loop. Release the lock to avoid deadlocks */
! 514: clear_bit(0,&global_irq_lock);
! 515:
! 516: for (;;) {
! 517: if (!--count) {
! 518: show("wait_on_irq");
! 519: count = ~0;
! 520: }
! 521: __sti();
! 522: SYNC_OTHER_CORES(cpu);
! 523: __cli();
! 524: //check_smp_invalidate(cpu);
! 525: if (atomic_read(&global_irq_count))
! 526: continue;
! 527: if (global_irq_lock)
! 528: continue;
! 529: if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
! 530: continue;
! 531: if (!test_and_set_bit(0,&global_irq_lock))
! 532: break;
! 533: }
! 534: }
! 535: }
! 536:
! 537: /*
! 538: * This is called when we want to synchronize with
! 539: * bottom half handlers. We need to wait until
! 540: * no other CPU is executing any bottom half handler.
! 541: *
! 542: * Don't wait if we're already running in an interrupt
! 543: * context or are inside a bh handler.
! 544: */
! 545: void synchronize_bh(void)
! 546: {
! 547: if (atomic_read(&global_bh_count) && !in_interrupt())
! 548: wait_on_bh();
! 549: }
! 550:
! 551: /*
! 552: * This is called when we want to synchronize with
! 553: * interrupts. We may for example tell a device to
! 554: * stop sending interrupts: but to make sure there
! 555: * are no interrupts that are executing on another
! 556: * CPU we need to call this function.
! 557: */
! 558: void synchronize_irq(void)
! 559: {
! 560: if (atomic_read(&global_irq_count)) {
! 561: /* Stupid approach */
! 562: cli();
! 563: sti();
! 564: }
! 565: }
! 566:
! 567: static inline void get_irqlock(int cpu)
! 568: {
! 569: if (test_and_set_bit(0,&global_irq_lock)) {
! 570: /* do we already hold the lock? */
! 571: if ((unsigned char) cpu == global_irq_holder)
! 572: return;
! 573: /* Uhhuh.. Somebody else got it. Wait.. */
! 574: do {
! 575: do {
! 576: //check_smp_invalidate(cpu);
! 577: } while (test_bit(0,&global_irq_lock));
! 578: } while (test_and_set_bit(0,&global_irq_lock));
! 579: }
! 580: /*
! 581: * We also to make sure that nobody else is running
! 582: * in an interrupt context.
! 583: */
! 584: wait_on_irq(cpu);
! 585:
! 586: /*
! 587: * Ok, finally..
! 588: */
! 589: global_irq_holder = cpu;
! 590: }
! 591:
! 592: #define EFLAGS_IF_SHIFT 9
! 593:
! 594: /*
! 595: * A global "cli()" while in an interrupt context
! 596: * turns into just a local cli(). Interrupts
! 597: * should use spinlocks for the (very unlikely)
! 598: * case that they ever want to protect against
! 599: * each other.
! 600: *
! 601: * If we already have local interrupts disabled,
! 602: * this will not turn a local disable into a
! 603: * global one (problems with spinlocks: this makes
! 604: * save_flags+cli+sti usable inside a spinlock).
! 605: */
! 606: void __global_cli(void)
! 607: {
! 608: unsigned int flags;
! 609:
! 610: __save_flags(flags);
! 611: if (flags & (1 << EFLAGS_IF_SHIFT)) {
! 612: int cpu = smp_processor_id();
! 613: __cli();
! 614: if (!local_irq_count[cpu])
! 615: get_irqlock(cpu);
! 616: }
! 617: }
! 618:
! 619: void __global_sti(void)
! 620: {
! 621: int cpu = smp_processor_id();
! 622:
! 623: if (!local_irq_count[cpu])
! 624: release_irqlock(cpu);
! 625: __sti();
! 626: }
! 627:
! 628: /*
! 629: * SMP flags value to restore to:
! 630: * 0 - global cli
! 631: * 1 - global sti
! 632: * 2 - local cli
! 633: * 3 - local sti
! 634: */
! 635: unsigned long __global_save_flags(void)
! 636: {
! 637: int retval;
! 638: int local_enabled;
! 639: unsigned long flags;
! 640:
! 641: __save_flags(flags);
! 642: local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
! 643: /* default to local */
! 644: retval = 2 + local_enabled;
! 645:
! 646: /* check for global flags if we're not in an interrupt */
! 647: if (!local_irq_count[smp_processor_id()]) {
! 648: if (local_enabled)
! 649: retval = 1;
! 650: if (global_irq_holder == (unsigned char) smp_processor_id())
! 651: retval = 0;
! 652: }
! 653: return retval;
! 654: }
! 655:
! 656: void __global_restore_flags(unsigned long flags)
! 657: {
! 658: switch (flags) {
! 659: case 0:
! 660: __global_cli();
! 661: break;
! 662: case 1:
! 663: __global_sti();
! 664: break;
! 665: case 2:
! 666: __cli();
! 667: break;
! 668: case 3:
! 669: __sti();
! 670: break;
! 671: default:
! 672: printk("global_restore_flags: %08lx (%08lx)\n",
! 673: flags, (&flags)[-1]);
! 674: }
! 675: }
! 676:
! 677: #endif
! 678:
! 679: static void (*old_clock_handler) ();
1.1 root 680: static int old_clock_pri;
681:
682: void
683: init_IRQ (void)
684: {
685: int i;
686: char *p;
687: int latch = (CLKNUM + hz / 2) / hz;
688:
689: /*
690: * Ensure interrupts are disabled.
691: */
692: (void) splhigh ();
693:
694: /*
695: * Program counter 0 of 8253 to interrupt hz times per second.
696: */
697: outb_p (PIT_C0 | PIT_SQUAREMODE | PIT_READMODE, PITCTL_PORT);
698: outb_p (latch && 0xff, PITCTR0_PORT);
699: outb (latch >> 8, PITCTR0_PORT);
700:
701: /*
702: * Install our clock interrupt handler.
703: */
704: old_clock_handler = ivect[0];
705: old_clock_pri = intpri[0];
706: ivect[0] = linux_timer_intr;
707: intpri[0] = SPLHI;
708:
709: reserve_mach_irqs ();
710:
711: for (i = 1; i < 16; i++)
712: {
713: /*
714: * irq2 and irq13 should be igonored.
715: */
716: if (i == 2 || i == 13)
717: continue;
718: if (ivect[i] == prtnull || ivect[i] == intnull)
719: {
720: ivect[i] = linux_bad_intr;
721: iunit[i] = i;
722: intpri[i] = SPL0;
723: }
724: }
725:
726: form_pic_mask ();
727:
728: /*
729: * Enable interrupts.
730: */
731: (void) spl0 ();
732:
733: /*
734: * Check if the machine has an EISA bus.
735: */
736: p = (char *) 0x0FFFD9;
737: if (*p++ == 'E' && *p++ == 'I' && *p++ == 'S' && *p == 'A')
738: EISA_bus = 1;
739:
740: /*
741: * Permanently allocate standard device ports.
742: */
743: request_region (0x00, 0x20, "dma1");
744: request_region (0x20, 0x20, "pic1");
745: request_region (0x40, 0x20, "timer");
746: request_region (0x70, 0x10, "rtc");
747: request_region (0x80, 0x20, "dma page reg");
748: request_region (0xa0, 0x20, "pic2");
749: request_region (0xc0, 0x20, "dma2");
750: request_region (0xf0, 0x10, "npu");
751: }
752:
753: void
754: restore_IRQ (void)
755: {
756: /*
757: * Disable interrupts.
758: */
759: (void) splhigh ();
760:
761: /*
762: * Restore clock interrupt handler.
763: */
764: ivect[0] = old_clock_handler;
765: intpri[0] = old_clock_pri;
766: form_pic_mask ();
767: }
768:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.