2005-04-17 02:20:36 +04:00
/*
pseudo . h ( c ) 1997 - 8 Grant R . Guenther < grant @ torque . net >
Under the terms of the GNU General Public License .
This is the " pseudo-interrupt " logic for parallel port drivers .
This module is # included into each driver . It makes one
function available :
ps_set_intr ( void ( * continuation ) ( void ) ,
int ( * ready ) ( void ) ,
int timeout ,
int nice )
Which will arrange for ready ( ) to be evaluated frequently and
when either it returns true , or timeout jiffies have passed ,
continuation ( ) will be invoked .
If nice is 1 , the test will done approximately once a
jiffy . If nice is 0 , the test will also be done whenever
the scheduler runs ( by adding it to a task queue ) . If
nice is greater than 1 , the test will be done once every
( nice - 1 ) jiffies .
*/
/* Changes:
1.01 1998.05 .03 Switched from cli ( ) / sti ( ) to spinlocks
1.02 1998.12 .14 Added support for nice > 1
*/
# define PS_VERSION "1.02"
# include <linux/sched.h>
# include <linux/workqueue.h>
2006-11-22 17:57:56 +03:00
static void ps_tq_int ( struct work_struct * work ) ;
2005-04-17 02:20:36 +04:00
static void ( * ps_continuation ) ( void ) ;
static int ( * ps_ready ) ( void ) ;
static unsigned long ps_timeout ;
static int ps_tq_active = 0 ;
static int ps_nice = 0 ;
static DEFINE_SPINLOCK ( ps_spinlock __attribute__ ( ( unused ) ) ) ;
2006-11-22 17:57:56 +03:00
static DECLARE_DELAYED_WORK ( ps_tq , ps_tq_int ) ;
2005-04-17 02:20:36 +04:00
static void ps_set_intr ( void ( * continuation ) ( void ) ,
int ( * ready ) ( void ) ,
int timeout , int nice )
{
unsigned long flags ;
spin_lock_irqsave ( & ps_spinlock , flags ) ;
ps_continuation = continuation ;
ps_ready = ready ;
ps_timeout = jiffies + timeout ;
ps_nice = nice ;
if ( ! ps_tq_active ) {
ps_tq_active = 1 ;
if ( ! ps_nice )
2006-11-22 17:57:56 +03:00
schedule_delayed_work ( & ps_tq , 0 ) ;
2005-04-17 02:20:36 +04:00
else
schedule_delayed_work ( & ps_tq , ps_nice - 1 ) ;
}
spin_unlock_irqrestore ( & ps_spinlock , flags ) ;
}
2006-11-22 17:57:56 +03:00
static void ps_tq_int ( struct work_struct * work )
2005-04-17 02:20:36 +04:00
{
void ( * con ) ( void ) ;
unsigned long flags ;
spin_lock_irqsave ( & ps_spinlock , flags ) ;
con = ps_continuation ;
ps_tq_active = 0 ;
if ( ! con ) {
spin_unlock_irqrestore ( & ps_spinlock , flags ) ;
return ;
}
if ( ! ps_ready | | ps_ready ( ) | | time_after_eq ( jiffies , ps_timeout ) ) {
ps_continuation = NULL ;
spin_unlock_irqrestore ( & ps_spinlock , flags ) ;
con ( ) ;
return ;
}
ps_tq_active = 1 ;
if ( ! ps_nice )
2006-11-22 17:57:56 +03:00
schedule_delayed_work ( & ps_tq , 0 ) ;
2005-04-17 02:20:36 +04:00
else
schedule_delayed_work ( & ps_tq , ps_nice - 1 ) ;
spin_unlock_irqrestore ( & ps_spinlock , flags ) ;
}
/* end of pseudo.h */