| 1 | /* $Id: interrupt.h,v 1.1.1.1 2003/07/02 13:57:00 eleph Exp $ */ | 
|---|
| 2 |  | 
|---|
| 3 | /* interrupt.h */ | 
|---|
| 4 | #ifndef _LINUX_INTERRUPT_H | 
|---|
| 5 | #define _LINUX_INTERRUPT_H | 
|---|
| 6 |  | 
|---|
| 7 | #include <linux/kernel.h> | 
|---|
| 8 | //#include <asm/bitops.h> | 
|---|
| 9 | #include <asm/atomic.h> | 
|---|
| 10 |  | 
|---|
| 11 | struct irqaction { | 
|---|
| 12 | void (*handler)(int, void *, struct pt_regs *); | 
|---|
| 13 | unsigned long flags; | 
|---|
| 14 | unsigned long mask; | 
|---|
| 15 | const char *name; | 
|---|
| 16 | void *dev_id; | 
|---|
| 17 | struct irqaction *next; | 
|---|
| 18 | }; | 
|---|
| 19 |  | 
|---|
| 20 | extern volatile unsigned char bh_running; | 
|---|
| 21 |  | 
|---|
| 22 | extern atomic_t bh_mask_count[32]; | 
|---|
| 23 | extern unsigned long bh_active; | 
|---|
| 24 | extern unsigned long bh_mask; | 
|---|
| 25 | extern void (*bh_base[32])(void); | 
|---|
| 26 |  | 
|---|
| 27 | void do_bottom_half(void); | 
|---|
| 28 |  | 
|---|
| 29 | /* Who gets which entry in bh_base.  Things which will occur most often | 
|---|
| 30 | should come first - in which case NET should be up the top with SERIAL/TQUEUE! */ | 
|---|
| 31 |  | 
|---|
| 32 | enum { | 
|---|
| 33 | TIMER_BH = 0, | 
|---|
| 34 | CONSOLE_BH, | 
|---|
| 35 | TQUEUE_BH, | 
|---|
| 36 | DIGI_BH, | 
|---|
| 37 | SERIAL_BH, | 
|---|
| 38 | RISCOM8_BH, | 
|---|
| 39 | SPECIALIX_BH, | 
|---|
| 40 | AURORA_BH, | 
|---|
| 41 | ESP_BH, | 
|---|
| 42 | NET_BH, | 
|---|
| 43 | SCSI_BH, | 
|---|
| 44 | IMMEDIATE_BH, | 
|---|
| 45 | KEYBOARD_BH, | 
|---|
| 46 | CYCLADES_BH, | 
|---|
| 47 | CM206_BH, | 
|---|
| 48 | JS_BH, | 
|---|
| 49 | MACSERIAL_BH, | 
|---|
| 50 | ISICOM_BH | 
|---|
| 51 | }; | 
|---|
| 52 | /* Tasklets --- multithreaded analogue of BHs. | 
|---|
| 53 |  | 
|---|
| 54 | Main feature differing them of generic softirqs: tasklet | 
|---|
| 55 | is running only on one CPU simultaneously. | 
|---|
| 56 |  | 
|---|
| 57 | Main feature differing them of BHs: different tasklets | 
|---|
| 58 | may be run simultaneously on different CPUs. | 
|---|
| 59 |  | 
|---|
| 60 | Properties: | 
|---|
| 61 | * If tasklet_schedule() is called, then tasklet is guaranteed | 
|---|
| 62 | to be executed on some cpu at least once after this. | 
|---|
| 63 | * If the tasklet is already scheduled, but its excecution is still not | 
|---|
| 64 | started, it will be executed only once. | 
|---|
| 65 | * If this tasklet is already running on another CPU (or schedule is called | 
|---|
| 66 | from tasklet itself), it is rescheduled for later. | 
|---|
| 67 | * Tasklet is strictly serialized wrt itself, but not | 
|---|
| 68 | wrt another tasklets. If client needs some intertask synchronization, | 
|---|
| 69 | he makes it with spinlocks. | 
|---|
| 70 | */ | 
|---|
| 71 |  | 
|---|
| 72 | struct tasklet_struct | 
|---|
| 73 | { | 
|---|
| 74 | struct tasklet_struct *next; | 
|---|
| 75 | unsigned long state; | 
|---|
| 76 | atomic_t count; | 
|---|
| 77 | void (*func)(unsigned long); | 
|---|
| 78 | unsigned long data; | 
|---|
| 79 | }; | 
|---|
| 80 |  | 
|---|
| 81 | extern void tasklet_hi_schedule(struct tasklet_struct *t); | 
|---|
| 82 |  | 
|---|
| 83 | extern void tasklet_init(struct tasklet_struct *t, | 
|---|
| 84 | void (*func)(unsigned long), unsigned long data); | 
|---|
| 85 |  | 
|---|
| 86 | /* | 
|---|
| 87 | * Autoprobing for irqs: | 
|---|
| 88 | * | 
|---|
| 89 | * probe_irq_on() and probe_irq_off() provide robust primitives | 
|---|
| 90 | * for accurate IRQ probing during kernel initialization.  They are | 
|---|
| 91 | * reasonably simple to use, are not "fooled" by spurious interrupts, | 
|---|
| 92 | * and, unlike other attempts at IRQ probing, they do not get hung on | 
|---|
| 93 | * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards). | 
|---|
| 94 | * | 
|---|
| 95 | * For reasonably foolproof probing, use them as follows: | 
|---|
| 96 | * | 
|---|
| 97 | * 1. clear and/or mask the device's internal interrupt. | 
|---|
| 98 | * 2. sti(); | 
|---|
| 99 | * 3. irqs = probe_irq_on();      // "take over" all unassigned idle IRQs | 
|---|
| 100 | * 4. enable the device and cause it to trigger an interrupt. | 
|---|
| 101 | * 5. wait for the device to interrupt, using non-intrusive polling or a delay. | 
|---|
| 102 | * 6. irq = probe_irq_off(irqs);  // get IRQ number, 0=none, negative=multiple | 
|---|
| 103 | * 7. service the device to clear its pending interrupt. | 
|---|
| 104 | * 8. loop again if paranoia is required. | 
|---|
| 105 | * | 
|---|
| 106 | * probe_irq_on() returns a mask of allocated irq's. | 
|---|
| 107 | * | 
|---|
| 108 | * probe_irq_off() takes the mask as a parameter, | 
|---|
| 109 | * and returns the irq number which occurred, | 
|---|
| 110 | * or zero if none occurred, or a negative irq number | 
|---|
| 111 | * if more than one irq occurred. | 
|---|
| 112 | */ | 
|---|
| 113 | extern unsigned long probe_irq_on(void);        /* returns 0 on failure */ | 
|---|
| 114 | extern int probe_irq_off(unsigned long);        /* returns 0 or negative on failure */ | 
|---|
| 115 |  | 
|---|
| 116 | #endif | 
|---|