2005-04-16 15:20:36 -07: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 : rioparam . c
* * SID : 1.3
* * Last Modified : 11 / 6 / 98 10 : 33 : 45
* * Retrieved : 11 / 6 / 98 10 : 33 : 50
* *
* * ident @ ( # ) rioparam . c 1.3
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/tty.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"
/*
* * The Scam , based on email from jeremyr @ bugs . specialix . co . uk . . . .
* *
* * To send a command on a particular port , you put a packet with the
* * command bit set onto the port . The command bit is in the len field ,
* * and gets ORed in with the actual byte count .
* *
2006-11-30 05:24:39 +01:00
* * When you send a packet with the command bit set the first
* * data byte ( data [ 0 ] ) is interpreted as the command to execute .
2005-04-16 15:20:36 -07:00
* * It also governs what data structure overlay should accompany the packet .
* * Commands are defined in cirrus / cirrus . h
* *
* * If you want the command to pre - emt data already on the queue for the
* * port , set the pre - emptive bit in conjunction with the command bit .
* * It is not defined what will happen if you set the preemptive bit
* * on a packet that is NOT a command .
* *
* * Pre - emptive commands should be queued at the head of the queue using
* * add_start ( ) , whereas normal commands and data are enqueued using
* * add_end ( ) .
* *
* * Most commands do not use the remaining bytes in the data array . The
* * exceptions are OPEN MOPEN and CONFIG . ( NB . As with the SI CONFIG and
2006-11-30 05:24:39 +01:00
* * OPEN are currently analogous ) . With these three commands the following
2005-04-16 15:20:36 -07:00
* * 11 data bytes are all used to pass config information such as baud rate etc .
* * The fields are also defined in cirrus . h . Some contain straightforward
* * information such as the transmit XON character . Two contain the transmit and
* * receive baud rates respectively . For most baud rates there is a direct
* * mapping between the rates defined in < sys / termio . h > and the byte in the
* * packet . There are additional ( non UNIX - standard ) rates defined in
* * / u / dos / rio / cirrus / h / brates . h .
* *
* * The rest of the data fields contain approximations to the Cirrus registers
* * that are used to program number of bits etc . Each registers bit fields is
* * defined in cirrus . h .
* *
* * NB . Only use those bits that are defined as being driver specific
* * or common to the RTA and the driver .
* *
* * All commands going from RTA - > Host will be dealt with by the Host code - you
* * will never see them . As with the SI there will be three fields to look out
* * for in each phb ( not yet defined - needs defining a . s . a . p ) .
* *
* * modem_status - current state of handshake pins .
* *
* * port_status - current port status - equivalent to hi_stat for SI , indicates
* * if port is IDLE_OPEN , IDLE_CLOSED etc .
* *
* * break_status - bit X set if break has been received .
* *
* * Happy hacking .
* *
*/
/*
* * RIOParam is used to open or configure a port . You pass it a PortP ,
* * which will have a tty struct attached to it . You also pass a command ,
* * either OPEN or CONFIG . The port ' s setup is taken from the t_ fields
* * of the tty struct inside the PortP , and the port is either opened
* * or re - configured . You must also tell RIOParam if the device is a modem
* * device or not ( i . e . top bit of minor number set or clear - take special
* * care when deciding on this ! ) .
* * RIOParam neither flushes nor waits for drain , and is NOT preemptive .
* *
* * RIOParam assumes it will be called at splrio ( ) , and also assumes
* * that CookMode is set correctly in the port structure .
* *
* * NB . for MPX
* * tty lock must NOT have been previously acquired .
*/
2006-03-24 03:18:27 -08:00
int RIOParam ( struct Port * PortP , int cmd , int Modem , int SleepFlag )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:27 -08:00
struct tty_struct * TtyP ;
2006-01-11 12:17:49 -08:00
int retval ;
2006-05-27 00:08:25 -04:00
struct phb_param __iomem * phb_param_ptr ;
struct PKT __iomem * PacketP ;
2005-04-16 15:20:36 -07:00
int res ;
2006-03-24 03:18:27 -08:00
u8 Cor1 = 0 , Cor2 = 0 , Cor4 = 0 , Cor5 = 0 ;
u8 TxXon = 0 , TxXoff = 0 , RxXon = 0 , RxXoff = 0 ;
u8 LNext = 0 , TxBaud = 0 , RxBaud = 0 ;
2006-01-11 12:17:49 -08:00
int retries = 0xff ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
2006-01-11 12:17:49 -08:00
func_enter ( ) ;
2005-04-16 15:20:36 -07:00
2008-07-16 21:55:20 +01:00
TtyP = PortP - > gs . port . tty ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p \n " , PortP - > PortNum , cmd , Modem , SleepFlag , PortP - > Mapped , TtyP ) ;
2005-04-16 15:20:36 -07:00
if ( ! TtyP ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " Can't call rioparam with null tty. \n " ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
func_exit ( ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
return RIO_FAIL ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
2008-04-30 00:53:57 -07:00
if ( cmd = = RIOC_OPEN ) {
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * If the port is set to store or lock the parameters , and it is
* * paramed with OPEN , we want to restore the saved port termio , but
* * only if StoredTermio has been saved , i . e . NOT 1 st open after reboot .
*/
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * wait for space
*/
while ( ! ( res = can_add_transmit ( & PacketP , PortP ) ) | | ( PortP - > InUse ! = NOT_INUSE ) ) {
if ( retries - - < = 0 ) {
2005-04-16 15:20:36 -07:00
break ;
}
2006-01-11 12:17:49 -08:00
if ( PortP - > InUse ! = NOT_INUSE ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Port IN_USE for pre-emptive command \n " ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( ! res ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Port has no space on transmit queue \n " ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( SleepFlag ! = OK_TO_SLEEP ) {
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
func_exit ( ) ;
2006-01-11 12:17:49 -08:00
2005-04-16 15:20:36 -07:00
return RIO_FAIL ;
}
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " wait for can_add_transmit \n " ) ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
retval = RIODelay ( PortP , HUNDRED_MS ) ;
2006-01-11 12:17:49 -08:00
rio_spin_lock_irqsave ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
if ( retval = = RIO_FAIL ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " wait for can_add_transmit broken by signal \n " ) ;
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
func_exit ( ) ;
2006-03-24 03:18:27 -08:00
return - EINTR ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( PortP - > State & RIO_DELETED ) {
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
func_exit ( ) ;
2006-03-24 03:18:32 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
}
if ( ! res ) {
2006-01-11 12:17:49 -08:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
func_exit ( ) ;
2005-04-16 15:20:36 -07:00
return RIO_FAIL ;
}
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " can_add_transmit() returns %x \n " , res ) ;
2006-03-24 03:18:32 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " Packet is %p \n " , PacketP ) ;
2005-04-16 15:20:36 -07:00
2006-05-27 00:08:25 -04:00
phb_param_ptr = ( struct phb_param __iomem * ) PacketP - > data ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
switch ( TtyP - > termios - > c_cflag & CSIZE ) {
case CS5 :
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " 5 bit data \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_5BITS ;
2005-04-16 15:20:36 -07:00
break ;
}
2006-01-11 12:17:49 -08:00
case CS6 :
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " 6 bit data \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_6BITS ;
2005-04-16 15:20:36 -07:00
break ;
}
2006-01-11 12:17:49 -08:00
case CS7 :
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " 7 bit data \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_7BITS ;
2005-04-16 15:20:36 -07:00
break ;
}
2006-01-11 12:17:49 -08:00
case CS8 :
2005-04-16 15:20:36 -07:00
{
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " 8 bit data \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_8BITS ;
2005-04-16 15:20:36 -07:00
break ;
}
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & CSTOPB ) {
rio_dprintk ( RIO_DEBUG_PARAM , " 2 stop bits \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_2STOP ;
2006-01-11 12:17:49 -08:00
} else {
rio_dprintk ( RIO_DEBUG_PARAM , " 1 stop bit \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_1STOP ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & PARENB ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Enable parity \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_NORMAL ;
2006-01-11 12:17:49 -08:00
} else {
rio_dprintk ( RIO_DEBUG_PARAM , " Disable parity \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_NOP ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & PARODD ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Odd parity \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_ODD ;
2006-01-11 12:17:49 -08:00
} else {
rio_dprintk ( RIO_DEBUG_PARAM , " Even parity \n " ) ;
2008-04-30 00:53:57 -07:00
Cor1 | = RIOC_COR1_EVEN ;
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * COR 2
*/
if ( TtyP - > termios - > c_iflag & IXON ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Enable start/stop output control \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_IXON ;
2006-01-11 12:17:49 -08:00
} else {
if ( PortP - > Config & RIO_IXON ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Force enable start/stop output control \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_IXON ;
2006-01-11 12:17:49 -08:00
} else
rio_dprintk ( RIO_DEBUG_PARAM , " IXON has been disabled. \n " ) ;
2005-04-16 15:20:36 -07:00
}
if ( TtyP - > termios - > c_iflag & IXANY ) {
2006-01-11 12:17:49 -08:00
if ( PortP - > Config & RIO_IXANY ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Enable any key to restart output \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_IXANY ;
2006-01-11 12:17:49 -08:00
} else
rio_dprintk ( RIO_DEBUG_PARAM , " IXANY has been disabled due to sanity reasons. \n " ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & IXOFF ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Enable start/stop input control 2 \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_IXOFF ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & HUPCL ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Hangup on last close \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_HUPCL ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( C_CRTSCTS ( TtyP ) ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Rx hardware flow control enabled \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 | = RIOC_COR2_CTSFLOW ;
Cor2 | = RIOC_COR2_RTSFLOW ;
2005-04-16 15:20:36 -07:00
} else {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " Rx hardware flow control disabled \n " ) ;
2008-04-30 00:53:57 -07:00
Cor2 & = ~ RIOC_COR2_CTSFLOW ;
Cor2 & = ~ RIOC_COR2_RTSFLOW ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & CLOCAL ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Local line \n " ) ;
} else {
rio_dprintk ( RIO_DEBUG_PARAM , " Possible Modem line \n " ) ;
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * COR 4 ( there is no COR 3 )
*/
if ( TtyP - > termios - > c_iflag & IGNBRK ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Ignore break condition \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_IGNBRK ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( ! ( TtyP - > termios - > c_iflag & BRKINT ) ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Break generates NULL condition \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_NBRKINT ;
2005-04-16 15:20:36 -07:00
} else {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " Interrupt on break condition \n " ) ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & INLCR ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Map newline to carriage return on input \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_INLCR ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & IGNCR ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Ignore carriage return on input \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_IGNCR ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & ICRNL ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Map carriage return to newline on input \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_ICRNL ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & IGNPAR ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Ignore characters with parity errors \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_IGNPAR ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & PARMRK ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Mark parity errors \n " ) ;
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_PARMRK ;
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * Set the RAISEMOD flag to ensure that the modem lines are raised
* * on reception of a config packet .
* * The download code handles the zero baud condition .
*/
2008-04-30 00:53:57 -07:00
Cor4 | = RIOC_COR4_RAISEMOD ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * COR 5
*/
2005-04-16 15:20:36 -07:00
2008-04-30 00:53:57 -07:00
Cor5 = RIOC_COR5_CMOE ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Set to monitor tbusy / tstop ( or not ) .
*/
2005-04-16 15:20:36 -07:00
if ( PortP - > MonitorTstate )
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_TSTATE_ON ;
2005-04-16 15:20:36 -07:00
else
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_TSTATE_OFF ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Could set LNE here if you wanted LNext processing . SVR4 will use it .
*/
if ( TtyP - > termios - > c_iflag & ISTRIP ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Strip input characters \n " ) ;
if ( ! ( PortP - > State & RIO_TRIAD_MODE ) ) {
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_ISTRIP ;
2005-04-16 15:20:36 -07:00
}
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_oflag & ONLCR ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Map newline to carriage-return, newline on output \n " ) ;
if ( PortP - > CookMode = = COOK_MEDIUM )
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_ONLCR ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_oflag & OCRNL ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Map carriage return to newline on output \n " ) ;
if ( PortP - > CookMode = = COOK_MEDIUM )
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_OCRNL ;
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
if ( ( TtyP - > termios - > c_oflag & TABDLY ) = = TAB3 ) {
rio_dprintk ( RIO_DEBUG_PARAM , " Tab delay 3 set \n " ) ;
if ( PortP - > CookMode = = COOK_MEDIUM )
2008-04-30 00:53:57 -07:00
Cor5 | = RIOC_COR5_TAB3 ;
2005-04-16 15:20:36 -07:00
}
/*
2006-01-11 12:17:49 -08:00
* * Flow control bytes .
*/
2005-04-16 15:20:36 -07:00
TxXon = TtyP - > termios - > c_cc [ VSTART ] ;
TxXoff = TtyP - > termios - > c_cc [ VSTOP ] ;
RxXon = TtyP - > termios - > c_cc [ VSTART ] ;
RxXoff = TtyP - > termios - > c_cc [ VSTOP ] ;
/*
2006-01-11 12:17:49 -08:00
* * LNEXT byte
*/
2005-04-16 15:20:36 -07:00
LNext = 0 ;
/*
2006-01-11 12:17:49 -08:00
* * Baud rate bytes
*/
rio_dprintk ( RIO_DEBUG_PARAM , " Mapping of rx/tx baud %x (%x) \n " , TtyP - > termios - > c_cflag , CBAUD ) ;
2005-04-16 15:20:36 -07:00
switch ( TtyP - > termios - > c_cflag & CBAUD ) {
# define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
2006-01-11 12:17:49 -08:00
e ( 50 ) ;
e ( 75 ) ;
e ( 110 ) ;
e ( 134 ) ;
e ( 150 ) ;
e ( 200 ) ;
e ( 300 ) ;
e ( 600 ) ;
e ( 1200 ) ;
e ( 1800 ) ;
e ( 2400 ) ;
e ( 4800 ) ;
e ( 9600 ) ;
e ( 19200 ) ;
e ( 38400 ) ;
e ( 57600 ) ;
e ( 115200 ) ; /* e(230400);e(460800); e(921600); */
2005-04-16 15:20:36 -07:00
}
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " tx baud 0x%x, rx baud 0x%x \n " , TxBaud , RxBaud ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Leftovers
*/
if ( TtyP - > termios - > c_cflag & CREAD )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable receiver \n " ) ;
2005-04-16 15:20:36 -07:00
# ifdef RCV1EN
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & RCV1EN )
rio_dprintk ( RIO_DEBUG_PARAM , " RCV1EN (?) \n " ) ;
2005-04-16 15:20:36 -07:00
# endif
# ifdef XMT1EN
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_cflag & XMT1EN )
rio_dprintk ( RIO_DEBUG_PARAM , " XMT1EN (?) \n " ) ;
2005-04-16 15:20:36 -07:00
# endif
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_lflag & ISIG )
rio_dprintk ( RIO_DEBUG_PARAM , " Input character signal generating enabled \n " ) ;
if ( TtyP - > termios - > c_lflag & ICANON )
rio_dprintk ( RIO_DEBUG_PARAM , " Canonical input: erase and kill enabled \n " ) ;
if ( TtyP - > termios - > c_lflag & XCASE )
rio_dprintk ( RIO_DEBUG_PARAM , " Canonical upper/lower presentation \n " ) ;
if ( TtyP - > termios - > c_lflag & ECHO )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable input echo \n " ) ;
if ( TtyP - > termios - > c_lflag & ECHOE )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable echo erase \n " ) ;
if ( TtyP - > termios - > c_lflag & ECHOK )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable echo kill \n " ) ;
if ( TtyP - > termios - > c_lflag & ECHONL )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable echo newline \n " ) ;
if ( TtyP - > termios - > c_lflag & NOFLSH )
rio_dprintk ( RIO_DEBUG_PARAM , " Disable flush after interrupt or quit \n " ) ;
2005-04-16 15:20:36 -07:00
# ifdef TOSTOP
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_lflag & TOSTOP )
rio_dprintk ( RIO_DEBUG_PARAM , " Send SIGTTOU for background output \n " ) ;
2005-04-16 15:20:36 -07:00
# endif
# ifdef XCLUDE
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_lflag & XCLUDE )
rio_dprintk ( RIO_DEBUG_PARAM , " Exclusive use of this line \n " ) ;
2005-04-16 15:20:36 -07:00
# endif
2006-01-11 12:17:49 -08:00
if ( TtyP - > termios - > c_iflag & IUCLC )
rio_dprintk ( RIO_DEBUG_PARAM , " Map uppercase to lowercase on input \n " ) ;
if ( TtyP - > termios - > c_oflag & OPOST )
rio_dprintk ( RIO_DEBUG_PARAM , " Enable output post-processing \n " ) ;
if ( TtyP - > termios - > c_oflag & OLCUC )
rio_dprintk ( RIO_DEBUG_PARAM , " Map lowercase to uppercase on output \n " ) ;
if ( TtyP - > termios - > c_oflag & ONOCR )
rio_dprintk ( RIO_DEBUG_PARAM , " No carriage return output at column 0 \n " ) ;
if ( TtyP - > termios - > c_oflag & ONLRET )
rio_dprintk ( RIO_DEBUG_PARAM , " Newline performs carriage return function \n " ) ;
if ( TtyP - > termios - > c_oflag & OFILL )
rio_dprintk ( RIO_DEBUG_PARAM , " Use fill characters for delay \n " ) ;
if ( TtyP - > termios - > c_oflag & OFDEL )
rio_dprintk ( RIO_DEBUG_PARAM , " Fill character is DEL \n " ) ;
if ( TtyP - > termios - > c_oflag & NLDLY )
rio_dprintk ( RIO_DEBUG_PARAM , " Newline delay set \n " ) ;
if ( TtyP - > termios - > c_oflag & CRDLY )
rio_dprintk ( RIO_DEBUG_PARAM , " Carriage return delay set \n " ) ;
if ( TtyP - > termios - > c_oflag & TABDLY )
rio_dprintk ( RIO_DEBUG_PARAM , " Tab delay set \n " ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * These things are kind of useful in a later life !
*/
2005-04-16 15:20:36 -07:00
PortP - > Cor2Copy = Cor2 ;
2006-01-11 12:17:49 -08:00
if ( PortP - > State & RIO_DELETED ) {
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
func_exit ( ) ;
2005-04-16 15:20:36 -07:00
return RIO_FAIL ;
}
/*
2006-01-11 12:17:49 -08:00
* * Actually write the info into the packet to be sent
*/
2006-03-24 03:18:27 -08:00
writeb ( cmd , & phb_param_ptr - > Cmd ) ;
writeb ( Cor1 , & phb_param_ptr - > Cor1 ) ;
writeb ( Cor2 , & phb_param_ptr - > Cor2 ) ;
writeb ( Cor4 , & phb_param_ptr - > Cor4 ) ;
writeb ( Cor5 , & phb_param_ptr - > Cor5 ) ;
writeb ( TxXon , & phb_param_ptr - > TxXon ) ;
writeb ( RxXon , & phb_param_ptr - > RxXon ) ;
writeb ( TxXoff , & phb_param_ptr - > TxXoff ) ;
writeb ( RxXoff , & phb_param_ptr - > RxXoff ) ;
writeb ( LNext , & phb_param_ptr - > LNext ) ;
writeb ( TxBaud , & phb_param_ptr - > TxBaud ) ;
writeb ( RxBaud , & phb_param_ptr - > RxBaud ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * Set the length / command field
*/
2006-03-24 03:18:27 -08:00
writeb ( 12 | PKT_CMD_BIT , & PacketP - > len ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * The packet is formed - now , whack it off
* * to its final destination :
*/
2005-04-16 15:20:36 -07:00
add_transmit ( PortP ) ;
/*
2006-01-11 12:17:49 -08:00
* * Count characters transmitted for port statistics reporting
*/
2005-04-16 15:20:36 -07:00
if ( PortP - > statsGather )
PortP - > txchars + = 12 ;
2006-01-11 12:17:49 -08:00
rio_spin_unlock_irqrestore ( & PortP - > portSem , flags ) ;
2005-04-16 15:20:36 -07:00
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " add_transmit returned. \n " ) ;
2005-04-16 15:20:36 -07:00
/*
2006-01-11 12:17:49 -08:00
* * job done .
*/
func_exit ( ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:32 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
/*
* * We can add another packet to a transmit queue if the packet pointer pointed
* * to by the TxAdd pointer has PKT_IN_USE clear in its address .
*/
2006-05-27 00:08:25 -04:00
int can_add_transmit ( struct PKT __iomem * * PktP , struct Port * PortP )
2005-04-16 15:20:36 -07:00
{
2006-05-27 00:08:25 -04:00
struct PKT __iomem * tp ;
2005-04-16 15:20:36 -07:00
2006-05-27 00:08:25 -04:00
* PktP = tp = ( struct PKT __iomem * ) RIO_PTR ( PortP - > Caddr , readw ( PortP - > TxAdd ) ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:27 -08:00
return ! ( ( unsigned long ) tp & PKT_IN_USE ) ;
2005-04-16 15:20:36 -07:00
}
/*
* * To add a packet to the queue , you set the PKT_IN_USE bit in the address ,
* * and then move the TxAdd pointer along one position to point to the next
* * packet pointer . You must wrap the pointer from the end back to the start .
*/
2006-03-24 03:18:27 -08:00
void add_transmit ( struct Port * PortP )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:27 -08:00
if ( readw ( PortP - > TxAdd ) & PKT_IN_USE ) {
2006-01-11 12:17:49 -08:00
rio_dprintk ( RIO_DEBUG_PARAM , " add_transmit: Packet has been stolen! " ) ;
}
2006-03-24 03:18:27 -08:00
writew ( readw ( PortP - > TxAdd ) | PKT_IN_USE , PortP - > TxAdd ) ;
2006-01-11 12:17:49 -08:00
PortP - > TxAdd = ( PortP - > TxAdd = = PortP - > TxEnd ) ? PortP - > TxStart : PortP - > TxAdd + 1 ;
2006-03-24 03:18:27 -08:00
writew ( RIO_OFF ( PortP - > Caddr , PortP - > TxAdd ) , & PortP - > PhbP - > tx_add ) ;
2005-04-16 15:20:36 -07:00
}
/****************************************
* Put a packet onto the end of the
* free list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-05-27 00:08:25 -04:00
void put_free_end ( struct Host * HostP , struct PKT __iomem * PktP )
2005-04-16 15:20:36 -07:00
{
2006-05-27 00:08:25 -04:00
struct rio_free_list __iomem * tmp_pointer ;
2006-03-24 03:18:32 -08:00
unsigned short old_end , new_end ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
rio_spin_lock_irqsave ( & HostP - > HostLock , flags ) ;
/*************************************************
* Put a packet back onto the back of the free list
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-24 03:18:27 -08:00
rio_dprintk ( RIO_DEBUG_PFE , " put_free_end(PktP=%p) \n " , PktP ) ;
2005-04-16 15:20:36 -07:00
2006-03-24 03:18:27 -08:00
if ( ( old_end = readw ( & HostP - > ParmMapP - > free_list_end ) ) ! = TPNULL ) {
2006-01-11 12:17:49 -08:00
new_end = RIO_OFF ( HostP - > Caddr , PktP ) ;
2006-05-27 00:08:25 -04:00
tmp_pointer = ( struct rio_free_list __iomem * ) RIO_PTR ( HostP - > Caddr , old_end ) ;
2006-03-24 03:18:27 -08:00
writew ( new_end , & tmp_pointer - > next ) ;
2006-05-27 00:08:25 -04:00
writew ( old_end , & ( ( struct rio_free_list __iomem * ) PktP ) - > prev ) ;
writew ( TPNULL , & ( ( struct rio_free_list __iomem * ) PktP ) - > next ) ;
2006-03-24 03:18:27 -08:00
writew ( new_end , & HostP - > ParmMapP - > free_list_end ) ;
2006-01-11 12:17:49 -08:00
} else { /* First packet on the free list this should never happen! */
rio_dprintk ( RIO_DEBUG_PFE , " put_free_end(): This should never happen \n " ) ;
2006-03-24 03:18:27 -08:00
writew ( RIO_OFF ( HostP - > Caddr , PktP ) , & HostP - > ParmMapP - > free_list_end ) ;
2006-05-27 00:08:25 -04:00
tmp_pointer = ( struct rio_free_list __iomem * ) PktP ;
2006-03-24 03:18:27 -08:00
writew ( TPNULL , & tmp_pointer - > prev ) ;
writew ( TPNULL , & tmp_pointer - > next ) ;
2006-01-11 12:17:49 -08:00
}
rio_dprintk ( RIO_DEBUG_CMD , " Before unlock: %p \n " , & HostP - > HostLock ) ;
2005-04-16 15:20:36 -07:00
rio_spin_unlock_irqrestore ( & HostP - > HostLock , flags ) ;
}
/*
* * can_remove_receive ( PktP , P ) returns non - zero if PKT_IN_USE is set
* * for the next packet on the queue . It will also set PktP to point to the
* * relevant packet , [ having cleared the PKT_IN_USE bit ] . If PKT_IN_USE is clear ,
* * then can_remove_receive ( ) returns 0.
*/
2006-05-27 00:08:25 -04:00
int can_remove_receive ( struct PKT __iomem * * PktP , struct Port * PortP )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:27 -08:00
if ( readw ( PortP - > RxRemove ) & PKT_IN_USE ) {
2006-05-27 00:08:25 -04:00
* PktP = ( struct PKT __iomem * ) RIO_PTR ( PortP - > Caddr , readw ( PortP - > RxRemove ) & ~ PKT_IN_USE ) ;
2005-04-16 15:20:36 -07:00
return 1 ;
}
return 0 ;
}
/*
* * To remove a packet from the receive queue you clear its PKT_IN_USE bit ,
* * and then bump the pointers . Once the pointers get to the end , they must
* * be wrapped back to the start .
*/
2006-03-24 03:18:27 -08:00
void remove_receive ( struct Port * PortP )
2005-04-16 15:20:36 -07:00
{
2006-03-24 03:18:27 -08:00
writew ( readw ( PortP - > RxRemove ) & ~ PKT_IN_USE , PortP - > RxRemove ) ;
2006-01-11 12:17:49 -08:00
PortP - > RxRemove = ( PortP - > RxRemove = = PortP - > RxEnd ) ? PortP - > RxStart : PortP - > RxRemove + 1 ;
2006-03-24 03:18:27 -08:00
writew ( RIO_OFF ( PortP - > Caddr , PortP - > RxRemove ) , & PortP - > PhbP - > rx_remove ) ;
2005-04-16 15:20:36 -07:00
}