116 lines
3.5 KiB
C
116 lines
3.5 KiB
C
|
/* auto_irq.c: Auto-configure IRQ lines for linux. */
|
|||
|
/*
|
|||
|
Written 1993 by Donald Becker.
|
|||
|
|
|||
|
The Author may be reached as becker@super.org or
|
|||
|
C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
|
|||
|
|
|||
|
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/18 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:v0.02 1993 Donald Becker (becker@super.org)";
|
|||
|
#endif
|
|||
|
|
|||
|
/*#include <linux/config.h>*/
|
|||
|
/*#include <linux/kernel.h>*/
|
|||
|
#include <linux/sched.h>
|
|||
|
#include <asm/bitops.h>
|
|||
|
#include <asm/io.h>
|
|||
|
#include "dev.h"
|
|||
|
/*#include <asm/system.h>*/
|
|||
|
|
|||
|
struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */};
|
|||
|
|
|||
|
int irqs_busy = 0x01; /* The set of fixed IRQs always enabled */
|
|||
|
int irqs_used = 0x01; /* The set of fixed IRQs sometimes enabled. */
|
|||
|
int irqs_reserved = 0x00; /* An advisory "reserved" table. */
|
|||
|
int irqs_shared = 0x00; /* 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; */
|
|||
|
return;
|
|||
|
}
|
|||
|
struct sigaction autoirq_sigaction = { autoirq_probe, 0, SA_INTERRUPT, NULL};
|
|||
|
|
|||
|
int autoirq_setup(int waittime)
|
|||
|
{
|
|||
|
int i, mask;
|
|||
|
int timeout = jiffies+waittime;
|
|||
|
|
|||
|
irq_number = 0;
|
|||
|
irq_bitmap = 0;
|
|||
|
irq_handled = 0;
|
|||
|
for (i = 0; i < 16; i++) {
|
|||
|
if (!irqaction(i, &autoirq_sigaction))
|
|||
|
set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/
|
|||
|
}
|
|||
|
/* Update our USED lists. */
|
|||
|
irqs_used |= ~irq_handled;
|
|||
|
|
|||
|
/* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */
|
|||
|
while (timeout > jiffies)
|
|||
|
;
|
|||
|
|
|||
|
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;
|
|||
|
|
|||
|
/* Hang out at least <waittime> jiffies waiting for the IRQ. */
|
|||
|
while (timeout > jiffies)
|
|||
|
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
|
|||
|
* End:
|
|||
|
*/
|