|
|
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.