Home | History | Annotate | Line # | Download | only in ic
z8530tty.c revision 1.6
      1 /*	$NetBSD: z8530tty.c,v 1.6 1996/04/10 21:44:47 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 	/*
    655 	 * Because PCLK is only run at 4.9 MHz, the fastest we
    656 	 * can go is 51200 baud (this corresponds to TC=1).
    657 	 * This is somewhat unfortunate as there is no real
    658 	 * reason we should not be able to handle higher rates.
    659 	 */
    660 	bps = t->c_ospeed;
    661 	if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
    662 		return (EINVAL);
    663 	if (bps == 0) {
    664 		/* stty 0 => drop DTR and RTS */
    665 		zs_modem(zst, 0);
    666 		return (0);
    667 	}
    668 	tconst = BPS_TO_TCONST(cs->cs_pclk_div16, bps);
    669 	if (tconst < 0)
    670 		return (EINVAL);
    671 
    672 	/* Convert back to make sure we can do it. */
    673 	bps = TCONST_TO_BPS(cs->cs_pclk_div16, tconst);
    674 	if (bps != t->c_ospeed)
    675 		return (EINVAL);
    676 	tp->t_ispeed = tp->t_ospeed = bps;
    677 
    678 	cflag = t->c_cflag;
    679 	tp->t_cflag = cflag;
    680 
    681 	/*
    682 	 * Block interrupts so that state will not
    683 	 * be altered until we are done setting it up.
    684 	 */
    685 	s = splzs();
    686 
    687 	/*
    688 	 * Initial values in cs_preg are set before
    689 	 * our attach routine is called.  The master
    690 	 * interrupt enable is handled by zsc.c
    691 	 */
    692 
    693 	cs->cs_preg[12] = tconst;
    694 	cs->cs_preg[13] = tconst >> 8;
    695 
    696 	switch (cflag & CSIZE) {
    697 	case CS5:
    698 		tmp3 = ZSWR3_RX_5;
    699 		tmp5 = ZSWR5_TX_5;
    700 		break;
    701 	case CS6:
    702 		tmp3 = ZSWR3_RX_6;
    703 		tmp5 = ZSWR5_TX_6;
    704 		break;
    705 	case CS7:
    706 		tmp3 = ZSWR3_RX_7;
    707 		tmp5 = ZSWR5_TX_7;
    708 		break;
    709 	case CS8:
    710 	default:
    711 		tmp3 = ZSWR3_RX_8;
    712 		tmp5 = ZSWR5_TX_8;
    713 		break;
    714 	}
    715 
    716 	/*
    717 	 * Output hardware flow control on the chip is horrendous: if
    718 	 * carrier detect drops, the receiver is disabled.  Hence we
    719 	 * can only do this when the carrier is on.
    720 	 */
    721 	tmp3 |= ZSWR3_RX_ENABLE;
    722 	if (cflag & CCTS_OFLOW) {
    723 		if (zs_read_csr(cs) & ZSRR0_DCD)
    724 			tmp3 |= ZSWR3_HFC;
    725 	}
    726 
    727 	cs->cs_preg[3] = tmp3;
    728 	cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
    729 
    730 	tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
    731 	if ((cflag & PARODD) == 0)
    732 		tmp4 |= ZSWR4_EVENP;
    733 	if (cflag & PARENB)
    734 		tmp4 |= ZSWR4_PARENB;
    735 	cs->cs_preg[4] = tmp4;
    736 
    737 	/*
    738 	 * If nothing is being transmitted, set up new current values,
    739 	 * else mark them as pending.
    740 	 */
    741 	if (cs->cs_heldchange == 0) {
    742 		if (tp->t_state & TS_BUSY) {
    743 			zst->zst_heldtbc = zst->zst_tbc;
    744 			zst->zst_tbc = 0;
    745 			cs->cs_heldchange = 1;
    746 		} else {
    747 			zs_loadchannelregs(cs);
    748 		}
    749 	}
    750 	splx(s);
    751 	return (0);
    752 }
    753 
    754 /*
    755  * Raise or lower modem control (DTR/RTS) signals.  If a character is
    756  * in transmission, the change is deferred.
    757  */
    758 static void
    759 zs_modem(zst, onoff)
    760 	struct zstty_softc *zst;
    761 	int onoff;
    762 {
    763 	struct zs_chanstate *cs;
    764 	struct tty *tp;
    765 	int s, bis, and;
    766 
    767 	cs = zst->zst_cs;
    768 	tp = zst->zst_tty;
    769 
    770 	if (onoff) {
    771 		bis = ZSWR5_DTR | ZSWR5_RTS;
    772 		and = ~0;
    773 	} else {
    774 		bis = 0;
    775 		and = ~(ZSWR5_DTR | ZSWR5_RTS);
    776 	}
    777 	s = splzs();
    778 	cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
    779 	if (cs->cs_heldchange == 0) {
    780 		if (tp->t_state & TS_BUSY) {
    781 			zst->zst_heldtbc = zst->zst_tbc;
    782 			zst->zst_tbc = 0;
    783 			cs->cs_heldchange = 1;
    784 		} else {
    785 			cs->cs_creg[5] = (cs->cs_creg[5] | bis) & and;
    786 			zs_write_reg(cs, 5, cs->cs_creg[5]);
    787 		}
    788 	}
    789 	splx(s);
    790 }
    791 
    792 
    793 /****************************************************************
    794  * Interface to the lower layer (zscc)
    795  ****************************************************************/
    796 
    797 /*
    798  * XXX: need to do input flow-control to avoid ring overrun.
    799  */
    800 
    801 /*
    802  * receiver ready interrupt.  (splzs)
    803  */
    804 static void
    805 zstty_rxint(cs)
    806 	register struct zs_chanstate *cs;
    807 {
    808 	register struct zstty_softc *zst;
    809 	register put, put_next, ringmask;
    810 	register u_char c, rr0, rr1;
    811 
    812 	zst = cs->cs_private;
    813 	put = zst->zst_rbput;
    814 	ringmask = zst->zst_ringmask;
    815 
    816 nextchar:
    817 
    818 	/*
    819 	 * First read the status, because reading the received char
    820 	 * destroys the status of this char.
    821 	 */
    822 	rr1 = zs_read_reg(cs, 1);
    823 	c = zs_read_data(cs);
    824 
    825 	if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
    826 		/* Clear the receive error. */
    827 		zs_write_csr(cs, ZSWR0_RESET_ERRORS);
    828 	}
    829 
    830 	zst->zst_rbuf[put] = (c << 8) | rr1;
    831 	put_next = (put + 1) & ringmask;
    832 
    833 	/* Would overrun if increment makes (put==get). */
    834 	if (put_next == zst->zst_rbget) {
    835 		zst->zst_intr_flags |= INTR_RX_OVERRUN;
    836 	} else {
    837 		/* OK, really increment. */
    838 		put = put_next;
    839 	}
    840 
    841 	/* Keep reading until the FIFO is empty. */
    842 	rr0 = zs_read_csr(cs);
    843 	if (rr0 & ZSRR0_RX_READY)
    844 		goto nextchar;
    845 
    846 	/* Done reading. */
    847 	zst->zst_rbput = put;
    848 
    849 	/* Ask for softint() call. */
    850 	cs->cs_softreq = 1;
    851 }
    852 
    853 /*
    854  * transmitter ready interrupt.  (splzs)
    855  */
    856 static void
    857 zstty_txint(cs)
    858 	register struct zs_chanstate *cs;
    859 {
    860 	register struct zstty_softc *zst;
    861 	register int count;
    862 
    863 	zst = cs->cs_private;
    864 	count = zst->zst_tbc;
    865 
    866 	/*
    867 	 * If our transmit buffer still has data,
    868 	 * just send the next character.
    869 	 */
    870 	if (count > 0) {
    871 		/* Send the next char. */
    872 		zst->zst_tbc = --count;
    873 		zs_write_data(cs, *zst->zst_tba);
    874 		zst->zst_tba++;
    875 		return;
    876 	}
    877 
    878 	zs_write_csr(cs, ZSWR0_RESET_TXINT);
    879 
    880 	/* Ask the softint routine for more output. */
    881 	zst->zst_intr_flags |= INTR_TX_EMPTY;
    882 	cs->cs_softreq = 1;
    883 }
    884 
    885 /*
    886  * status change interrupt.  (splzs)
    887  */
    888 static void
    889 zstty_stint(cs)
    890 	register struct zs_chanstate *cs;
    891 {
    892 	register struct zstty_softc *zst;
    893 	register struct tty *tp;
    894 	register u_char rr0;
    895 
    896 	zst = cs->cs_private;
    897 	tp  = zst->zst_tty;
    898 
    899 	rr0 = zs_read_csr(cs);
    900 	zs_write_csr(cs, ZSWR0_RESET_STATUS);
    901 
    902 	/*
    903 	 * The chip's hardware flow control is, as noted in zsreg.h,
    904 	 * busted---if the DCD line goes low the chip shuts off the
    905 	 * receiver (!).  If we want hardware CTS flow control but do
    906 	 * not have it, and carrier is now on, turn HFC on; if we have
    907 	 * HFC now but carrier has gone low, turn it off.
    908 	 */
    909 	if (rr0 & ZSRR0_DCD) {
    910 		if (tp->t_cflag & CCTS_OFLOW &&
    911 			(cs->cs_creg[3] & ZSWR3_HFC) == 0) {
    912 			cs->cs_creg[3] |= ZSWR3_HFC;
    913 			zs_write_reg(cs, 3, cs->cs_creg[3]);
    914 		}
    915 	} else {
    916 		if (cs->cs_creg[3] & ZSWR3_HFC) {
    917 			cs->cs_creg[3] &= ~ZSWR3_HFC;
    918 			zs_write_reg(cs, 3, cs->cs_creg[3]);
    919 		}
    920 	}
    921 
    922 	/*
    923 	 * Check here for console break, so that we can abort
    924 	 * even when interrupts are locking up the machine.
    925 	 */
    926 	if ((rr0 & ZSRR0_BREAK) &&
    927 		(zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
    928 	{
    929 		zs_abort();
    930 		return;
    931 	}
    932 
    933 	cs->cs_rr0_new = rr0;
    934 	zst->zst_intr_flags |= INTR_ST_CHECK;
    935 
    936 	/* Ask for softint() call. */
    937 	cs->cs_softreq = 1;
    938 }
    939 
    940 /*
    941  * Print out a ring or fifo overrun error message.
    942  */
    943 static void
    944 zsoverrun(zst, ptime, what)
    945 	struct zstty_softc *zst;
    946 	long *ptime;
    947 	char *what;
    948 {
    949 
    950 	if (*ptime != time.tv_sec) {
    951 		*ptime = time.tv_sec;
    952 		log(LOG_WARNING, "%s: %s overrun\n",
    953 			zst->zst_dev.dv_xname, what);
    954 	}
    955 }
    956 
    957 /*
    958  * Software interrupt.  Called at zssoft
    959  */
    960 static void
    961 zstty_softint(cs)
    962 	struct zs_chanstate *cs;
    963 {
    964 	register struct zstty_softc *zst;
    965 	register struct linesw *line;
    966 	register struct tty *tp;
    967 	register int get, c, s;
    968 	int intr_flags, ringmask;
    969 	register u_short ring_data;
    970 	register u_char rr0, rr1;
    971 
    972 	zst  = cs->cs_private;
    973 	tp   = zst->zst_tty;
    974 	line = &linesw[tp->t_line];
    975 	ringmask = zst->zst_ringmask;
    976 
    977 	/* Atomically get and clear flags. */
    978 	s = splzs();
    979 	intr_flags = zst->zst_intr_flags;
    980 	zst->zst_intr_flags = 0;
    981 
    982 	/*
    983 	 * Lower to tty priority while servicing the ring.
    984 	 */
    985 	(void) spltty();
    986 
    987 	if (intr_flags & INTR_RX_OVERRUN) {
    988 		/* May turn this on again below. */
    989 		intr_flags &= ~INTR_RX_OVERRUN;
    990 		zsoverrun(zst, &zst->zst_rotime, "ring");
    991 	}
    992 
    993 	/*
    994 	 * Copy data from the receive ring into the tty layer.
    995 	 */
    996 	get = zst->zst_rbget;
    997 	while (get != zst->zst_rbput) {
    998 		ring_data = zst->zst_rbuf[get];
    999 		get = (get + 1) & ringmask;
   1000 
   1001 		if (ring_data & ZSRR1_DO)
   1002 			intr_flags |= INTR_RX_OVERRUN;
   1003 		/* low byte of ring_data is rr1 */
   1004 		c = (ring_data >> 8) & 0xff;
   1005 		if (ring_data & ZSRR1_FE)
   1006 			c |= TTY_FE;
   1007 		if (ring_data & ZSRR1_PE)
   1008 			c |= TTY_PE;
   1009 
   1010 		line->l_rint(c, tp);
   1011 	}
   1012 	zst->zst_rbget = get;
   1013 
   1014 	/*
   1015 	 * If the overrun flag is set now, it was set while
   1016 	 * copying char/status pairs from the ring, which
   1017 	 * means this was a hardware (fifo) overrun.
   1018 	 */
   1019 	if (intr_flags & INTR_RX_OVERRUN) {
   1020 		zsoverrun(zst, &zst->zst_fotime, "fifo");
   1021 	}
   1022 
   1023 	if (intr_flags & INTR_TX_EMPTY) {
   1024 		/*
   1025 		 * The transmitter output buffer count is zero.
   1026 		 * If we suspended output for a "held" change,
   1027 		 * then handle that now and resume.  Otherwise,
   1028 		 * try to start a new output chunk.
   1029 		 */
   1030 		if (cs->cs_heldchange) {
   1031 			(void) splzs();
   1032 			rr0 = zs_read_csr(cs);
   1033 			if ((rr0 & ZSRR0_DCD) == 0)
   1034 				cs->cs_preg[3] &= ~ZSWR3_HFC;
   1035 			zs_loadchannelregs(cs);
   1036 			(void) spltty();
   1037 			cs->cs_heldchange = 0;
   1038 			if (zst->zst_heldtbc &&
   1039 				(tp->t_state & TS_TTSTOP) == 0)
   1040 			{
   1041 				zst->zst_tbc = zst->zst_heldtbc - 1;
   1042 				zs_write_data(cs, *zst->zst_tba);
   1043 				zst->zst_tba++;
   1044 				goto tx_resumed;
   1045 			}
   1046 		}
   1047 		tp->t_state &= ~TS_BUSY;
   1048 		if (tp->t_state & TS_FLUSH)
   1049 			tp->t_state &= ~TS_FLUSH;
   1050 		else
   1051 			ndflush(&tp->t_outq, zst->zst_tba -
   1052 					(caddr_t) tp->t_outq.c_cf);
   1053 		line->l_start(tp);
   1054 	tx_resumed:
   1055 	}
   1056 
   1057 	if (intr_flags & INTR_ST_CHECK) {
   1058 		/*
   1059 		 * Status line change.  HFC bit is run in
   1060 		 * hardware interrupt, to avoid locking
   1061 		 * at splzs here.
   1062 		 */
   1063 		rr0 = cs->cs_rr0_new;
   1064 		if ((rr0 ^ cs->cs_rr0) & ZSRR0_DCD) {
   1065 			c = ((rr0 & ZSRR0_DCD) != 0);
   1066 			if (line->l_modem(tp, c) == 0)
   1067 				zs_modem(zst, c);
   1068 		}
   1069 		cs->cs_rr0 = rr0;
   1070 	}
   1071 
   1072 	splx(s);
   1073 }
   1074 
   1075 struct zsops zsops_tty = {
   1076 	zstty_rxint,	/* receive char available */
   1077 	zstty_stint,	/* external/status */
   1078 	zstty_txint,	/* xmit buffer empty */
   1079 	zstty_softint,	/* process software interrupt */
   1080 };
   1081 
   1082