1 /* auto_irq.c: Auto-configure IRQ lines for linux. */ 2 /* 3 Written 1993 by Donald Becker. 4 5 The Author may be reached as becker@super.org or 6 C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 7 8 This code is a general-purpose IRQ line detector for devices with 9 jumpered IRQ lines. If you can make the device raise an IRQ (and 10 that IRQ line isn't already being used), these routines will tell 11 you what IRQ line it's using -- perfect for those oh-so-cool boot-time 12 device probes! 13 14 To use this, first call autoirq_setup(timeout). TIMEOUT is how many 15 'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines, 16 and can usually be zero at boot. 'autoirq_setup()' returns the bit 17 vector of nominally-available IRQ lines (lines may be physically in-use, 18 but not yet registered to a device). 19 Next, set up your device to trigger an interrupt. 20 Finally call autoirq_report(TIMEOUT) to find out which IRQ line was 21 most recently active. The TIMEOUT should usually be zero, but may 22 be set to the number of jiffies to wait for a slow device to raise an IRQ. 23 24 The idea of using the setup timeout to filter out bogus IRQs came from 25 the serial driver. 26 */ 27 28 29 #ifdef version 30 static char *version="auto_irq.c:v0.02 1993 Donald Becker (becker@super.org)"; 31 #endif 32 33 /*#include <linux/config.h>*/ 34 /*#include <linux/kernel.h>*/ 35 #include <linux/sched.h> 36 #include <asm/bitops.h> 37 #include <asm/io.h> 38 #include <linux/netdevice.h> 39 /*#include <asm/system.h>*/ 40 41 struct device *irq2dev_map[16] = {0, 0, /* ... zeroed */}; 42 43 int irqs_busy = 0x01; /* The set of fixed IRQs always enabled */ 44 int irqs_used = 0x01; /* The set of fixed IRQs sometimes enabled. */ 45 int irqs_reserved = 0x00; /* An advisory "reserved" table. */ 46 int irqs_shared = 0x00; /* IRQ lines "shared" among conforming cards.*/ 47 48 static volatile int irq_number; /* The latest irq number we actually found. */ 49 static volatile int irq_bitmap; /* The irqs we actually found. */ 50 static int irq_handled; /* The irq lines we have a handler on. */ 51 52 static void autoirq_probe(int irq) /* */ 53 { 54 irq_number = irq; 55 set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */ 56 return; 57 } 58 59 int autoirq_setup(int waittime) /* */ 60 { 61 int i, mask; 62 int timeout = jiffies+waittime; 63 64 irq_handled = 0; 65 for (i = 0; i < 16; i++) { 66 if (!request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe")) 67 set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ 68 } 69 /* Update our USED lists. */ 70 irqs_used |= ~irq_handled; 71 irq_number = 0; 72 irq_bitmap = 0; 73 74 /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */ 75 while (timeout > jiffies) 76 ; 77 78 for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { 79 if (irq_bitmap & irq_handled & mask) { 80 irq_handled &= ~mask; 81 #ifdef notdef 82 printk(" Spurious interrupt on IRQ %d\n", i); 83 #endif 84 free_irq(i); 85 } 86 } 87 return irq_handled; 88 } 89 90 int autoirq_report(int waittime) /* */ 91 { 92 int i; 93 int timeout = jiffies+waittime; 94 95 /* Hang out at least <waittime> jiffies waiting for the IRQ. */ 96 while (timeout > jiffies) 97 if (irq_number) 98 break; 99 100 /* Retract the irq handlers that we installed. */ 101 for (i = 0; i < 16; i++) { 102 if (test_bit(i, (void *)&irq_handled)) 103 free_irq(i); 104 } 105 return irq_number; 106 } 107 108 /* 109 * Local variables: 110 * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" 111 * version-control: t 112 * kept-new-versions: 5 113 * End: 114 */