z8530tty.c revision 1.10 1 /* $NetBSD: z8530tty.c,v 1.10 1996/09/02 06:44:44 mycroft 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 (at) netbsd.org>,
64 * Bill Studenmund <wrstuden (at) loki.stanford.edu>
65 * Ian Dall <Ian.Dall (at) 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 #ifdef KGDB
85 extern int zs_check_kgdb();
86 #endif
87
88 /*
89 * Allow the MD var.h to override the default CFLAG so that
90 * console messages during boot come out with correct parity.
91 */
92 #ifndef ZSTTY_DEF_CFLAG
93 #define ZSTTY_DEF_CFLAG TTYDEF_CFLAG
94 #endif
95
96 /*
97 * How many input characters we can buffer.
98 * The port-specific var.h may override this.
99 * Note: must be a power of two!
100 */
101 #ifndef ZSTTY_RING_SIZE
102 #define ZSTTY_RING_SIZE 2048
103 #endif
104
105 /*
106 * Make this an option variable one can patch.
107 * But be warned: this must be a power of 2!
108 */
109 int zstty_rbuf_size = ZSTTY_RING_SIZE;
110
111 /* This should usually be 3/4 of ZSTTY_RING_SIZE */
112 int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE - (ZSTTY_RING_SIZE >> 2));
113
114 struct zstty_softc {
115 struct device zst_dev; /* required first: base device */
116 struct tty *zst_tty;
117 struct zs_chanstate *zst_cs;
118
119 int zst_hwflags; /* see z8530var.h */
120 int zst_swflags; /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
121
122 /*
123 * Printing an overrun error message often takes long enough to
124 * cause another overrun, so we only print one per second.
125 */
126 long zst_rotime; /* time of last ring overrun */
127 long zst_fotime; /* time of last fifo overrun */
128
129 /*
130 * The receive ring buffer.
131 */
132 int zst_rbget; /* ring buffer `get' index */
133 volatile int zst_rbput; /* ring buffer `put' index */
134 int zst_ringmask;
135 int zst_rbhiwat;
136
137 u_short *zst_rbuf; /* rr1, data pairs */
138
139 /*
140 * The transmit byte count and address are used for pseudo-DMA
141 * output in the hardware interrupt code. PDMA can be suspended
142 * to get pending changes done; heldtbc is used for this. It can
143 * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
144 */
145 int zst_tbc; /* transmit byte count */
146 caddr_t zst_tba; /* transmit buffer address */
147 int zst_heldtbc; /* held tbc while xmission stopped */
148
149 /* Flags to communicate with zstty_softint() */
150 volatile char zst_rx_blocked; /* input block at ring */
151 volatile char zst_rx_overrun; /* ring overrun */
152 volatile char zst_tx_busy; /* working on an output chunk */
153 volatile char zst_tx_done; /* done with one output chunk */
154 volatile char zst_tx_stopped; /* H/W level stop (lost CTS) */
155 volatile char zst_st_check; /* got a status interrupt */
156 char pad[2];
157 };
158
159
160 /* Definition of the driver for autoconfig. */
161 static int zstty_match(struct device *, void *, void *);
162 static void zstty_attach(struct device *, struct device *, void *);
163
164 struct cfattach zstty_ca = {
165 sizeof(struct zstty_softc), zstty_match, zstty_attach
166 };
167
168 struct cfdriver zstty_cd = {
169 NULL, "zstty", DV_TTY
170 };
171
172 struct zsops zsops_tty;
173
174 /* Routines called from other code. */
175 cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */
176
177 static void zsstart(struct tty *);
178 static int zsparam(struct tty *, struct termios *);
179 static void zs_modem(struct zstty_softc *zst, int onoff);
180 static int zshwiflow(struct tty *, int);
181 static void zs_hwiflow(struct zstty_softc *, int);
182
183 /*
184 * zstty_match: how is this zs channel configured?
185 */
186 int
187 zstty_match(parent, match, aux)
188 struct device *parent;
189 void *match, *aux;
190 {
191 struct cfdata *cf = match;
192 struct zsc_attach_args *args = aux;
193
194 /* Exact match is better than wildcard. */
195 if (cf->cf_loc[0] == args->channel)
196 return 2;
197
198 /* This driver accepts wildcard. */
199 if (cf->cf_loc[0] == -1)
200 return 1;
201
202 return 0;
203 }
204
205 void
206 zstty_attach(parent, self, aux)
207 struct device *parent, *self;
208 void *aux;
209
210 {
211 struct zsc_softc *zsc = (void *) parent;
212 struct zstty_softc *zst = (void *) self;
213 struct zsc_attach_args *args = aux;
214 struct zs_chanstate *cs;
215 struct cfdata *cf;
216 struct tty *tp;
217 int channel, tty_unit;
218 dev_t dev;
219
220 cf = zst->zst_dev.dv_cfdata;
221 tty_unit = zst->zst_dev.dv_unit;
222 channel = args->channel;
223 cs = &zsc->zsc_cs[channel];
224 cs->cs_private = zst;
225 cs->cs_ops = &zsops_tty;
226
227 zst->zst_cs = cs;
228 zst->zst_swflags = cf->cf_flags; /* softcar, etc. */
229 zst->zst_hwflags = args->hwflags;
230 dev = makedev(ZSTTY_MAJOR, tty_unit);
231
232 if (zst->zst_swflags)
233 printf(" flags 0x%x", zst->zst_swflags);
234
235 if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
236 printf(" (console)");
237 else {
238 #ifdef KGDB
239 /*
240 * Allow kgdb to "take over" this port. If this port is
241 * NOT the kgdb port, zs_check_kgdb() will return zero.
242 * If it IS the kgdb port, it will print "kgdb,...\n"
243 * and then return non-zero.
244 */
245 if (zs_check_kgdb(cs, dev)) {
246 /*
247 * This is the kgdb port (exclusive use)
248 * so skip the normal attach code.
249 */
250 return;
251 }
252 #endif
253 }
254 printf("\n");
255
256 tp = ttymalloc();
257 tp->t_dev = dev;
258 tp->t_oproc = zsstart;
259 tp->t_param = zsparam;
260 tp->t_hwiflow = zshwiflow;
261 tty_attach(tp);
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 struct zsinfo *zi;
438 int hup, s;
439
440 zst = zstty_cd.cd_devs[minor(dev)];
441 cs = zst->zst_cs;
442 tp = zst->zst_tty;
443
444 /* XXX This is for cons.c. */
445 if ((tp->t_state & TS_ISOPEN) == 0)
446 return 0;
447
448 (*linesw[tp->t_line].l_close)(tp, flags);
449 hup = tp->t_cflag & HUPCL;
450 if (zst->zst_swflags & TIOCFLAG_SOFTCAR)
451 hup = 0;
452 if (hup) {
453 zs_modem(zst, 0);
454 /* hold low for 1 second */
455 (void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
456 }
457 if (cs->cs_creg[5] & ZSWR5_BREAK) {
458 zs_break(cs, 0);
459 }
460 /* XXX - turn off interrupts? */
461
462 ttyclose(tp);
463 return (0);
464 }
465
466 /*
467 * Read/write zs serial port.
468 */
469 int
470 zsread(dev, uio, flags)
471 dev_t dev;
472 struct uio *uio;
473 int flags;
474 {
475 register struct zstty_softc *zst;
476 register struct tty *tp;
477
478 zst = zstty_cd.cd_devs[minor(dev)];
479 tp = zst->zst_tty;
480 return (linesw[tp->t_line].l_read(tp, uio, flags));
481 }
482
483 int
484 zswrite(dev, uio, flags)
485 dev_t dev;
486 struct uio *uio;
487 int flags;
488 {
489 register struct zstty_softc *zst;
490 register struct tty *tp;
491
492 zst = zstty_cd.cd_devs[minor(dev)];
493 tp = zst->zst_tty;
494 return (linesw[tp->t_line].l_write(tp, uio, flags));
495 }
496
497 #define TIOCFLAG_ALL (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | \
498 TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF )
499
500 int
501 zsioctl(dev, cmd, data, flag, p)
502 dev_t dev;
503 u_long cmd;
504 caddr_t data;
505 int flag;
506 struct proc *p;
507 {
508 register struct zstty_softc *zst;
509 register struct zs_chanstate *cs;
510 register struct tty *tp;
511 register int error, tmp;
512
513 zst = zstty_cd.cd_devs[minor(dev)];
514 cs = zst->zst_cs;
515 tp = zst->zst_tty;
516
517 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
518 if (error >= 0)
519 return (error);
520 error = ttioctl(tp, cmd, data, flag, p);
521 if (error >= 0)
522 return (error);
523
524 switch (cmd) {
525
526 case TIOCSBRK:
527 zs_break(cs, 1);
528 break;
529
530 case TIOCCBRK:
531 zs_break(cs, 0);
532 break;
533
534 case TIOCGFLAGS:
535 *(int *)data = zst->zst_swflags;
536 break;
537
538 case TIOCSFLAGS:
539 error = suser(p->p_ucred, &p->p_acflag);
540 if (error != 0)
541 return (EPERM);
542 tmp = *(int *)data;
543 /* Check for random bits... */
544 if (tmp & ~TIOCFLAG_ALL)
545 return(EINVAL);
546 /* Silently enforce softcar on the console. */
547 if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
548 tmp |= TIOCFLAG_SOFTCAR;
549 /* These flags take effect during open. */
550 zst->zst_swflags = tmp;
551 break;
552
553 case TIOCSDTR:
554 zs_modem(zst, 1);
555 break;
556
557 case TIOCCDTR:
558 zs_modem(zst, 0);
559 break;
560
561 case TIOCMSET:
562 case TIOCMBIS:
563 case TIOCMBIC:
564 case TIOCMGET:
565 default:
566 return (ENOTTY);
567 }
568 return (0);
569 }
570
571 /*
572 * Start or restart transmission.
573 */
574 static void
575 zsstart(tp)
576 register struct tty *tp;
577 {
578 register struct zstty_softc *zst;
579 register struct zs_chanstate *cs;
580 register int s, nch;
581
582 zst = zstty_cd.cd_devs[minor(tp->t_dev)];
583 cs = zst->zst_cs;
584
585 s = spltty();
586
587 /*
588 * If currently active or delaying, no need to do anything.
589 */
590 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
591 goto out;
592
593 /*
594 * If under CRTSCTS hfc and halted, do nothing
595 */
596 if (tp->t_cflag & CRTSCTS)
597 if (zst->zst_tx_stopped)
598 goto out;
599
600 /*
601 * If there are sleepers, and output has drained below low
602 * water mark, awaken.
603 */
604 if (tp->t_outq.c_cc <= tp->t_lowat) {
605 if (tp->t_state & TS_ASLEEP) {
606 tp->t_state &= ~TS_ASLEEP;
607 wakeup((caddr_t)&tp->t_outq);
608 }
609 selwakeup(&tp->t_wsel);
610 }
611
612 nch = ndqb(&tp->t_outq, 0); /* XXX */
613 (void) splzs();
614
615 if (nch) {
616 register char *p = tp->t_outq.c_cf;
617
618 /* mark busy, enable tx done interrupts, & send first byte */
619 tp->t_state |= TS_BUSY;
620 zst->zst_tx_busy = 1;
621 cs->cs_preg[1] |= ZSWR1_TIE;
622 cs->cs_creg[1] = cs->cs_preg[1];
623 zs_write_reg(cs, 1, cs->cs_creg[1]);
624 zs_write_data(cs, *p);
625 zst->zst_tba = p + 1;
626 zst->zst_tbc = nch - 1;
627 } else {
628 /*
629 * Nothing to send, turn off transmit done interrupts.
630 * This is useful if something is doing polled output.
631 */
632 cs->cs_preg[1] &= ~ZSWR1_TIE;
633 cs->cs_creg[1] = cs->cs_preg[1];
634 zs_write_reg(cs, 1, cs->cs_creg[1]);
635 }
636 out:
637 splx(s);
638 }
639
640 /*
641 * Stop output, e.g., for ^S or output flush.
642 */
643 void
644 zsstop(tp, flag)
645 struct tty *tp;
646 int flag;
647 {
648 register struct zstty_softc *zst;
649 register struct zs_chanstate *cs;
650 register int s;
651
652 zst = zstty_cd.cd_devs[minor(tp->t_dev)];
653 cs = zst->zst_cs;
654
655 s = splzs();
656 if (tp->t_state & TS_BUSY) {
657 /*
658 * Device is transmitting; must stop it.
659 * Also clear _heldtbc to prevent any
660 * flow-control event from resuming.
661 */
662 zst->zst_tbc = 0;
663 zst->zst_heldtbc = 0;
664 if ((tp->t_state & TS_TTSTOP) == 0)
665 tp->t_state |= TS_FLUSH;
666 }
667 splx(s);
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, reset;
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 cs->cs_rr0_new = rr0;
1070 zst->zst_st_check = 1;
1071
1072 /* Ask for softint() call. */
1073 cs->cs_softreq = 1;
1074 }
1075
1076 /*
1077 * Print out a ring or fifo overrun error message.
1078 */
1079 static void
1080 zsoverrun(zst, ptime, what)
1081 struct zstty_softc *zst;
1082 long *ptime;
1083 char *what;
1084 {
1085
1086 if (*ptime != time.tv_sec) {
1087 *ptime = time.tv_sec;
1088 log(LOG_WARNING, "%s: %s overrun\n",
1089 zst->zst_dev.dv_xname, what);
1090 }
1091 }
1092
1093 /*
1094 * Software interrupt. Called at zssoft
1095 *
1096 * The main job to be done here is to empty the input ring
1097 * by passing its contents up to the tty layer. The ring is
1098 * always emptied during this operation, therefore the ring
1099 * must not be larger than the space after "high water" in
1100 * the tty layer, or the tty layer might drop our input.
1101 *
1102 * Note: an "input blockage" condition is assumed to exist if
1103 * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set.
1104 */
1105 static void
1106 zstty_softint(cs)
1107 struct zs_chanstate *cs;
1108 {
1109 register struct zstty_softc *zst;
1110 register struct linesw *line;
1111 register struct tty *tp;
1112 register int get, c, s;
1113 int ringmask, overrun;
1114 register u_short ring_data;
1115 register u_char rr0, rr1, delta;
1116
1117 zst = cs->cs_private;
1118 tp = zst->zst_tty;
1119 line = &linesw[tp->t_line];
1120 ringmask = zst->zst_ringmask;
1121 overrun = 0;
1122
1123 /*
1124 * Raise to tty priority while servicing the ring.
1125 */
1126 s = spltty();
1127
1128 if (zst->zst_rx_overrun) {
1129 zst->zst_rx_overrun = 0;
1130 zsoverrun(zst, &zst->zst_rotime, "ring");
1131 }
1132
1133 /*
1134 * Copy data from the receive ring into the tty layer.
1135 */
1136 get = zst->zst_rbget;
1137 while (get != zst->zst_rbput) {
1138 ring_data = zst->zst_rbuf[get];
1139 get = (get + 1) & ringmask;
1140
1141 if (ring_data & ZSRR1_DO)
1142 overrun++;
1143 /* low byte of ring_data is rr1 */
1144 c = (ring_data >> 8) & 0xff;
1145 if (ring_data & ZSRR1_FE)
1146 c |= TTY_FE;
1147 if (ring_data & ZSRR1_PE)
1148 c |= TTY_PE;
1149
1150 line->l_rint(c, tp);
1151 }
1152 zst->zst_rbget = get;
1153
1154 /*
1155 * If the overrun flag is set now, it was set while
1156 * copying char/status pairs from the ring, which
1157 * means this was a hardware (fifo) overrun.
1158 */
1159 if (overrun) {
1160 zsoverrun(zst, &zst->zst_fotime, "fifo");
1161 }
1162
1163 /*
1164 * We have emptied the input ring. Maybe unblock input.
1165 * Note: an "input blockage" condition is assumed to exist
1166 * when EITHER zst_rx_blocked or the TS_TBLOCK flag is set,
1167 * so unblock here ONLY if TS_TBLOCK has not been set.
1168 */
1169 if (zst->zst_rx_blocked && ((tp->t_state & TS_TBLOCK) == 0)) {
1170 (void) splzs();
1171 zst->zst_rx_blocked = 0;
1172 zs_hwiflow(zst, 0); /* unblock input */
1173 (void) spltty();
1174 }
1175
1176 /*
1177 * Do any deferred work for status interrupts.
1178 * The rr0 was saved in the h/w interrupt to
1179 * avoid another splzs in here.
1180 */
1181 if (zst->zst_st_check) {
1182 zst->zst_st_check = 0;
1183
1184 rr0 = cs->cs_rr0_new;
1185 delta = rr0 ^ cs->cs_rr0;
1186 cs->cs_rr0 = rr0;
1187 if (delta & ZSRR0_DCD) {
1188 c = ((rr0 & ZSRR0_DCD) != 0);
1189 if (line->l_modem(tp, c) == 0)
1190 zs_modem(zst, c);
1191 }
1192 if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
1193 /*
1194 * Only do restart here. Stop is handled
1195 * at the h/w interrupt level.
1196 */
1197 if (rr0 & ZSRR0_CTS) {
1198 zst->zst_tx_stopped = 0;
1199 tp->t_state &= ~TS_TTSTOP;
1200 (*line->l_start)(tp);
1201 }
1202 }
1203 }
1204
1205 if (zst->zst_tx_done) {
1206 zst->zst_tx_done = 0;
1207 tp->t_state &= ~TS_BUSY;
1208 if (tp->t_state & TS_FLUSH)
1209 tp->t_state &= ~TS_FLUSH;
1210 else
1211 ndflush(&tp->t_outq, zst->zst_tba -
1212 (caddr_t) tp->t_outq.c_cf);
1213 line->l_start(tp);
1214 }
1215
1216 splx(s);
1217 }
1218
1219 struct zsops zsops_tty = {
1220 zstty_rxint, /* receive char available */
1221 zstty_stint, /* external/status */
1222 zstty_txint, /* xmit buffer empty */
1223 zstty_softint, /* process software interrupt */
1224 };
1225
1226