sys/sparc/dev/zs.c
/*
 * ZS software interrupt.  Scan all channels for deferred interrupts.
 */
ZS software interrupt.  Scan all channels for deferred interrupts.
ZS software interrupt . Scan all channels for deferred interrupts .
int
zssoft(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;	
		if (get == n)		
			continue;
		unit = cs->cs_unit;	
		zc = cs->cs_zc;
		tp = cs->cs_ttyp;
		line = &linesw[tp->t_line];
		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) {
			c = cs->cs_rbuf[get++ & ZLRB_RING_MASK];
			switch (ZRING_TYPE(c)) {
			case ZRING_RINT:
				c = ZRING_VALUE(c);
				if (c & ZSRR1_DO)
					zsoverrun(unit, &cs->cs_fotime, "fifo");
				cc = c >> 8;
				if (c & ZSRR1_FE)
					cc |= TTY_FE;
				if (c & ZSRR1_PE)
					cc |= TTY_PE;
				if (unit == ZS_KBD)
					kbd_rint(cc);
				else if (unit == ZS_MOUSE)
					ms_rint(cc);
				else
					line->l_rint(cc, tp);
				break;
			case ZRING_XINT:
				if (cs->cs_heldchange) {
					s = splzs();
					c = zc->zc_csr;
					if ((c & ZSRR0_DCD) == 0)
						cs->cs_preg[3] &= ~ZSWR3_HFC;
					bcopy((caddr_t)cs->cs_preg,
					    (caddr_t)cs->cs_creg, 16);
					zs_loadchannelregs(zc, cs->cs_creg);
					splx(s);
					cs->cs_heldchange = 0;
					if (cs->cs_heldtbc &&
					    (tp->t_state & TS_TTSTOP) == 0) {
						cs->cs_tbc = cs->cs_heldtbc - 1;
						zc->zc_data = *cs->cs_tba++;
						goto again;
					}
				}
				tp->t_state &= ~TS_BUSY;
				if (tp->t_state & TS_FLUSH)
					tp->t_state &= ~TS_FLUSH;
				else
					ndflush(&tp->t_outq,
					    cs->cs_tba - tp->t_outq.c_cf);
				line->l_start(tp);
				break;
			case ZRING_SINT:
				c = ZRING_VALUE(c);
				if ((c ^ cs->cs_rr0) & ZSRR0_DCD) {
					cc = (c & ZSRR0_DCD) != 0;
					if (line->l_modem(tp, cc) == 0)
						zs_modem(cs, cc);
				}
				cs->cs_rr0 = c;
				break;
			default:
				log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n",
				    unit >> 1, (unit & 1) + 'a', c);
				break;
			}
		}
		cs->cs_rbget = get;
		goto again;
	}
	return (1);
}
int zssoft ( 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 ; if ( get == n ) continue ; unit = cs -> cs_unit ; zc = cs -> cs_zc ; tp = cs -> cs_ttyp ; line = & linesw [ tp -> t_line ] ; n -= get ; if ( n > ZLRB_RING_SIZE ) { zsoverrun ( unit , & cs -> cs_rotime , " " ) ; get += n - ZLRB_RING_SIZE ; n = ZLRB_RING_SIZE ; } while ( -- n >= 0 ) { c = cs -> cs_rbuf [ get ++ & ZLRB_RING_MASK ] ; switch ( ZRING_TYPE ( c ) ) { case ZRING_RINT : c = ZRING_VALUE ( c ) ; if ( c & ZSRR1_DO ) zsoverrun ( unit , & cs -> cs_fotime , " " ) ; cc = c >> 8 ; if ( c & ZSRR1_FE ) cc |= TTY_FE ; if ( c & ZSRR1_PE ) cc |= TTY_PE ; if ( unit == ZS_KBD ) kbd_rint ( cc ) ; else if ( unit == ZS_MOUSE ) ms_rint ( cc ) ; else line -> l_rint ( cc , tp ) ; break ; case ZRING_XINT : if ( cs -> cs_heldchange ) { s = splzs ( ) ; c = zc -> zc_csr ; if ( ( c & ZSRR0_DCD ) == 0 ) cs -> cs_preg [ 3 ] &= ~ ZSWR3_HFC ; bcopy ( ( caddr_t ) cs -> cs_preg , ( caddr_t ) cs -> cs_creg , 16 ) ; zs_loadchannelregs ( zc , cs -> cs_creg ) ; splx ( s ) ; cs -> cs_heldchange = 0 ; if ( cs -> cs_heldtbc && ( tp -> t_state & TS_TTSTOP ) == 0 ) { cs -> cs_tbc = cs -> cs_heldtbc - 1 ; zc -> zc_data = * cs -> cs_tba ++ ; goto again ; } } tp -> t_state &= ~ TS_BUSY ; if ( tp -> t_state & TS_FLUSH ) tp -> t_state &= ~ TS_FLUSH ; else ndflush ( & tp -> t_outq , cs -> cs_tba - tp -> t_outq . c_cf ) ; line -> l_start ( tp ) ; break ; case ZRING_SINT : c = ZRING_VALUE ( c ) ; if ( ( c ^ cs -> cs_rr0 ) & ZSRR0_DCD ) { cc = ( c & ZSRR0_DCD ) != 0 ; if ( line -> l_modem ( tp , cc ) == 0 ) zs_modem ( cs , cc ) ; } cs -> cs_rr0 = c ; break ; default : log ( LOG_ERR , " \n " , unit >> 1 , ( unit & 1 ) + ' ' , c ) ; break ; } } cs -> cs_rbget = get ; goto again ; } return ( 1 ) ; }
ZS software interrupt.
ZS software interrupt .
/* atomic */ /* nothing more on this line */ /* set up to handle interrupts */ /*
		 * 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).
		 */ /* race to keep ahead of incoming interrupts */ /*
				 * this should be done through
				 * bstreams	XXX gag choke
				 */ /*
				 * Transmit done: change registers and resume,
				 * or clear BUSY.
				 */ /*
				 * Status line change.  HFC bit is run in
				 * hardware interrupt, to avoid locking
				 * at splzs here.
				 */