|
|
1.1 ! root 1: /* ! 2: * Linux auto-irq support. ! 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: * Written 1994 by Donald Becker. ! 22: * ! 23: * The author may be reached as [email protected], or C/O ! 24: * Center of Excellence in Space Data and Information Sciences ! 25: * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 ! 26: * ! 27: * This code is a general-purpose IRQ line detector for devices with ! 28: * jumpered IRQ lines. If you can make the device raise an IRQ (and ! 29: * that IRQ line isn't already being used), these routines will tell ! 30: * you what IRQ line it's using -- perfect for those oh-so-cool boot-time ! 31: * device probes! ! 32: * ! 33: * To use this, first call autoirq_setup(timeout). TIMEOUT is how many ! 34: * 'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines, ! 35: * and can usually be zero at boot. 'autoirq_setup()' returns the bit ! 36: * vector of nominally-available IRQ lines (lines may be physically in-use, ! 37: * but not yet registered to a device). ! 38: * Next, set up your device to trigger an interrupt. ! 39: * Finally call autoirq_report(TIMEOUT) to find out which IRQ line was ! 40: * most recently active. The TIMEOUT should usually be zero, but may ! 41: * be set to the number of jiffies to wait for a slow device to raise an IRQ. ! 42: * ! 43: * The idea of using the setup timeout to filter out bogus IRQs came from ! 44: * the serial driver. ! 45: */ ! 46: ! 47: #include <i386/pic.h> ! 48: #include <i386/ipl.h> ! 49: ! 50: #include <linux/sched.h> ! 51: #include <linux/ptrace.h> ! 52: ! 53: #include <asm/bitops.h> ! 54: #include <asm/system.h> ! 55: ! 56: /* ! 57: * IRQ to network device map. ! 58: */ ! 59: void *irq2dev_map[16]; ! 60: ! 61: /* ! 62: * Set of fixed IRQs ! 63: * (fpu, rtc, com1, PIC slave cascade, keyboard, timer). ! 64: */ ! 65: int irqs_busy = 0x2147; ! 66: ! 67: static volatile int irq_number; /* latest irq found */ ! 68: static volatile int irq_bitmap; /* bitmap of IRQs found */ ! 69: static int irq_handled; /* irq lines we have a handler on */ ! 70: ! 71: extern unsigned long loops_per_sec; ! 72: ! 73: /* ! 74: * Interrupt handler when probing an IRQ. ! 75: */ ! 76: static void ! 77: autoirq_probe(irq) ! 78: int irq; ! 79: { ! 80: /* ! 81: * Mark this IRQ as the last one ! 82: * that interrupted and disable it. ! 83: */ ! 84: irq_number = irq; ! 85: set_bit(irq, (void *)&irq_bitmap); ! 86: disable_irq(irq); ! 87: } ! 88: ! 89: /* ! 90: * Set up for auto-irq. ! 91: */ ! 92: int ! 93: autoirq_setup(waittime) ! 94: int waittime; ! 95: { ! 96: int i, mask; ! 97: int timeout = jiffies + waittime; ! 98: int boguscount = (waittime * loops_per_sec) / 100; ! 99: ! 100: /* ! 101: * Allocate all possible IRQs. ! 102: */ ! 103: irq_handled = 0; ! 104: for (i = 0; i < 16; i++) { ! 105: if (test_bit(i, (void *)&irqs_busy) == 0 ! 106: && request_irq(i, autoirq_probe, 0, 0) == 0) ! 107: set_bit(i, (void *)&irq_handled); ! 108: } ! 109: ! 110: irq_number = 0; ! 111: irq_bitmap = 0; ! 112: ! 113: /* ! 114: * Hang out at least <waittime> ! 115: * jiffies waiting for bogus IRQ hits. ! 116: */ ! 117: while (timeout > jiffies && --boguscount > 0) ! 118: ; ! 119: ! 120: /* ! 121: * Free IRQs that caused bogus hits. ! 122: */ ! 123: for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { ! 124: if (irq_bitmap & irq_handled & mask) { ! 125: irq_handled &= ~mask; ! 126: free_irq(i); ! 127: } ! 128: } ! 129: ! 130: return (irq_handled); ! 131: } ! 132: ! 133: /* ! 134: * Return the last IRQ that caused an interrupt. ! 135: */ ! 136: int ! 137: autoirq_report(waittime) ! 138: int waittime; ! 139: { ! 140: int i; ! 141: int timeout = jiffies + waittime; ! 142: int boguscount = (waittime * loops_per_sec) / 100; ! 143: ! 144: /* ! 145: * Hang out at least <waittime> ! 146: * jiffies waiting for the IRQ. ! 147: */ ! 148: while (timeout > jiffies && --boguscount > 0) ! 149: if (irq_number) ! 150: break; ! 151: ! 152: /* ! 153: * Retract the IRQ handlers that we handled. ! 154: */ ! 155: for (i = 0; i < 16; i++) { ! 156: if (test_bit(i, (void *)&irq_handled)) ! 157: free_irq(i); ! 158: } ! 159: ! 160: return (irq_number); ! 161: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.