1 /* $OpenBSD: z8530tty.c,v 1.16 2006/04/27 19:31:44 deraadt 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