1 /* interrupt.h */
2 #ifndef _LINUX_INTERRUPT_H
3 #define _LINUX_INTERRUPT_H
4
5 #include <linux/kernel.h>
6 #include <asm/bitops.h>
7
8 struct irqaction {
9 void (*handler)(int, void *, struct pt_regs *);
10 unsigned long flags;
11 unsigned long mask;
12 const char *name;
13 void *dev_id;
14 struct irqaction *next;
15 };
16
17
18 extern int bh_mask_count[32];
19 extern unsigned long bh_active;
20 extern unsigned long bh_mask;
21 extern void (*bh_base[32])(void);
22
23 asmlinkage void do_bottom_half(void);
24
25 /* Who gets which entry in bh_base. Things which will occur most often
26 should come first - in which case NET should be up the top with SERIAL/TQUEUE! */
27
28 enum {
29 TIMER_BH = 0,
30 CONSOLE_BH,
31 TQUEUE_BH,
32 DIGI_BH,
33 SERIAL_BH,
34 RISCOM8_BH,
35 NET_BH,
36 IMMEDIATE_BH,
37 KEYBOARD_BH,
38 CYCLADES_BH,
39 CM206_BH
40 };
41
42 extern inline void init_bh(int nr, void (*routine)(void))
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
43 {
44 bh_base[nr] = routine;
45 bh_mask_count[nr] = 0;
46 bh_mask |= 1 << nr;
47 }
48
49 extern inline void mark_bh(int nr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
50 {
51 set_bit(nr, &bh_active);
52 }
53
54 /*
55 * These use a mask count to correctly handle
56 * nested disable/enable calls
57 */
58 extern inline void disable_bh(int nr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
59 {
60 bh_mask &= ~(1 << nr);
61 bh_mask_count[nr]++;
62 }
63
64 extern inline void enable_bh(int nr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
65 {
66 if (!--bh_mask_count[nr])
67 bh_mask |= 1 << nr;
68 }
69
70 /*
71 * start_bh_atomic/end_bh_atomic also nest
72 * naturally by using a counter
73 */
74 extern inline void start_bh_atomic(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
75 {
76 intr_count++;
77 barrier();
78 }
79
80 extern inline void end_bh_atomic(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
81 {
82 barrier();
83 intr_count--;
84 }
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