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