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