2005-04-17 02:20:36 +04:00
/*
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
* * Perle Specialix driver for Linux
* * Ported from existing RIO Driver for SCO sources .
*
* ( C ) 1990 - 2000 Specialix International Ltd . , Byfleet , Surrey , UK .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
* *
* * Module : riotty . c
* * SID : 1.3
* * Last Modified : 11 / 6 / 98 10 : 33 : 47
* * Retrieved : 11 / 6 / 98 10 : 33 : 50
* *
* * ident @ ( # ) riotty . c 1.3
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# define __EXPLICIT_DEF_H__
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/errno.h>
# include <linux/tty.h>
# include <linux/string.h>
# include <asm/io.h>
# include <asm/system.h>
# include <asm/string.h>
# include <asm/uaccess.h>
# include <linux/termios.h>
# include <linux/serial.h>
# include <linux/generic_serial.h>
# include "linux_compat.h"
# include "rio_linux.h"
# include "pkt.h"
# include "daemon.h"
# include "rio.h"
# include "riospace.h"
# include "cmdpkt.h"
# include "map.h"
# include "rup.h"
# include "port.h"
# include "riodrvr.h"
# include "rioinfo.h"
# include "func.h"
# include "errors.h"
# include "pci.h"
# include "parmmap.h"
# include "unixrup.h"
# include "board.h"
# include "host.h"
# include "phb.h"
# include "link.h"
# include "cmdblk.h"
# include "route.h"
# include "cirrus.h"
# include "rioioctl.h"
# include "param.h"
static void RIOClearUp ( struct Port * PortP ) ;
2006-03-24 14:18:32 +03:00
/* Below belongs in func.h */
int RIOShortCommand ( struct rio_info * p , struct Port * PortP , int command , int len , int arg ) ;
2005-04-17 02:20:36 +04:00
extern struct rio_info * p ;
2006-01-11 23:17:49 +03:00
int riotopen ( struct tty_struct * tty , struct file * filp )
2005-04-17 02:20:36 +04:00
{
2006-03-24 14:18:27 +03:00
unsigned int SysPort ;
2005-04-17 02:20:36 +04:00
int repeat_this = 250 ;
2006-01-11 23:17:49 +03:00
struct Port * PortP ; /* pointer to the port structure */
2005-04-17 02:20:36 +04:00
unsigned long flags ;
int retval = 0 ;
2006-01-11 23:17:49 +03:00
func_enter ( ) ;
2005-04-17 02:20:36 +04:00
/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
is going to oops .
2006-01-11 23:17:49 +03:00
*/
2005-04-17 02:20:36 +04:00
tty - > driver_data = NULL ;
2006-01-11 23:17:49 +03:00
2005-04-17 02:20:36 +04:00
SysPort = rio_minor ( tty ) ;
2006-01-11 23:17:49 +03:00
if ( p - > RIOFailed ) {
rio_dprintk ( RIO_DEBUG_TTY , " System initialisation failed \n " ) ;
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
2006-03-24 14:18:32 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " port open SysPort %d (mapped:%d) \n " , SysPort , p - > RIOPortp [ SysPort ] - > Mapped ) ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * Validate that we have received a legitimate request .
* * Currently , just check that we are opening a port on
* * a host card that actually exists , and that the port
* * has been mapped onto a host .
*/
2005-04-17 02:20:36 +04:00
if ( SysPort > = RIO_PORTS ) { /* out of range ? */
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Illegal port number %d \n " , SysPort ) ;
2005-04-17 02:20:36 +04:00
func_exit ( ) ;
return - ENXIO ;
}
/*
2006-01-11 23:17:49 +03:00
* * Grab pointer to the port stucture
*/
2005-04-17 02:20:36 +04:00
PortP = p - > RIOPortp [ SysPort ] ; /* Get control struc */
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " PortP: %p \n " , PortP ) ;
if ( ! PortP - > Mapped ) { /* we aren't mapped yet! */
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * The system doesn ' t know which RTA this port
* * corresponds to .
*/
rio_dprintk ( RIO_DEBUG_TTY , " port not mapped into system \n " ) ;
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
tty - > driver_data = PortP ;
2008-07-17 00:55:20 +04:00
PortP - > gs . port . tty = tty ;
PortP - > gs . port . count + + ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " %d bytes in tx buffer \n " , PortP - > gs . xmit_cnt ) ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
retval = gs_init_port ( & PortP - > gs ) ;
2005-04-17 02:20:36 +04:00
if ( retval ) {
2008-07-17 00:55:20 +04:00
PortP - > gs . port . count - - ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
/*
2006-01-11 23:17:49 +03:00
* * If the host hasn ' t been booted yet , then
* * fail
*/
if ( ( PortP - > HostP - > Flags & RUN_STATE ) ! = RC_RUNNING ) {
rio_dprintk ( RIO_DEBUG_TTY , " Host not running \n " ) ;
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
/*
2006-01-11 23:17:49 +03:00
* * If the RTA has not booted yet and the user has choosen to block
* * until the RTA is present then we must spin here waiting for
* * the RTA to boot .
*/
2005-04-17 02:20:36 +04:00
/* I find the above code a bit hairy. I find the below code
2006-01-11 23:17:49 +03:00
easier to read and shorter . Now , if it works too that would
2005-04-17 02:20:36 +04:00
be great . . . - - REW
2006-01-11 23:17:49 +03:00
*/
rio_dprintk ( RIO_DEBUG_TTY , " Checking if RTA has booted... \n " ) ;
2005-04-17 02:20:36 +04:00
while ( ! ( PortP - > HostP - > Mapping [ PortP - > RupNum ] . Flags & RTA_BOOTED ) ) {
2006-01-11 23:17:49 +03:00
if ( ! PortP - > WaitUntilBooted ) {
rio_dprintk ( RIO_DEBUG_TTY , " RTA never booted \n " ) ;
func_exit ( ) ;
return - ENXIO ;
}
/* Under Linux you'd normally use a wait instead of this
busy - waiting . I ' ll stick with the old implementation for
now . - - REW
*/
if ( RIODelay ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
rio_dprintk ( RIO_DEBUG_TTY , " RTA_wait_for_boot: EINTR in delay \n " ) ;
func_exit ( ) ;
return - EINTR ;
}
if ( repeat_this - - < = 0 ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for RTA to boot timeout \n " ) ;
func_exit ( ) ;
return - EIO ;
}
2005-04-17 02:20:36 +04:00
}
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " RTA has been booted \n " ) ;
2005-04-17 02:20:36 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
2005-04-17 02:20:36 +04:00
goto bombout ;
}
/*
2006-01-11 23:17:49 +03:00
* * If the port is in the final throws of being closed ,
* * we should wait here ( politely ) , waiting
* * for it to finish , so that it doesn ' t close us !
*/
while ( ( PortP - > State & RIO_CLOSING ) & & ! p - > RIOHalted ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for RIO_CLOSING to go away \n " ) ;
if ( repeat_this - - < = 0 ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for not idle closed broken by signal \n " ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2005-04-17 02:20:36 +04:00
retval = - EINTR ;
goto bombout ;
}
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( RIODelay ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
2006-01-11 23:17:49 +03:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-04-17 02:20:36 +04:00
retval = - EINTR ;
goto bombout ;
}
2006-01-11 23:17:49 +03:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-04-17 02:20:36 +04:00
}
2006-01-11 23:17:49 +03:00
if ( ! PortP - > Mapped ) {
rio_dprintk ( RIO_DEBUG_TTY , " Port unmapped while closing! \n " ) ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
retval = - ENXIO ;
2006-01-11 23:17:49 +03:00
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
2005-04-17 02:20:36 +04:00
goto bombout ;
}
/*
* * 15.10 .1998 ARG - ESIL 0761 part fix
* * RIO has it ' s own CTSFLOW and RTSFLOW flags in ' Config ' in the port structure ,
* * we need to make sure that the flags are clear when the port is opened .
*/
/* Uh? Suppose I turn these on and then another process opens
the port again ? The flags get cleared ! Not good . - - REW */
2006-01-11 23:17:49 +03:00
if ( ! ( PortP - > State & ( RIO_LOPEN | RIO_MOPEN ) ) ) {
PortP - > Config & = ~ ( RIO_CTSFLOW | RIO_RTSFLOW ) ;
2005-04-17 02:20:36 +04:00
}
if ( ! ( PortP - > firstOpen ) ) { /* First time ? */
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " First open for this port \n " ) ;
2005-04-17 02:20:36 +04:00
PortP - > firstOpen + + ;
2006-01-11 23:17:49 +03:00
PortP - > CookMode = 0 ; /* XXX RIOCookMode(tp); */
2005-04-17 02:20:36 +04:00
PortP - > InUse = NOT_INUSE ;
/* Tentative fix for bug PR27. Didn't work. */
/* PortP->gs.xmit_cnt = 0; */
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
/* Someone explain to me why this delay/config is
2006-01-11 23:17:49 +03:00
here . If I read the docs correctly the " open "
command piggybacks the parameters immediately .
2005-04-17 02:20:36 +04:00
- - REW */
2008-04-30 11:53:57 +04:00
RIOParam ( PortP , RIOC_OPEN , 1 , OK_TO_SLEEP ) ; /* Open the port */
2005-04-17 02:20:36 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
/*
2006-01-11 23:17:49 +03:00
* * wait for the port to be not closed .
*/
while ( ! ( PortP - > PortState & PORT_ISOPEN ) & & ! p - > RIOHalted ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for PORT_ISOPEN-currently %x \n " , PortP - > PortState ) ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( RIODelay ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for open to finish broken by signal \n " ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2006-01-11 23:17:49 +03:00
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return - EINTR ;
}
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
}
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
retval = - EIO ;
bombout :
/* RIOClearUp( PortP ); */
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return retval ;
}
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " PORT_ISOPEN found \n " ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-24 14:18:32 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Modem - test for carrier \n " ) ;
/*
* * ACTION
* * insert test for carrier here . - - ? ? ?
* * I already see that test here . What ' s the deal ? - - REW
*/
2008-07-17 00:55:20 +04:00
if ( ( PortP - > gs . port . tty - > termios - > c_cflag & CLOCAL ) | |
2008-04-30 11:53:57 +04:00
( PortP - > ModemState & RIOC_MSVR1_CD ) ) {
2006-03-24 14:18:32 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " open(%d) Modem carr on \n " , SysPort ) ;
2005-04-17 02:20:36 +04:00
/*
2006-03-24 14:18:32 +03:00
tp - > tm . c_state | = CARR_ON ;
wakeup ( ( caddr_t ) & tp - > tm . c_canq ) ;
2006-01-11 23:17:49 +03:00
*/
2006-03-24 14:18:32 +03:00
PortP - > State | = RIO_CARR_ON ;
2008-07-17 00:55:20 +04:00
wake_up_interruptible ( & PortP - > gs . port . open_wait ) ;
2006-03-24 14:18:32 +03:00
} else { /* no carrier - wait for DCD */
2005-04-17 02:20:36 +04:00
/*
2008-07-17 00:55:20 +04:00
while ( ! ( PortP - > gs . port . tty - > termios - > c_state & CARR_ON ) & &
2006-03-24 14:18:32 +03:00
! ( filp - > f_flags & O_NONBLOCK ) & & ! p - > RIOHalted )
*/
while ( ! ( PortP - > State & RIO_CARR_ON ) & & ! ( filp - > f_flags & O_NONBLOCK ) & & ! p - > RIOHalted ) {
rio_dprintk ( RIO_DEBUG_TTY , " open(%d) sleeping for carr on \n " , SysPort ) ;
2006-01-11 23:17:49 +03:00
/*
2008-07-17 00:55:20 +04:00
PortP - > gs . port . tty - > termios - > c_state | = WOPEN ;
2006-01-11 23:17:49 +03:00
*/
2006-03-24 14:18:32 +03:00
PortP - > State | = RIO_WOPEN ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( RIODelay ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
2008-04-03 00:04:48 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-03-24 14:18:32 +03:00
/*
* * ACTION : verify that this is a good thing
* * to do here . - - ? ? ?
* * I think it ' s OK . - - REW
*/
rio_dprintk ( RIO_DEBUG_TTY , " open(%d) sleeping for carr broken by signal \n " , SysPort ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2005-04-17 02:20:36 +04:00
/*
2006-03-24 14:18:32 +03:00
tp - > tm . c_state & = ~ WOPEN ;
2006-01-11 23:17:49 +03:00
*/
2006-03-24 14:18:32 +03:00
PortP - > State & = ~ RIO_WOPEN ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-03-24 14:18:32 +03:00
func_exit ( ) ;
return - EINTR ;
2005-04-17 02:20:36 +04:00
}
2008-04-03 00:04:48 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-24 14:18:32 +03:00
PortP - > State & = ~ RIO_WOPEN ;
2005-04-17 02:20:36 +04:00
}
2006-03-24 14:18:32 +03:00
if ( p - > RIOHalted )
goto bombout ;
rio_dprintk ( RIO_DEBUG_TTY , " Setting RIO_MOPEN \n " ) ;
PortP - > State | = RIO_MOPEN ;
2005-04-17 02:20:36 +04:00
2006-03-24 14:18:32 +03:00
if ( p - > RIOHalted )
2005-04-17 02:20:36 +04:00
goto bombout ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " high level open done \n " ) ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * Count opens for port statistics reporting
*/
2005-04-17 02:20:36 +04:00
if ( PortP - > statsGather )
PortP - > opens + + ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Returning from open \n " ) ;
func_exit ( ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*
* * RIOClose the port .
* * The operating system thinks that this is last close for the device .
* * As there are two interfaces to the port ( Modem and tty ) , we need to
* * check that both are closed before we close the device .
2006-01-11 23:17:49 +03:00
*/
int riotclose ( void * ptr )
2005-04-17 02:20:36 +04:00
{
2005-06-26 01:58:40 +04:00
struct Port * PortP = ptr ; /* pointer to the port structure */
2005-04-17 02:20:36 +04:00
int deleted = 0 ;
2006-01-11 23:17:49 +03:00
int try = - 1 ; /* Disable the timeouts by setting them to -1 */
int repeat_this = - 1 ; /* Congrats to those having 15 years of
uptime ! ( You get to break the driver . ) */
2005-06-26 01:58:40 +04:00
unsigned long end_time ;
2006-01-11 23:17:49 +03:00
struct tty_struct * tty ;
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2005-06-26 01:58:40 +04:00
int rv = 0 ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " port close SysPort %d \n " , PortP - > PortNum ) ;
2005-04-17 02:20:36 +04:00
/* PortP = p->RIOPortp[SysPort]; */
2006-03-24 14:18:32 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Port is at address %p \n " , PortP ) ;
2006-01-11 23:17:49 +03:00
/* tp = PortP->TtyP; */ /* Get tty */
2008-07-17 00:55:20 +04:00
tty = PortP - > gs . port . tty ;
2006-03-24 14:18:32 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " TTY is at address %p \n " , tty ) ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
if ( PortP - > gs . closing_wait )
2005-04-17 02:20:36 +04:00
end_time = jiffies + PortP - > gs . closing_wait ;
2006-01-11 23:17:49 +03:00
else
2005-04-17 02:20:36 +04:00
end_time = jiffies + MAX_SCHEDULE_TIMEOUT ;
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
/*
2006-01-11 23:17:49 +03:00
* * Setting this flag will make any process trying to open
* * this port block until we are complete closing it .
*/
2005-04-17 02:20:36 +04:00
PortP - > State | = RIO_CLOSING ;
2006-01-11 23:17:49 +03:00
if ( ( PortP - > State & RIO_DELETED ) ) {
rio_dprintk ( RIO_DEBUG_TTY , " Close on deleted RTA \n " ) ;
2005-04-17 02:20:36 +04:00
deleted = 1 ;
}
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
RIOClearUp ( PortP ) ;
2005-04-17 02:20:36 +04:00
rv = - EIO ;
goto close_end ;
}
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Clear bits \n " ) ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * clear the open bits for this device
*/
2006-03-24 14:18:32 +03:00
PortP - > State & = ~ RIO_MOPEN ;
2005-04-17 02:20:36 +04:00
PortP - > State & = ~ RIO_CARR_ON ;
2008-04-30 11:53:57 +04:00
PortP - > ModemState & = ~ RIOC_MSVR1_CD ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * If the device was open as both a Modem and a tty line
* * then we need to wimp out here , as the port has not really
* * been finally closed ( gee , whizz ! ) The test here uses the
* * bit for the OTHER mode of operation , to see if THAT is
* * still active !
*/
if ( ( PortP - > State & ( RIO_LOPEN | RIO_MOPEN ) ) ) {
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * The port is still open for the other task -
* * return , pretending that we are still active .
*/
rio_dprintk ( RIO_DEBUG_TTY , " Channel %d still open ! \n " , PortP - > PortNum ) ;
2005-04-17 02:20:36 +04:00
PortP - > State & = ~ RIO_CLOSING ;
if ( PortP - > firstOpen )
PortP - > firstOpen - - ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return - EIO ;
}
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Closing down - everything must go! \n " ) ;
2005-04-17 02:20:36 +04:00
PortP - > State & = ~ RIO_DYNOROD ;
/*
2006-01-11 23:17:49 +03:00
* * This is where we wait for the port
* * to drain down before closing . Bye - bye . . . .
* * ( We never meant to do this )
*/
rio_dprintk ( RIO_DEBUG_TTY , " Timeout 1 starts \n " ) ;
2005-04-17 02:20:36 +04:00
if ( ! deleted )
2006-01-11 23:17:49 +03:00
while ( ( PortP - > InUse ! = NOT_INUSE ) & & ! p - > RIOHalted & & ( PortP - > TxBufferIn ! = PortP - > TxBufferOut ) ) {
if ( repeat_this - - < = 0 ) {
rv = - EINTR ;
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for not idle closed broken by signal \n " ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2006-01-11 23:17:49 +03:00
goto close_end ;
}
rio_dprintk ( RIO_DEBUG_TTY , " Calling timeout to flush in closing \n " ) ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( RIODelay_ni ( PortP , HUNDRED_MS * 10 ) = = RIO_FAIL ) {
rio_dprintk ( RIO_DEBUG_TTY , " RTA EINTR in delay \n " ) ;
rv = - EINTR ;
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
goto close_end ;
}
2005-04-17 02:20:36 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
}
PortP - > TxBufferIn = PortP - > TxBufferOut = 0 ;
repeat_this = 0xff ;
PortP - > InUse = 0 ;
2006-01-11 23:17:49 +03:00
if ( ( PortP - > State & ( RIO_LOPEN | RIO_MOPEN ) ) ) {
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * The port has been re - opened for the other task -
* * return , pretending that we are still active .
*/
rio_dprintk ( RIO_DEBUG_TTY , " Channel %d re-open! \n " , PortP - > PortNum ) ;
2005-04-17 02:20:36 +04:00
PortP - > State & = ~ RIO_CLOSING ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( PortP - > firstOpen )
PortP - > firstOpen - - ;
return - EIO ;
}
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
RIOClearUp ( PortP ) ;
2005-04-17 02:20:36 +04:00
goto close_end ;
}
/* Can't call RIOShortCommand with the port locked. */
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2008-04-30 11:53:57 +04:00
if ( RIOShortCommand ( p , PortP , RIOC_CLOSE , 1 , 0 ) = = RIO_FAIL ) {
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2008-04-03 00:04:48 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-06-26 01:58:40 +04:00
goto close_end ;
2005-04-17 02:20:36 +04:00
}
if ( ! deleted )
2006-01-11 23:17:49 +03:00
while ( try & & ( PortP - > PortState & PORT_ISOPEN ) ) {
try - - ;
if ( time_after ( jiffies , end_time ) ) {
rio_dprintk ( RIO_DEBUG_TTY , " Run out of tries - force the bugger shut! \n " ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2006-01-11 23:17:49 +03:00
break ;
}
rio_dprintk ( RIO_DEBUG_TTY , " Close: PortState:ISOPEN is %d \n " , PortP - > PortState & PORT_ISOPEN ) ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
RIOClearUp ( PortP ) ;
2008-04-03 00:04:48 +04:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-01-11 23:17:49 +03:00
goto close_end ;
}
if ( RIODelay ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
rio_dprintk ( RIO_DEBUG_TTY , " RTA EINTR in delay \n " ) ;
2008-04-30 11:53:57 +04:00
RIOPreemptiveCmd ( p , PortP , RIOC_FCLOSE ) ;
2006-01-11 23:17:49 +03:00
break ;
}
2005-04-17 02:20:36 +04:00
}
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Close: try was %d on completion \n " , try ) ;
2008-04-30 11:53:57 +04:00
/* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
2005-04-17 02:20:36 +04:00
/*
* * 15.10 .1998 ARG - ESIL 0761 part fix
* * RIO has it ' s own CTSFLOW and RTSFLOW flags in ' Config ' in the port structure , * * we need to make sure that the flags are clear when the port is opened .
*/
2006-01-11 23:17:49 +03:00
PortP - > Config & = ~ ( RIO_CTSFLOW | RIO_RTSFLOW ) ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * Count opens for port statistics reporting
*/
2005-04-17 02:20:36 +04:00
if ( PortP - > statsGather )
PortP - > closes + + ;
2006-03-24 14:18:32 +03:00
close_end :
2005-04-17 02:20:36 +04:00
/* XXX: Why would a "DELETED" flag be reset here? I'd have
thought that a " deleted " flag means that the port was
permanently gone , but here we can make it reappear by it
being in close during the " deletion " .
2006-01-11 23:17:49 +03:00
*/
PortP - > State & = ~ ( RIO_CLOSING | RIO_DELETED ) ;
2005-04-17 02:20:36 +04:00
if ( PortP - > firstOpen )
PortP - > firstOpen - - ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " Return from close \n " ) ;
2005-04-17 02:20:36 +04:00
return rv ;
}
2006-03-24 14:18:32 +03:00
static void RIOClearUp ( struct Port * PortP )
2005-04-17 02:20:36 +04:00
{
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " RIOHalted set \n " ) ;
PortP - > Config = 0 ; /* Direct semaphore */
2005-04-17 02:20:36 +04:00
PortP - > PortState = 0 ;
PortP - > firstOpen = 0 ;
PortP - > FlushCmdBodge = 0 ;
PortP - > ModemState = PortP - > CookMode = 0 ;
PortP - > Mapped = 0 ;
PortP - > WflushFlag = 0 ;
2006-01-11 23:17:49 +03:00
PortP - > MagicFlags = 0 ;
2005-04-17 02:20:36 +04:00
PortP - > RxDataStart = 0 ;
PortP - > TxBufferIn = 0 ;
PortP - > TxBufferOut = 0 ;
}
/*
* * Put a command onto a port .
* * The PortPointer , command , length and arg are passed .
* * The len is the length * inclusive * of the command byte ,
* * and so for a command that takes no data , len = = 1.
* * The arg is a single byte , and is only used if len = = 2.
* * Other values of len aren ' t allowed , and will cause
* * a panic .
*/
2006-01-11 23:17:49 +03:00
int RIOShortCommand ( struct rio_info * p , struct Port * PortP , int command , int len , int arg )
2005-04-17 02:20:36 +04:00
{
2006-05-27 08:08:25 +04:00
struct PKT __iomem * PacketP ;
2006-01-11 23:17:49 +03:00
int retries = 20 ; /* at 10 per second -> 2 seconds */
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " entering shortcommand. \n " ) ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
if ( PortP - > State & RIO_DELETED ) {
rio_dprintk ( RIO_DEBUG_TTY , " Short command to deleted RTA ignored \n " ) ;
2005-04-17 02:20:36 +04:00
return RIO_FAIL ;
}
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
/*
2006-01-11 23:17:49 +03:00
* * If the port is in use for pre - emptive command , then wait for it to
* * be free again .
*/
while ( ( PortP - > InUse ! = NOT_INUSE ) & & ! p - > RIOHalted ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting for not in use (%d) \n " , retries ) ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( retries - - < = 0 ) {
return RIO_FAIL ;
}
if ( RIODelay_ni ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
return RIO_FAIL ;
}
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
}
2006-01-11 23:17:49 +03:00
if ( PortP - > State & RIO_DELETED ) {
rio_dprintk ( RIO_DEBUG_TTY , " Short command to deleted RTA ignored \n " ) ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return RIO_FAIL ;
}
2006-01-11 23:17:49 +03:00
while ( ! can_add_transmit ( & PacketP , PortP ) & & ! p - > RIOHalted ) {
rio_dprintk ( RIO_DEBUG_TTY , " Waiting to add short command to queue (%d) \n " , retries ) ;
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
if ( retries - - < = 0 ) {
2006-01-11 23:17:49 +03:00
rio_dprintk ( RIO_DEBUG_TTY , " out of tries. Failing \n " ) ;
2005-04-17 02:20:36 +04:00
return RIO_FAIL ;
}
2006-01-11 23:17:49 +03:00
if ( RIODelay_ni ( PortP , HUNDRED_MS ) = = RIO_FAIL ) {
2005-04-17 02:20:36 +04:00
return RIO_FAIL ;
}
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
}
2006-01-11 23:17:49 +03:00
if ( p - > RIOHalted ) {
2005-04-17 02:20:36 +04:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return RIO_FAIL ;
}
/*
2006-01-11 23:17:49 +03:00
* * set the command byte and the argument byte
*/
2006-03-24 14:18:27 +03:00
writeb ( command , & PacketP - > data [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
2006-01-11 23:17:49 +03:00
if ( len = = 2 )
2006-03-24 14:18:27 +03:00
writeb ( arg , & PacketP - > data [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
/*
2006-01-11 23:17:49 +03:00
* * set the length of the packet and set the command bit .
*/
2006-03-24 14:18:27 +03:00
writeb ( PKT_CMD_BIT | len , & PacketP - > len ) ;
2005-04-17 02:20:36 +04:00
add_transmit ( PortP ) ;
/*
2006-01-11 23:17:49 +03:00
* * Count characters transmitted for port statistics reporting
*/
2005-04-17 02:20:36 +04:00
if ( PortP - > statsGather )
PortP - > txchars + = len ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
return p - > RIOHalted ? RIO_FAIL : ~ RIO_FAIL ;
}