📄 rioparam.c
字号:
/*** -----------------------------------------------------------------------------**** 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 02139, 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**** -----------------------------------------------------------------------------*/#ifdef SCCS_LABELSstatic char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";#endif#include <linux/module.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/tty.h>#include <asm/io.h>#include <asm/system.h>#include <asm/string.h>#include <asm/semaphore.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 "typdef.h"#include "pkt.h"#include "daemon.h"#include "rio.h"#include "riospace.h"#include "top.h"#include "cmdpkt.h"#include "map.h"#include "riotypes.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 "error.h"#include "phb.h"#include "link.h"#include "cmdblk.h"#include "route.h"#include "control.h"#include "cirrus.h"#include "rioioctl.h"#include "param.h"#include "list.h"#include "sam.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.**** When you send a packet with the command bit set, then the first** data byte ( data[0] ) is interpretted as the command to execute.** 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** OPEN are currently analagous). With these three commands the following** 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.*/intRIOParam(PortP, cmd, Modem, SleepFlag)struct Port *PortP;int cmd;int Modem;int SleepFlag; { register struct tty_struct *TtyP; int retval; register struct phb_param *phb_param_ptr; PKT *PacketP; int res; uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0; uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0; uchar LNext=0, TxBaud=0, RxBaud=0; int retries = 0xff; unsigned long flags; func_enter (); TtyP = PortP->gs.tty; 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); if (!TtyP) { rio_dprintk (RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n"); func_exit (); return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags ); if (cmd == OPEN) { /* ** 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 1st open after reboot. */#if 0 if (PortP->FirstOpen) { PortP->StoredTty.iflag = TtyP->tm.c_iflag; PortP->StoredTty.oflag = TtyP->tm.c_oflag; PortP->StoredTty.cflag = TtyP->tm.c_cflag; PortP->StoredTty.lflag = TtyP->tm.c_lflag; PortP->StoredTty.line = TtyP->tm.c_line; for (i = 0; i < NCC + 5; i++) PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i]; PortP->FirstOpen = 0; } else if (PortP->Store || PortP->Lock) { rio_dprintk (RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n"); TtyP->tm.c_iflag = PortP->StoredTty.iflag; TtyP->tm.c_oflag = PortP->StoredTty.oflag; TtyP->tm.c_cflag = PortP->StoredTty.cflag; TtyP->tm.c_lflag = PortP->StoredTty.lflag; TtyP->tm.c_line = PortP->StoredTty.line; for (i = 0; i < NCC + 5; i++) TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i]; }#endif } /* ** wait for space */ while ( !(res=can_add_transmit(&PacketP,PortP)) || (PortP->InUse != NOT_INUSE) ) { if (retries -- <= 0) { break; } if ( PortP->InUse != NOT_INUSE ) { rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n"); } if ( !res ) { rio_dprintk (RIO_DEBUG_PARAM, "Port has no space on transmit queue\n"); } if ( SleepFlag != OK_TO_SLEEP ) { rio_spin_unlock_irqrestore( &PortP->portSem, flags); func_exit(); return RIO_FAIL; } rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit\n"); rio_spin_unlock_irqrestore( &PortP->portSem, flags); retval = RIODelay(PortP, HUNDRED_MS); rio_spin_lock_irqsave( &PortP->portSem, flags); if (retval == RIO_FAIL) { rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n"); rio_spin_unlock_irqrestore( &PortP->portSem, flags); pseterr(EINTR); func_exit(); return RIO_FAIL; } if ( PortP->State & RIO_DELETED ) { rio_spin_unlock_irqrestore( &PortP->portSem, flags); func_exit (); return RIO_SUCCESS; } } if (!res) { rio_spin_unlock_irqrestore( &PortP->portSem, flags); func_exit (); return RIO_FAIL; } rio_dprintk (RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n",res); rio_dprintk (RIO_DEBUG_PARAM, "Packet is 0x%x\n",(int) PacketP); phb_param_ptr = (struct phb_param *)PacketP->data;#if 0 /* ** COR 1 */ if ( TtyP->tm.c_iflag & INPCK ) { rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n"); Cor1 |= COR1_INPCK; }#endif switch ( TtyP->termios->c_cflag & CSIZE ) { case CS5: { rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n"); Cor1 |= COR1_5BITS; break; } case CS6: { rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n"); Cor1 |= COR1_6BITS; break; } case CS7: { rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n"); Cor1 |= COR1_7BITS; break; } case CS8: { rio_dprintk (RIO_DEBUG_PARAM, "8 bit data\n"); Cor1 |= COR1_8BITS; break; } } if ( TtyP->termios->c_cflag & CSTOPB ) { rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n"); Cor1 |= COR1_2STOP; } else { rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n"); Cor1 |= COR1_1STOP; } if ( TtyP->termios->c_cflag & PARENB ) { rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n"); Cor1 |= COR1_NORMAL; } else { rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n"); Cor1 |= COR1_NOP; } if ( TtyP->termios->c_cflag & PARODD ) { rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n"); Cor1 |= COR1_ODD; } else { rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n"); Cor1 |= COR1_EVEN; } /* ** COR 2 */ if ( TtyP->termios->c_iflag & IXON ) { rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n"); Cor2 |= COR2_IXON; } else { if ( PortP->Config & RIO_IXON ) { rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n"); Cor2 |= COR2_IXON; } else rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n"); } if (TtyP->termios->c_iflag & IXANY) { if ( PortP->Config & RIO_IXANY ) { rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n"); Cor2 |= COR2_IXANY; } else rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n"); } if ( TtyP->termios->c_iflag & IXOFF ) { rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n"); Cor2 |= COR2_IXOFF; } if ( TtyP->termios->c_cflag & HUPCL ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -