2008-10-16 09:04:33 +04:00
/*
2005-04-17 02:20:36 +04:00
* Parallel - port resource manager code .
*
* Authors : David Campbell < campbell @ tirian . che . curtin . edu . au >
* Tim Waugh < tim @ cyberelk . demon . co . uk >
* Jose Renau < renau @ acm . org >
* Philip Blundell < philb @ gnu . org >
* Andrea Arcangeli
*
* based on work by Grant Guenther < grant @ torque . net >
* and Philip Blundell
*
* Any part of this program may be used in documents licensed under
* the GNU Free Documentation License , Version 1.1 or any later version
* published by the Free Software Foundation .
*/
# undef PARPORT_DEBUG_SHARING /* undef for production */
# include <linux/module.h>
# include <linux/string.h>
# include <linux/threads.h>
# include <linux/parport.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/interrupt.h>
# include <linux/ioport.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/sched.h>
# include <linux/kmod.h>
# include <linux/spinlock.h>
2006-03-26 13:37:14 +04:00
# include <linux/mutex.h>
2005-04-17 02:20:36 +04:00
# include <asm/irq.h>
# undef PARPORT_PARANOID
# define PARPORT_DEFAULT_TIMESLICE (HZ / 5)
unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE ;
int parport_default_spintime = DEFAULT_SPIN_TIME ;
static LIST_HEAD ( portlist ) ;
static DEFINE_SPINLOCK ( parportlist_lock ) ;
/* list of all allocated ports, sorted by ->number */
static LIST_HEAD ( all_ports ) ;
static DEFINE_SPINLOCK ( full_list_lock ) ;
static LIST_HEAD ( drivers ) ;
2006-03-26 13:37:14 +04:00
static DEFINE_MUTEX ( registration_lock ) ;
2005-04-17 02:20:36 +04:00
/* What you can do to a port that's gone away.. */
static void dead_write_lines ( struct parport * p , unsigned char b ) { }
static unsigned char dead_read_lines ( struct parport * p ) { return 0 ; }
static unsigned char dead_frob_lines ( struct parport * p , unsigned char b ,
unsigned char c ) { return 0 ; }
static void dead_onearg ( struct parport * p ) { }
static void dead_initstate ( struct pardevice * d , struct parport_state * s ) { }
static void dead_state ( struct parport * p , struct parport_state * s ) { }
static size_t dead_write ( struct parport * p , const void * b , size_t l , int f )
{ return 0 ; }
static size_t dead_read ( struct parport * p , void * b , size_t l , int f )
{ return 0 ; }
static struct parport_operations dead_ops = {
. write_data = dead_write_lines , /* data */
. read_data = dead_read_lines ,
. write_control = dead_write_lines , /* control */
. read_control = dead_read_lines ,
. frob_control = dead_frob_lines ,
. read_status = dead_read_lines , /* status */
. enable_irq = dead_onearg , /* enable_irq */
. disable_irq = dead_onearg , /* disable_irq */
. data_forward = dead_onearg , /* data_forward */
. data_reverse = dead_onearg , /* data_reverse */
. init_state = dead_initstate , /* init_state */
. save_state = dead_state ,
. restore_state = dead_state ,
. epp_write_data = dead_write , /* epp */
. epp_read_data = dead_read ,
. epp_write_addr = dead_write ,
. epp_read_addr = dead_read ,
. ecp_write_data = dead_write , /* ecp */
. ecp_read_data = dead_read ,
. ecp_write_addr = dead_write ,
. compat_write_data = dead_write , /* compat */
. nibble_read_data = dead_read , /* nibble */
. byte_read_data = dead_read , /* byte */
. owner = NULL ,
} ;
/* Call attach(port) for each registered driver. */
static void attach_driver_chain ( struct parport * port )
{
/* caller has exclusive registration_lock */
struct parport_driver * drv ;
list_for_each_entry ( drv , & drivers , list )
drv - > attach ( port ) ;
}
/* Call detach(port) for each registered driver. */
static void detach_driver_chain ( struct parport * port )
{
struct parport_driver * drv ;
/* caller has exclusive registration_lock */
list_for_each_entry ( drv , & drivers , list )
drv - > detach ( port ) ;
}
/* Ask kmod for some lowlevel drivers. */
static void get_lowlevel_driver ( void )
{
/* There is no actual module called this: you should set
* up an alias for modutils . */
request_module ( " parport_lowlevel " ) ;
}
/**
* parport_register_driver - register a parallel port device driver
* @ drv : structure describing the driver
*
* This can be called by a parallel port device driver in order
* to receive notifications about ports being found in the
* system , as well as ports no longer available .
*
* The @ drv structure is allocated by the caller and must not be
* deallocated until after calling parport_unregister_driver ( ) .
*
* The driver ' s attach ( ) function may block . The port that
* attach ( ) is given will be valid for the duration of the
* callback , but if the driver wants to take a copy of the
* pointer it must call parport_get_port ( ) to do so . Calling
* parport_register_device ( ) on that port will do this for you .
*
* The driver ' s detach ( ) function may block . The port that
* detach ( ) is given will be valid for the duration of the
* callback , but if the driver wants to take a copy of the
* pointer it must call parport_get_port ( ) to do so .
*
* Returns 0 on success . Currently it always succeeds .
* */
int parport_register_driver ( struct parport_driver * drv )
{
struct parport * port ;
if ( list_empty ( & portlist ) )
get_lowlevel_driver ( ) ;
2006-03-26 13:37:14 +04:00
mutex_lock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
list_for_each_entry ( port , & portlist , list )
drv - > attach ( port ) ;
list_add ( & drv - > list , & drivers ) ;
2006-03-26 13:37:14 +04:00
mutex_unlock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/**
* parport_unregister_driver - deregister a parallel port device driver
* @ drv : structure describing the driver that was given to
* parport_register_driver ( )
*
* This should be called by a parallel port device driver that
* has registered itself using parport_register_driver ( ) when it
* is about to be unloaded .
*
* When it returns , the driver ' s attach ( ) routine will no longer
* be called , and for each port that attach ( ) was called for , the
* detach ( ) routine will have been called .
*
* All the driver ' s attach ( ) and detach ( ) calls are guaranteed to have
* finished by the time this function returns .
* */
void parport_unregister_driver ( struct parport_driver * drv )
{
struct parport * port ;
2006-03-26 13:37:14 +04:00
mutex_lock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
list_del_init ( & drv - > list ) ;
list_for_each_entry ( port , & portlist , list )
drv - > detach ( port ) ;
2006-03-26 13:37:14 +04:00
mutex_unlock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
}
static void free_port ( struct parport * port )
{
int d ;
spin_lock ( & full_list_lock ) ;
list_del ( & port - > full_list ) ;
spin_unlock ( & full_list_lock ) ;
for ( d = 0 ; d < 5 ; d + + ) {
2005-11-07 12:01:32 +03:00
kfree ( port - > probe_info [ d ] . class_name ) ;
kfree ( port - > probe_info [ d ] . mfr ) ;
kfree ( port - > probe_info [ d ] . model ) ;
kfree ( port - > probe_info [ d ] . cmdset ) ;
kfree ( port - > probe_info [ d ] . description ) ;
2005-04-17 02:20:36 +04:00
}
kfree ( port - > name ) ;
kfree ( port ) ;
}
/**
* parport_get_port - increment a port ' s reference count
* @ port : the port
*
2006-06-25 16:49:29 +04:00
* This ensures that a struct parport pointer remains valid
2005-04-17 02:20:36 +04:00
* until the matching parport_put_port ( ) call .
* */
struct parport * parport_get_port ( struct parport * port )
{
atomic_inc ( & port - > ref_count ) ;
return port ;
}
/**
* parport_put_port - decrement a port ' s reference count
* @ port : the port
*
* This should be called once for each call to parport_get_port ( ) ,
* once the port is no longer needed .
* */
void parport_put_port ( struct parport * port )
{
if ( atomic_dec_and_test ( & port - > ref_count ) )
/* Can destroy it now. */
free_port ( port ) ;
return ;
}
/**
* parport_register_port - register a parallel port
* @ base : base I / O address
* @ irq : IRQ line
* @ dma : DMA channel
* @ ops : pointer to the port driver ' s port operations structure
*
* When a parallel port ( lowlevel ) driver finds a port that
* should be made available to parallel port device drivers , it
* should call parport_register_port ( ) . The @ base , @ irq , and
* @ dma parameters are for the convenience of port drivers , and
* for ports where they aren ' t meaningful needn ' t be set to
* anything special . They can be altered afterwards by adjusting
* the relevant members of the parport structure that is returned
* and represents the port . They should not be tampered with
* after calling parport_announce_port , however .
*
* If there are parallel port device drivers in the system that
* have registered themselves using parport_register_driver ( ) ,
* they are not told about the port at this time ; that is done by
* parport_announce_port ( ) .
*
* The @ ops structure is allocated by the caller , and must not be
* deallocated before calling parport_remove_port ( ) .
*
* If there is no memory to allocate a new parport structure ,
* this function will return % NULL .
* */
struct parport * parport_register_port ( unsigned long base , int irq , int dma ,
struct parport_operations * ops )
{
struct list_head * l ;
struct parport * tmp ;
int num ;
int device ;
char * name ;
tmp = kmalloc ( sizeof ( struct parport ) , GFP_KERNEL ) ;
if ( ! tmp ) {
printk ( KERN_WARNING " parport: memory squeeze \n " ) ;
return NULL ;
}
/* Init our structure */
memset ( tmp , 0 , sizeof ( struct parport ) ) ;
tmp - > base = base ;
tmp - > irq = irq ;
tmp - > dma = dma ;
tmp - > muxport = tmp - > daisy = tmp - > muxsel = - 1 ;
tmp - > modes = 0 ;
INIT_LIST_HEAD ( & tmp - > list ) ;
tmp - > devices = tmp - > cad = NULL ;
tmp - > flags = 0 ;
tmp - > ops = ops ;
tmp - > physport = tmp ;
memset ( tmp - > probe_info , 0 , 5 * sizeof ( struct parport_device_info ) ) ;
rwlock_init ( & tmp - > cad_lock ) ;
spin_lock_init ( & tmp - > waitlist_lock ) ;
spin_lock_init ( & tmp - > pardevice_lock ) ;
tmp - > ieee1284 . mode = IEEE1284_MODE_COMPAT ;
tmp - > ieee1284 . phase = IEEE1284_PH_FWD_IDLE ;
2010-09-07 18:32:34 +04:00
sema_init ( & tmp - > ieee1284 . irq , 0 ) ;
2005-04-17 02:20:36 +04:00
tmp - > spintime = parport_default_spintime ;
atomic_set ( & tmp - > ref_count , 1 ) ;
INIT_LIST_HEAD ( & tmp - > full_list ) ;
name = kmalloc ( 15 , GFP_KERNEL ) ;
if ( ! name ) {
printk ( KERN_ERR " parport: memory squeeze \n " ) ;
kfree ( tmp ) ;
return NULL ;
}
/* Search for the lowest free parport number. */
spin_lock ( & full_list_lock ) ;
for ( l = all_ports . next , num = 0 ; l ! = & all_ports ; l = l - > next , num + + ) {
struct parport * p = list_entry ( l , struct parport , full_list ) ;
if ( p - > number ! = num )
break ;
}
tmp - > portnum = tmp - > number = num ;
list_add_tail ( & tmp - > full_list , l ) ;
spin_unlock ( & full_list_lock ) ;
/*
* Now that the portnum is known finish doing the Init .
*/
sprintf ( name , " parport%d " , tmp - > portnum = tmp - > number ) ;
tmp - > name = name ;
for ( device = 0 ; device < 5 ; device + + )
/* assume the worst */
tmp - > probe_info [ device ] . class = PARPORT_CLASS_LEGACY ;
tmp - > waithead = tmp - > waittail = NULL ;
return tmp ;
}
/**
* parport_announce_port - tell device drivers about a parallel port
* @ port : parallel port to announce
*
* After a port driver has registered a parallel port with
* parport_register_port , and performed any necessary
* initialisation or adjustments , it should call
* parport_announce_port ( ) in order to notify all device drivers
* that have called parport_register_driver ( ) . Their attach ( )
* functions will be called , with @ port as the parameter .
* */
void parport_announce_port ( struct parport * port )
{
int i ;
# ifdef CONFIG_PARPORT_1284
/* Analyse the IEEE1284.3 topology of the port. */
parport_daisy_init ( port ) ;
# endif
2007-05-08 11:27:35 +04:00
if ( ! port - > dev )
printk ( KERN_WARNING " %s: fix this legacy "
" no-device port driver! \n " ,
port - > name ) ;
2005-04-17 02:20:36 +04:00
parport_proc_register ( port ) ;
2006-03-26 13:37:14 +04:00
mutex_lock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
spin_lock_irq ( & parportlist_lock ) ;
list_add_tail ( & port - > list , & portlist ) ;
for ( i = 1 ; i < 3 ; i + + ) {
struct parport * slave = port - > slaves [ i - 1 ] ;
if ( slave )
list_add_tail ( & slave - > list , & portlist ) ;
}
spin_unlock_irq ( & parportlist_lock ) ;
/* Let drivers know that new port(s) has arrived. */
attach_driver_chain ( port ) ;
for ( i = 1 ; i < 3 ; i + + ) {
struct parport * slave = port - > slaves [ i - 1 ] ;
if ( slave )
attach_driver_chain ( slave ) ;
}
2006-03-26 13:37:14 +04:00
mutex_unlock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
}
/**
* parport_remove_port - deregister a parallel port
* @ port : parallel port to deregister
*
* When a parallel port driver is forcibly unloaded , or a
* parallel port becomes inaccessible , the port driver must call
* this function in order to deal with device drivers that still
* want to use it .
*
* The parport structure associated with the port has its
* operations structure replaced with one containing ' null '
* operations that return errors or just don ' t do anything .
*
* Any drivers that have registered themselves using
* parport_register_driver ( ) are notified that the port is no
* longer accessible by having their detach ( ) routines called
* with @ port as the parameter .
* */
void parport_remove_port ( struct parport * port )
{
int i ;
2006-03-26 13:37:14 +04:00
mutex_lock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
/* Spread the word. */
detach_driver_chain ( port ) ;
# ifdef CONFIG_PARPORT_1284
/* Forget the IEEE1284.3 topology of the port. */
parport_daisy_fini ( port ) ;
for ( i = 1 ; i < 3 ; i + + ) {
struct parport * slave = port - > slaves [ i - 1 ] ;
if ( ! slave )
continue ;
detach_driver_chain ( slave ) ;
parport_daisy_fini ( slave ) ;
}
# endif
port - > ops = & dead_ops ;
spin_lock ( & parportlist_lock ) ;
list_del_init ( & port - > list ) ;
for ( i = 1 ; i < 3 ; i + + ) {
struct parport * slave = port - > slaves [ i - 1 ] ;
if ( slave )
list_del_init ( & slave - > list ) ;
}
spin_unlock ( & parportlist_lock ) ;
2006-03-26 13:37:14 +04:00
mutex_unlock ( & registration_lock ) ;
2005-04-17 02:20:36 +04:00
parport_proc_unregister ( port ) ;
for ( i = 1 ; i < 3 ; i + + ) {
struct parport * slave = port - > slaves [ i - 1 ] ;
if ( slave )
parport_put_port ( slave ) ;
}
}
/**
* parport_register_device - register a device on a parallel port
* @ port : port to which the device is attached
* @ name : a name to refer to the device
* @ pf : preemption callback
* @ kf : kick callback ( wake - up )
* @ irq_func : interrupt handler
* @ flags : registration flags
* @ handle : data for callback functions
*
* This function , called by parallel port device drivers ,
* declares that a device is connected to a port , and tells the
* system all it needs to know .
*
* The @ name is allocated by the caller and must not be
* deallocated until the caller calls @ parport_unregister_device
* for that device .
*
* The preemption callback function , @ pf , is called when this
* device driver has claimed access to the port but another
* device driver wants to use it . It is given @ handle as its
* parameter , and should return zero if it is willing for the
* system to release the port to another driver on its behalf .
* If it wants to keep control of the port it should return
* non - zero , and no action will be taken . It is good manners for
* the driver to try to release the port at the earliest
* opportunity after its preemption callback rejects a preemption
* attempt . Note that if a preemption callback is happy for
* preemption to go ahead , there is no need to release the port ;
* it is done automatically . This function may not block , as it
* may be called from interrupt context . If the device driver
* does not support preemption , @ pf can be % NULL .
*
* The wake - up ( " kick " ) callback function , @ kf , is called when
* the port is available to be claimed for exclusive access ; that
* is , parport_claim ( ) is guaranteed to succeed when called from
* inside the wake - up callback function . If the driver wants to
* claim the port it should do so ; otherwise , it need not take
* any action . This function may not block , as it may be called
* from interrupt context . If the device driver does not want to
* be explicitly invited to claim the port in this way , @ kf can
* be % NULL .
*
* The interrupt handler , @ irq_func , is called when an interrupt
* arrives from the parallel port . Note that if a device driver
* wants to use interrupts it should use parport_enable_irq ( ) ,
* and can also check the irq member of the parport structure
* representing the port .
*
* The parallel port ( lowlevel ) driver is the one that has called
* request_irq ( ) and whose interrupt handler is called first .
* This handler does whatever needs to be done to the hardware to
* acknowledge the interrupt ( for PC - style ports there is nothing
* special to be done ) . It then tells the IEEE 1284 code about
* the interrupt , which may involve reacting to an IEEE 1284
* event depending on the current IEEE 1284 phase . After this ,
* it calls @ irq_func . Needless to say , @ irq_func will be called
* from interrupt context , and may not block .
*
* The % PARPORT_DEV_EXCL flag is for preventing port sharing , and
* so should only be used when sharing the port with other device
* drivers is impossible and would lead to incorrect behaviour .
* Use it sparingly ! Normally , @ flags will be zero .
*
* This function returns a pointer to a structure that represents
* the device on the port , or % NULL if there is not enough memory
* to allocate space for that structure .
* */
struct pardevice *
parport_register_device ( struct parport * port , const char * name ,
int ( * pf ) ( void * ) , void ( * kf ) ( void * ) ,
2007-10-19 10:54:26 +04:00
void ( * irq_func ) ( void * ) ,
2005-04-17 02:20:36 +04:00
int flags , void * handle )
{
struct pardevice * tmp ;
if ( port - > physport - > flags & PARPORT_FLAG_EXCL ) {
/* An exclusive device is registered. */
printk ( KERN_DEBUG " %s: no more devices allowed \n " ,
port - > name ) ;
return NULL ;
}
if ( flags & PARPORT_DEV_LURK ) {
if ( ! pf | | ! kf ) {
printk ( KERN_INFO " %s: refused to register lurking device (%s) without callbacks \n " , port - > name , name ) ;
return NULL ;
}
}
/* We up our own module reference count, and that of the port
on which a device is to be registered , to ensure that
neither of us gets unloaded while we sleep in ( e . g . )
kmalloc .
*/
if ( ! try_module_get ( port - > ops - > owner ) ) {
return NULL ;
}
parport_get_port ( port ) ;
tmp = kmalloc ( sizeof ( struct pardevice ) , GFP_KERNEL ) ;
if ( tmp = = NULL ) {
printk ( KERN_WARNING " %s: memory squeeze, couldn't register %s. \n " , port - > name , name ) ;
goto out ;
}
tmp - > state = kmalloc ( sizeof ( struct parport_state ) , GFP_KERNEL ) ;
if ( tmp - > state = = NULL ) {
printk ( KERN_WARNING " %s: memory squeeze, couldn't register %s. \n " , port - > name , name ) ;
goto out_free_pardevice ;
}
tmp - > name = name ;
tmp - > port = port ;
tmp - > daisy = - 1 ;
tmp - > preempt = pf ;
tmp - > wakeup = kf ;
tmp - > private = handle ;
tmp - > flags = flags ;
tmp - > irq_func = irq_func ;
tmp - > waiting = 0 ;
tmp - > timeout = 5 * HZ ;
/* Chain this onto the list */
tmp - > prev = NULL ;
/*
* This function must not run from an irq handler so we don ' t need
* to clear irq on the local CPU . - arca
*/
spin_lock ( & port - > physport - > pardevice_lock ) ;
if ( flags & PARPORT_DEV_EXCL ) {
if ( port - > physport - > devices ) {
spin_unlock ( & port - > physport - > pardevice_lock ) ;
printk ( KERN_DEBUG
" %s: cannot grant exclusive access for "
" device %s \n " , port - > name , name ) ;
goto out_free_all ;
}
port - > flags | = PARPORT_FLAG_EXCL ;
}
tmp - > next = port - > physport - > devices ;
wmb ( ) ; /* Make sure that tmp->next is written before it's
added to the list ; see comments marked ' no locking
required ' */
if ( port - > physport - > devices )
port - > physport - > devices - > prev = tmp ;
port - > physport - > devices = tmp ;
spin_unlock ( & port - > physport - > pardevice_lock ) ;
init_waitqueue_head ( & tmp - > wait_q ) ;
tmp - > timeslice = parport_default_timeslice ;
tmp - > waitnext = tmp - > waitprev = NULL ;
/*
* This has to be run as last thing since init_state may need other
* pardevice fields . - arca
*/
port - > ops - > init_state ( tmp , tmp - > state ) ;
2009-06-02 19:58:10 +04:00
if ( ! test_and_set_bit ( PARPORT_DEVPROC_REGISTERED , & port - > devflags ) ) {
port - > proc_device = tmp ;
parport_device_proc_register ( tmp ) ;
}
2005-04-17 02:20:36 +04:00
return tmp ;
out_free_all :
2005-11-07 12:01:32 +03:00
kfree ( tmp - > state ) ;
2005-04-17 02:20:36 +04:00
out_free_pardevice :
2005-11-07 12:01:32 +03:00
kfree ( tmp ) ;
2005-04-17 02:20:36 +04:00
out :
parport_put_port ( port ) ;
module_put ( port - > ops - > owner ) ;
return NULL ;
}
/**
* parport_unregister_device - deregister a device on a parallel port
* @ dev : pointer to structure representing device
*
* This undoes the effect of parport_register_device ( ) .
* */
void parport_unregister_device ( struct pardevice * dev )
{
struct parport * port ;
# ifdef PARPORT_PARANOID
if ( dev = = NULL ) {
printk ( KERN_ERR " parport_unregister_device: passed NULL \n " ) ;
return ;
}
# endif
port = dev - > port - > physport ;
2009-06-02 19:58:10 +04:00
if ( port - > proc_device = = dev ) {
port - > proc_device = NULL ;
clear_bit ( PARPORT_DEVPROC_REGISTERED , & port - > devflags ) ;
parport_device_proc_unregister ( dev ) ;
}
2005-04-17 02:20:36 +04:00
if ( port - > cad = = dev ) {
printk ( KERN_DEBUG " %s: %s forgot to release port \n " ,
port - > name , dev - > name ) ;
parport_release ( dev ) ;
}
spin_lock ( & port - > pardevice_lock ) ;
if ( dev - > next )
dev - > next - > prev = dev - > prev ;
if ( dev - > prev )
dev - > prev - > next = dev - > next ;
else
port - > devices = dev - > next ;
if ( dev - > flags & PARPORT_DEV_EXCL )
port - > flags & = ~ PARPORT_FLAG_EXCL ;
spin_unlock ( & port - > pardevice_lock ) ;
/* Make sure we haven't left any pointers around in the wait
* list . */
2011-01-26 02:07:16 +03:00
spin_lock_irq ( & port - > waitlist_lock ) ;
2005-04-17 02:20:36 +04:00
if ( dev - > waitprev | | dev - > waitnext | | port - > waithead = = dev ) {
if ( dev - > waitprev )
dev - > waitprev - > waitnext = dev - > waitnext ;
else
port - > waithead = dev - > waitnext ;
if ( dev - > waitnext )
dev - > waitnext - > waitprev = dev - > waitprev ;
else
port - > waittail = dev - > waitprev ;
}
2011-01-26 02:07:16 +03:00
spin_unlock_irq ( & port - > waitlist_lock ) ;
2005-04-17 02:20:36 +04:00
kfree ( dev - > state ) ;
kfree ( dev ) ;
module_put ( port - > ops - > owner ) ;
parport_put_port ( port ) ;
}
/**
* parport_find_number - find a parallel port by number
* @ number : parallel port number
*
* This returns the parallel port with the specified number , or
* % NULL if there is none .
*
* There is an implicit parport_get_port ( ) done already ; to throw
* away the reference to the port that parport_find_number ( )
* gives you , use parport_put_port ( ) .
*/
struct parport * parport_find_number ( int number )
{
struct parport * port , * result = NULL ;
if ( list_empty ( & portlist ) )
get_lowlevel_driver ( ) ;
spin_lock ( & parportlist_lock ) ;
list_for_each_entry ( port , & portlist , list ) {
if ( port - > number = = number ) {
result = parport_get_port ( port ) ;
break ;
}
}
spin_unlock ( & parportlist_lock ) ;
return result ;
}
/**
* parport_find_base - find a parallel port by base address
* @ base : base I / O address
*
* This returns the parallel port with the specified base
* address , or % NULL if there is none .
*
* There is an implicit parport_get_port ( ) done already ; to throw
* away the reference to the port that parport_find_base ( )
* gives you , use parport_put_port ( ) .
*/
struct parport * parport_find_base ( unsigned long base )
{
struct parport * port , * result = NULL ;
if ( list_empty ( & portlist ) )
get_lowlevel_driver ( ) ;
spin_lock ( & parportlist_lock ) ;
list_for_each_entry ( port , & portlist , list ) {
if ( port - > base = = base ) {
result = parport_get_port ( port ) ;
break ;
}
}
spin_unlock ( & parportlist_lock ) ;
return result ;
}
/**
* parport_claim - claim access to a parallel port device
* @ dev : pointer to structure representing a device on the port
*
* This function will not block and so can be used from interrupt
* context . If parport_claim ( ) succeeds in claiming access to
* the port it returns zero and the port is available to use . It
* may fail ( returning non - zero ) if the port is in use by another
* driver and that driver is not willing to relinquish control of
* the port .
* */
int parport_claim ( struct pardevice * dev )
{
struct pardevice * oldcad ;
struct parport * port = dev - > port - > physport ;
unsigned long flags ;
if ( port - > cad = = dev ) {
printk ( KERN_INFO " %s: %s already owner \n " ,
dev - > port - > name , dev - > name ) ;
return 0 ;
}
/* Preempt any current device */
write_lock_irqsave ( & port - > cad_lock , flags ) ;
if ( ( oldcad = port - > cad ) ! = NULL ) {
if ( oldcad - > preempt ) {
if ( oldcad - > preempt ( oldcad - > private ) )
goto blocked ;
port - > ops - > save_state ( port , dev - > state ) ;
} else
goto blocked ;
if ( port - > cad ! = oldcad ) {
/* I think we'll actually deadlock rather than
get here , but just in case . . */
printk ( KERN_WARNING
" %s: %s released port when preempted! \n " ,
port - > name , oldcad - > name ) ;
if ( port - > cad )
goto blocked ;
}
}
/* Can't fail from now on, so mark ourselves as no longer waiting. */
if ( dev - > waiting & 1 ) {
dev - > waiting = 0 ;
/* Take ourselves out of the wait list again. */
spin_lock_irq ( & port - > waitlist_lock ) ;
if ( dev - > waitprev )
dev - > waitprev - > waitnext = dev - > waitnext ;
else
port - > waithead = dev - > waitnext ;
if ( dev - > waitnext )
dev - > waitnext - > waitprev = dev - > waitprev ;
else
port - > waittail = dev - > waitprev ;
spin_unlock_irq ( & port - > waitlist_lock ) ;
dev - > waitprev = dev - > waitnext = NULL ;
}
/* Now we do the change of devices */
port - > cad = dev ;
# ifdef CONFIG_PARPORT_1284
/* If it's a mux port, select it. */
if ( dev - > port - > muxport > = 0 ) {
/* FIXME */
port - > muxsel = dev - > port - > muxport ;
}
/* If it's a daisy chain device, select it. */
if ( dev - > daisy > = 0 ) {
/* This could be lazier. */
if ( ! parport_daisy_select ( port , dev - > daisy ,
IEEE1284_MODE_COMPAT ) )
port - > daisy = dev - > daisy ;
}
# endif /* IEEE1284.3 support */
/* Restore control registers */
port - > ops - > restore_state ( port , dev - > state ) ;
write_unlock_irqrestore ( & port - > cad_lock , flags ) ;
dev - > time = jiffies ;
return 0 ;
blocked :
/* If this is the first time we tried to claim the port, register an
interest . This is only allowed for devices sleeping in
parport_claim_or_block ( ) , or those with a wakeup function . */
/* The cad_lock is still held for writing here */
if ( dev - > waiting & 2 | | dev - > wakeup ) {
spin_lock ( & port - > waitlist_lock ) ;
if ( test_and_set_bit ( 0 , & dev - > waiting ) = = 0 ) {
/* First add ourselves to the end of the wait list. */
dev - > waitnext = NULL ;
dev - > waitprev = port - > waittail ;
if ( port - > waittail ) {
port - > waittail - > waitnext = dev ;
port - > waittail = dev ;
} else
port - > waithead = port - > waittail = dev ;
}
spin_unlock ( & port - > waitlist_lock ) ;
}
write_unlock_irqrestore ( & port - > cad_lock , flags ) ;
return - EAGAIN ;
}
/**
* parport_claim_or_block - claim access to a parallel port device
* @ dev : pointer to structure representing a device on the port
*
* This behaves like parport_claim ( ) , but will block if necessary
* to wait for the port to be free . A return value of 1
* indicates that it slept ; 0 means that it succeeded without
* needing to sleep . A negative error code indicates failure .
* */
int parport_claim_or_block ( struct pardevice * dev )
{
int r ;
/* Signal to parport_claim() that we can wait even without a
wakeup function . */
dev - > waiting = 2 ;
/* Try to claim the port. If this fails, we need to sleep. */
r = parport_claim ( dev ) ;
if ( r = = - EAGAIN ) {
# ifdef PARPORT_DEBUG_SHARING
printk ( KERN_DEBUG " %s: parport_claim() returned -EAGAIN \n " , dev - > name ) ;
# endif
/*
* FIXME ! ! ! Use the proper locking for dev - > waiting ,
* and make this use the " wait_event_interruptible() "
* interfaces . The cli / sti that used to be here
* did nothing .
*
* See also parport_release ( )
*/
/* If dev->waiting is clear now, an interrupt
gave us the port and we would deadlock if we slept . */
if ( dev - > waiting ) {
interruptible_sleep_on ( & dev - > wait_q ) ;
if ( signal_pending ( current ) ) {
return - EINTR ;
}
r = 1 ;
} else {
r = 0 ;
# ifdef PARPORT_DEBUG_SHARING
printk ( KERN_DEBUG " %s: didn't sleep in parport_claim_or_block() \n " ,
dev - > name ) ;
# endif
}
# ifdef PARPORT_DEBUG_SHARING
if ( dev - > port - > physport - > cad ! = dev )
printk ( KERN_DEBUG " %s: exiting parport_claim_or_block "
" but %s owns port! \n " , dev - > name ,
dev - > port - > physport - > cad ?
dev - > port - > physport - > cad - > name : " nobody " ) ;
# endif
}
dev - > waiting = 0 ;
return r ;
}
/**
* parport_release - give up access to a parallel port device
* @ dev : pointer to structure representing parallel port device
*
* This function cannot fail , but it should not be called without
* the port claimed . Similarly , if the port is already claimed
* you should not try claiming it again .
* */
void parport_release ( struct pardevice * dev )
{
struct parport * port = dev - > port - > physport ;
struct pardevice * pd ;
unsigned long flags ;
/* Make sure that dev is the current device */
write_lock_irqsave ( & port - > cad_lock , flags ) ;
if ( port - > cad ! = dev ) {
write_unlock_irqrestore ( & port - > cad_lock , flags ) ;
printk ( KERN_WARNING " %s: %s tried to release parport "
" when not owner \n " , port - > name , dev - > name ) ;
return ;
}
# ifdef CONFIG_PARPORT_1284
/* If this is on a mux port, deselect it. */
if ( dev - > port - > muxport > = 0 ) {
/* FIXME */
port - > muxsel = - 1 ;
}
/* If this is a daisy device, deselect it. */
if ( dev - > daisy > = 0 ) {
parport_daisy_deselect_all ( port ) ;
port - > daisy = - 1 ;
}
# endif
port - > cad = NULL ;
write_unlock_irqrestore ( & port - > cad_lock , flags ) ;
/* Save control registers */
port - > ops - > save_state ( port , dev - > state ) ;
/* If anybody is waiting, find out who's been there longest and
then wake them up . ( Note : no locking required ) */
/* !!! LOCKING IS NEEDED HERE */
for ( pd = port - > waithead ; pd ; pd = pd - > waitnext ) {
if ( pd - > waiting & 2 ) { /* sleeping in claim_or_block */
parport_claim ( pd ) ;
if ( waitqueue_active ( & pd - > wait_q ) )
wake_up_interruptible ( & pd - > wait_q ) ;
return ;
} else if ( pd - > wakeup ) {
pd - > wakeup ( pd - > private ) ;
if ( dev - > port - > cad ) /* racy but no matter */
return ;
} else {
printk ( KERN_ERR " %s: don't know how to wake %s \n " , port - > name , pd - > name ) ;
}
}
/* Nobody was waiting, so walk the list to see if anyone is
interested in being woken up . ( Note : no locking required ) */
/* !!! LOCKING IS NEEDED HERE */
for ( pd = port - > devices ; ( port - > cad = = NULL ) & & pd ; pd = pd - > next ) {
if ( pd - > wakeup & & pd ! = dev )
pd - > wakeup ( pd - > private ) ;
}
}
2007-10-19 09:42:14 +04:00
irqreturn_t parport_irq_handler ( int irq , void * dev_id )
{
struct parport * port = dev_id ;
2007-10-19 09:56:02 +04:00
parport_generic_irq ( port ) ;
2007-10-19 09:42:14 +04:00
return IRQ_HANDLED ;
}
2005-04-17 02:20:36 +04:00
/* Exported symbols for modules. */
EXPORT_SYMBOL ( parport_claim ) ;
EXPORT_SYMBOL ( parport_claim_or_block ) ;
EXPORT_SYMBOL ( parport_release ) ;
EXPORT_SYMBOL ( parport_register_port ) ;
EXPORT_SYMBOL ( parport_announce_port ) ;
EXPORT_SYMBOL ( parport_remove_port ) ;
EXPORT_SYMBOL ( parport_register_driver ) ;
EXPORT_SYMBOL ( parport_unregister_driver ) ;
EXPORT_SYMBOL ( parport_register_device ) ;
EXPORT_SYMBOL ( parport_unregister_device ) ;
2006-01-06 11:19:51 +03:00
EXPORT_SYMBOL ( parport_get_port ) ;
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( parport_put_port ) ;
EXPORT_SYMBOL ( parport_find_number ) ;
EXPORT_SYMBOL ( parport_find_base ) ;
2007-10-19 09:42:14 +04:00
EXPORT_SYMBOL ( parport_irq_handler ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL " ) ;