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

📄 simcons.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifndef lintstatic	char sccsid[] = "@(#)simcons.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1987 by Sun Microsystems, Inc. *//* * Console driver for the kernel under the Sparc Architecture Simulator. */#include <sys/param.h>#include <sys/systm.h>#include <sys/termios.h>#include <sys/termio.h>#include <sys/ttold.h>#include <sys/stropts.h>#include <sys/stream.h>#include <sys/tty.h>#include <sys/user.h>#include <sys/proc.h>#include <sys/conf.h>#include <sys/file.h>#include <sys/uio.h>#include <sys/buf.h>#include <sys/kernel.h>#include <machine/clock.h>#include <machine/mmu.h>#include <machine/cpu.h>#include <sundev/mbvar.h>#define	ISPEED	B9600#define	IFLAGS	(CS7|CREAD|PARENB)int	simc_flags;		/* random flags */tty_common_t simc_ttycommon;	/* data common to all tty drivers */#define	SIMC_ISOPEN	0x00000002	/* open is complete */#define	SIMC_STOPPED	0x00000010	/* output is stopped */static int simcopen();static int simcclose();static int simcwput();static struct module_info simcm_info = {	0,	"simc",	0,	INFPSZ,	2048,	128};static struct qinit simcrinit = {	putq,	NULL,	simcopen,	simcclose,	NULL,	&simcm_info,	NULL};static struct qinit simcwinit = {	simcwput,	NULL,	simcopen,	simcclose,	NULL,	&simcm_info,	NULL};static char *simcmodlist[] = {	"ldterm",	"ttcompat",	NULL};struct streamtab simcstab = {	&simcrinit,	&simcwinit,	NULL,	NULL,	simcmodlist};static void	simcioctl(/*queue_t *q, mblk_t *mp*/);static void	simcstart();extern void	tty_qfull();extern char	simxinc();/*ARGSUSED*/static intsimcopen(q, dev, flag, sflag)	register queue_t *q;	dev_t dev;{	if (minor(dev) != 0)		return (OPENFAIL);	if (!(simc_flags & SIMC_ISOPEN)) {		simc_ttycommon.t_iflag = 0;		simc_ttycommon.t_cflag = (ISPEED << IBSHIFT)|ISPEED|IFLAGS;		simc_flags = SIMC_ISOPEN;	} else if (simc_ttycommon.t_flags & TS_XCLUDE && u.u_uid != 0) {		u.u_error = EBUSY;		return (OPENFAIL);	}	simc_ttycommon.t_readq = q;	simc_ttycommon.t_writeq = WR(q);	return (dev);}static intsimcclose(q)	register queue_t *q;{	simc_flags &= ~SIMC_ISOPEN;	simc_ttycommon.t_flags &= ~TS_XCLUDE;}/* * Put procedure for write queue. * Respond to M_STOP, M_START, M_IOCTL, and M_FLUSH messages here; * set the flow control character for M_STOPI and M_STARTI messages; * queue up M_BREAK, M_DELAY, and M_DATA messages for processing * by the start routine, and then call the start routine; discard * everything else. */static intsimcwput(q, mp)	register queue_t *q;	register mblk_t *mp;{	register int s;	switch (mp->b_datap->db_type) {	case M_STOP:		/*		 * Since we don't do real DMA, we can just let the		 * chip coast to a stop after applying the brakes.		 */		simc_flags |= SIMC_STOPPED;		freemsg(mp);		break;	case M_START:		if (simc_flags & SIMC_STOPPED) {			simc_flags &= ~SIMC_STOPPED;			simcstart();		}		freemsg(mp);		break;	case M_IOCTL:		simcioctl(q, mp);		break;	case M_FLUSH:		if (*mp->b_rptr & FLUSHW) {			s = splzs();			/*			 * Flush our write queue.			 * Probably unnecessary here.			 */			flushq(q, FLUSHDATA);	/* XXX doesn't flush M_DELAY */			(void) splx(s);			*mp->b_rptr &= ~FLUSHW;	/* it has been flushed */		}		if (*mp->b_rptr & FLUSHR) {			s = splzs();			flushq(RD(q), FLUSHDATA);			(void) splx(s);			qreply(q, mp);	/* give the read queues a crack at it */		} else			freemsg(mp);		break;	case M_DATA:		/*		 * Queue the message up to be transmitted,		 * and poke the start routine.		 */		putq(q, mp);		simcstart();		break;	case M_BREAK:	case M_DELAY:	default:		/*		 * "No, I don't want a subscription to Chain Store Age,		 * thank you anyway."		 */		freemsg(mp);		break;	}}/* * Retry an "ioctl", now that "bufcall" claims we may be able to allocate * the buffer we need. *//*ARGSUSED*/static intsimcreioctl(unit)	long unit;{	queue_t *q;	register mblk_t *mp;	if ((q = simc_ttycommon.t_writeq) == NULL)		return;	if ((mp = simc_ttycommon.t_iocpending) != NULL) {		simc_ttycommon.t_iocpending = NULL;		simcioctl(q, mp);	}}/* * Process an "ioctl" message sent down to us. */static voidsimcioctl(q, mp)	queue_t *q;	register mblk_t *mp;{	struct iocblk *iocp;	register unsigned datasize;	int error;	int s;	if (simc_ttycommon.t_iocpending != NULL) {		/*		 * We were holding an "ioctl" response pending the		 * availability of an "mblk" to hold data to be passed up;		 * another "ioctl" came through, which means that "ioctl"		 * must have timed out or been aborted.		 */		freemsg(simc_ttycommon.t_iocpending);		simc_ttycommon.t_iocpending = NULL;	}	iocp = (struct iocblk *)mp->b_rptr;	/*	 * The only way in which "ttycommon_ioctl" can fail is if the "ioctl"	 * requires a response containing data to be returned to the user,	 * and no mblk could be allocated for the data.	 * No such "ioctl" alters our state. Thus, we always go ahead and	 * do any state-changes the "ioctl" calls for, and just stash the	 * "ioctl" response structure away for a later retry if we couldn't	 * allocate the data.	 */	if ((datasize = ttycommon_ioctl(&simc_ttycommon, q, mp, &error)) != 0) {		simc_ttycommon.t_iocpending = mp;		(void) bufcall(datasize, BPRI_HI, simcreioctl, 0L);		return;	}	if (error < 0) {		/*		 * "ttyioctl" didn't do anything; we process it here.		 */		error = 0;		switch (iocp->ioc_cmd) {		case TIOCSBRK:		case TIOCCBRK:			break;		default:			/*			 * We don't understand it either.			 */			error = ENOTTY;			break;		}	}	if (error != 0) {		((struct iocblk *)mp->b_rptr)->ioc_error = error;		mp->b_datap->db_type = M_IOCNAK;	}	qreply(q, mp);}/* * Start output on a line, unless it's busy, frozen, or otherwise. */static voidsimcstart(){	register queue_t *q;	register mblk_t *bp;	register int s;	if ((q = simc_ttycommon.t_writeq) == NULL)		return;		/* not attached to a stream */	s = splzs();	while ((bp = getq(q)) != NULL) {		/*		 * We have a message block to work on.		 */		switch (bp->b_datap->db_type) {		case M_BREAK:		case M_DELAY:		case M_IOCTL:			freemsg(bp);			continue;		default:			do {				register int cc;				register mblk_t *nbp;				cc = bp->b_wptr - bp->b_rptr;				while (cc--) {					/* let input in every 8 chars */					if ((cc % 8) == 7) {						(void) splx(s);						(void) splzs();					}					/*					 * If output is stopped, put it back					 * and try again later.					 */					if (simc_flags & SIMC_STOPPED) {						putbq(q, bp);						(void) splx(s);						return;					}					simcoutc(*bp->b_rptr++);				}				nbp = bp->b_cont;				freeb(bp);				bp = nbp;			} while (bp != NULL);		}	}	(void) splx(s);}/* * Receiver interrupt. */intsimcintr(){	register mblk_t *bp;	register queue_t *q;	/*	 * Send data up the stream if there's somebody listening.	 */	if ((q = simc_ttycommon.t_readq) != NULL) {		if ((bp = allocb(1 , BPRI_MED)) != NULL) {			if (!canput(q->q_next)) {				tty_qfull(q);				freemsg(bp);			} else {				*bp->b_wptr++ = simcinc();				putnext(q, bp);			}		}	} else 		(void) simcinc();}cnputc(c)	register int c;{	if (c == '\n')		simcoutc('\r');	simcoutc(c);}intcngetc(){	return ((int) simcinc());}getchar(){	register c;	c = cngetc();	if (c=='\r')		c = '\n';	cnputc(c);	return (c);}gets(cp)	char *cp;{	register char *lp;	register c;	lp = cp;	for (;;) {		c = getchar() & 0177;		switch (c) {		case '\n':		case '\r':			*lp++ = '\0';			return;		case 0177:			cnputc('\b');		case '\b':		case '#':			lp--;			if (lp < cp)				lp = cp;			continue;		case '@':		case 'u'&037:			lp = cp;			cnputc('\n');			continue;		default:			*lp++ = c;		}	}}

⌨️ 快捷键说明

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