2005-04-17 02:20:36 +04:00
/* IEEE-1284 operations for parport.
*
* This file is for generic IEEE 1284 operations . The idea is that
* they are used by the low - level drivers . If they have a special way
* of doing something , they can provide their own routines ( and put
* the function pointers in port - > ops ) ; if not , they can just use these
* as a fallback .
*
* Note : Make no assumptions about hardware or architecture in this file !
*
* Author : Tim Waugh < tim @ cyberelk . demon . co . uk >
* Fixed AUTOFD polarity in ecp_forward_to_reverse ( ) . Fred Barnes , 1999
* Software emulated EPP fixes , Fred Barnes , 04 / 2001.
*/
# include <linux/config.h>
# include <linux/module.h>
# include <linux/parport.h>
# include <linux/delay.h>
# include <linux/sched.h>
# include <asm/uaccess.h>
# undef DEBUG /* undef me for production */
# ifdef CONFIG_LP_CONSOLE
# undef DEBUG /* Don't want a garbled console */
# endif
# ifdef DEBUG
# define DPRINTK(stuff...) printk (stuff)
# else
# define DPRINTK(stuff...)
# endif
/*** *
* One - way data transfer functions . *
* * * */
/* Compatibility mode. */
size_t parport_ieee1284_write_compat ( struct parport * port ,
const void * buffer , size_t len ,
int flags )
{
int no_irq = 1 ;
ssize_t count = 0 ;
const unsigned char * addr = buffer ;
unsigned char byte ;
struct pardevice * dev = port - > physport - > cad ;
unsigned char ctl = ( PARPORT_CONTROL_SELECT
| PARPORT_CONTROL_INIT ) ;
if ( port - > irq ! = PARPORT_IRQ_NONE ) {
parport_enable_irq ( port ) ;
no_irq = 0 ;
}
port - > physport - > ieee1284 . phase = IEEE1284_PH_FWD_DATA ;
parport_write_control ( port , ctl ) ;
parport_data_forward ( port ) ;
while ( count < len ) {
unsigned long expire = jiffies + dev - > timeout ;
2005-09-10 11:27:31 +04:00
long wait = msecs_to_jiffies ( 10 ) ;
2005-04-17 02:20:36 +04:00
unsigned char mask = ( PARPORT_STATUS_ERROR
| PARPORT_STATUS_BUSY ) ;
unsigned char val = ( PARPORT_STATUS_ERROR
| PARPORT_STATUS_BUSY ) ;
/* Wait until the peripheral's ready */
do {
/* Is the peripheral ready yet? */
if ( ! parport_wait_peripheral ( port , mask , val ) )
/* Skip the loop */
goto ready ;
/* Is the peripheral upset? */
if ( ( parport_read_status ( port ) &
( PARPORT_STATUS_PAPEROUT |
PARPORT_STATUS_SELECT |
PARPORT_STATUS_ERROR ) )
! = ( PARPORT_STATUS_SELECT |
PARPORT_STATUS_ERROR ) )
/* If nFault is asserted (i.e. no
* error ) and PAPEROUT and SELECT are
* just red herrings , give the driver
* a chance to check it ' s happy with
* that before continuing . */
goto stop ;
/* Have we run out of time? */
if ( ! time_before ( jiffies , expire ) )
break ;
/* Yield the port for a while. If this is the
first time around the loop , don ' t let go of
the port . This way , we find out if we have
our interrupt handler called . */
if ( count & & no_irq ) {
parport_release ( dev ) ;
2005-09-10 11:27:31 +04:00
schedule_timeout_interruptible ( wait ) ;
2005-04-17 02:20:36 +04:00
parport_claim_or_block ( dev ) ;
}
else
/* We must have the device claimed here */
parport_wait_event ( port , wait ) ;
/* Is there a signal pending? */
if ( signal_pending ( current ) )
break ;
/* Wait longer next time. */
wait * = 2 ;
} while ( time_before ( jiffies , expire ) ) ;
if ( signal_pending ( current ) )
break ;
DPRINTK ( KERN_DEBUG " %s: Timed out \n " , port - > name ) ;
break ;
ready :
/* Write the character to the data lines. */
byte = * addr + + ;
parport_write_data ( port , byte ) ;
udelay ( 1 ) ;
/* Pulse strobe. */
parport_write_control ( port , ctl | PARPORT_CONTROL_STROBE ) ;
udelay ( 1 ) ; /* strobe */
parport_write_control ( port , ctl ) ;
udelay ( 1 ) ; /* hold */
/* Assume the peripheral received it. */
count + + ;
/* Let another process run if it needs to. */
if ( time_before ( jiffies , expire ) )
if ( ! parport_yield_blocking ( dev )
& & need_resched ( ) )
schedule ( ) ;
}
stop :
port - > physport - > ieee1284 . phase = IEEE1284_PH_FWD_IDLE ;
return count ;
}
/* Nibble mode. */
size_t parport_ieee1284_read_nibble ( struct parport * port ,
void * buffer , size_t len ,
int flags )
{
# ifndef CONFIG_PARPORT_1284
return 0 ;
# else
unsigned char * buf = buffer ;
int i ;
unsigned char byte = 0 ;
len * = 2 ; /* in nibbles */
for ( i = 0 ; i < len ; i + + ) {
unsigned char nibble ;
/* Does the error line indicate end of data? */
if ( ( ( i & 1 ) = = 0 ) & &
( parport_read_status ( port ) & PARPORT_STATUS_ERROR ) ) {
2006-01-06 11:19:44 +03:00
goto end_of_data ;
2005-04-17 02:20:36 +04:00
}
/* Event 7: Set nAutoFd low. */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
/* Event 9: nAck goes low. */
port - > ieee1284 . phase = IEEE1284_PH_REV_DATA ;
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_ACK , 0 ) ) {
/* Timeout -- no more data? */
DPRINTK ( KERN_DEBUG
" %s: Nibble timeout at event 9 (%d bytes) \n " ,
port - > name , i / 2 ) ;
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD , 0 ) ;
break ;
}
/* Read a nibble. */
nibble = parport_read_status ( port ) > > 3 ;
nibble & = ~ 8 ;
if ( ( nibble & 0x10 ) = = 0 )
nibble | = 8 ;
nibble & = 0xf ;
/* Event 10: Set nAutoFd high. */
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD , 0 ) ;
/* Event 11: nAck goes high. */
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_ACK ,
PARPORT_STATUS_ACK ) ) {
/* Timeout -- no more data? */
DPRINTK ( KERN_DEBUG
" %s: Nibble timeout at event 11 \n " ,
port - > name ) ;
break ;
}
if ( i & 1 ) {
/* Second nibble */
byte | = nibble < < 4 ;
* buf + + = byte ;
} else
byte = nibble ;
}
if ( i = = len ) {
/* Read the last nibble without checking data avail. */
2006-01-06 11:19:44 +03:00
if ( parport_read_status ( port ) & PARPORT_STATUS_ERROR ) {
end_of_data :
DPRINTK ( KERN_DEBUG
" %s: No more nibble data (%d bytes) \n " ,
port - > name , i / 2 ) ;
/* Go to reverse idle phase. */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
port - > physport - > ieee1284 . phase = IEEE1284_PH_REV_IDLE ;
}
2005-04-17 02:20:36 +04:00
else
2006-01-06 11:19:44 +03:00
port - > physport - > ieee1284 . phase = IEEE1284_PH_HBUSY_DAVAIL ;
2005-04-17 02:20:36 +04:00
}
2006-01-06 11:19:44 +03:00
return i / 2 ;
2005-04-17 02:20:36 +04:00
# endif /* IEEE1284 support */
}
/* Byte mode. */
size_t parport_ieee1284_read_byte ( struct parport * port ,
void * buffer , size_t len ,
int flags )
{
# ifndef CONFIG_PARPORT_1284
return 0 ;
# else
unsigned char * buf = buffer ;
ssize_t count = 0 ;
for ( count = 0 ; count < len ; count + + ) {
unsigned char byte ;
/* Data available? */
if ( parport_read_status ( port ) & PARPORT_STATUS_ERROR ) {
2006-01-06 11:19:44 +03:00
goto end_of_data ;
2005-04-17 02:20:36 +04:00
}
/* Event 14: Place data bus in high impedance state. */
parport_data_reverse ( port ) ;
/* Event 7: Set nAutoFd low. */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
/* Event 9: nAck goes low. */
port - > physport - > ieee1284 . phase = IEEE1284_PH_REV_DATA ;
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_ACK ,
0 ) ) {
/* Timeout -- no more data? */
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD ,
0 ) ;
DPRINTK ( KERN_DEBUG " %s: Byte timeout at event 9 \n " ,
port - > name ) ;
break ;
}
byte = parport_read_data ( port ) ;
* buf + + = byte ;
/* Event 10: Set nAutoFd high */
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD , 0 ) ;
/* Event 11: nAck goes high. */
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_ACK ,
PARPORT_STATUS_ACK ) ) {
/* Timeout -- no more data? */
DPRINTK ( KERN_DEBUG " %s: Byte timeout at event 11 \n " ,
port - > name ) ;
break ;
}
/* Event 16: Set nStrobe low. */
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE ,
PARPORT_CONTROL_STROBE ) ;
udelay ( 5 ) ;
/* Event 17: Set nStrobe high. */
parport_frob_control ( port , PARPORT_CONTROL_STROBE , 0 ) ;
}
if ( count = = len ) {
/* Read the last byte without checking data avail. */
2006-01-06 11:19:44 +03:00
if ( parport_read_status ( port ) & PARPORT_STATUS_ERROR ) {
end_of_data :
DPRINTK ( KERN_DEBUG
" %s: No more byte data (%Zd bytes) \n " ,
port - > name , count ) ;
/* Go to reverse idle phase. */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
port - > physport - > ieee1284 . phase = IEEE1284_PH_REV_IDLE ;
}
2005-04-17 02:20:36 +04:00
else
2006-01-06 11:19:44 +03:00
port - > physport - > ieee1284 . phase = IEEE1284_PH_HBUSY_DAVAIL ;
2005-04-17 02:20:36 +04:00
}
return count ;
# endif /* IEEE1284 support */
}
/*** *
* ECP Functions . *
* * * */
# ifdef CONFIG_PARPORT_1284
static inline
int ecp_forward_to_reverse ( struct parport * port )
{
int retval ;
/* Event 38: Set nAutoFd low */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
parport_data_reverse ( port ) ;
udelay ( 5 ) ;
/* Event 39: Set nInit low to initiate bus reversal */
parport_frob_control ( port ,
PARPORT_CONTROL_INIT ,
0 ) ;
/* Event 40: PError goes low */
retval = parport_wait_peripheral ( port ,
PARPORT_STATUS_PAPEROUT , 0 ) ;
if ( ! retval ) {
DPRINTK ( KERN_DEBUG " %s: ECP direction: reverse \n " ,
port - > name ) ;
port - > ieee1284 . phase = IEEE1284_PH_REV_IDLE ;
} else {
DPRINTK ( KERN_DEBUG " %s: ECP direction: failed to reverse \n " ,
port - > name ) ;
port - > ieee1284 . phase = IEEE1284_PH_ECP_DIR_UNKNOWN ;
}
return retval ;
}
static inline
int ecp_reverse_to_forward ( struct parport * port )
{
int retval ;
/* Event 47: Set nInit high */
parport_frob_control ( port ,
PARPORT_CONTROL_INIT
| PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_INIT
| PARPORT_CONTROL_AUTOFD ) ;
/* Event 49: PError goes high */
retval = parport_wait_peripheral ( port ,
PARPORT_STATUS_PAPEROUT ,
PARPORT_STATUS_PAPEROUT ) ;
if ( ! retval ) {
parport_data_forward ( port ) ;
DPRINTK ( KERN_DEBUG " %s: ECP direction: forward \n " ,
port - > name ) ;
port - > ieee1284 . phase = IEEE1284_PH_FWD_IDLE ;
} else {
DPRINTK ( KERN_DEBUG
" %s: ECP direction: failed to switch forward \n " ,
port - > name ) ;
port - > ieee1284 . phase = IEEE1284_PH_ECP_DIR_UNKNOWN ;
}
return retval ;
}
# endif /* IEEE1284 support */
/* ECP mode, forward channel, data. */
size_t parport_ieee1284_ecp_write_data ( struct parport * port ,
const void * buffer , size_t len ,
int flags )
{
# ifndef CONFIG_PARPORT_1284
return 0 ;
# else
const unsigned char * buf = buffer ;
size_t written ;
int retry ;
port = port - > physport ;
if ( port - > ieee1284 . phase ! = IEEE1284_PH_FWD_IDLE )
if ( ecp_reverse_to_forward ( port ) )
return 0 ;
port - > ieee1284 . phase = IEEE1284_PH_FWD_DATA ;
/* HostAck high (data, not command) */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD
| PARPORT_CONTROL_STROBE
| PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_INIT ) ;
for ( written = 0 ; written < len ; written + + , buf + + ) {
unsigned long expire = jiffies + port - > cad - > timeout ;
unsigned char byte ;
byte = * buf ;
try_again :
parport_write_data ( port , byte ) ;
parport_frob_control ( port , PARPORT_CONTROL_STROBE ,
PARPORT_CONTROL_STROBE ) ;
udelay ( 5 ) ;
for ( retry = 0 ; retry < 100 ; retry + + ) {
if ( ! parport_wait_peripheral ( port ,
PARPORT_STATUS_BUSY , 0 ) )
goto success ;
if ( signal_pending ( current ) ) {
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE ,
0 ) ;
break ;
}
}
/* Time for Host Transfer Recovery (page 41 of IEEE1284) */
DPRINTK ( KERN_DEBUG " %s: ECP transfer stalled! \n " , port - > name ) ;
parport_frob_control ( port , PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_INIT ) ;
udelay ( 50 ) ;
if ( parport_read_status ( port ) & PARPORT_STATUS_PAPEROUT ) {
/* It's buggered. */
parport_frob_control ( port , PARPORT_CONTROL_INIT , 0 ) ;
break ;
}
parport_frob_control ( port , PARPORT_CONTROL_INIT , 0 ) ;
udelay ( 50 ) ;
if ( ! ( parport_read_status ( port ) & PARPORT_STATUS_PAPEROUT ) )
break ;
DPRINTK ( KERN_DEBUG " %s: Host transfer recovered \n " ,
port - > name ) ;
if ( time_after_eq ( jiffies , expire ) ) break ;
goto try_again ;
success :
parport_frob_control ( port , PARPORT_CONTROL_STROBE , 0 ) ;
udelay ( 5 ) ;
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY ) )
/* Peripheral hasn't accepted the data. */
break ;
}
port - > ieee1284 . phase = IEEE1284_PH_FWD_IDLE ;
return written ;
# endif /* IEEE1284 support */
}
/* ECP mode, reverse channel, data. */
size_t parport_ieee1284_ecp_read_data ( struct parport * port ,
void * buffer , size_t len , int flags )
{
# ifndef CONFIG_PARPORT_1284
return 0 ;
# else
struct pardevice * dev = port - > cad ;
unsigned char * buf = buffer ;
int rle_count = 0 ; /* shut gcc up */
unsigned char ctl ;
int rle = 0 ;
ssize_t count = 0 ;
port = port - > physport ;
if ( port - > ieee1284 . phase ! = IEEE1284_PH_REV_IDLE )
if ( ecp_forward_to_reverse ( port ) )
return 0 ;
port - > ieee1284 . phase = IEEE1284_PH_REV_DATA ;
/* Set HostAck low to start accepting data. */
ctl = parport_read_control ( port ) ;
ctl & = ~ ( PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT |
PARPORT_CONTROL_AUTOFD ) ;
parport_write_control ( port ,
ctl | PARPORT_CONTROL_AUTOFD ) ;
while ( count < len ) {
unsigned long expire = jiffies + dev - > timeout ;
unsigned char byte ;
int command ;
/* Event 43: Peripheral sets nAck low. It can take as
long as it wants . */
while ( parport_wait_peripheral ( port , PARPORT_STATUS_ACK , 0 ) ) {
/* The peripheral hasn't given us data in
35 ms . If we have data to give back to the
caller , do it now . */
if ( count )
goto out ;
/* If we've used up all the time we were allowed,
give up altogether . */
if ( ! time_before ( jiffies , expire ) )
goto out ;
/* Yield the port for a while. */
if ( count & & dev - > port - > irq ! = PARPORT_IRQ_NONE ) {
parport_release ( dev ) ;
2005-09-10 11:27:31 +04:00
schedule_timeout_interruptible ( msecs_to_jiffies ( 40 ) ) ;
2005-04-17 02:20:36 +04:00
parport_claim_or_block ( dev ) ;
}
else
/* We must have the device claimed here. */
2005-09-10 11:27:31 +04:00
parport_wait_event ( port , msecs_to_jiffies ( 40 ) ) ;
2005-04-17 02:20:36 +04:00
/* Is there a signal pending? */
if ( signal_pending ( current ) )
goto out ;
}
/* Is this a command? */
if ( rle )
/* The last byte was a run-length count, so
this can ' t be as well . */
command = 0 ;
else
command = ( parport_read_status ( port ) &
PARPORT_STATUS_BUSY ) ? 1 : 0 ;
/* Read the data. */
byte = parport_read_data ( port ) ;
/* If this is a channel command, rather than an RLE
command or a normal data byte , don ' t accept it . */
if ( command ) {
if ( byte & 0x80 ) {
DPRINTK ( KERN_DEBUG " %s: stopping short at "
" channel command (%02x) \n " ,
port - > name , byte ) ;
goto out ;
}
else if ( port - > ieee1284 . mode ! = IEEE1284_MODE_ECPRLE )
DPRINTK ( KERN_DEBUG " %s: device illegally "
" using RLE; accepting anyway \n " ,
port - > name ) ;
rle_count = byte + 1 ;
/* Are we allowed to read that many bytes? */
if ( rle_count > ( len - count ) ) {
DPRINTK ( KERN_DEBUG " %s: leaving %d RLE bytes "
" for next time \n " , port - > name ,
rle_count ) ;
break ;
}
rle = 1 ;
}
/* Event 44: Set HostAck high, acknowledging handshake. */
parport_write_control ( port , ctl ) ;
/* Event 45: The peripheral has 35ms to set nAck high. */
if ( parport_wait_peripheral ( port , PARPORT_STATUS_ACK ,
PARPORT_STATUS_ACK ) ) {
/* It's gone wrong. Return what data we have
to the caller . */
DPRINTK ( KERN_DEBUG " ECP read timed out at 45 \n " ) ;
if ( command )
printk ( KERN_WARNING
" %s: command ignored (%02x) \n " ,
port - > name , byte ) ;
break ;
}
/* Event 46: Set HostAck low and accept the data. */
parport_write_control ( port ,
ctl | PARPORT_CONTROL_AUTOFD ) ;
/* If we just read a run-length count, fetch the data. */
if ( command )
continue ;
/* If this is the byte after a run-length count, decompress. */
if ( rle ) {
rle = 0 ;
memset ( buf , byte , rle_count ) ;
buf + = rle_count ;
count + = rle_count ;
DPRINTK ( KERN_DEBUG " %s: decompressed to %d bytes \n " ,
port - > name , rle_count ) ;
} else {
/* Normal data byte. */
* buf = byte ;
buf + + , count + + ;
}
}
out :
port - > ieee1284 . phase = IEEE1284_PH_REV_IDLE ;
return count ;
# endif /* IEEE1284 support */
}
/* ECP mode, forward channel, commands. */
size_t parport_ieee1284_ecp_write_addr ( struct parport * port ,
const void * buffer , size_t len ,
int flags )
{
# ifndef CONFIG_PARPORT_1284
return 0 ;
# else
const unsigned char * buf = buffer ;
size_t written ;
int retry ;
port = port - > physport ;
if ( port - > ieee1284 . phase ! = IEEE1284_PH_FWD_IDLE )
if ( ecp_reverse_to_forward ( port ) )
return 0 ;
port - > ieee1284 . phase = IEEE1284_PH_FWD_DATA ;
/* HostAck low (command, not data) */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD
| PARPORT_CONTROL_STROBE
| PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_AUTOFD
| PARPORT_CONTROL_INIT ) ;
for ( written = 0 ; written < len ; written + + , buf + + ) {
unsigned long expire = jiffies + port - > cad - > timeout ;
unsigned char byte ;
byte = * buf ;
try_again :
parport_write_data ( port , byte ) ;
parport_frob_control ( port , PARPORT_CONTROL_STROBE ,
PARPORT_CONTROL_STROBE ) ;
udelay ( 5 ) ;
for ( retry = 0 ; retry < 100 ; retry + + ) {
if ( ! parport_wait_peripheral ( port ,
PARPORT_STATUS_BUSY , 0 ) )
goto success ;
if ( signal_pending ( current ) ) {
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE ,
0 ) ;
break ;
}
}
/* Time for Host Transfer Recovery (page 41 of IEEE1284) */
DPRINTK ( KERN_DEBUG " %s: ECP transfer stalled! \n " , port - > name ) ;
parport_frob_control ( port , PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_INIT ) ;
udelay ( 50 ) ;
if ( parport_read_status ( port ) & PARPORT_STATUS_PAPEROUT ) {
/* It's buggered. */
parport_frob_control ( port , PARPORT_CONTROL_INIT , 0 ) ;
break ;
}
parport_frob_control ( port , PARPORT_CONTROL_INIT , 0 ) ;
udelay ( 50 ) ;
if ( ! ( parport_read_status ( port ) & PARPORT_STATUS_PAPEROUT ) )
break ;
DPRINTK ( KERN_DEBUG " %s: Host transfer recovered \n " ,
port - > name ) ;
if ( time_after_eq ( jiffies , expire ) ) break ;
goto try_again ;
success :
parport_frob_control ( port , PARPORT_CONTROL_STROBE , 0 ) ;
udelay ( 5 ) ;
if ( parport_wait_peripheral ( port ,
PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY ) )
/* Peripheral hasn't accepted the data. */
break ;
}
port - > ieee1284 . phase = IEEE1284_PH_FWD_IDLE ;
return written ;
# endif /* IEEE1284 support */
}
/*** *
* EPP functions . *
* * * */
/* EPP mode, forward channel, data. */
size_t parport_ieee1284_epp_write_data ( struct parport * port ,
const void * buffer , size_t len ,
int flags )
{
unsigned char * bp = ( unsigned char * ) buffer ;
size_t ret = 0 ;
/* set EPP idle state (just to make sure) with strobe low */
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_INIT ) ;
port - > ops - > data_forward ( port ) ;
for ( ; len > 0 ; len - - , bp + + ) {
/* Event 62: Write data and set autofd low */
parport_write_data ( port , * bp ) ;
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
/* Event 58: wait for busy (nWait) to go high */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY , 0 , 10 ) )
break ;
/* Event 63: set nAutoFd (nDStrb) high */
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD , 0 ) ;
/* Event 60: wait for busy (nWait) to go low */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY , 5 ) )
break ;
ret + + ;
}
/* Event 61: set strobe (nWrite) high */
parport_frob_control ( port , PARPORT_CONTROL_STROBE , 0 ) ;
return ret ;
}
/* EPP mode, reverse channel, data. */
size_t parport_ieee1284_epp_read_data ( struct parport * port ,
void * buffer , size_t len ,
int flags )
{
unsigned char * bp = ( unsigned char * ) buffer ;
unsigned ret = 0 ;
/* set EPP idle state (just to make sure) with strobe high */
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_INIT ) ;
port - > ops - > data_reverse ( port ) ;
for ( ; len > 0 ; len - - , bp + + ) {
/* Event 67: set nAutoFd (nDStrb) low */
parport_frob_control ( port ,
PARPORT_CONTROL_AUTOFD ,
PARPORT_CONTROL_AUTOFD ) ;
/* Event 58: wait for Busy to go high */
if ( parport_wait_peripheral ( port , PARPORT_STATUS_BUSY , 0 ) ) {
break ;
}
* bp = parport_read_data ( port ) ;
/* Event 63: set nAutoFd (nDStrb) high */
parport_frob_control ( port , PARPORT_CONTROL_AUTOFD , 0 ) ;
/* Event 60: wait for Busy to go low */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY , 5 ) ) {
break ;
}
ret + + ;
}
port - > ops - > data_forward ( port ) ;
return ret ;
}
/* EPP mode, forward channel, addresses. */
size_t parport_ieee1284_epp_write_addr ( struct parport * port ,
const void * buffer , size_t len ,
int flags )
{
unsigned char * bp = ( unsigned char * ) buffer ;
size_t ret = 0 ;
/* set EPP idle state (just to make sure) with strobe low */
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_INIT ) ;
port - > ops - > data_forward ( port ) ;
for ( ; len > 0 ; len - - , bp + + ) {
/* Event 56: Write data and set nAStrb low. */
parport_write_data ( port , * bp ) ;
parport_frob_control ( port , PARPORT_CONTROL_SELECT ,
PARPORT_CONTROL_SELECT ) ;
/* Event 58: wait for busy (nWait) to go high */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY , 0 , 10 ) )
break ;
/* Event 59: set nAStrb high */
parport_frob_control ( port , PARPORT_CONTROL_SELECT , 0 ) ;
/* Event 60: wait for busy (nWait) to go low */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY , 5 ) )
break ;
ret + + ;
}
/* Event 61: set strobe (nWrite) high */
parport_frob_control ( port , PARPORT_CONTROL_STROBE , 0 ) ;
return ret ;
}
/* EPP mode, reverse channel, addresses. */
size_t parport_ieee1284_epp_read_addr ( struct parport * port ,
void * buffer , size_t len ,
int flags )
{
unsigned char * bp = ( unsigned char * ) buffer ;
unsigned ret = 0 ;
/* Set EPP idle state (just to make sure) with strobe high */
parport_frob_control ( port ,
PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
PARPORT_CONTROL_SELECT |
PARPORT_CONTROL_INIT ,
PARPORT_CONTROL_INIT ) ;
port - > ops - > data_reverse ( port ) ;
for ( ; len > 0 ; len - - , bp + + ) {
/* Event 64: set nSelectIn (nAStrb) low */
parport_frob_control ( port , PARPORT_CONTROL_SELECT ,
PARPORT_CONTROL_SELECT ) ;
/* Event 58: wait for Busy to go high */
if ( parport_wait_peripheral ( port , PARPORT_STATUS_BUSY , 0 ) ) {
break ;
}
* bp = parport_read_data ( port ) ;
/* Event 59: set nSelectIn (nAStrb) high */
parport_frob_control ( port , PARPORT_CONTROL_SELECT ,
PARPORT_CONTROL_SELECT ) ;
/* Event 60: wait for Busy to go low */
if ( parport_poll_peripheral ( port , PARPORT_STATUS_BUSY ,
PARPORT_STATUS_BUSY , 5 ) )
break ;
ret + + ;
}
port - > ops - > data_forward ( port ) ;
return ret ;
}
EXPORT_SYMBOL ( parport_ieee1284_ecp_write_data ) ;
EXPORT_SYMBOL ( parport_ieee1284_ecp_read_data ) ;
EXPORT_SYMBOL ( parport_ieee1284_ecp_write_addr ) ;
EXPORT_SYMBOL ( parport_ieee1284_write_compat ) ;
EXPORT_SYMBOL ( parport_ieee1284_read_nibble ) ;
EXPORT_SYMBOL ( parport_ieee1284_read_byte ) ;
EXPORT_SYMBOL ( parport_ieee1284_epp_write_data ) ;
EXPORT_SYMBOL ( parport_ieee1284_epp_read_data ) ;
EXPORT_SYMBOL ( parport_ieee1284_epp_write_addr ) ;
EXPORT_SYMBOL ( parport_ieee1284_epp_read_addr ) ;