riotty.c

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

C
747
字号
/*** -----------------------------------------------------------------------------****  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		: 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**** -----------------------------------------------------------------------------*/#ifdef SCCS_LABELSstatic char *_riotty_c_sccs_ = "@(#)riotty.c	1.3";#endif#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/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"static void RIOClearUp(struct Port *PortP);int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);extern int conv_vb[];		/* now defined in ttymgr.c */extern int conv_bv[];		/* now defined in ttymgr.c *//*** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support**** ep.def.h is necessary for Modular Kernel Support** DO NOT place any kernel 'extern's after this line** or this source file will not build riotty.k.o*/#ifdef uLYNX#include <ep.def.h>#endif#ifdef NEED_THIS2static struct old_sgttyb default_sg = {	B19200, B19200,		/* input and output speed */	'H' - '@',		/* erase char */	-1,			/* 2nd erase char */	'U' - '@',		/* kill char */	ECHO | CRMOD,		/* mode */	'C' - '@',		/* interrupt character */	'\\' - '@',		/* quit char */	'Q' - '@',		/* start char */	'S' - '@',		/* stop char */	'D' - '@',		/* EOF */	-1,			/* brk */	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */	'Z' - '@',		/* process stop */	'Y' - '@',		/* delayed stop */	'R' - '@',		/* reprint line */	'O' - '@',		/* flush output */	'W' - '@',		/* word erase */	'V' - '@'		/* literal next char */};#endifextern struct rio_info *p;int riotopen(struct tty_struct *tty, struct file *filp){	register uint SysPort;	int Modem;	int repeat_this = 250;	struct Port *PortP;	/* pointer to the port structure */	unsigned long flags;	int retval = 0;	func_enter();	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close	   is going to oops.	 */	tty->driver_data = NULL;	SysPort = rio_minor(tty);	Modem = rio_ismodem(tty);	if (p->RIOFailed) {		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");		pseterr(ENXIO);		func_exit();		return -ENXIO;	}	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", SysPort, Modem ? "Modem" : "tty", p->RIOPortp[SysPort]->Mapped);	/*	 ** 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.	 */	if (SysPort >= RIO_PORTS) {	/* out of range ? */		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);		pseterr(ENXIO);		func_exit();		return -ENXIO;	}	/*	 ** Grab pointer to the port stucture	 */	PortP = p->RIOPortp[SysPort];	/* Get control struc */	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);	if (!PortP->Mapped) {	/* we aren't mapped yet! */		/*		 ** The system doesn't know which RTA this port		 ** corresponds to.		 */		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");		func_exit();		pseterr(ENXIO);		return -ENXIO;	}	tty->driver_data = PortP;	PortP->gs.tty = tty;	PortP->gs.count++;	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);	retval = gs_init_port(&PortP->gs);	if (retval) {		PortP->gs.count--;		return -ENXIO;	}	/*	 ** 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");		pseterr(ENXIO);		func_exit();		return -ENXIO;	}	/*	 ** 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.	 */	/* I find the above code a bit hairy. I find the below code	   easier to read and shorter. Now, if it works too that would	   be great... -- REW 	 */	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {		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;		}	}	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");	rio_spin_lock_irqsave(&PortP->portSem, flags);	if (p->RIOHalted) {		goto bombout;	}	/*	 ** 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");			RIOPreemptiveCmd(p, PortP, FCLOSE);			retval = -EINTR;			goto bombout;		}		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {			rio_spin_lock_irqsave(&PortP->portSem, flags);			retval = -EINTR;			goto bombout;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);	}	if (!PortP->Mapped) {		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		retval = -ENXIO;		func_exit();		return retval;	}	if (p->RIOHalted) {		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 */	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);	}	if (!(PortP->firstOpen)) {	/* First time ? */		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");		PortP->firstOpen++;		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */		PortP->InUse = NOT_INUSE;		/* Tentative fix for bug PR27. Didn't work. */		/* PortP->gs.xmit_cnt = 0; */		rio_spin_unlock_irqrestore(&PortP->portSem, flags);#ifdef NEED_THIS		ttyseth(PortP, tp, (struct old_sgttyb *) &default_sg);#endif		/* Someone explain to me why this delay/config is		   here. If I read the docs correctly the "open"		   command piggybacks the parameters immediately.		   -- REW */		RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP);	/* Open the port */		rio_spin_lock_irqsave(&PortP->portSem, flags);		/*		 ** 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);/*** 15.10.1998 ARG - ESIL 0759** (Part) fix for port being trashed when opened whilst RTA "disconnected"** Take out the limited wait - now wait for ever or until user** bangs us out.**			if (repeat_this -- <= 0) {				rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish timed out.\n"));				RIOPreemptiveCmd(p, PortP, FCLOSE ); 				rio_spin_unlock_irqrestore(&PortP->portSem, flags);				return -EINTR;			}***/			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");				RIOPreemptiveCmd(p, PortP, FCLOSE);				func_exit();				return -EINTR;			}			rio_spin_lock_irqsave(&PortP->portSem, flags);		}		if (p->RIOHalted) {			retval = -EIO;		      bombout:			/*                    RIOClearUp( PortP ); */			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			return retval;		}		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");	}#ifdef MODEM_SUPPORT	if (Modem) {		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		 */		if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {			rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);			/*			   tp->tm.c_state |= CARR_ON;			   wakeup((caddr_t) &tp->tm.c_canq);			 */

⌨️ 快捷键说明

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