18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci        pseudo.h    (c) 1997-8  Grant R. Guenther <grant@torque.net>
38c2ecf20Sopenharmony_ci                                Under the terms of the GNU General Public License.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci	This is the "pseudo-interrupt" logic for parallel port drivers.
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci        This module is #included into each driver.  It makes one
88c2ecf20Sopenharmony_ci        function available:
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci		ps_set_intr( void (*continuation)(void),
118c2ecf20Sopenharmony_ci			     int  (*ready)(void),
128c2ecf20Sopenharmony_ci			     int timeout,
138c2ecf20Sopenharmony_ci			     int nice )
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	Which will arrange for ready() to be evaluated frequently and
168c2ecf20Sopenharmony_ci	when either it returns true, or timeout jiffies have passed,
178c2ecf20Sopenharmony_ci	continuation() will be invoked.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	If nice is 1, the test will done approximately once a
208c2ecf20Sopenharmony_ci	jiffy.  If nice is 0, the test will also be done whenever
218c2ecf20Sopenharmony_ci	the scheduler runs (by adding it to a task queue).  If
228c2ecf20Sopenharmony_ci	nice is greater than 1, the test will be done once every
238c2ecf20Sopenharmony_ci	(nice-1) jiffies.
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci*/
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Changes:
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	1.01	1998.05.03	Switched from cli()/sti() to spinlocks
308c2ecf20Sopenharmony_ci	1.02    1998.12.14      Added support for nice > 1
318c2ecf20Sopenharmony_ci*/
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define PS_VERSION	"1.02"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/sched.h>
368c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic void ps_tq_int(struct work_struct *work);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic void (* ps_continuation)(void);
418c2ecf20Sopenharmony_cistatic int (* ps_ready)(void);
428c2ecf20Sopenharmony_cistatic unsigned long ps_timeout;
438c2ecf20Sopenharmony_cistatic int ps_tq_active = 0;
448c2ecf20Sopenharmony_cistatic int ps_nice = 0;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic void ps_set_intr(void (*continuation)(void),
518c2ecf20Sopenharmony_ci			int (*ready)(void),
528c2ecf20Sopenharmony_ci			int timeout, int nice)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	unsigned long	flags;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ps_spinlock,flags);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	ps_continuation = continuation;
598c2ecf20Sopenharmony_ci	ps_ready = ready;
608c2ecf20Sopenharmony_ci	ps_timeout = jiffies + timeout;
618c2ecf20Sopenharmony_ci	ps_nice = nice;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	if (!ps_tq_active) {
648c2ecf20Sopenharmony_ci		ps_tq_active = 1;
658c2ecf20Sopenharmony_ci		if (!ps_nice)
668c2ecf20Sopenharmony_ci			schedule_delayed_work(&ps_tq, 0);
678c2ecf20Sopenharmony_ci		else
688c2ecf20Sopenharmony_ci			schedule_delayed_work(&ps_tq, ps_nice-1);
698c2ecf20Sopenharmony_ci	}
708c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ps_spinlock,flags);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic void ps_tq_int(struct work_struct *work)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	void (*con)(void);
768c2ecf20Sopenharmony_ci	unsigned long flags;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	spin_lock_irqsave(&ps_spinlock,flags);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	con = ps_continuation;
818c2ecf20Sopenharmony_ci	ps_tq_active = 0;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (!con) {
848c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&ps_spinlock,flags);
858c2ecf20Sopenharmony_ci		return;
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci	if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
888c2ecf20Sopenharmony_ci		ps_continuation = NULL;
898c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&ps_spinlock,flags);
908c2ecf20Sopenharmony_ci		con();
918c2ecf20Sopenharmony_ci		return;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci	ps_tq_active = 1;
948c2ecf20Sopenharmony_ci	if (!ps_nice)
958c2ecf20Sopenharmony_ci		schedule_delayed_work(&ps_tq, 0);
968c2ecf20Sopenharmony_ci	else
978c2ecf20Sopenharmony_ci		schedule_delayed_work(&ps_tq, ps_nice-1);
988c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&ps_spinlock,flags);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci/* end of pseudo.h */
1028c2ecf20Sopenharmony_ci
103