Home | History | Annotate | Line # | Download | only in ic
z8530tty.c revision 1.7
      1 /*	$NetBSD: z8530tty.c,v 1.7 1996/05/17 19:30:37 gwr Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994 Gordon W. Ross
      5  * Copyright (c) 1992, 1993
      6  *	The Regents of the University of California.  All rights reserved.
      7  *
      8  * This software was developed by the Computer Systems Engineering group
      9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     10  * contributed to Berkeley.
     11  *
     12  * All advertising materials mentioning features or use of this software
     13  * must display the following acknowledgement:
     14  *	This product includes software developed by the University of
     15  *	California, Lawrence Berkeley Laboratory.
     16  *
     17  * Redistribution and use in source and binary forms, with or without
     18  * modification, are permitted provided that the following conditions
     19  * are met:
     20  * 1. Redistributions of source code must retain the above copyright
     21  *    notice, this list of conditions and the following disclaimer.
     22  * 2. Redistributions in binary form must reproduce the above copyright
     23  *    notice, this list of conditions and the following disclaimer in the
     24  *    documentation and/or other materials provided with the distribution.
     25  * 3. All advertising materials mentioning features or use of this software
     26  *    must display the following acknowledgement:
     27  *	This product includes software developed by the University of
     28  *	California, Berkeley and its contributors.
     29  * 4. Neither the name of the University nor the names of its contributors
     30  *    may be used to endorse or promote products derived from this software
     31  *    without specific prior written permission.
     32  *
     33  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     43  * SUCH DAMAGE.
     44  *
     45  *	@(#)zs.c	8.1 (Berkeley) 7/19/93
     46  */
     47 
     48 /*
     49  * Zilog Z8530 Dual UART driver (tty interface)
     50  *
     51  * This is the "slave" driver that will be attached to
     52  * the "zsc" driver for plain "tty" async. serial lines.
     53  */
     54 
     55 #include <sys/param.h>
     56 #include <sys/systm.h>
     57 #include <sys/proc.h>
     58 #include <sys/device.h>
     59 #include <sys/conf.h>
     60 #include <sys/file.h>
     61 #include <sys/ioctl.h>
     62 #include <sys/malloc.h>
     63 #include <sys/tty.h>
     64 #include <sys/time.h>
     65 #include <sys/kernel.h>
     66 #include <sys/syslog.h>
     67 
     68 #include <dev/ic/z8530reg.h>
     69 #include <machine/z8530var.h>
     70 
     71 #ifdef KGDB
     72 extern int zs_check_kgdb();
     73 #endif
     74 
     75 /*
     76  * Allow the MD var.h to override the default CFLAG so that
     77  * console messages during boot come out with correct parity.
     78  */
     79 #ifndef	ZSTTY_DEF_CFLAG
     80 #define	ZSTTY_DEF_CFLAG	TTYDEF_CFLAG
     81 #endif
     82 
     83 /*
     84  * How many input characters we can buffer.
     85  * The port-specific var.h may override this.
     86  * Note: must be a power of two!
     87  */
     88 #ifndef	ZSTTY_RING_SIZE
     89 #define	ZSTTY_RING_SIZE	2048
     90 #endif
     91 
     92 /*
     93  * Make this an option variable one can patch.
     94  * But be warned:  this must be a power of 2!
     95  */
     96 int zstty_rbuf_size = ZSTTY_RING_SIZE;
     97 
     98 struct zstty_softc {
     99 	struct	device zst_dev;		/* required first: base device */
    100 	struct  tty *zst_tty;
    101 	struct	zs_chanstate *zst_cs;
    102 
    103 	int zst_hwflags;	/* see z8530var.h */
    104 	int zst_swflags;	/* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
    105 
    106 	/* Flags to communicate with zstty_softint() */
    107 	volatile int zst_intr_flags;
    108 #define	INTR_RX_OVERRUN 1
    109 #define INTR_TX_EMPTY   2
    110 #define INTR_ST_CHECK   4
    111 
    112 	/*
    113 	 * The transmit byte count and address are used for pseudo-DMA
    114 	 * output in the hardware interrupt code.  PDMA can be suspended
    115 	 * to get pending changes done; heldtbc is used for this.  It can
    116 	 * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
    117 	 */
    118 	int 	zst_tbc;			/* transmit byte count */
    119 	caddr_t	zst_tba;			/* transmit buffer address */
    120 	int 	zst_heldtbc;		/* held tbc while xmission stopped */
    121 
    122 	/*
    123 	 * Printing an overrun error message often takes long enough to
    124 	 * cause another overrun, so we only print one per second.
    125 	 */
    126 	long	zst_rotime;		/* time of last ring overrun */
    127 	long	zst_fotime;		/* time of last fifo overrun */
    128 
    129 	/*
    130 	 * The receive ring buffer.
    131 	 */
    132 	u_int	zst_rbget;	/* ring buffer `get' index */
    133 	volatile u_int	zst_rbput;	/* ring buffer `put' index */
    134 	u_int	zst_ringmask;
    135 	u_short	*zst_rbuf; /* rr1, data pairs */
    136 };
    137 
    138 
    139 /* Definition of the driver for autoconfig. */
    140 static int	zstty_match(struct device *, void *, void *);
    141 static void	zstty_attach(struct device *, struct device *, void *);
    142 
    143 struct cfattach zstty_ca = {
    144 	sizeof(struct zstty_softc), zstty_match, zstty_attach
    145 };
    146 
    147 struct cfdriver zstty_cd = {
    148 	NULL, "zstty", DV_TTY
    149 };
    150 
    151 struct zsops zsops_tty;
    152 
    153 /* Routines called from other code. */
    154 cdev_decl(zs);	/* open, close, read, write, ioctl, stop, ... */
    155 
    156 static void	zsstart(struct tty *);
    157 static int	zsparam(struct tty *, struct termios *);
    158 static void zs_modem(struct zstty_softc *zst, int onoff);
    159 
    160 /*
    161  * zstty_match: how is this zs channel configured?
    162  */
    163 int
    164 zstty_match(parent, match, aux)
    165 	struct device *parent;
    166 	void   *match, *aux;
    167 {
    168 	struct cfdata *cf = match;
    169 	struct zsc_attach_args *args = aux;
    170 
    171 	/* Exact match is better than wildcard. */
    172 	if (cf->cf_loc[0] == args->channel)
    173 		return 2;
    174 
    175 	/* This driver accepts wildcard. */
    176 	if (cf->cf_loc[0] == -1)
    177 		return 1;
    178 
    179 	return 0;
    180 }
    181 
    182 void
    183 zstty_attach(parent, self, aux)
    184 	struct device *parent, *self;
    185 	void   *aux;
    186 
    187 {
    188 	struct zsc_softc *zsc = (void *) parent;
    189 	struct zstty_softc *zst = (void *) self;
    190 	struct zsc_attach_args *args = aux;
    191 	struct zs_chanstate *cs;
    192 	struct cfdata *cf;
    193 	struct tty *tp;
    194 	int channel, tty_unit;
    195 	dev_t dev;
    196 
    197 	cf = zst->zst_dev.dv_cfdata;
    198 	tty_unit = zst->zst_dev.dv_unit;
    199 	channel = args->channel;
    200 	cs = &zsc->zsc_cs[channel];
    201 	cs->cs_private = zst;
    202 	cs->cs_ops = &zsops_tty;
    203 
    204 	zst->zst_cs = cs;
    205 	zst->zst_swflags = cf->cf_flags;	/* softcar, etc. */
    206 	zst->zst_hwflags = args->hwflags;
    207 	dev = makedev(ZSTTY_MAJOR, tty_unit);
    208 
    209 	if (zst->zst_swflags)
    210 		printf(" flags 0x%x", zst->zst_swflags);
    211 
    212 	if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
    213 		printf(" (console)");
    214 	else {
    215 #ifdef KGDB
    216 		/*
    217 		 * Allow kgdb to "take over" this port.  If this port is
    218 		 * NOT the kgdb port, zs_check_kgdb() will return zero.
    219 		 * If it IS the kgdb port, it will print "kgdb,...\n"
    220 		 * and then return non-zero.
    221 		 */
    222 		if (zs_check_kgdb(cs, dev)) {
    223 			/*
    224 			 * This is the kgdb port (exclusive use)
    225 			 * so skip the normal attach code.
    226 			 */
    227 			return;
    228 		}
    229 #endif
    230 	}
    231 	printf("\n");
    232 
    233 	tp = ttymalloc();
    234 	tp->t_dev = dev;
    235 	tp->t_oproc = zsstart;
    236 	tp->t_param = zsparam;
    237 
    238 	zst->zst_tty = tp;
    239 	zst->zst_ringmask = zstty_rbuf_size - 1;
    240 	zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
    241 			      M_DEVBUF, M_WAITOK);
    242 
    243 	/*
    244 	 * Hardware init
    245 	 */
    246 	if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) {
    247 		/* This unit is the console. */
    248 		zst->zst_swflags |= TIOCFLAG_SOFTCAR;
    249 		/* Call _param so interrupts get enabled. */
    250 		cs->cs_defspeed = zs_getspeed(cs);
    251 		tp->t_ispeed = cs->cs_defspeed;
    252 		tp->t_ospeed = cs->cs_defspeed;
    253 		tp->t_cflag = ZSTTY_DEF_CFLAG;
    254 		(void) zsparam(tp, &tp->t_termios);
    255 	} else {
    256 		/* Not the console; may need reset. */
    257 		int reset, s;
    258 		reset = (channel == 0) ?
    259 			ZSWR9_A_RESET : ZSWR9_B_RESET;
    260 		s = splzs();
    261 		zs_write_reg(cs, 9, reset);
    262 		splx(s);
    263 	}
    264 
    265 	/*
    266 	 * Initialize state of modem control lines (DTR).
    267 	 * If softcar is set, turn on DTR now and leave it.
    268 	 * otherwise, turn off DTR now, and raise in open.
    269 	 * (Keeps modem from answering too early.)
    270 	 */
    271 	zs_modem(zst, (zst->zst_swflags & TIOCFLAG_SOFTCAR) ? 1 : 0);
    272 }
    273 
    274 
    275 /*
    276  * Return pointer to our tty.
    277  */
    278 struct tty *
    279 zstty(dev)
    280 	dev_t dev;
    281 {
    282 	struct zstty_softc *zst;
    283 	int unit = minor(dev);
    284 
    285 #ifdef	DIAGNOSTIC
    286 	if (unit >= zstty_cd.cd_ndevs)
    287 		panic("zstty");
    288 #endif
    289 	zst = zstty_cd.cd_devs[unit];
    290 	return (zst->zst_tty);
    291 }
    292 
    293 
    294 /*
    295  * Open a zs serial (tty) port.
    296  */
    297 int
    298 zsopen(dev, flags, mode, p)
    299 	dev_t dev;
    300 	int flags;
    301 	int mode;
    302 	struct proc *p;
    303 {
    304 	register struct tty *tp;
    305 	register struct zs_chanstate *cs;
    306 	struct zstty_softc *zst;
    307 	int error, s, unit;
    308 
    309 	unit = minor(dev);
    310 	if (unit >= zstty_cd.cd_ndevs)
    311 		return (ENXIO);
    312 	zst = zstty_cd.cd_devs[unit];
    313 	if (zst == NULL)
    314 		return (ENXIO);
    315 	tp = zst->zst_tty;
    316 	cs = zst->zst_cs;
    317 
    318 	/* If KGDB took the line, then tp==NULL */
    319 	if (tp == NULL)
    320 		return (EBUSY);
    321 
    322 	/* It's simpler to do this up here. */
    323 	if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE))
    324 	     ==             (TS_ISOPEN | TS_XCLUDE))
    325 	    && (p->p_ucred->cr_uid != 0) )
    326 	{
    327 		return (EBUSY);
    328 	}
    329 
    330 	s = spltty();
    331 
    332 	if ((tp->t_state & TS_ISOPEN) == 0) {
    333 		/* First open. */
    334 		ttychars(tp);
    335 		tp->t_iflag = TTYDEF_IFLAG;
    336 		tp->t_oflag = TTYDEF_OFLAG;
    337 		tp->t_cflag = ZSTTY_DEF_CFLAG;
    338 		if (zst->zst_swflags & TIOCFLAG_CLOCAL)
    339 			tp->t_cflag |= CLOCAL;
    340 		if (zst->zst_swflags & TIOCFLAG_CRTSCTS)
    341 			tp->t_cflag |= CRTSCTS;
    342 		if (zst->zst_swflags & TIOCFLAG_MDMBUF)
    343 			tp->t_cflag |= MDMBUF;
    344 		tp->t_lflag = TTYDEF_LFLAG;
    345 		tp->t_ispeed = tp->t_ospeed = cs->cs_defspeed;
    346 		(void) zsparam(tp, &tp->t_termios);
    347 		ttsetwater(tp);
    348 		/* Flush any pending input. */
    349 		zst->zst_rbget = zst->zst_rbput;
    350 		zs_iflush(cs);	/* XXX */
    351 		/* Turn on DTR */
    352 		zs_modem(zst, 1);
    353 		if (zst->zst_swflags & TIOCFLAG_SOFTCAR) {
    354 			tp->t_state |= TS_CARR_ON;
    355 		}
    356 	}
    357 	error = 0;
    358 
    359 	/* Wait for carrier. */
    360 	for (;;) {
    361 
    362 		/* Might never get status intr if carrier already on. */
    363 		cs->cs_rr0 = zs_read_csr(cs);
    364 		if (cs->cs_rr0 & ZSRR0_DCD) {
    365 			tp->t_state |= TS_CARR_ON;
    366 			break;
    367 		}
    368 
    369 		if ((tp->t_state & TS_CARR_ON) ||
    370 		    (tp->t_cflag & CLOCAL) ||
    371 		    (flags & O_NONBLOCK) )
    372 		{
    373 			break;
    374 		}
    375 
    376 		tp->t_state |= TS_WOPEN;
    377 		error = ttysleep(tp, (caddr_t)&tp->t_rawq,
    378 			TTIPRI | PCATCH, ttopen, 0);
    379 		if (error) {
    380 			if ((tp->t_state & TS_ISOPEN) == 0) {
    381 				/* Never get here with softcar */
    382 				zs_modem(zst, 0);
    383 				tp->t_state &= ~TS_WOPEN;
    384 				ttwakeup(tp);
    385 			}
    386 			break;
    387 		}
    388 	}
    389 
    390 	splx(s);
    391 
    392 	if (error == 0)
    393 		error = linesw[tp->t_line].l_open(dev, tp);
    394 
    395 	return (error);
    396 }
    397 
    398 /*
    399  * Close a zs serial port.
    400  */
    401 int
    402 zsclose(dev, flags, mode, p)
    403 	dev_t dev;
    404 	int flags;
    405 	int mode;
    406 	struct proc *p;
    407 {
    408 	struct zstty_softc *zst;
    409 	register struct zs_chanstate *cs;
    410 	register struct tty *tp;
    411 	struct zsinfo *zi;
    412 	int hup, s;
    413 
    414 	zst = zstty_cd.cd_devs[minor(dev)];
    415 	cs = zst->zst_cs;
    416 	tp = zst->zst_tty;
    417 
    418 	/* XXX This is for cons.c. */
    419 	if ((tp->t_state & TS_ISOPEN) == 0)
    420 		return 0;
    421 
    422 	(*linesw[tp->t_line].l_close)(tp, flags);
    423 	hup = tp->t_cflag & HUPCL;
    424 	if (zst->zst_swflags & TIOCFLAG_SOFTCAR)
    425 		hup = 0;
    426 	if (hup) {
    427 		zs_modem(zst, 0);
    428 		/* hold low for 1 second */
    429 		(void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
    430 	}
    431 	if (cs->cs_creg[5] & ZSWR5_BREAK) {
    432 		zs_break(cs, 0);
    433 	}
    434 	/* XXX - turn off interrupts? */
    435 
    436 	ttyclose(tp);
    437 	return (0);
    438 }
    439 
    440 /*
    441  * Read/write zs serial port.
    442  */
    443 int
    444 zsread(dev, uio, flags)
    445 	dev_t dev;
    446 	struct uio *uio;
    447 	int flags;
    448 {
    449 	register struct zstty_softc *zst;
    450 	register struct tty *tp;
    451 
    452 	zst = zstty_cd.cd_devs[minor(dev)];
    453 	tp = zst->zst_tty;
    454 	return (linesw[tp->t_line].l_read(tp, uio, flags));
    455 }
    456 
    457 int
    458 zswrite(dev, uio, flags)
    459 	dev_t dev;
    460 	struct uio *uio;
    461 	int flags;
    462 {
    463 	register struct zstty_softc *zst;
    464 	register struct tty *tp;
    465 
    466 	zst = zstty_cd.cd_devs[minor(dev)];
    467 	tp = zst->zst_tty;
    468 	return (linesw[tp->t_line].l_write(tp, uio, flags));
    469 }
    470 
    471 #define TIOCFLAG_ALL (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | \
    472                       TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF )
    473 
    474 int
    475 zsioctl(dev, cmd, data, flag, p)
    476 	dev_t dev;
    477 	u_long cmd;
    478 	caddr_t data;
    479 	int flag;
    480 	struct proc *p;
    481 {
    482 	register struct zstty_softc *zst;
    483 	register struct zs_chanstate *cs;
    484 	register struct tty *tp;
    485 	register int error, tmp;
    486 
    487 	zst = zstty_cd.cd_devs[minor(dev)];
    488 	cs = zst->zst_cs;
    489 	tp = zst->zst_tty;
    490 
    491 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    492 	if (error >= 0)
    493 		return (error);
    494 	error = ttioctl(tp, cmd, data, flag, p);
    495 	if (error >= 0)
    496 		return (error);
    497 
    498 	switch (cmd) {
    499 
    500 	case TIOCSBRK:
    501 		zs_break(cs, 1);
    502 		break;
    503 
    504 	case TIOCCBRK:
    505 		zs_break(cs, 0);
    506 		break;
    507 
    508 	case TIOCGFLAGS:
    509 		*(int *)data = zst->zst_swflags;
    510 		break;
    511 
    512 	case TIOCSFLAGS:
    513 		error = suser(p->p_ucred, &p->p_acflag);
    514 		if (error != 0)
    515 			return (EPERM);
    516 		tmp = *(int *)data;
    517 		/* Check for random bits... */
    518 		if (tmp & ~TIOCFLAG_ALL)
    519 			return(EINVAL);
    520 		/* Silently enforce softcar on the console. */
    521 		if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
    522 			tmp |= TIOCFLAG_SOFTCAR;
    523 		/* These flags take effect during open. */
    524 		zst->zst_swflags = tmp;
    525 		break;
    526 
    527 	case TIOCSDTR:
    528 		zs_modem(zst, 1);
    529 		break;
    530 
    531 	case TIOCCDTR:
    532 		zs_modem(zst, 0);
    533 		break;
    534 
    535 	case TIOCMSET:
    536 	case TIOCMBIS:
    537 	case TIOCMBIC:
    538 	case TIOCMGET:
    539 	default:
    540 		return (ENOTTY);
    541 	}
    542 	return (0);
    543 }
    544 
    545 /*
    546  * Start or restart transmission.
    547  */
    548 static void
    549 zsstart(tp)
    550 	register struct tty *tp;
    551 {
    552 	register struct zstty_softc *zst;
    553 	register struct zs_chanstate *cs;
    554 	register int s, nch;
    555 
    556 	zst = zstty_cd.cd_devs[minor(tp->t_dev)];
    557 	cs = zst->zst_cs;
    558 
    559 	s = spltty();
    560 
    561 	/*
    562 	 * If currently active or delaying, no need to do anything.
    563 	 */
    564 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
    565 		goto out;
    566 
    567 	/*
    568 	 * If there are sleepers, and output has drained below low
    569 	 * water mark, awaken.
    570 	 */
    571 	if (tp->t_outq.c_cc <= tp->t_lowat) {
    572 		if (tp->t_state & TS_ASLEEP) {
    573 			tp->t_state &= ~TS_ASLEEP;
    574 			wakeup((caddr_t)&tp->t_outq);
    575 		}
    576 		selwakeup(&tp->t_wsel);
    577 	}
    578 
    579 	nch = ndqb(&tp->t_outq, 0);	/* XXX */
    580 	if (nch) {
    581 		register char *p = tp->t_outq.c_cf;
    582 
    583 		/* mark busy, enable tx done interrupts, & send first byte */
    584 		tp->t_state |= TS_BUSY;
    585 		(void) splzs();
    586 
    587 		cs->cs_preg[1] |= ZSWR1_TIE;
    588 		cs->cs_creg[1] |= ZSWR1_TIE;
    589 		zs_write_reg(cs, 1, cs->cs_creg[1]);
    590 		zs_write_data(cs, *p);
    591 		zst->zst_tba = p + 1;
    592 		zst->zst_tbc = nch - 1;
    593 	} else {
    594 		/*
    595 		 * Nothing to send, turn off transmit done interrupts.
    596 		 * This is useful if something is doing polled output.
    597 		 */
    598 		(void) splzs();
    599 		cs->cs_preg[1] &= ~ZSWR1_TIE;
    600 		cs->cs_creg[1] &= ~ZSWR1_TIE;
    601 		zs_write_reg(cs, 1, cs->cs_creg[1]);
    602 	}
    603 out:
    604 	splx(s);
    605 }
    606 
    607 /*
    608  * Stop output, e.g., for ^S or output flush.
    609  */
    610 int
    611 zsstop(tp, flag)
    612 	struct tty *tp;
    613 	int flag;
    614 {
    615 	register struct zstty_softc *zst;
    616 	register struct zs_chanstate *cs;
    617 	register int s;
    618 
    619 	zst = zstty_cd.cd_devs[minor(tp->t_dev)];
    620 	cs = zst->zst_cs;
    621 
    622 	s = splzs();
    623 	if (tp->t_state & TS_BUSY) {
    624 		/*
    625 		 * Device is transmitting; must stop it.
    626 		 */
    627 		zst->zst_tbc = 0;
    628 		if ((tp->t_state & TS_TTSTOP) == 0)
    629 			tp->t_state |= TS_FLUSH;
    630 	}
    631 	splx(s);
    632 	return (0);
    633 }
    634 
    635 /*
    636  * Set ZS tty parameters from termios.
    637  * XXX - Should just copy the whole termios after
    638  * making sure all the changes could be done.
    639  * XXX - Only whack the UART when params change...
    640  */
    641 static int
    642 zsparam(tp, t)
    643 	register struct tty *tp;
    644 	register struct termios *t;
    645 {
    646 	register struct zstty_softc *zst;
    647 	register struct zs_chanstate *cs;
    648 	register int s, bps, cflag, tconst;
    649 	u_char tmp3, tmp4, tmp5, reset;
    650 
    651 	zst = zstty_cd.cd_devs[minor(tp->t_dev)];
    652 	cs = zst->zst_cs;
    653 
    654 	bps = t->c_ospeed;
    655 	if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
    656 		return (EINVAL);
    657 	if (bps == 0) {
    658 		/* stty 0 => drop DTR and RTS */
    659 		zs_modem(zst, 0);
    660 		return (0);
    661 	}
    662 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
    663 	if (tconst < 0)
    664 		return (EINVAL);
    665 
    666 	/* Convert back to make sure we can do it. */
    667 	bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
    668 	if (bps != t->c_ospeed)
    669 		return (EINVAL);
    670 	tp->t_ispeed = tp->t_ospeed = bps;
    671 
    672 	cflag = t->c_cflag;
    673 	tp->t_cflag = cflag;
    674 
    675 	/*
    676 	 * Block interrupts so that state will not
    677 	 * be altered until we are done setting it up.
    678 	 */
    679 	s = splzs();
    680 
    681 	/*
    682 	 * Initial values in cs_preg are set before
    683 	 * our attach routine is called.  The master
    684 	 * interrupt enable is handled by zsc.c
    685 	 */
    686 
    687 	cs->cs_preg[12] = tconst;
    688 	cs->cs_preg[13] = tconst >> 8;
    689 
    690 	switch (cflag & CSIZE) {
    691 	case CS5:
    692 		tmp3 = ZSWR3_RX_5;
    693 		tmp5 = ZSWR5_TX_5;
    694 		break;
    695 	case CS6:
    696 		tmp3 = ZSWR3_RX_6;
    697 		tmp5 = ZSWR5_TX_6;
    698 		break;
    699 	case CS7:
    700 		tmp3 = ZSWR3_RX_7;
    701 		tmp5 = ZSWR5_TX_7;
    702 		break;
    703 	case CS8:
    704 	default:
    705 		tmp3 = ZSWR3_RX_8;
    706 		tmp5 = ZSWR5_TX_8;
    707 		break;
    708 	}
    709 
    710 	/*
    711 	 * Output hardware flow control on the chip is horrendous: if
    712 	 * carrier detect drops, the receiver is disabled.  Hence we
    713 	 * can only do this when the carrier is on.
    714 	 */
    715 	tmp3 |= ZSWR3_RX_ENABLE;
    716 	if (cflag & CCTS_OFLOW) {
    717 		if (zs_read_csr(cs) & ZSRR0_DCD)
    718 			tmp3 |= ZSWR3_HFC;
    719 	}
    720 
    721 	cs->cs_preg[3] = tmp3;
    722 	cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
    723 
    724 	tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
    725 	if ((cflag & PARODD) == 0)
    726 		tmp4 |= ZSWR4_EVENP;
    727 	if (cflag & PARENB)
    728 		tmp4 |= ZSWR4_PARENB;
    729 	cs->cs_preg[4] = tmp4;
    730 
    731 	/*
    732 	 * If nothing is being transmitted, set up new current values,
    733 	 * else mark them as pending.
    734 	 */
    735 	if (cs->cs_heldchange == 0) {
    736 		if (tp->t_state & TS_BUSY) {
    737 			zst->zst_heldtbc = zst->zst_tbc;
    738 			zst->zst_tbc = 0;
    739 			cs->cs_heldchange = 1;
    740 		} else {
    741 			zs_loadchannelregs(cs);
    742 		}
    743 	}
    744 	splx(s);
    745 	return (0);
    746 }
    747 
    748 /*
    749  * Raise or lower modem control (DTR/RTS) signals.  If a character is
    750  * in transmission, the change is deferred.
    751  */
    752 static void
    753 zs_modem(zst, onoff)
    754 	struct zstty_softc *zst;
    755 	int onoff;
    756 {
    757 	struct zs_chanstate *cs;
    758 	struct tty *tp;
    759 	int s, bis, and;
    760 
    761 	cs = zst->zst_cs;
    762 	tp = zst->zst_tty;
    763 
    764 	if (onoff) {
    765 		bis = ZSWR5_DTR | ZSWR5_RTS;
    766 		and = ~0;
    767 	} else {
    768 		bis = 0;
    769 		and = ~(ZSWR5_DTR | ZSWR5_RTS);
    770 	}
    771 	s = splzs();
    772 	cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
    773 	if (cs->cs_heldchange == 0) {
    774 		if (tp->t_state & TS_BUSY) {
    775 			zst->zst_heldtbc = zst->zst_tbc;
    776 			zst->zst_tbc = 0;
    777 			cs->cs_heldchange = 1;
    778 		} else {
    779 			cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and;
    780 			zs_write_reg(cs, 5, cs->cs_creg[5]);
    781 		}
    782 	}
    783 	splx(s);
    784 }
    785 
    786 
    787 /****************************************************************
    788  * Interface to the lower layer (zscc)
    789  ****************************************************************/
    790 
    791 /*
    792  * XXX: need to do input flow-control to avoid ring overrun.
    793  */
    794 
    795 /*
    796  * receiver ready interrupt.  (splzs)
    797  */
    798 static void
    799 zstty_rxint(cs)
    800 	register struct zs_chanstate *cs;
    801 {
    802 	register struct zstty_softc *zst;
    803 	register put, put_next, ringmask;
    804 	register u_char c, rr0, rr1;
    805 
    806 	zst = cs->cs_private;
    807 	put = zst->zst_rbput;
    808 	ringmask = zst->zst_ringmask;
    809 
    810 nextchar:
    811 
    812 	/*
    813 	 * First read the status, because reading the received char
    814 	 * destroys the status of this char.
    815 	 */
    816 	rr1 = zs_read_reg(cs, 1);
    817 	c = zs_read_data(cs);
    818 
    819 	if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
    820 		/* Clear the receive error. */
    821 		zs_write_csr(cs, ZSWR0_RESET_ERRORS);
    822 	}
    823 
    824 	zst->zst_rbuf[put] = (c << 8) | rr1;
    825 	put_next = (put + 1) & ringmask;
    826 
    827 	/* Would overrun if increment makes (put==get). */
    828 	if (put_next == zst->zst_rbget) {
    829 		zst->zst_intr_flags |= INTR_RX_OVERRUN;
    830 	} else {
    831 		/* OK, really increment. */
    832 		put = put_next;
    833 	}
    834 
    835 	/* Keep reading until the FIFO is empty. */
    836 	rr0 = zs_read_csr(cs);
    837 	if (rr0 & ZSRR0_RX_READY)
    838 		goto nextchar;
    839 
    840 	/* Done reading. */
    841 	zst->zst_rbput = put;
    842 
    843 	/* Ask for softint() call. */
    844 	cs->cs_softreq = 1;
    845 }
    846 
    847 /*
    848  * transmitter ready interrupt.  (splzs)
    849  */
    850 static void
    851 zstty_txint(cs)
    852 	register struct zs_chanstate *cs;
    853 {
    854 	register struct zstty_softc *zst;
    855 	register int count;
    856 
    857 	zst = cs->cs_private;
    858 	count = zst->zst_tbc;
    859 
    860 	/*
    861 	 * If our transmit buffer still has data,
    862 	 * just send the next character.
    863 	 */
    864 	if (count > 0) {
    865 		/* Send the next char. */
    866 		zst->zst_tbc = --count;
    867 		zs_write_data(cs, *zst->zst_tba);
    868 		zst->zst_tba++;
    869 		return;
    870 	}
    871 
    872 	zs_write_csr(cs, ZSWR0_RESET_TXINT);
    873 
    874 	/* Ask the softint routine for more output. */
    875 	zst->zst_intr_flags |= INTR_TX_EMPTY;
    876 	cs->cs_softreq = 1;
    877 }
    878 
    879 /*
    880  * status change interrupt.  (splzs)
    881  */
    882 static void
    883 zstty_stint(cs)
    884 	register struct zs_chanstate *cs;
    885 {
    886 	register struct zstty_softc *zst;
    887 	register struct tty *tp;
    888 	register u_char rr0;
    889 
    890 	zst = cs->cs_private;
    891 	tp  = zst->zst_tty;
    892 
    893 	rr0 = zs_read_csr(cs);
    894 	zs_write_csr(cs, ZSWR0_RESET_STATUS);
    895 
    896 	/*
    897 	 * The chip's hardware flow control is, as noted in zsreg.h,
    898 	 * busted---if the DCD line goes low the chip shuts off the
    899 	 * receiver (!).  If we want hardware CTS flow control but do
    900 	 * not have it, and carrier is now on, turn HFC on; if we have
    901 	 * HFC now but carrier has gone low, turn it off.
    902 	 */
    903 	if (rr0 & ZSRR0_DCD) {
    904 		if (tp->t_cflag & CCTS_OFLOW &&
    905 			(cs->cs_creg[3] & ZSWR3_HFC) == 0) {
    906 			cs->cs_creg[3] |= ZSWR3_HFC;
    907 			zs_write_reg(cs, 3, cs->cs_creg[3]);
    908 		}
    909 	} else {
    910 		if (cs->cs_creg[3] & ZSWR3_HFC) {
    911 			cs->cs_creg[3] &= ~ZSWR3_HFC;
    912 			zs_write_reg(cs, 3, cs->cs_creg[3]);
    913 		}
    914 	}
    915 
    916 	/*
    917 	 * Check here for console break, so that we can abort
    918 	 * even when interrupts are locking up the machine.
    919 	 */
    920 	if ((rr0 & ZSRR0_BREAK) &&
    921 		(zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
    922 	{
    923 		zs_abort();
    924 		return;
    925 	}
    926 
    927 	cs->cs_rr0_new = rr0;
    928 	zst->zst_intr_flags |= INTR_ST_CHECK;
    929 
    930 	/* Ask for softint() call. */
    931 	cs->cs_softreq = 1;
    932 }
    933 
    934 /*
    935  * Print out a ring or fifo overrun error message.
    936  */
    937 static void
    938 zsoverrun(zst, ptime, what)
    939 	struct zstty_softc *zst;
    940 	long *ptime;
    941 	char *what;
    942 {
    943 
    944 	if (*ptime != time.tv_sec) {
    945 		*ptime = time.tv_sec;
    946 		log(LOG_WARNING, "%s: %s overrun\n",
    947 			zst->zst_dev.dv_xname, what);
    948 	}
    949 }
    950 
    951 /*
    952  * Software interrupt.  Called at zssoft
    953  */
    954 static void
    955 zstty_softint(cs)
    956 	struct zs_chanstate *cs;
    957 {
    958 	register struct zstty_softc *zst;
    959 	register struct linesw *line;
    960 	register struct tty *tp;
    961 	register int get, c, s;
    962 	int intr_flags, ringmask;
    963 	register u_short ring_data;
    964 	register u_char rr0, rr1;
    965 
    966 	zst  = cs->cs_private;
    967 	tp   = zst->zst_tty;
    968 	line = &linesw[tp->t_line];
    969 	ringmask = zst->zst_ringmask;
    970 
    971 	/* Atomically get and clear flags. */
    972 	s = splzs();
    973 	intr_flags = zst->zst_intr_flags;
    974 	zst->zst_intr_flags = 0;
    975 
    976 	/*
    977 	 * Lower to tty priority while servicing the ring.
    978 	 */
    979 	(void) spltty();
    980 
    981 	if (intr_flags & INTR_RX_OVERRUN) {
    982 		/* May turn this on again below. */
    983 		intr_flags &= ~INTR_RX_OVERRUN;
    984 		zsoverrun(zst, &zst->zst_rotime, "ring");
    985 	}
    986 
    987 	/*
    988 	 * Copy data from the receive ring into the tty layer.
    989 	 */
    990 	get = zst->zst_rbget;
    991 	while (get != zst->zst_rbput) {
    992 		ring_data = zst->zst_rbuf[get];
    993 		get = (get + 1) & ringmask;
    994 
    995 		if (ring_data & ZSRR1_DO)
    996 			intr_flags |= INTR_RX_OVERRUN;
    997 		/* low byte of ring_data is rr1 */
    998 		c = (ring_data >> 8) & 0xff;
    999 		if (ring_data & ZSRR1_FE)
   1000 			c |= TTY_FE;
   1001 		if (ring_data & ZSRR1_PE)
   1002 			c |= TTY_PE;
   1003 
   1004 		line->l_rint(c, tp);
   1005 	}
   1006 	zst->zst_rbget = get;
   1007 
   1008 	/*
   1009 	 * If the overrun flag is set now, it was set while
   1010 	 * copying char/status pairs from the ring, which
   1011 	 * means this was a hardware (fifo) overrun.
   1012 	 */
   1013 	if (intr_flags & INTR_RX_OVERRUN) {
   1014 		zsoverrun(zst, &zst->zst_fotime, "fifo");
   1015 	}
   1016 
   1017 	if (intr_flags & INTR_TX_EMPTY) {
   1018 		/*
   1019 		 * The transmitter output buffer count is zero.
   1020 		 * If we suspended output for a "held" change,
   1021 		 * then handle that now and resume.  Otherwise,
   1022 		 * try to start a new output chunk.
   1023 		 */
   1024 		if (cs->cs_heldchange) {
   1025 			(void) splzs();
   1026 			rr0 = zs_read_csr(cs);
   1027 			if ((rr0 & ZSRR0_DCD) == 0)
   1028 				cs->cs_preg[3] &= ~ZSWR3_HFC;
   1029 			zs_loadchannelregs(cs);
   1030 			(void) spltty();
   1031 			cs->cs_heldchange = 0;
   1032 			if (zst->zst_heldtbc &&
   1033 				(tp->t_state & TS_TTSTOP) == 0)
   1034 			{
   1035 				zst->zst_tbc = zst->zst_heldtbc - 1;
   1036 				zs_write_data(cs, *zst->zst_tba);
   1037 				zst->zst_tba++;
   1038 				goto tx_resumed;
   1039 			}
   1040 		}
   1041 		tp->t_state &= ~TS_BUSY;
   1042 		if (tp->t_state & TS_FLUSH)
   1043 			tp->t_state &= ~TS_FLUSH;
   1044 		else
   1045 			ndflush(&tp->t_outq, zst->zst_tba -
   1046 					(caddr_t) tp->t_outq.c_cf);
   1047 		line->l_start(tp);
   1048 	tx_resumed:
   1049 	}
   1050 
   1051 	if (intr_flags & INTR_ST_CHECK) {
   1052 		/*
   1053 		 * Status line change.  HFC bit is run in
   1054 		 * hardware interrupt, to avoid locking
   1055 		 * at splzs here.
   1056 		 */
   1057 		rr0 = cs->cs_rr0_new;
   1058 		if ((rr0 ^ cs->cs_rr0) & ZSRR0_DCD) {
   1059 			c = ((rr0 & ZSRR0_DCD) != 0);
   1060 			if (line->l_modem(tp, c) == 0)
   1061 				zs_modem(zst, c);
   1062 		}
   1063 		cs->cs_rr0 = rr0;
   1064 	}
   1065 
   1066 	splx(s);
   1067 }
   1068 
   1069 struct zsops zsops_tty = {
   1070 	zstty_rxint,	/* receive char available */
   1071 	zstty_stint,	/* external/status */
   1072 	zstty_txint,	/* xmit buffer empty */
   1073 	zstty_softint,	/* process software interrupt */
   1074 };
   1075 
   1076