diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1994-11-28 11:59:19 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1994-11-28 11:59:19 +0000 |
commit | 1513ff9b7899ab588401c89db0e99903dbf5f886 (patch) | |
tree | f69cc81a940a502ea23d664c3ffb2d215a479667 /drivers/net/auto_irq.c |
Import of Linus's Linux 1.1.68
Diffstat (limited to 'drivers/net/auto_irq.c')
-rw-r--r-- | drivers/net/auto_irq.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/drivers/net/auto_irq.c b/drivers/net/auto_irq.c new file mode 100644 index 000000000..0bab58cb1 --- /dev/null +++ b/drivers/net/auto_irq.c @@ -0,0 +1,125 @@ +/* auto_irq.c: Auto-configure IRQ lines for linux. */ +/* + Written 1994 by Donald Becker. + + The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + Center of Excellence in Space Data and Information Sciences + Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + + This code is a general-purpose IRQ line detector for devices with + jumpered IRQ lines. If you can make the device raise an IRQ (and + that IRQ line isn't already being used), these routines will tell + you what IRQ line it's using -- perfect for those oh-so-cool boot-time + device probes! + + To use this, first call autoirq_setup(timeout). TIMEOUT is how many + 'jiffies' (1/100 sec.) to detect other devices that have active IRQ lines, + and can usually be zero at boot. 'autoirq_setup()' returns the bit + vector of nominally-available IRQ lines (lines may be physically in-use, + but not yet registered to a device). + Next, set up your device to trigger an interrupt. + Finally call autoirq_report(TIMEOUT) to find out which IRQ line was + most recently active. The TIMEOUT should usually be zero, but may + be set to the number of jiffies to wait for a slow device to raise an IRQ. + + The idea of using the setup timeout to filter out bogus IRQs came from + the serial driver. +*/ + + +#ifdef version +static char *version= +"auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)"; +#endif + +/*#include <linux/config.h>*/ +/*#include <linux/kernel.h>*/ +#include <linux/sched.h> +#include <linux/delay.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <linux/netdevice.h> +/*#include <asm/system.h>*/ + +struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */}; + +int irqs_busy = 0x2147; /* The set of fixed IRQs (keyboard, timer, etc) */ +int irqs_used = 0x0001; /* The set of fixed IRQs sometimes enabled. */ +int irqs_reserved = 0x0000; /* An advisory "reserved" table. */ +int irqs_shared = 0x0000; /* IRQ lines "shared" among conforming cards.*/ + +static volatile int irq_number; /* The latest irq number we actually found. */ +static volatile int irq_bitmap; /* The irqs we actually found. */ +static int irq_handled; /* The irq lines we have a handler on. */ + +static void autoirq_probe(int irq) +{ + irq_number = irq; + set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */ + disable_irq(irq); + return; +} + +int autoirq_setup(int waittime) +{ + int i, mask; + int timeout = jiffies + waittime; + int boguscount = (waittime*loops_per_sec) / 100; + + irq_handled = 0; + for (i = 0; i < 16; i++) { + if (test_bit(i, &irqs_busy) == 0 + && request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe") == 0) + set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ + } + /* Update our USED lists. */ + irqs_used |= ~irq_handled; + irq_number = 0; + irq_bitmap = 0; + + /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */ + while (timeout > jiffies && --boguscount > 0) + ; + + for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { + if (irq_bitmap & irq_handled & mask) { + irq_handled &= ~mask; +#ifdef notdef + printk(" Spurious interrupt on IRQ %d\n", i); +#endif + free_irq(i); + } + } + return irq_handled; +} + +int autoirq_report(int waittime) +{ + int i; + int timeout = jiffies+waittime; + int boguscount = (waittime*loops_per_sec) / 100; + + /* Hang out at least <waittime> jiffies waiting for the IRQ. */ + + while (timeout > jiffies && --boguscount > 0) + if (irq_number) + break; + + /* Retract the irq handlers that we installed. */ + for (i = 0; i < 16; i++) { + if (test_bit(i, (void *)&irq_handled)) + free_irq(i); + } + return irq_number; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" + * version-control: t + * kept-new-versions: 5 + * c-indent-level: 4 + * tab-width: 4 + * End: + */ |