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

📄 zs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	    zi->zi_dev.dv_xname, (unit & 1) + 'a', i ? (o ? "i/o" : i) : o);	cs->cs_consio = 1;	cs->cs_brkabort = 1;	return (tp);}#ifdef KGDB/* * The kgdb zs port, if any, was altered at boot time (see zs_kgdb_init). * Pick up the current speed and character size and restore the original * speed. */static voidzs_checkkgdb(int unit, struct zs_chanstate *cs, struct tty *tp){	if (kgdb_dev == makedev(ZSMAJOR, unit)) {		tp->t_ispeed = tp->t_ospeed = kgdb_rate;		tp->t_cflag = CS8;		cs->cs_kgdb = 1;		cs->cs_speed = zs_kgdb_savedspeed;		(void) zsparam(tp, &tp->t_termios);	}}#endif/* * Compute the current baud rate given a ZSCC channel. */static intzs_getspeed(zc)	register volatile struct zschan *zc;{	register int tconst;	tconst = ZS_READ(zc, 12);	tconst |= ZS_READ(zc, 13) << 8;	return (TCONST_TO_BPS(PCLK / 16, tconst));}/* * Do an internal open. */static voidzsiopen(struct tty *tp){	(void) zsparam(tp, &tp->t_termios);	ttsetwater(tp);	tp->t_state = TS_ISOPEN | TS_CARR_ON;}/* * Do an internal close.  Eventually we should shut off the chip when both * ports on it are closed. */static voidzsiclose(struct tty *tp){	ttylclose(tp, 0);	/* ??? */	ttyclose(tp);		/* ??? */	tp->t_state = 0;}/* * Open a zs serial port.  This interface may not be used to open * the keyboard and mouse ports. (XXX) */intzsopen(dev_t dev, int flags, int mode, struct proc *p){	register struct tty *tp;	register struct zs_chanstate *cs;	struct zsinfo *zi;	int unit = minor(dev), zs = unit >> 1, error, s;	if (zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL ||	    unit == ZS_KBD || unit == ZS_MOUSE)		return (ENXIO);	cs = &zi->zi_cs[unit & 1];	if (cs->cs_consio)		return (ENXIO);		/* ??? */	tp = cs->cs_ttyp;	s = spltty();	if ((tp->t_state & TS_ISOPEN) == 0) {		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 = cs->cs_speed;		}		(void) zsparam(tp, &tp->t_termios);		ttsetwater(tp);	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {		splx(s);		return (EBUSY);	}	error = 0;	for (;;) {		/* loop, turning on the device, until carrier present */		zs_modem(cs, 1);		if (cs->cs_softcar)			tp->t_state |= TS_CARR_ON;		if (flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||		    tp->t_state & TS_CARR_ON)			break;		tp->t_state |= TS_WOPEN;		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,		    ttopen, 0))			break;	}	splx(s);	if (error == 0)		error = linesw[tp->t_line].l_open(dev, tp);	if (error)		zs_modem(cs, 0);	return (error);}/* * Close a zs serial port. */intzsclose(dev_t dev, int flags, int mode, struct proc *p){	register struct zs_chanstate *cs;	register struct tty *tp;	struct zsinfo *zi;	int unit = minor(dev), s;	zi = zscd.cd_devs[unit >> 1];	cs = &zi->zi_cs[unit & 1];	tp = cs->cs_ttyp;	linesw[tp->t_line].l_close(tp, flags);	if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||	    (tp->t_state & TS_ISOPEN) == 0) {		zs_modem(cs, 0);		/* hold low for 1 second */		(void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);	}	ttyclose(tp);#ifdef KGDB	/* Reset the speed if we're doing kgdb on this port */	if (cs->cs_kgdb) {		tp->t_ispeed = tp->t_ospeed = kgdb_rate;		(void) zsparam(tp, &tp->t_termios);	}#endif	return (0);}/* * Read/write zs serial port. */intzsread(dev_t dev, struct uio *uio, int flags){	register struct tty *tp = &zs_tty[minor(dev)];	return (linesw[tp->t_line].l_read(tp, uio, flags));}intzswrite(dev_t dev, struct uio *uio, int flags){	register struct tty *tp = &zs_tty[minor(dev)];	return (linesw[tp->t_line].l_write(tp, uio, flags));}/* * ZS hardware interrupt.  Scan all ZS channels.  NB: we know here that * channels are kept in (A,B) pairs. * * Do just a little, then get out; set a software interrupt if more * work is needed. * * We deliberately ignore the vectoring Zilog gives us, and match up * only the number of `reset interrupt under service' operations, not * the order. *//* ARGSUSED */intzshard(void *intrarg){	register struct zs_chanstate *a;#define	b (a + 1)	register volatile struct zschan *zc;	register int rr3, intflags = 0, v, i;	static int zsrint(struct zs_chanstate *, volatile struct zschan *);	static int zsxint(struct zs_chanstate *, volatile struct zschan *);	static int zssint(struct zs_chanstate *, volatile struct zschan *);	for (a = zslist; a != NULL; a = b->cs_next) {		rr3 = ZS_READ(a->cs_zc, 3);		if (rr3 & (ZSRR3_IP_A_RX|ZSRR3_IP_A_TX|ZSRR3_IP_A_STAT)) {			intflags |= 2;			zc = a->cs_zc;			i = a->cs_rbput;			if (rr3 & ZSRR3_IP_A_RX && (v = zsrint(a, zc)) != 0) {				a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			if (rr3 & ZSRR3_IP_A_TX && (v = zsxint(a, zc)) != 0) {				a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			if (rr3 & ZSRR3_IP_A_STAT && (v = zssint(a, zc)) != 0) {				a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			a->cs_rbput = i;		}		if (rr3 & (ZSRR3_IP_B_RX|ZSRR3_IP_B_TX|ZSRR3_IP_B_STAT)) {			intflags |= 2;			zc = b->cs_zc;			i = b->cs_rbput;			if (rr3 & ZSRR3_IP_B_RX && (v = zsrint(b, zc)) != 0) {				b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			if (rr3 & ZSRR3_IP_B_TX && (v = zsxint(b, zc)) != 0) {				b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			if (rr3 & ZSRR3_IP_B_STAT && (v = zssint(b, zc)) != 0) {				b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;				intflags |= 1;			}			b->cs_rbput = i;		}	}#undef b	if (intflags & 1) {#if sun4c /* XXX -- but this will go away when zshard moves to locore.s */		struct clockframe *p = intrarg;		if ((p->psr & PSR_PIL) < (PIL_TTY << 8)) {			zsshortcuts++;			(void) spltty();			if (zshardscope) {				LED_ON;				LED_OFF;			}			return (zssoft(intrarg));		}#endif		ienab_bis(IE_ZSSOFT);	}	return (intflags & 2);}static intzsrint(register struct zs_chanstate *cs, register volatile struct zschan *zc){	register int c = zc->zc_data;	if (cs->cs_conk) {		register struct conk_state *conk = &zsconk_state;		/*		 * Check here for console abort function, so that we		 * can abort even when interrupts are locking up the		 * machine.		 */		if (c == KBD_RESET) {			conk->conk_id = 1;	/* ignore next byte */			conk->conk_l1 = 0;		} else if (conk->conk_id)			conk->conk_id = 0;	/* stop ignoring bytes */		else if (c == KBD_L1)			conk->conk_l1 = 1;	/* L1 went down */		else if (c == (KBD_L1|KBD_UP))			conk->conk_l1 = 0;	/* L1 went up */		else if (c == KBD_A && conk->conk_l1) {			zsabort();			conk->conk_l1 = 0;	/* we never see the up */			goto clearit;		/* eat the A after L1-A */		}	}#ifdef KGDB	if (c == FRAME_START && cs->cs_kgdb && 	    (cs->cs_ttyp->t_state & TS_ISOPEN) == 0) {		zskgdb(cs->cs_unit);		goto clearit;	}#endif	/* compose receive character and status */	c <<= 8;	c |= ZS_READ(zc, 1);	/* clear receive error & interrupt condition */	zc->zc_csr = ZSWR0_RESET_ERRORS;	zc->zc_csr = ZSWR0_CLR_INTR;	return (ZRING_MAKE(ZRING_RINT, c));clearit:	zc->zc_csr = ZSWR0_RESET_ERRORS;	zc->zc_csr = ZSWR0_CLR_INTR;	return (0);}static intzsxint(register struct zs_chanstate *cs, register volatile struct zschan *zc){	register int i = cs->cs_tbc;	if (i == 0) {		zc->zc_csr = ZSWR0_RESET_TXINT;		zc->zc_csr = ZSWR0_CLR_INTR;		return (ZRING_MAKE(ZRING_XINT, 0));	}	cs->cs_tbc = i - 1;	zc->zc_data = *cs->cs_tba++;	zc->zc_csr = ZSWR0_CLR_INTR;	return (0);}static intzssint(register struct zs_chanstate *cs, register volatile struct zschan *zc){	register int rr0;	rr0 = zc->zc_csr;	zc->zc_csr = ZSWR0_RESET_STATUS;	zc->zc_csr = ZSWR0_CLR_INTR;	/*	 * The chip's hardware flow control is, as noted in zsreg.h,	 * busted---if the DCD line goes low the chip shuts off the	 * receiver (!).  If we want hardware CTS flow control but do	 * not have it, and carrier is now on, turn HFC on; if we have	 * HFC now but carrier has gone low, turn it off.	 */	if (rr0 & ZSRR0_DCD) {		if (cs->cs_ttyp->t_cflag & CCTS_OFLOW &&		    (cs->cs_creg[3] & ZSWR3_HFC) == 0) {			cs->cs_creg[3] |= ZSWR3_HFC;			ZS_WRITE(zc, 3, cs->cs_creg[3]);		}	} else {		if (cs->cs_creg[3] & ZSWR3_HFC) {			cs->cs_creg[3] &= ~ZSWR3_HFC;			ZS_WRITE(zc, 3, cs->cs_creg[3]);		}	}	if ((rr0 & ZSRR0_BREAK) && cs->cs_brkabort) {		zsabort();		return (0);	}	return (ZRING_MAKE(ZRING_SINT, rr0));}zsabort(){	printf("stopping on keyboard abort\n");	callrom();}#ifdef KGDB/* * KGDB framing character received: enter kernel debugger.  This probably * should time out after a few seconds to avoid hanging on spurious input. */zskgdb(int unit){	printf("zs%d%c: kgdb interrupt\n", unit >> 1, (unit & 1) + 'a');	kgdb_connect(1);}#endif/* * Print out a ring or fifo overrun error message. */static voidzsoverrun(int unit, long *ptime, char *what){	if (*ptime != time.tv_sec) {		*ptime = time.tv_sec;		log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1,		    (unit & 1) + 'a', what);	}}/* * ZS software interrupt.  Scan all channels for deferred interrupts. */intzssoft(void *arg){	register struct zs_chanstate *cs;	register volatile struct zschan *zc;	register struct linesw *line;	register struct tty *tp;	register int get, n, c, cc, unit, s;	for (cs = zslist; cs != NULL; cs = cs->cs_next) {		get = cs->cs_rbget;again:		n = cs->cs_rbput;	/* atomic */		if (get == n)		/* nothing more on this line */			continue;		unit = cs->cs_unit;	/* set up to handle interrupts */		zc = cs->cs_zc;		tp = cs->cs_ttyp;		line = &linesw[tp->t_line];		/*		 * Compute the number of interrupts in the receive ring.		 * If the count is overlarge, we lost some events, and		 * must advance to the first valid one.  It may get		 * overwritten if more data are arriving, but this is		 * too expensive to check and gains nothing (we already		 * lost out; all we can do at this point is trade one		 * kind of loss for another).		 */		n -= get;		if (n > ZLRB_RING_SIZE) {			zsoverrun(unit, &cs->cs_rotime, "ring");			get += n - ZLRB_RING_SIZE;			n = ZLRB_RING_SIZE;		}		while (--n >= 0) {			/* race to keep ahead of incoming interrupts */

⌨️ 快捷键说明

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