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