rioparam.c

来自「linux2.6.16版本」· C语言 代码 · 共 695 行 · 第 1/2 页

C
695
字号
/*** -----------------------------------------------------------------------------****  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.*/int RIOParam(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.		 */	}	/*	 ** 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;	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) {		rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");		Cor2 |= COR2_HUPCL;	}	if (C_CRTSCTS(TtyP)) {		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");		Cor2 |= COR2_CTSFLOW;		Cor2 |= COR2_RTSFLOW;	} else {		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");		Cor2 &= ~COR2_CTSFLOW;		Cor2 &= ~COR2_RTSFLOW;	}	if (TtyP->termios->c_cflag & CLOCAL) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?