|
|
1.1 root 1: /* auto_irq.c: Auto-configure IRQ lines for linux. */
2: /*
3: Written 1994 by Donald Becker.
4:
5: The author may be reached as [email protected], or C/O
6: Center of Excellence in Space Data and Information Sciences
7: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
8:
9: This code is a general-purpose IRQ line detector for devices with
10: jumpered IRQ lines. If you can make the device raise an IRQ (and
11: that IRQ line isn't already being used), these routines will tell
12: you what IRQ line it's using -- perfect for those oh-so-cool boot-time
13: device probes!
14:
15: To use this, first call autoirq_setup(timeout). TIMEOUT is how many
16: 'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines,
17: and can usually be zero at boot. 'autoirq_setup()' returns the bit
18: vector of nominally-available IRQ lines (lines may be physically in-use,
19: but not yet registered to a device).
20: Next, set up your device to trigger an interrupt.
21: Finally call autoirq_report(TIMEOUT) to find out which IRQ line was
22: most recently active. The TIMEOUT should usually be zero, but may
23: be set to the number of jiffies to wait for a slow device to raise an IRQ.
24:
25: The idea of using the setup timeout to filter out bogus IRQs came from
26: the serial driver.
27: */
28:
29:
30: #ifdef version
31: static const char *version =
32: "auto_irq.c:v1.11 Donald Becker ([email protected])";
33: #endif
34:
35: #include <sys/types.h>
36: #include <mach/mach_types.h>
37: #include <mach/vm_param.h>
38:
39: #define MACH_INCLUDE
40: #include <linux/sched.h>
41: #include <linux/delay.h>
42: #include <asm/bitops.h>
43: #include <asm/io.h>
44: #include <asm/irq.h>
45: #include <linux/netdevice.h>
46:
47: void *irq2dev_map[NR_IRQS] = {0, 0, /* ... zeroed */ };
48:
49: unsigned long irqs_busy = 0x2147; /* The set of fixed IRQs (keyboard, timer, etc) */
50: unsigned long irqs_used = 0x0001; /* The set of fixed IRQs sometimes enabled. */
51: unsigned long irqs_reserved = 0x0000; /* An advisory "reserved" table. */
52: unsigned long irqs_shared = 0x0000; /* IRQ lines "shared" among conforming cards. */
53:
54: static volatile unsigned long irq_bitmap; /* The irqs we actually found. */
55: static unsigned long irq_handled; /* The irq lines we have a handler on. */
56: static volatile int irq_number; /* The latest irq number we actually found. */
57:
58: static void
59: autoirq_probe (int irq, void *dev_id, struct pt_regs *regs)
60: {
61: irq_number = irq;
62: set_bit (irq, (void *) &irq_bitmap); /* irq_bitmap |= 1 << irq; */
63: /* This code used to disable the irq. However, the interrupt stub
64: * would then re-enable the interrupt with (potentially) disastrous
65: * consequences
66: */
67: free_irq (irq, dev_id);
68: return;
69: }
70:
71: int
72: autoirq_setup (int waittime)
73: {
74: int i;
75: unsigned long timeout = jiffies + waittime;
76: unsigned long boguscount = (waittime * loops_per_sec) / 100;
77:
78: irq_handled = 0;
79: irq_bitmap = 0;
80:
81: for (i = 0; i < 16; i++)
82: {
83: if (test_bit (i, &irqs_busy) == 0
84: && request_irq (i, autoirq_probe, SA_INTERRUPT, "irq probe", NULL) == 0)
85: set_bit (i, (void *) &irq_handled); /* irq_handled |= 1 << i; */
86: }
87: /* Update our USED lists. */
88: irqs_used |= ~irq_handled;
89:
90: /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
91: while (timeout > jiffies && --boguscount > 0)
92: ;
93:
94: irq_handled &= ~irq_bitmap;
95:
96: irq_number = 0; /* We are interested in new interrupts from now on */
97:
98: return irq_handled;
99: }
100:
101: int
102: autoirq_report (int waittime)
103: {
104: int i;
105: unsigned long timeout = jiffies + waittime;
106: unsigned long boguscount = (waittime * loops_per_sec) / 100;
107:
108: /* Hang out at least <waittime> jiffies waiting for the IRQ. */
109:
110: while (timeout > jiffies && --boguscount > 0)
111: if (irq_number)
112: break;
113:
114: irq_handled &= ~irq_bitmap; /* This eliminates the already reset handlers */
115:
116: /* Retract the irq handlers that we installed. */
117: for (i = 0; i < 16; i++)
118: {
119: if (test_bit (i, (void *) &irq_handled))
120: free_irq (i, NULL);
121: }
122: return irq_number;
123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.