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

📄 rs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: $Hdr: rs.c,v 4.300 91/06/09 06:43:03 root Rel41 $ SONY * *	@(#)rs.c	8.1 (Berkeley) 6/11/93 *//*	rs.c	6.1	83/07/29	*/#include "rs.h"#if NRS > 0/* * RS driver * */#if NBK > 0#include "bk.h"#endif#include <sys/param.h>#include <sys/conf.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/kernel.h>#include <sys/ioctl.h>#include <sys/tty.h>#include <sys/buf.h>#include <sys/malloc.h>#ifdef CPU_SINGLE#include <news3400/hbdev/hbvar.h>#else#include "../iop/iopvar.h"#endif#include <news3400/iop/rsreg.h>#include <news3400/sio/sccparam.h>#define	RS_RXE	RXE#define	RS_TXE	TXE#define	RS_ON	(RXE|TXE|RTS|DTR)#define	RS_OFF	TXE#define	RS_RTS	RTS#define	RS_DTR	DTR#define	RS_CTS	CTS#define	RS_DCD	DCD#define	RS_DSR	DSR#define	RS_RI	RI#define	RS_BRK	XBREAK#ifdef AUTO_ENABLE#define	RS_AUTO_ENABLE	AUTO_ENABLE#endif#ifdef CPU_SINGLE#define	iop_device	hb_device#define	ii_unit		hi_unit#define	ii_flags	hi_flags#define	ii_alive	hi_alive#endif/* * Definition of the driver for the auto-configuration program. */int rsprobe(), rsattach(), rsrint(), rsxint(), rssint();struct iop_device *rsinfo[NRS];#ifdef CPU_SINGLEstruct hb_driver rsdriver = { rsprobe, 0, rsattach, 0, 0, "rs", rsinfo };#elsestruct iop_driver rsdriver = { rsprobe, 0, rsattach, 0, "rs", rsinfo };#endif/* * Local variables for the driver */struct	tty rs_tty[NRS*4];char	rssoftCAR[NRS];int	rs_flags[NRS*4];int	rs_param[NRS*4];char	rs_active[NRS*4];char	rs_stopped[NRS*4];int	rs_rate[NRS*4];int	rs_average[NRS*4];char	rs_timeout[NRS*4];char	rs_watch;#ifndef lintint	nrs = NRS*4;			/* used by iostat */#endifextern	int tty00_is_console;extern void rsstart();extern void ttrstrt();extern void rsctrl();#define	RS_CARR(unit) (rssoftCAR[(unit) >> 2] & (1 << ((unit) & 03)))#define	RS_FLAG(unit, flag) (rs_flags[unit] & (flag))#define	RF_FLOWCTL	0x0010		/* use H/W flow control */#define	RF_EXTCLK	0x0100		/* allow external clock */#define	RF_NODELAY	0x1000		/* disable interrupt delay *//* * Routine for configuration *//*ARGSUSED*/rsprobe(ii)	struct iop_device *ii;{	return (rs_probe(ii));}/* * Routine called to attach a rs. */rsattach(ii)	register struct iop_device *ii;{	int i;	rssoftCAR[ii->ii_unit] = ii->ii_flags;	for (i = 0; i < 4; i++)		rs_flags[ii->ii_unit * 4 + i] =		    (ii->ii_flags >> i) & (RF_FLOWCTL|RF_EXTCLK|RF_NODELAY);	if (rs_watch == 0) {		rs_watchdog();		rs_watch = 1;	}}rs_watchdog(){	register int unit, s;	for (unit = 0; unit < NRS*4; unit++) {		if (rs_active[unit] == 0)			continue;		s = spltty();		rs_average[unit] = (rs_average[unit] * 7 + rs_rate[unit]) >> 3;		rs_rate[unit] = 0;		(void) splx(s);	}	timeout(rs_watchdog, (caddr_t)0, hz / 10);}/* * Open a RS line. Turn on this rs if this is the first use of it. *//*ARGSUSED*/rsopen(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	register int unit;	register struct tty *tp;	register struct iop_device *ii;	int s;	unit = minor(dev);	if (unit >= NRS*4 || (ii = rsinfo[unit >> 2]) == 0 || ii->ii_alive == 0)		return (ENXIO);	if (rs_active[unit] == 0) {		if (rs_init(unit) < 0)			return (ENXIO);		rs_enable(unit);		rs_active[unit] = 1;	}	tp = &rs_tty[unit];	if (tp->t_state&TS_XCLUDE && curproc->p_ucred->cr_uid != 0)		return (EBUSY);	tp->t_addr = (caddr_t)0;	tp->t_oproc = rsstart;#ifdef notyet /* KU:XXX */	tp->t_ctrlproc = rsctrl;#endif	/*	 * If this is first open, initialze tty state to default.	 */	if ((tp->t_state & TS_ISOPEN) == 0) {		tp->t_state |= TS_WOPEN;		ttychars(tp);		if (tp->t_ispeed == 0) {			tp->t_iflag = TTYDEF_IFLAG;			tp->t_oflag = TTYDEF_OFLAG;			tp->t_cflag = TTYDEF_CFLAG;			tp->t_lflag = TTYDEF_LFLAG;			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;		}		rsparam(tp, &tp->t_termios);		ttsetwater(tp);	}	/*	 * Wait receiver and status interrupt	 */	/*	 * Wait for carrier, then process line discipline specific open.	 */	rsmctl(dev, RS_ON, DMSET);	if (rs_param[unit] & DCD || RS_CARR(unit))		tp->t_state |= TS_CARR_ON;	s = spltty();		/* spl5 -> spltty, 90/02/28 sak */	while ((tp->t_state & TS_CARR_ON) == 0) {		tp->t_state |= TS_WOPEN;		sleep((caddr_t)&tp->t_rawq, TTIPRI);	}#ifdef notyet /* KU:XXX */	if (RS_FLAG(unit, RF_FLOWCTL)) {		tp->t_state |= TS_HFLWCTL;		rsmctl(dev, RS_AUTO_ENABLE, DMBIS);	} else {		tp->t_state &= ~TS_HFLWCTL;		rsmctl(dev, RS_AUTO_ENABLE, DMBIC);	}#endif	(void) splx(s);	return ((*linesw[tp->t_line].l_open)(dev, tp));}/* * Close a RS line. *//*ARGSUSED*/rsclose(dev, flag)	dev_t dev;	int flag;{	register struct tty *tp;	register unit;	unit = minor(dev);	tp = &rs_tty[unit];	(*linesw[tp->t_line].l_close)(tp);	(void) rsmctl(unit, RS_BRK, DMBIC);	if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)		(void) rsmctl(unit, RS_OFF, DMSET);	ttyclose(tp);	if (RS_FLAG(unit, RF_FLOWCTL))		(void)rsmctl(unit, RS_RTS, DMBIC);}rsread(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp;	tp = &rs_tty[minor(dev)];	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));}rswrite(dev, uio, flag)	dev_t dev;	struct uio *uio;	int flag;{	register struct tty *tp;	tp = &rs_tty[minor(dev)];	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));}rsenable(unit)	int unit;{	rs_timeout[unit] = 0;	rs_enable(unit);}/* * RS receiver interrupt. */_rsrint(unit, buf, n)	register int unit;	register char *buf;	register int n;{	register struct iop_device *ii;	register struct tty *tp;	register int (*rint)();#ifdef notyet /* KU:XXX */	intrcnt[INTR_RS0 + unit]++;#endif	ii = rsinfo[unit >> 2];	if (ii == 0 || ii->ii_alive == 0)		return;	tp = &rs_tty[unit];	if ((tp->t_state & TS_ISOPEN) == 0) {		wakeup((caddr_t)&tp->t_rawq);		goto enable;	}	/*	 * Loop fetching characters from the silo for this	 * rs until there are no more in the silo.	 */	rint = linesw[tp->t_line].l_rint;	while (--n >= 0) {#if NBK > 0		if (tp->t_line == NETLDISC) {			c &= 0177;			BKINPUT(c, tp);		} else#endif /* NBK > 0 */			(*rint)(*buf++, tp);	}enable:	rs_rate[unit]++;	if (rs_average[unit] >= 10 && RS_FLAG(unit, RF_NODELAY) == 0) {		if (rs_timeout[unit] == 0) {			rs_timeout[unit] = 1;			timeout(rsenable, (caddr_t)unit, hz / 100);		}	} else		rs_enable(unit);}/*ARGSUSED*/rsioctl(dev, cmd, data, flag)	dev_t dev;	caddr_t data;{	register struct tty *tp;	register int unit = minor(dev);	int error; 	tp = &rs_tty[unit];	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);	if (error >= 0)		return (error);	error = ttioctl(tp, cmd, data, flag);	if (error >= 0)		return (error);	switch (cmd) {	case TIOCSBRK:		(void) rsmctl(dev, RS_BRK, DMBIS);		break;	case TIOCCBRK:		(void) rsmctl(dev, RS_BRK, DMBIC);		break;	case TIOCSDTR:		(void) rsmctl(dev, RS_DTR|RS_RTS, DMBIS);		break;	case TIOCCDTR:		if (curproc->p_ucred->cr_uid &&		    curproc->p_session->s_ttyp != tp)			return (EACCES);		(void) rsmctl(dev, RS_DTR|RS_RTS, DMBIC);		break;	case TIOCMSET:		(void) rsmctl(dev, dmtors(*(int *)data), DMSET);		break;	case TIOCMBIS:		(void) rsmctl(dev, dmtors(*(int *)data), DMBIS);		break;	case TIOCMBIC:		(void) rsmctl(dev, dmtors(*(int *)data), DMBIC);		break;	case TIOCMGET:		*(int *)data = rstodm(rsmctl(dev, 0, DMGET));		break;	default:		return (ENOTTY);	}	return (0);}dmtors(bits)	register int bits;{	register int b;	b = 0;	if (bits & DML_LE)  b |= RS_TXE|RS_RXE;	if (bits & DML_DTR) b |= RS_DTR;	if (bits & DML_RTS) b |= RS_RTS;	if (bits & DML_CTS) b |= RS_CTS;	if (bits & DML_CAR) b |= RS_DCD;	if (bits & DML_RNG) b |= RS_RI;	if (bits & DML_DSR) b |= RS_DSR;#ifdef AUTO_ENABLE	if (bits & DML_USR) b |= RS_AUTO_ENABLE;#endif /* AUTO_ENABLE */	return(b);}rstodm(bits)	register int bits;{	register int b;	b = 0;	if (bits & (RS_TXE|RS_RXE)) b |= DML_LE;	if (bits & RS_DTR) b |= DML_DTR;	if (bits & RS_RTS) b |= DML_RTS;	if (bits & RS_CTS) b |= DML_CTS;	if (bits & RS_DCD) b |= DML_CAR;	if (bits & RS_RI)  b |= DML_RNG;	if (bits & RS_DSR) b |= DML_DSR;#ifdef AUTO_ENABLE	if (bits & RS_AUTO_ENABLE) b |= DML_USR;#endif	return(b);} /* * compat table */struct speedtab rsspeedtab[] = {	0,	0,	50,	1,	75,	2,	110,	3,	134,	4,	150,	5,	200,	6,	300,	7,	600,	8,	1200,	9,	1800,	10,	2400,	11,	4800,	12,	9600,	13,	19200,	14,	38400,	15,	-1,	-1};/* * Set parameters from open or stty into the RS hardware * registers. */rsparam(tp, t)	register struct tty *tp;	register struct termios *t;{	register int param;	register int cflag = t->c_cflag;	int unit = minor(tp->t_dev);	int s;	int ospeed = ttspeedtab(t->c_ospeed, rsspeedtab);	/* check requested parameters */	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||	    (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6)		return (EINVAL);	/* and copy to tty */	tp->t_ispeed = t->c_ispeed;	tp->t_ospeed = t->c_ospeed;	tp->t_cflag = cflag;	/*	 * Block interrupts so parameters will be set	 * before the line interrupts.	 */	s = spltty();	if (tp->t_ospeed == 0) {		tp->t_cflag |= HUPCL;		(void) rsmctl(unit, RS_OFF, DMSET);		(void) splx(s);		return (0);	}	param = rs_get_param(unit) &		~(CHAR_SIZE|PARITY|EVEN|STOPBIT|BAUD_RATE|NOCHECK);	if ((cflag & CREAD) == 0)		param &= ~RXE;	if (cflag & CS6)		param |= C6BIT;	if (cflag & CS7)		param |= C7BIT;	if (cflag & PARENB)		param |= PARITY;	if ((cflag & PARODD) == 0)		param |= EVEN;	if ((tp->t_iflag & INPCK) == 0)		param |= NOCHECK;	if (cflag & CSTOPB)		param |= STOP2;	else		param |= STOP1;	rs_param[unit] = param | ospeed;	if (RS_FLAG(unit, RF_EXTCLK))		rs_param[unit] |= EXTCLK_ENABLE;	else		rs_param[unit] &= ~EXTCLK_ENABLE;	rs_set_param(unit, rs_param[unit]);	(void) splx(s);	return (0);}/* * RS transmitter interrupt. * Restart the idle line. */_rsxint(unit, count)	int unit;	int count;{	register struct tty *tp;	register int s;#ifdef notyet /* KU:XXX */	intrcnt[INTR_RS0 + unit]++;#endif	rs_stopped[unit] = 0;	tp = &rs_tty[unit];	tp->t_state &= ~TS_BUSY;	s = spltty();	if (tp->t_state & TS_FLUSH)		tp->t_state &= ~TS_FLUSH;

⌨️ 快捷键说明

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