xref: /OK3568_Linux_fs/kernel/drivers/block/paride/pseudo.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun         pseudo.h    (c) 1997-8  Grant R. Guenther <grant@torque.net>
3*4882a593Smuzhiyun                                 Under the terms of the GNU General Public License.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun 	This is the "pseudo-interrupt" logic for parallel port drivers.
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun         This module is #included into each driver.  It makes one
8*4882a593Smuzhiyun         function available:
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun 		ps_set_intr( void (*continuation)(void),
11*4882a593Smuzhiyun 			     int  (*ready)(void),
12*4882a593Smuzhiyun 			     int timeout,
13*4882a593Smuzhiyun 			     int nice )
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun 	Which will arrange for ready() to be evaluated frequently and
16*4882a593Smuzhiyun 	when either it returns true, or timeout jiffies have passed,
17*4882a593Smuzhiyun 	continuation() will be invoked.
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 	If nice is 1, the test will done approximately once a
20*4882a593Smuzhiyun 	jiffy.  If nice is 0, the test will also be done whenever
21*4882a593Smuzhiyun 	the scheduler runs (by adding it to a task queue).  If
22*4882a593Smuzhiyun 	nice is greater than 1, the test will be done once every
23*4882a593Smuzhiyun 	(nice-1) jiffies.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun /* Changes:
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	1.01	1998.05.03	Switched from cli()/sti() to spinlocks
30*4882a593Smuzhiyun 	1.02    1998.12.14      Added support for nice > 1
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define PS_VERSION	"1.02"
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <linux/sched.h>
36*4882a593Smuzhiyun #include <linux/workqueue.h>
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static void ps_tq_int(struct work_struct *work);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static void (* ps_continuation)(void);
41*4882a593Smuzhiyun static int (* ps_ready)(void);
42*4882a593Smuzhiyun static unsigned long ps_timeout;
43*4882a593Smuzhiyun static int ps_tq_active = 0;
44*4882a593Smuzhiyun static int ps_nice = 0;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
49*4882a593Smuzhiyun 
ps_set_intr(void (* continuation)(void),int (* ready)(void),int timeout,int nice)50*4882a593Smuzhiyun static void ps_set_intr(void (*continuation)(void),
51*4882a593Smuzhiyun 			int (*ready)(void),
52*4882a593Smuzhiyun 			int timeout, int nice)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	unsigned long	flags;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	spin_lock_irqsave(&ps_spinlock,flags);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	ps_continuation = continuation;
59*4882a593Smuzhiyun 	ps_ready = ready;
60*4882a593Smuzhiyun 	ps_timeout = jiffies + timeout;
61*4882a593Smuzhiyun 	ps_nice = nice;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (!ps_tq_active) {
64*4882a593Smuzhiyun 		ps_tq_active = 1;
65*4882a593Smuzhiyun 		if (!ps_nice)
66*4882a593Smuzhiyun 			schedule_delayed_work(&ps_tq, 0);
67*4882a593Smuzhiyun 		else
68*4882a593Smuzhiyun 			schedule_delayed_work(&ps_tq, ps_nice-1);
69*4882a593Smuzhiyun 	}
70*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ps_spinlock,flags);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
ps_tq_int(struct work_struct * work)73*4882a593Smuzhiyun static void ps_tq_int(struct work_struct *work)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	void (*con)(void);
76*4882a593Smuzhiyun 	unsigned long flags;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	spin_lock_irqsave(&ps_spinlock,flags);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	con = ps_continuation;
81*4882a593Smuzhiyun 	ps_tq_active = 0;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	if (!con) {
84*4882a593Smuzhiyun 		spin_unlock_irqrestore(&ps_spinlock,flags);
85*4882a593Smuzhiyun 		return;
86*4882a593Smuzhiyun 	}
87*4882a593Smuzhiyun 	if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
88*4882a593Smuzhiyun 		ps_continuation = NULL;
89*4882a593Smuzhiyun 		spin_unlock_irqrestore(&ps_spinlock,flags);
90*4882a593Smuzhiyun 		con();
91*4882a593Smuzhiyun 		return;
92*4882a593Smuzhiyun 	}
93*4882a593Smuzhiyun 	ps_tq_active = 1;
94*4882a593Smuzhiyun 	if (!ps_nice)
95*4882a593Smuzhiyun 		schedule_delayed_work(&ps_tq, 0);
96*4882a593Smuzhiyun 	else
97*4882a593Smuzhiyun 		schedule_delayed_work(&ps_tq, ps_nice-1);
98*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ps_spinlock,flags);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun /* end of pseudo.h */
102*4882a593Smuzhiyun 
103