Back to home page

OSCL-LXR

 
 

    


0001 /* 
0002         pseudo.h    (c) 1997-8  Grant R. Guenther <grant@torque.net>
0003                                 Under the terms of the GNU General Public License.
0004 
0005     This is the "pseudo-interrupt" logic for parallel port drivers.
0006 
0007         This module is #included into each driver.  It makes one
0008         function available:
0009 
0010         ps_set_intr( void (*continuation)(void),
0011                  int  (*ready)(void),
0012                  int timeout,
0013                  int nice )
0014 
0015     Which will arrange for ready() to be evaluated frequently and
0016     when either it returns true, or timeout jiffies have passed,
0017     continuation() will be invoked.
0018 
0019     If nice is 1, the test will done approximately once a
0020     jiffy.  If nice is 0, the test will also be done whenever
0021     the scheduler runs (by adding it to a task queue).  If
0022     nice is greater than 1, the test will be done once every
0023     (nice-1) jiffies. 
0024 
0025 */
0026 
0027 /* Changes:
0028 
0029     1.01    1998.05.03  Switched from cli()/sti() to spinlocks
0030     1.02    1998.12.14      Added support for nice > 1
0031 */
0032     
0033 #define PS_VERSION  "1.02"
0034 
0035 #include <linux/sched.h>
0036 #include <linux/workqueue.h>
0037 
0038 static void ps_tq_int(struct work_struct *work);
0039 
0040 static void (* ps_continuation)(void);
0041 static int (* ps_ready)(void);
0042 static unsigned long ps_timeout;
0043 static int ps_tq_active = 0;
0044 static int ps_nice = 0;
0045 
0046 static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
0047 
0048 static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
0049 
0050 static void ps_set_intr(void (*continuation)(void), 
0051             int (*ready)(void),
0052             int timeout, int nice)
0053 {
0054     unsigned long   flags;
0055 
0056     spin_lock_irqsave(&ps_spinlock,flags);
0057 
0058     ps_continuation = continuation;
0059     ps_ready = ready;
0060     ps_timeout = jiffies + timeout;
0061     ps_nice = nice;
0062 
0063     if (!ps_tq_active) {
0064         ps_tq_active = 1;
0065         if (!ps_nice)
0066             schedule_delayed_work(&ps_tq, 0);
0067         else
0068             schedule_delayed_work(&ps_tq, ps_nice-1);
0069     }
0070     spin_unlock_irqrestore(&ps_spinlock,flags);
0071 }
0072 
0073 static void ps_tq_int(struct work_struct *work)
0074 {
0075     void (*con)(void);
0076     unsigned long flags;
0077 
0078     spin_lock_irqsave(&ps_spinlock,flags);
0079 
0080     con = ps_continuation;
0081     ps_tq_active = 0;
0082 
0083     if (!con) {
0084         spin_unlock_irqrestore(&ps_spinlock,flags);
0085         return;
0086     }
0087     if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
0088         ps_continuation = NULL;
0089         spin_unlock_irqrestore(&ps_spinlock,flags);
0090         con();
0091         return;
0092     }
0093     ps_tq_active = 1;
0094     if (!ps_nice)
0095         schedule_delayed_work(&ps_tq, 0);
0096     else
0097         schedule_delayed_work(&ps_tq, ps_nice-1);
0098     spin_unlock_irqrestore(&ps_spinlock,flags);
0099 }
0100 
0101 /* end of pseudo.h */
0102