Commit | Line | Data |
---|---|---|
1da177e4 LT |
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/workqueue.h> | |
37 | ||
c4028958 | 38 | static void ps_tq_int(struct work_struct *work); |
1da177e4 LT |
39 | |
40 | static void (* ps_continuation)(void); | |
41 | static int (* ps_ready)(void); | |
42 | static unsigned long ps_timeout; | |
43 | static int ps_tq_active = 0; | |
44 | static int ps_nice = 0; | |
45 | ||
46 | static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused))); | |
47 | ||
c4028958 | 48 | static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int); |
1da177e4 LT |
49 | |
50 | static void ps_set_intr(void (*continuation)(void), | |
51 | int (*ready)(void), | |
52 | int timeout, int nice) | |
53 | { | |
54 | unsigned long flags; | |
55 | ||
56 | spin_lock_irqsave(&ps_spinlock,flags); | |
57 | ||
58 | ps_continuation = continuation; | |
59 | ps_ready = ready; | |
60 | ps_timeout = jiffies + timeout; | |
61 | ps_nice = nice; | |
62 | ||
63 | if (!ps_tq_active) { | |
64 | ps_tq_active = 1; | |
65 | if (!ps_nice) | |
c4028958 | 66 | schedule_delayed_work(&ps_tq, 0); |
1da177e4 LT |
67 | else |
68 | schedule_delayed_work(&ps_tq, ps_nice-1); | |
69 | } | |
70 | spin_unlock_irqrestore(&ps_spinlock,flags); | |
71 | } | |
72 | ||
c4028958 | 73 | static void ps_tq_int(struct work_struct *work) |
1da177e4 LT |
74 | { |
75 | void (*con)(void); | |
76 | unsigned long flags; | |
77 | ||
78 | spin_lock_irqsave(&ps_spinlock,flags); | |
79 | ||
80 | con = ps_continuation; | |
81 | ps_tq_active = 0; | |
82 | ||
83 | if (!con) { | |
84 | spin_unlock_irqrestore(&ps_spinlock,flags); | |
85 | return; | |
86 | } | |
87 | if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) { | |
88 | ps_continuation = NULL; | |
89 | spin_unlock_irqrestore(&ps_spinlock,flags); | |
90 | con(); | |
91 | return; | |
92 | } | |
93 | ps_tq_active = 1; | |
94 | if (!ps_nice) | |
c4028958 | 95 | schedule_delayed_work(&ps_tq, 0); |
1da177e4 LT |
96 | else |
97 | schedule_delayed_work(&ps_tq, ps_nice-1); | |
98 | spin_unlock_irqrestore(&ps_spinlock,flags); | |
99 | } | |
100 | ||
101 | /* end of pseudo.h */ | |
102 |