riotty.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 655 行 · 第 1/2 页

C
655
字号
/*** -----------------------------------------------------------------------------****  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 "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);/* Below belongs in func.h */int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);extern struct rio_info *p;int riotopen(struct tty_struct *tty, struct file *filp){	unsigned int SysPort;	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);	if (p->RIOFailed) {		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");		func_exit();		return -ENXIO;	}	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, 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);		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();		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");		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);		/* 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, 1, 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);			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");	}	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);		 */		PortP->State |= RIO_CARR_ON;		wake_up_interruptible(&PortP->gs.open_wait);	} else {	/* no carrier - wait for DCD */			/*		   while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&		   !(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);			/*			   PortP->gs.tty->termios->c_state |= WOPEN;			 */			PortP->State |= RIO_WOPEN;			rio_spin_unlock_irqrestore(&PortP->portSem, flags);			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {				/*				 ** 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);				RIOPreemptiveCmd(p, PortP, FCLOSE);

⌨️ 快捷键说明

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