File: /usr/src/linux/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     {       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     	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() || (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     	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() || (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     
148