brute-forced more changes from MontaVista's tree. SCSI partition table read still...
[linux-2.4.git] / drivers / block / paride / pseudo.h
1 /* 
2         pseudo.h    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3                                 Under the terms of the GNU General Public License.
4
5         This is the "pseudo-interrupt" logic for parallel port drivers.
6
7         This module is #included into each driver.  It makes one
8         function available:
9
10                 ps_set_intr( void (*continuation)(void),
11                              int  (*ready)(void),
12                              int timeout,
13                              int nice )
14
15         Which will arrange for ready() to be evaluated frequently and
16         when either it returns true, or timeout jiffies have passed,
17         continuation() will be invoked.
18
19         If nice is 1, the test will done approximately once a
20         jiffy.  If nice is 0, the test will also be done whenever
21         the scheduler runs (by adding it to a task queue).  If
22         nice is greater than 1, the test will be done once every
23         (nice-1) jiffies. 
24
25 */
26
27 /* Changes:
28
29         1.01    1998.05.03      Switched from cli()/sti() to spinlocks
30         1.02    1998.12.14      Added support for nice > 1
31 */
32         
33 #define PS_VERSION      "1.02"
34
35 #include <linux/sched.h>
36 #include <linux/timer.h>
37 #include <linux/tqueue.h>
38
39 static void ps_timer_int( unsigned long data);
40 static void ps_tq_int( void *data);
41
42 static void (* ps_continuation)(void);
43 static int (* ps_ready)(void);
44 static int ps_then;
45 static int ps_timeout;
46 static int ps_timer_active = 0;
47 static int ps_tq_active = 0;
48 static int ps_nice = 0;
49
50 static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;
51
52 static struct timer_list ps_timer = { function: ps_timer_int };
53 static struct tq_struct ps_tq = { routine: ps_tq_int };
54
55 static void ps_set_intr( void (*continuation)(void), 
56                          int (*ready)(void),
57                          int timeout, int nice )
58
59 {       unsigned long   flags;
60
61         spin_lock_irqsave(&ps_spinlock,flags);
62
63         ps_continuation = continuation;
64         ps_ready = ready;
65         ps_then = jiffies;
66         ps_timeout = jiffies + timeout;
67         ps_nice = nice;
68
69         if (!ps_nice && !ps_tq_active) {
70 #ifdef HAVE_DISABLE_HLT
71                 disable_hlt();
72 #endif
73                 ps_tq_active = 1;
74                 schedule_task(&ps_tq);
75         }
76
77         if (!ps_timer_active) {
78                 ps_timer_active = 1;
79                 ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
80                 add_timer(&ps_timer);
81         }
82
83         spin_unlock_irqrestore(&ps_spinlock,flags);
84 }
85
86 static void ps_tq_int( void *data )
87
88 {       void (*con)(void);
89         unsigned long flags;
90
91         spin_lock_irqsave(&ps_spinlock,flags);
92
93         con = ps_continuation;
94
95 #ifdef HAVE_DISABLE_HLT
96         enable_hlt();
97 #endif
98
99         ps_tq_active = 0;
100
101         if (!con) {
102                 spin_unlock_irqrestore(&ps_spinlock,flags);
103                 return;
104         }
105         if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
106                 ps_continuation = NULL;
107                 spin_unlock_irqrestore(&ps_spinlock,flags);
108                 con();
109                 return;
110                 }
111
112 #ifdef HAVE_DISABLE_HLT
113         disable_hlt();
114 #endif
115
116         ps_tq_active = 1;
117         schedule_task(&ps_tq);
118         spin_unlock_irqrestore(&ps_spinlock,flags);
119 }
120
121 static void ps_timer_int( unsigned long data)
122
123 {       void (*con)(void);
124         unsigned long   flags;
125
126         spin_lock_irqsave(&ps_spinlock,flags);
127
128         con = ps_continuation;
129         ps_timer_active = 0;
130         if (!con) {
131                 spin_unlock_irqrestore(&ps_spinlock,flags);
132                 return;
133         }
134         if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
135                 ps_continuation = NULL;
136                 spin_unlock_irqrestore(&ps_spinlock,flags);
137                 con();
138                 return;
139                 }
140         ps_timer_active = 1;
141         ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
142         add_timer(&ps_timer);
143         spin_unlock_irqrestore(&ps_spinlock,flags);
144 }
145
146 /* end of pseudo.h */
147