|
|
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 <linux/sched.h> ! 36: #include <linux/delay.h> ! 37: #include <asm/bitops.h> ! 38: #include <asm/io.h> ! 39: #include <asm/irq.h> ! 40: #include <linux/netdevice.h> ! 41: ! 42: struct device *irq2dev_map[NR_IRQS] = {0, 0, /* ... zeroed */}; ! 43: ! 44: unsigned long irqs_busy = 0x2147; /* The set of fixed IRQs (keyboard, timer, etc) */ ! 45: unsigned long irqs_used = 0x0001; /* The set of fixed IRQs sometimes enabled. */ ! 46: unsigned long irqs_reserved = 0x0000; /* An advisory "reserved" table. */ ! 47: unsigned long irqs_shared = 0x0000; /* IRQ lines "shared" among conforming cards.*/ ! 48: ! 49: static volatile unsigned long irq_bitmap; /* The irqs we actually found. */ ! 50: static unsigned long irq_handled; /* The irq lines we have a handler on. */ ! 51: static volatile int irq_number; /* The latest irq number we actually found. */ ! 52: ! 53: static void autoirq_probe(int irq, void *dev_id, struct pt_regs * regs) ! 54: { ! 55: irq_number = irq; ! 56: set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */ ! 57: /* This code used to disable the irq. However, the interrupt stub ! 58: * would then re-enable the interrupt with (potentially) disastrous ! 59: * consequences ! 60: */ ! 61: free_irq(irq, dev_id); ! 62: return; ! 63: } ! 64: ! 65: int autoirq_setup(int waittime) ! 66: { ! 67: int i; ! 68: unsigned long timeout = jiffies + waittime; ! 69: unsigned long boguscount = (waittime*loops_per_sec) / 100; ! 70: ! 71: irq_handled = 0; ! 72: irq_bitmap = 0; ! 73: ! 74: for (i = 0; i < 16; i++) { ! 75: if (test_bit(i, &irqs_busy) == 0 ! 76: && request_irq(i, autoirq_probe, SA_INTERRUPT, "irq probe", NULL) == 0) ! 77: set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ ! 78: } ! 79: /* Update our USED lists. */ ! 80: irqs_used |= ~irq_handled; ! 81: ! 82: /* Hang out at least <waittime> jiffies waiting for bogus IRQ hits. */ ! 83: while (timeout > jiffies && --boguscount > 0) ! 84: ; ! 85: ! 86: irq_handled &= ~irq_bitmap; ! 87: ! 88: irq_number = 0; /* We are interested in new interrupts from now on */ ! 89: ! 90: return irq_handled; ! 91: } ! 92: ! 93: int autoirq_report(int waittime) ! 94: { ! 95: int i; ! 96: unsigned long timeout = jiffies+waittime; ! 97: unsigned long boguscount = (waittime*loops_per_sec) / 100; ! 98: ! 99: /* Hang out at least <waittime> jiffies waiting for the IRQ. */ ! 100: ! 101: while (timeout > jiffies && --boguscount > 0) ! 102: if (irq_number) ! 103: break; ! 104: ! 105: irq_handled &= ~irq_bitmap; /* This eliminates the already reset handlers */ ! 106: ! 107: /* Retract the irq handlers that we installed. */ ! 108: for (i = 0; i < 16; i++) { ! 109: if (test_bit(i, (void *)&irq_handled)) ! 110: free_irq(i, NULL); ! 111: } ! 112: return irq_number; ! 113: } ! 114: ! 115: /* ! 116: * Local variables: ! 117: * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" ! 118: * version-control: t ! 119: * kept-new-versions: 5 ! 120: * c-indent-level: 4 ! 121: * tab-width: 4 ! 122: * End: ! 123: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.