|
|
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.