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