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