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