1 /* $OpenBSD: z8530tty.c,v 1.14 2003/10/03 16:44:51 miod 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
zstty_match(parent,match,aux)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
zstty_attach(parent,self,aux)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 *
zstty(dev)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
zsopen(dev,flags,mode,p)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
zsclose(dev,flags,mode,p)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
zsread(dev,uio,flags)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
zswrite(dev,uio,flags)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
zsioctl(dev,cmd,data,flag,p)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
zsstart(tp)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
zsstop(tp,flag)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
zsparam(tp,t)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
zs_modem(zst,onoff)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
zshwiflow(tp,stop)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
zs_hwiflow(zst,stop)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
zstty_rxint(cs)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
zstty_txint(cs)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
zstty_stint(cs)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 cs->cs_rr0 = rr0;
1078 zst->zst_st_check = 1;
1079
1080 /* Ask for softint() call. */
1081 cs->cs_softreq = 1;
1082 }
1083
1084 /*
1085 * Print out a ring or fifo overrun error message.
1086 */
1087 static void
zsoverrun(zst,ptime,what)1088 zsoverrun(zst, ptime, what)
1089 struct zstty_softc *zst;
1090 long *ptime;
1091 char *what;
1092 {
1093
1094 if (*ptime != time.tv_sec) {
1095 *ptime = time.tv_sec;
1096 log(LOG_WARNING, "%s: %s overrun\n",
1097 zst->zst_dev.dv_xname, what);
1098 }
1099 }
1100
1101 /*
1102 * Software interrupt. Called at zssoft
1103 *
1104 * The main job to be done here is to empty the input ring
1105 * by passing its contents up to the tty layer. The ring is
1106 * always emptied during this operation, therefore the ring
1107 * must not be larger than the space after "high water" in
1108 * the tty layer, or the tty layer might drop our input.
1109 *
1110 * Note: an "input blockage" condition is assumed to exist if
1111 * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set.
1112 */
1113 static void
zstty_softint(cs)1114 zstty_softint(cs)
1115 struct zs_chanstate *cs;
1116 {
1117 register struct zstty_softc *zst;
1118 register struct linesw *line;
1119 register struct tty *tp;
1120 register int get, c, s;
1121 int ringmask, overrun;
1122 register u_short ring_data;
1123 register u_char rr0, delta;
1124
1125 zst = cs->cs_private;
1126 tp = zst->zst_tty;
1127 line = &linesw[tp->t_line];
1128 ringmask = zst->zst_ringmask;
1129 overrun = 0;
1130
1131 /*
1132 * Raise to tty priority while servicing the ring.
1133 */
1134 s = spltty();
1135
1136 if (zst->zst_rx_overrun) {
1137 zst->zst_rx_overrun = 0;
1138 zsoverrun(zst, &zst->zst_rotime, "ring");
1139 }
1140
1141 /*
1142 * Copy data from the receive ring into the tty layer.
1143 */
1144 get = zst->zst_rbget;
1145 while (get != zst->zst_rbput) {
1146 ring_data = zst->zst_rbuf[get];
1147 get = (get + 1) & ringmask;
1148
1149 if (ring_data & ZSRR1_DO)
1150 overrun++;
1151 /* low byte of ring_data is rr1 */
1152 c = (ring_data >> 8) & 0xff;
1153 if (ring_data & ZSRR1_FE)
1154 c |= TTY_FE;
1155 if (ring_data & ZSRR1_PE)
1156 c |= TTY_PE;
1157
1158 line->l_rint(c, tp);
1159 }
1160 zst->zst_rbget = get;
1161
1162 /*
1163 * If the overrun flag is set now, it was set while
1164 * copying char/status pairs from the ring, which
1165 * means this was a hardware (fifo) overrun.
1166 */
1167 if (overrun) {
1168 zsoverrun(zst, &zst->zst_fotime, "fifo");
1169 }
1170
1171 /*
1172 * We have emptied the input ring. Maybe unblock input.
1173 * Note: an "input blockage" condition is assumed to exist
1174 * when EITHER zst_rx_blocked or the TS_TBLOCK flag is set,
1175 * so unblock here ONLY if TS_TBLOCK has not been set.
1176 */
1177 if (zst->zst_rx_blocked && ((tp->t_state & TS_TBLOCK) == 0)) {
1178 (void) splzs();
1179 zst->zst_rx_blocked = 0;
1180 zs_hwiflow(zst, 0); /* unblock input */
1181 (void) spltty();
1182 }
1183
1184 /*
1185 * Do any deferred work for status interrupts.
1186 * The rr0 was saved in the h/w interrupt to
1187 * avoid another splzs in here.
1188 */
1189 if (zst->zst_st_check) {
1190 zst->zst_st_check = 0;
1191
1192 rr0 = cs->cs_rr0;
1193 delta = cs->cs_rr0_delta;
1194 cs->cs_rr0_delta = 0;
1195 if (delta & ZSRR0_DCD) {
1196 c = ((rr0 & ZSRR0_DCD) != 0);
1197 if (line->l_modem(tp, c) == 0)
1198 zs_modem(zst, c);
1199 }
1200 if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
1201 /*
1202 * Only do restart here. Stop is handled
1203 * at the h/w interrupt level.
1204 */
1205 if (rr0 & ZSRR0_CTS) {
1206 zst->zst_tx_stopped = 0;
1207 tp->t_state &= ~TS_TTSTOP;
1208 (*line->l_start)(tp);
1209 }
1210 }
1211 }
1212
1213 if (zst->zst_tx_done) {
1214 zst->zst_tx_done = 0;
1215 tp->t_state &= ~TS_BUSY;
1216 if (tp->t_state & TS_FLUSH)
1217 tp->t_state &= ~TS_FLUSH;
1218 else
1219 ndflush(&tp->t_outq, zst->zst_tba -
1220 (caddr_t) tp->t_outq.c_cf);
1221 line->l_start(tp);
1222 }
1223
1224 splx(s);
1225 }
1226
1227 struct zsops zsops_tty = {
1228 zstty_rxint, /* receive char available */
1229 zstty_stint, /* external/status */
1230 zstty_txint, /* xmit buffer empty */
1231 zstty_softint, /* process software interrupt */
1232 };
1233
1234