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

📄 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 <sun/autoconf.h>#ifdef PSMP#include <os/mutex.h>#endif PSMP#include <machine/clock.h>#include <machine/mmu.h>#include <machine/cpu.h>#include <machine/intreg.h>#include <sundev/mbvar.h>#include <sys/varargs.h>#define	ISPEED	B9600#define	IFLAGS	(CS7|CREAD|PARENB)int	nsimc = 0;int	console_via_map = 0;int	simcidentify();int	simcattach();int	simcintr();int	simcintr_lowpri();struct dev_ops simc_ops = {	1,	simcidentify,	simcattach,};intsimcidentify(name)	char *name;{	if (strcmp(name, "simc"))		return 0;	nsimc ++;	return 1;}struct simcregs {	unsigned char	data;};#define	SIMC_ISOPEN	0x00000002	/* open is complete */#define	SIMC_STOPPED	0x00000010	/* output is stopped *//* * Fast ring buffer code from zs driver, sorta. */#define	RINGSIZE	256#define	RINGFRAC	2		/* fraction of ring to force flush */#define	RING_INIT	(sc->rput = sc->rget = 0)#define	RING_CNT	((sc->rput - sc->rget))#define	RING_EMPTY	(sc->rput == sc->rget)#define	RING_PUT(c)	(sc->data[sc->rput++] = (u_char)(c))#define	RING_GET	(sc->data[sc->rget++])#define	RING_EAT(n)	(sc->rget += (n))struct simcons {	struct simcregs *regs;	unsigned	flags;	/* random flags */	tty_common_t	tty_common;	unsigned char	rput;	unsigned char	rget;	unsigned char	data[RINGSIZE];}      *simcunits = 0;intsimcattach(dev)	struct dev_info *dev;{	struct simcons *sc;	static int unit = -1;	int nreg, nint, part;	unit ++;	if (!simcunits) {		simcunits = (struct simcons *)			new_kmem_zalloc((u_int)(nsimc * sizeof (struct simcons)),					KMEM_SLEEP);		if (!simcunits) {			printf ("simc: no space for structures\n");			return -1;		}	}	dev->devi_unit = unit;	sc = simcunits + unit;	RING_INIT;	nreg = dev->devi_nreg;	if (nreg != 1) {		printf("simc: regs not specified correctly for unit %d\n",		       unit);		return -1;	}	sc->regs = (struct simcregs *)		map_regs(dev->devi_reg->reg_addr,			 dev->devi_reg->reg_size,			 dev->devi_reg->reg_bustype);	if (!sc->regs) {		printf("simc: unable to map registers\n");		return -1;	}	nint = dev->devi_nintr;	if (nint != 2) {		printf("simc: ints not specified correctly for unit %d\n",		       unit);		return -1;	}	addintr(dev->devi_intr[0].int_pri, simcintr, dev->devi_name, unit);	addintr(dev->devi_intr[1].int_pri, simcintr_lowpri, dev->devi_name, unit);	report_dev(dev);	return 0;}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 char	simxinc();#ifndef	PSMP#define	cpuid	0#else	PSMPextern int cpuid;#endif	PSMP/*ARGSUSED*/static intsimcopen(q, dev, flag, sflag)	register queue_t *q;	dev_t dev;{	register int unit = minor(dev);	register struct simcons *sc = simcunits + unit;	if (unit >= nsimc)		return (OPENFAIL);	if (!(sc->flags & SIMC_ISOPEN)) {		sc->tty_common.t_iflag = 0;		sc->tty_common.t_cflag = (ISPEED << IBSHIFT)|ISPEED|IFLAGS;		sc->flags = SIMC_ISOPEN;	} else if ((sc->tty_common.t_flags & TS_XCLUDE) && (u.u_uid != 0)) {		u.u_error = EBUSY;		return (OPENFAIL);	}	sc->tty_common.t_readq = q;	sc->tty_common.t_writeq = WR(q);	q->q_ptr = WR(q)->q_ptr = (caddr_t)sc;	console_via_map = 1;	return (dev);}static intsimcclose(q)	register queue_t *q;{	struct simcons *sc = (struct simcons *)q->q_ptr;	sc->flags &= ~SIMC_ISOPEN;	ttycommon_close (&sc->tty_common);}/* * 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 struct simcons *sc = (struct simcons *)q->q_ptr;	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.		 */		sc->flags |= SIMC_STOPPED;		freemsg(mp);		break;	case M_START:		if (sc->flags & SIMC_STOPPED) {			sc->flags &= ~SIMC_STOPPED;			simcstart(sc);		}		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(sc);		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;{	struct simcons *sc = simcunits + unit;	queue_t *q;	register mblk_t *mp;	if ((q = sc->tty_common.t_writeq) == NULL)		return;	if ((mp = sc->tty_common.t_iocpending) != NULL) {		sc->tty_common.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 simcons *sc = (struct simcons *)q->q_ptr;	struct iocblk *iocp;	register unsigned datasize;	int error;	int s;	if (sc->tty_common.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(sc->tty_common.t_iocpending);		sc->tty_common.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(&sc->tty_common, q, mp, &error)) != 0) {		sc->tty_common.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(sc)	register struct simcons *sc;{	register queue_t *q;	register mblk_t *bp;	register int s;	register int unit;	if ((q = sc->tty_common.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 (sc->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. * Model the standard serial ports on sun machines * with a two level interrupt handler. */intsimcintr_lowpri(){	mblk_t *bp;	queue_t *q;	char c;	int unit;	struct simcons *sc;	int rv=0;	for (unit=0; unit<nsimc; ++unit) {		sc = simcunits + unit;		while (!RING_EMPTY) {			rv = 1;			c = RING_GET;			/*			 * Send data up the stream if there's somebody listening.			 */			if ((q = sc->tty_common.t_readq) != NULL) {				if ((bp = allocb(1, BPRI_MED)) != NULL) {					if (!canput(q->q_next)) {						ttycommon_qfull(&sc->tty_common, q);						freemsg(bp);					} else {						*bp->b_wptr++ = c;						putnext(q, bp);					}				}			}		}	}	return rv;}/* * High priority interrupt handler. * Read the character and stick in a ringbuffer. */intsimcintr(){	int c, unit, rv=0;	struct simcons *sc;	rv = 0;	for (unit=0; unit<nsimc; ++unit) {		sc = simcunits + unit;		while ((c = sc->regs->data) != 0) { /* %%% null == nothing available */			rv = 1;			RING_PUT(c);			if (RING_EMPTY)				RING_EAT(1); /* overflow, toss ancient character */		}	}	/*	 * handle rest of interrupt processing later, at lower priority,	 * don't fool around with streams buffers at hi priority	 */	if (rv)		send_dirint(cpuid, 6); /* turn on softint level 6 */		return rv;}cnputc(c)	register char c;{	int unit = 0;		/* cnputc goes to unit zero */	struct simcons *sc = simcunits + unit;	if (console_via_map)		sc->regs->data = c;	else		simcoutc(c);	/* use magic-traps if not mapped yet */	if ((c&127) == '\n')		cnputc('\r');}intcngetc(){	int unit = 0;		/* cngetc gets from unit zero */	struct simcons *sc = simcunits + unit;	if (console_via_map)		return sc->regs->data;	return simcinc();	/* use magic-traps if not mapped yet */}getchar(){	register char c;	c = cngetc();	if (c=='\r')		c = '\n';	cnputc(c);	return (c);}gets(cp)	char *cp;{	register char *lp;	register char c;	lp = cp;	while (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;		}	}	*lp++ = '\0';}#ifdef	SHOWSTAGEint	simcshowstartenable = 0;int	simcshowstart_last[4] = { 0, 0, 0, 0 };int	simcshowstart_curr[4] = { 0, 0, 0, 0 };simcshowexit(pp)    register struct proc *pp;{    struct user *up;    int who, pid;    char *cp;    if (!simcshowstartenable)	return;    who = 3 & getprocessorid();    pid = (pp==0) ? -2 : pp->p_pid;    up = (pp==0) ? 0 : pp->p_uarea;    cp = (up==0) ? 0 : up->u_comm;    simcprtf("cpu %d <= pid %d exit %s\n\r",	   who, pid, cp);}simcshowexec(pp)    register struct proc *pp;{    struct user *up;    int who, pid;    char *cp;    if (!simcshowstartenable)	return;    who = 3 & getprocessorid();    pid = (pp==0) ? -2 : pp->p_pid;    up = (pp==0) ? 0 : pp->p_uarea;    cp = (up==0) ? 0 : up->u_comm;    simcprtf("cpu %d <= pid %d exec %s\n\r",	   who, pid, cp);}simcshowstart(pp)    register struct proc *pp;{    struct user *up;    int who, pid, i;    char *cp;    if (!simcshowstartenable)	return;    who = 3 & getprocessorid();    pid = (pp==0) ? -2 : pp->p_pid;    up = (pp==0) ? 0 : pp->p_uarea;    cp = (up==0) ? 0 : up->u_comm;    simcshowstart_curr[who] = pid;    if (simcshowstartenable < 2) {	if (pid < 0)	    return;		/* no report when going idle */	if (simcshowstart_last[who] == pid)	    return;		/* no report if pid did not change */	simcshowstart_last[who] = pid;	if (pid > 0)	    for (i=0; i<4; ++i)		if ((i != who) && (simcshowstart_last[i] == pid))		    if (simcshowstart_curr[i] == pid)			simcprtf("cpu %d <= pid %d, DUPLICATED\n\r", i, pid);		    else {			simcprtf("cpu %d <= pid %d (%d MIGRATED)\n\r",				 i, simcshowstart_curr[i], pid);			simcshowstart_last[i] = simcshowstart_curr[i];		    }    }    simcprtf("cpu %d <= pid %d command %s\n\r",	   who, pid, cp);}simcouts(s)	char *s;{	int ch;	while (ch = *s++)		simcoutc(ch);}simcouti(i, b)	unsigned int i;	unsigned int b;{	char	ibuf[16], *p;	if ((b == 10) && (i & 0x80000000)) {		simcoutc('-');		i = 1 + ~i;	}	p = ibuf+b;	*--p = 0;	do {		*--p = "0123456789ABCDEF"[i%b];		i /= b;	} while (i>0);	simcouts(p);}intisdigit(c)int c;{    return (c >= '0') && (c <= '9');}#ifdef	PSMPmutex_t	simcprflock[1];int	simcprflockinit = 0;#endif	PSMPsimcprtf(fmt, va_alist)    char *fmt;    va_dcl{    int width, altfmt, sign, val, base, ch;    va_list x1;#ifdef PSMP    if (!simcprflockinit) {	mutex_init (simcprflock, 15, (void *)0);	simcprflockinit = 1;    }    mutex_enter (simcprflock);#endif    va_start(x1);    while (ch = *fmt++) {	if (ch != '%') {	    simcoutc(ch);	    continue;	}	width = altfmt = sign = 0;	if (*fmt == '0') {	    fmt++;	    altfmt = 1;	}	while (*fmt && isdigit (*fmt)) {	    ch = *fmt++;	    width = width * 10 + ch - '0';	}	if (!*fmt) {	    simcoutc('%');	    break;	}	switch (ch = *fmt++) {	  case 'o':	    base = 8;	    val = va_arg (x1, int);	    if (altfmt && val)		simcoutc('0');	    goto basecommon;	  case 'd':	    base = 10;	    val = va_arg (x1, int);	    goto basecommon;	  case 'x':	    base = 16;	    val = va_arg (x1, int);	    if (altfmt && val)		simcouts("0x");	  basecommon:	    simcouti (val, base);	    break;	  case 'c':	    simcoutc(va_arg (x1, int));	    break;	  case 's':	    simcouts(va_arg (x1, char *));	    break;	  case '%':	    simcoutc('%');	    break;	  default:	    simcoutc('%');	    simcoutc(ch);	    break;	}    }    va_end(x1);#ifdef PSMP    mutex_exit (simcprflock);#endif}#endif STAGE

⌨️ 快捷键说明

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