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