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