⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 riotty.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
					** 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 );					/*					tp->tm.c_state &= ~WOPEN;					*/					PortP->State &= ~RIO_WOPEN;					rio_spin_unlock_irqrestore(&PortP->portSem, flags);					func_exit ();					return -EINTR;				}			}			PortP->State &= ~RIO_WOPEN;		}		if ( p->RIOHalted )			goto bombout;		rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");		PortP->State |= RIO_MOPEN;	}	else#endif	{		/*		** ACTION		** Direct line open - force carrier (will probably mean		** that sleeping Modem line fubar)		*/		PortP->State |= RIO_LOPEN;	}	if ( p->RIOHalted ) {		goto bombout;	}	rio_dprintk (RIO_DEBUG_TTY, "high level open done\n");#ifdef STATS	PortP->Stat.OpenCnt++;#endif	/*	** Count opens for port statistics reporting	*/	if (PortP->statsGather)		PortP->opens++;	rio_spin_unlock_irqrestore(&PortP->portSem, flags);	rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n");	func_exit ();	return 0;}/*** RIOClose the port.** The operating system thinks that this is last close for the device.** As there are two interfaces to the port (Modem and tty), we need to** check that both are closed before we close the device.*/ intriotclose(void  *ptr){#if 0	register uint SysPort = dev;	struct ttystatics *tp;		/* pointer to our ttystruct */#endif	struct Port *PortP = ptr;	/* pointer to the port structure */	int deleted = 0;	int	try = -1; /* Disable the timeouts by setting them to -1 */	int	repeat_this = -1; /* Congrats to those having 15 years of 				     uptime! (You get to break the driver.) */	unsigned long end_time;	struct tty_struct * tty;	unsigned long flags;	int Modem;	int rv = 0;		rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);	/* PortP = p->RIOPortp[SysPort]; */	rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP);	/* tp = PortP->TtyP;*/			/* Get tty */	tty = PortP->gs.tty;	rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty);	if (PortP->gs.closing_wait) 		end_time = jiffies + PortP->gs.closing_wait;	else 		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;	Modem = rio_ismodem(tty);#if 0	/* What F.CKING cache? Even then, a higly idle multiprocessor,	   system with large caches this won't work . Better find out when 	   this doesn't work asap, and fix the cause.  -- REW */		RIODelay(PortP, HUNDRED_MS*10);	/* To flush the cache */#endif	rio_spin_lock_irqsave(&PortP->portSem, flags);	/*	** Setting this flag will make any process trying to open	** this port block until we are complete closing it.	*/	PortP->State |= RIO_CLOSING;	if ( (PortP->State & RIO_DELETED) ) {		rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n");		deleted = 1;	}		if ( p->RIOHalted ) {		RIOClearUp( PortP );		rv = -EIO;		goto close_end;	}	rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n");	/*	** clear the open bits for this device	*/	PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);	PortP->State &= ~RIO_CARR_ON;	PortP->ModemState &= ~MSVR1_CD;	/*	** If the device was open as both a Modem and a tty line	** then we need to wimp out here, as the port has not really	** been finally closed (gee, whizz!) The test here uses the	** bit for the OTHER mode of operation, to see if THAT is	** still active!	*/	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {		/*		** The port is still open for the other task -		** return, pretending that we are still active.		*/		rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum);		PortP->State &= ~RIO_CLOSING;		if (PortP->firstOpen)			PortP->firstOpen--;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return -EIO;	}	rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n");	PortP->State &= ~RIO_DYNOROD;	/*	** This is where we wait for the port	** to drain down before closing. Bye-bye....	** (We never meant to do this)	*/	rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n");	if (!deleted)	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && 		(PortP->TxBufferIn != PortP->TxBufferOut) ) {		cprintf("Need to flush the ttyport\n");		if (repeat_this -- <= 0) {			rv = -EINTR;			rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");			RIOPreemptiveCmd(p, PortP, FCLOSE);			goto close_end;		}		rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) {			rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");			rv = -EINTR;			rio_spin_lock_irqsave(&PortP->portSem, flags);			goto close_end;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);	}	PortP->TxBufferIn = PortP->TxBufferOut = 0;	repeat_this = 0xff;	PortP->InUse = 0;	if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {		/*		** The port has been re-opened for the other task -		** return, pretending that we are still active.		*/		rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);		PortP->State &= ~RIO_CLOSING;		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (PortP->firstOpen)			PortP->firstOpen--;		return -EIO;	}	if ( p->RIOHalted ) {		RIOClearUp( PortP );		goto close_end;	}	/* Can't call RIOShortCommand with the port locked. */	rio_spin_unlock_irqrestore(&PortP->portSem, flags);	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {		RIOPreemptiveCmd(p, PortP, FCLOSE);		goto close_end;	}	if (!deleted)	  while (try && (PortP->PortState & PORT_ISOPEN)) {	        try--;		if (time_after (jiffies, end_time)) {		  rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" );		  RIOPreemptiveCmd(p, PortP,FCLOSE);		  break;		}		rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", 					   PortP->PortState & PORT_ISOPEN);		if ( p->RIOHalted ) {			RIOClearUp( PortP );			goto close_end;		}		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {			rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");			RIOPreemptiveCmd(p, PortP,FCLOSE);			break;		}	}	rio_spin_lock_irqsave(&PortP->portSem, flags);	rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try ); 	/* RIOPreemptiveCmd(p, PortP, FCLOSE); *//*** 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.*/	PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);#ifdef STATS	PortP->Stat.CloseCnt++;#endif	/*	** Count opens for port statistics reporting	*/	if (PortP->statsGather)		PortP->closes++;close_end:	/* XXX: Why would a "DELETED" flag be reset here? I'd have	   thought that a "deleted" flag means that the port was	   permanently gone, but here we can make it reappear by it	   being in close during the "deletion".	*/	PortP->State &= ~(RIO_CLOSING|RIO_DELETED);	if (PortP->firstOpen)		PortP->firstOpen--;	rio_spin_unlock_irqrestore(&PortP->portSem, flags);	rio_dprintk (RIO_DEBUG_TTY, "Return from close\n");	return rv;}/*** decide if we need to use the line discipline.** This routine can return one of three values:** COOK_RAW if no processing has to be done by the line discipline or the card** COOK_WELL if the line discipline must be used to do the processing** COOK_MEDIUM if the card can do all the processing necessary.*/#if 0static intRIOCookMode(struct ttystatics *tp){	/*	** We can't handle tm.c_mstate != 0 on SCO	** We can't handle mapping	** We can't handle non-ttwrite line disc.	** We can't handle lflag XCASE	** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)	*/#ifdef CHECK	CheckTtyP( tp );#endif	if (!(tp->tm.c_oflag & OPOST))	/* No post processing */		return COOK_RAW;	/* Raw mode o/p */	if ( tp->tm.c_lflag & XCASE )		return COOK_WELL;	/* Use line disc */	if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )		return COOK_WELL;	/* Use line disc for strange modes */	if ( tp->tm.c_oflag == OPOST )	/* If only OPOST is set, do RAW */		return COOK_RAW;	/*	** So, we need to output process!	*/	return COOK_MEDIUM;}#endifstatic voidRIOClearUp(PortP)struct Port *PortP;{	rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n");	PortP->Config = 0;	  /* Direct semaphore */	PortP->PortState = 0;	PortP->firstOpen = 0;	PortP->FlushCmdBodge = 0;	PortP->ModemState = PortP->CookMode = 0;	PortP->Mapped = 0;	PortP->WflushFlag = 0;	PortP->MagicFlags	= 0;	PortP->RxDataStart = 0;	PortP->TxBufferIn = 0;	PortP->TxBufferOut = 0;}/*** Put a command onto a port.** The PortPointer, command, length and arg are passed.** The len is the length *inclusive* of the command byte,** and so for a command that takes no data, len==1.** The arg is a single byte, and is only used if len==2.** Other values of len aren't allowed, and will cause** a panic.*/int RIOShortCommand(struct rio_info *p, struct Port *PortP,		int command, int len, int arg){	PKT *PacketP;	int		retries = 20; /* at 10 per second -> 2 seconds */	unsigned long flags;	rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n");#ifdef CHECK	CheckPortP( PortP );	if ( len < 1 || len > 2 )		cprintf(("STUPID LENGTH %d\n",len));#endif	if ( PortP->State & RIO_DELETED ) {		rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");		return RIO_FAIL;	}	rio_spin_lock_irqsave(&PortP->portSem, flags);	/*	** If the port is in use for pre-emptive command, then wait for it to 	** be free again.	*/	while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) {		rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", 					   retries);		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (retries-- <= 0) {			return RIO_FAIL;		}		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {			return RIO_FAIL;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);	}	if ( PortP->State & RIO_DELETED ) {		rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return RIO_FAIL;	}	while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) {		rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		if (retries-- <= 0) {		  rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n");			return RIO_FAIL;		}		if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) {			return RIO_FAIL;		}		rio_spin_lock_irqsave(&PortP->portSem, flags);	}	if ( p->RIOHalted ) {		rio_spin_unlock_irqrestore(&PortP->portSem, flags);		return RIO_FAIL;	}	/*	** set the command byte and the argument byte	*/	WBYTE(PacketP->data[0] , command);	if ( len==2 )		WBYTE(PacketP->data[1] , arg);	/*	** set the length of the packet and set the command bit.	*/	WBYTE(PacketP->len , PKT_CMD_BIT | len);	add_transmit(PortP);	/*	** Count characters transmitted for port statistics reporting	*/	if (PortP->statsGather)		PortP->txchars += len;	rio_spin_unlock_irqrestore(&PortP->portSem, flags);	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;}#if 0/*** This is an ioctl interface. This is the twentieth century. You know what** its all about.*/intriotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg){	register struct		Port *PortP;	register struct		ttystatics *tp;	int					current;	int					ParamSemIncremented = 0;	int					old_oflag, old_cflag, old_iflag, changed, oldcook;	int					i;	unsigned char		sio_regs[5];		/* Here be magic */	short				vpix_cflag;	short				divisor;	int					baud;	uint				SysPort = rio_minor(tty);	int				Modem = rio_ismodem(tty);	int					ioctl_processed;	rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n",			SysPort, cmd, arg, Modem?"Modem":"tty") ;	if ( SysPort >= RIO_PORTS ) {		rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort);		return -ENXIO;	}	PortP = p->RIOPortp[SysPort];	tp = PortP->TtyP;	rio_spin_lock_irqsave(&PortP->portSem, flags);#ifdef STATS	PortP->Stat.IoctlCnt++;#endif	if ( PortP->State & RIO_DELETED ) {		rio_spin_unlock_irqrestore(&PortP->portSem, flags);

⌨️ 快捷键说明

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