📄 riotty.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 : 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"#if 0static void ttyseth_pv(struct Port *, struct ttystatics *, struct termios *sg, int);#endifstatic void RIOClearUp(struct Port *PortP);int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);#if 0static int RIOCookMode(struct ttystatics *);#endifextern 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;intriotopen(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. */#if 0 if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { if (PortP->WaitUntilBooted) { rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot\n"); do { if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); func_exit (); return -EINTR; } if (repeat_this -- <= 0) { rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n"); RIOPreemptiveCmd(p, PortP, FCLOSE ); pseterr(EINTR); func_exit (); return -EIO; } } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n"); } else { rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n"); pseterr(ENXIO); func_exit (); return 0; } }#else /* 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");#endif#if 0 tp = PortP->TtyP; /* get tty struct */#endif rio_spin_lock_irqsave(&PortP->portSem, flags); if ( p->RIOHalted ) { goto bombout; }#if 0 retval = gs_init_port(&PortP->gs); if (retval){ func_exit (); return retval; }#endif /* ** 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 */#if 0 /* This delay of 1 second was annoying. I removed it. -- REW */ RIODelay(PortP, HUNDRED_MS*10); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); /* Config the port */#endif 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); */ 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)#if 0 if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH))#endif { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -