dz.c revision 1.9 1 /* $NetBSD: dz.c,v 1.9 2002/10/23 09:13:09 jdolecek Exp $ */
2 /*
3 * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: dz.c,v 1.9 2002/10/23 09:13:09 jdolecek Exp $");
41
42 #include "opt_ddb.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/callout.h>
47 #include <sys/ioctl.h>
48 #include <sys/tty.h>
49 #include <sys/proc.h>
50 #include <sys/buf.h>
51 #include <sys/conf.h>
52 #include <sys/file.h>
53 #include <sys/uio.h>
54 #include <sys/kernel.h>
55 #include <sys/syslog.h>
56 #include <sys/device.h>
57
58 #include <machine/bus.h>
59
60 #include <dev/dec/dzreg.h>
61 #include <dev/dec/dzvar.h>
62
63 #define DZ_READ_BYTE(adr) \
64 bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
65 #define DZ_READ_WORD(adr) \
66 bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
67 #define DZ_WRITE_BYTE(adr, val) \
68 bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
69 #define DZ_WRITE_WORD(adr, val) \
70 bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
71
72 #include "ioconf.h"
73
74 /* Flags used to monitor modem bits, make them understood outside driver */
75
76 #define DML_DTR TIOCM_DTR
77 #define DML_DCD TIOCM_CD
78 #define DML_RI TIOCM_RI
79 #define DML_BRK 0100000 /* no equivalent, we will mask */
80
81 static struct speedtab dzspeedtab[] =
82 {
83 { 0, 0 },
84 { 50, DZ_LPR_B50 },
85 { 75, DZ_LPR_B75 },
86 { 110, DZ_LPR_B110 },
87 { 134, DZ_LPR_B134 },
88 { 150, DZ_LPR_B150 },
89 { 300, DZ_LPR_B300 },
90 { 600, DZ_LPR_B600 },
91 { 1200, DZ_LPR_B1200 },
92 { 1800, DZ_LPR_B1800 },
93 { 2000, DZ_LPR_B2000 },
94 { 2400, DZ_LPR_B2400 },
95 { 3600, DZ_LPR_B3600 },
96 { 4800, DZ_LPR_B4800 },
97 { 7200, DZ_LPR_B7200 },
98 { 9600, DZ_LPR_B9600 },
99 { 19200, DZ_LPR_B19200 },
100 { -1, -1 }
101 };
102
103 static void dzstart(struct tty *);
104 static int dzparam(struct tty *, struct termios *);
105 static unsigned dzmctl(struct dz_softc *, int, int, int);
106 static void dzscan(void *);
107
108 dev_type_open(dzopen);
109 dev_type_close(dzclose);
110 dev_type_read(dzread);
111 dev_type_write(dzwrite);
112 dev_type_ioctl(dzioctl);
113 dev_type_stop(dzstop);
114 dev_type_tty(dztty);
115 dev_type_poll(dzpoll);
116
117 const struct cdevsw dz_cdevsw = {
118 dzopen, dzclose, dzread, dzwrite, dzioctl,
119 dzstop, dztty, dzpoll, nommap, ttykqfilter, D_TTY
120 };
121
122 /*
123 * The DZ series doesn't interrupt on carrier transitions,
124 * so we have to use a timer to watch it.
125 */
126 int dz_timer; /* true if timer started */
127 struct callout dzscan_ch;
128
129 void
130 dzattach(struct dz_softc *sc, struct evcnt *parent_evcnt, int consline)
131 {
132 int n;
133
134 sc->sc_rxint = sc->sc_brk = 0;
135 sc->sc_consline = consline;
136
137 sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
138 DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
139 DZ_WRITE_BYTE(dr_dtr, 0);
140 DZ_WRITE_BYTE(dr_break, 0);
141
142 /* Initialize our softc structure. Should be done in open? */
143
144 for (n = 0; n < sc->sc_type; n++) {
145 sc->sc_dz[n].dz_sc = sc;
146 sc->sc_dz[n].dz_line = n;
147 sc->sc_dz[n].dz_tty = ttymalloc();
148 }
149
150 evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
151 sc->sc_dev.dv_xname, "rintr");
152 evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
153 sc->sc_dev.dv_xname, "tintr");
154
155 /* Alas no interrupt on modem bit changes, so we manually scan */
156
157 if (dz_timer == 0) {
158 dz_timer = 1;
159 callout_init(&dzscan_ch);
160 callout_reset(&dzscan_ch, hz, dzscan, NULL);
161 }
162 printf("\n");
163 }
164
165 /* Receiver Interrupt */
166
167 void
168 dzrint(void *arg)
169 {
170 struct dz_softc *sc = arg;
171 struct tty *tp;
172 int cc, line;
173 unsigned c;
174 int overrun = 0;
175
176 sc->sc_rxint++;
177
178 while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) {
179 cc = c & 0xFF;
180 line = DZ_PORT(c>>8);
181 tp = sc->sc_dz[line].dz_tty;
182
183 /* Must be caught early */
184 if (sc->sc_dz[line].dz_catch &&
185 (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
186 continue;
187
188 if (!(tp->t_state & TS_ISOPEN)) {
189 wakeup((caddr_t)&tp->t_rawq);
190 continue;
191 }
192
193 if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
194 log(LOG_WARNING, "%s: silo overflow, line %d\n",
195 sc->sc_dev.dv_xname, line);
196 overrun = 1;
197 }
198 #if defined(pmax) && defined(DDB)
199 else if (line == sc->sc_consline) {
200 /*
201 * A BREAK key will appear as a NUL with a framing
202 * error.
203 */
204 if (cc == 0 && (c & DZ_RBUF_FRAMING_ERR) != 0)
205 Debugger();
206 }
207 #endif
208 if (c & DZ_RBUF_FRAMING_ERR)
209 cc |= TTY_FE;
210 if (c & DZ_RBUF_PARITY_ERR)
211 cc |= TTY_PE;
212
213 (*tp->t_linesw->l_rint)(cc, tp);
214 }
215 }
216
217 /* Transmitter Interrupt */
218
219 void
220 dzxint(void *arg)
221 {
222 struct dz_softc *sc = arg;
223 struct tty *tp;
224 struct clist *cl;
225 int line, ch, csr;
226 u_char tcr;
227
228 /*
229 * Switch to POLLED mode.
230 * Some simple measurements indicated that even on
231 * one port, by freeing the scanner in the controller
232 * by either providing a character or turning off
233 * the port when output is complete, the transmitter
234 * was ready to accept more output when polled again.
235 * With just two ports running the game "worms,"
236 * almost every interrupt serviced both transmitters!
237 * Each UART is double buffered, so if the scanner
238 * is quick enough and timing works out, we can even
239 * feed the same port twice.
240 *
241 * Ragge 980517:
242 * Do not need to turn off interrupts, already at interrupt level.
243 * Remove the pdma stuff; no great need of it right now.
244 */
245
246 while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) {
247
248 line = DZ_PORT(csr>>8);
249
250 tp = sc->sc_dz[line].dz_tty;
251 cl = &tp->t_outq;
252 tp->t_state &= ~TS_BUSY;
253
254 /* Just send out a char if we have one */
255 /* As long as we can fill the chip buffer, we just loop here */
256 if (cl->c_cc) {
257 tp->t_state |= TS_BUSY;
258 ch = getc(cl);
259 DZ_WRITE_BYTE(dr_tbuf, ch);
260 continue;
261 }
262 /* Nothing to send; clear the scan bit */
263 /* Clear xmit scanner bit; dzstart may set it again */
264 tcr = DZ_READ_WORD(dr_tcrw);
265 tcr &= 255;
266 tcr &= ~(1 << line);
267 DZ_WRITE_BYTE(dr_tcr, tcr);
268 if (sc->sc_dz[line].dz_catch)
269 continue;
270
271 if (tp->t_state & TS_FLUSH)
272 tp->t_state &= ~TS_FLUSH;
273 else
274 ndflush (&tp->t_outq, cl->c_cc);
275
276 (*tp->t_linesw->l_start)(tp);
277 }
278 }
279
280 int
281 dzopen(dev_t dev, int flag, int mode, struct proc *p)
282 {
283 struct tty *tp;
284 int unit, line;
285 struct dz_softc *sc;
286 int s, error = 0;
287
288 unit = DZ_I2C(minor(dev));
289 line = DZ_PORT(minor(dev));
290 if (unit >= dz_cd.cd_ndevs || dz_cd.cd_devs[unit] == NULL)
291 return (ENXIO);
292
293 sc = dz_cd.cd_devs[unit];
294
295 if (line >= sc->sc_type)
296 return ENXIO;
297
298 /* if some other device is using the line, it's busy */
299 if (sc->sc_dz[line].dz_catch)
300 return EBUSY;
301
302 tp = sc->sc_dz[line].dz_tty;
303 if (tp == NULL)
304 return (ENODEV);
305 tp->t_oproc = dzstart;
306 tp->t_param = dzparam;
307 tp->t_dev = dev;
308 if ((tp->t_state & TS_ISOPEN) == 0) {
309 ttychars(tp);
310 if (tp->t_ispeed == 0) {
311 tp->t_iflag = TTYDEF_IFLAG;
312 tp->t_oflag = TTYDEF_OFLAG;
313 tp->t_cflag = TTYDEF_CFLAG;
314 tp->t_lflag = TTYDEF_LFLAG;
315 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
316 }
317 (void) dzparam(tp, &tp->t_termios);
318 ttsetwater(tp);
319 } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
320 return (EBUSY);
321 /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
322 if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
323 tp->t_state |= TS_CARR_ON;
324 s = spltty();
325 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
326 !(tp->t_state & TS_CARR_ON)) {
327 tp->t_wopen++;
328 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
329 TTIPRI | PCATCH, ttopen, 0);
330 tp->t_wopen--;
331 if (error)
332 break;
333 }
334 (void) splx(s);
335 if (error)
336 return (error);
337 return ((*tp->t_linesw->l_open)(dev, tp));
338 }
339
340 /*ARGSUSED*/
341 int
342 dzclose(dev_t dev, int flag, int mode, struct proc *p)
343 {
344 struct dz_softc *sc;
345 struct tty *tp;
346 int unit, line;
347
348
349 unit = DZ_I2C(minor(dev));
350 line = DZ_PORT(minor(dev));
351 sc = dz_cd.cd_devs[unit];
352
353 tp = sc->sc_dz[line].dz_tty;
354
355 (*tp->t_linesw->l_close)(tp, flag);
356
357 /* Make sure a BREAK state is not left enabled. */
358 (void) dzmctl(sc, line, DML_BRK, DMBIC);
359
360 /* Do a hangup if so required. */
361 if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
362 (void) dzmctl(sc, line, 0, DMSET);
363
364 return (ttyclose(tp));
365 }
366
367 int
368 dzread(dev_t dev, struct uio *uio, int flag)
369 {
370 struct tty *tp;
371 struct dz_softc *sc;
372
373 sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
374
375 tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
376 return ((*tp->t_linesw->l_read)(tp, uio, flag));
377 }
378
379 int
380 dzwrite(dev_t dev, struct uio *uio, int flag)
381 {
382 struct tty *tp;
383 struct dz_softc *sc;
384
385 sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
386
387 tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
388 return ((*tp->t_linesw->l_write)(tp, uio, flag));
389 }
390
391 int
392 dzpoll(dev, events, p)
393 dev_t dev;
394 int events;
395 struct proc *p;
396 {
397 struct tty *tp;
398 struct dz_softc *sc;
399
400 sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
401
402 tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
403 return ((*tp->t_linesw->l_poll)(tp, events, p));
404 }
405
406 /*ARGSUSED*/
407 int
408 dzioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
409 {
410 struct dz_softc *sc;
411 struct tty *tp;
412 int unit, line;
413 int error;
414
415 unit = DZ_I2C(minor(dev));
416 line = DZ_PORT(minor(dev));
417 sc = dz_cd.cd_devs[unit];
418 tp = sc->sc_dz[line].dz_tty;
419
420 error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
421 if (error >= 0)
422 return (error);
423
424 error = ttioctl(tp, cmd, data, flag, p);
425 if (error >= 0)
426 return (error);
427
428 switch (cmd) {
429
430 case TIOCSBRK:
431 (void) dzmctl(sc, line, DML_BRK, DMBIS);
432 break;
433
434 case TIOCCBRK:
435 (void) dzmctl(sc, line, DML_BRK, DMBIC);
436 break;
437
438 case TIOCSDTR:
439 (void) dzmctl(sc, line, DML_DTR, DMBIS);
440 break;
441
442 case TIOCCDTR:
443 (void) dzmctl(sc, line, DML_DTR, DMBIC);
444 break;
445
446 case TIOCMSET:
447 (void) dzmctl(sc, line, *(int *)data, DMSET);
448 break;
449
450 case TIOCMBIS:
451 (void) dzmctl(sc, line, *(int *)data, DMBIS);
452 break;
453
454 case TIOCMBIC:
455 (void) dzmctl(sc, line, *(int *)data, DMBIC);
456 break;
457
458 case TIOCMGET:
459 *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
460 break;
461
462 default:
463 return (EPASSTHROUGH);
464 }
465 return (0);
466 }
467
468 struct tty *
469 dztty(dev_t dev)
470 {
471 struct dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
472 struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
473
474 return (tp);
475 }
476
477 /*ARGSUSED*/
478 void
479 dzstop(struct tty *tp, int flag)
480 {
481 if (tp->t_state & TS_BUSY)
482 if (!(tp->t_state & TS_TTSTOP))
483 tp->t_state |= TS_FLUSH;
484 }
485
486 void
487 dzstart(struct tty *tp)
488 {
489 struct dz_softc *sc;
490 struct clist *cl;
491 int unit, line, s;
492 char state;
493
494 unit = DZ_I2C(minor(tp->t_dev));
495 line = DZ_PORT(minor(tp->t_dev));
496 sc = dz_cd.cd_devs[unit];
497
498 s = spltty();
499 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
500 return;
501 cl = &tp->t_outq;
502 if (cl->c_cc <= tp->t_lowat) {
503 if (tp->t_state & TS_ASLEEP) {
504 tp->t_state &= ~TS_ASLEEP;
505 wakeup((caddr_t)cl);
506 }
507 selwakeup(&tp->t_wsel);
508 }
509 if (cl->c_cc == 0)
510 return;
511
512 tp->t_state |= TS_BUSY;
513
514 state = DZ_READ_WORD(dr_tcrw) & 255;
515 if ((state & (1 << line)) == 0) {
516 DZ_WRITE_BYTE(dr_tcr, state | (1 << line));
517 }
518 dzxint(sc);
519 splx(s);
520 }
521
522 static int
523 dzparam(struct tty *tp, struct termios *t)
524 {
525 struct dz_softc *sc;
526 int cflag = t->c_cflag;
527 int unit, line;
528 int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
529 int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
530 unsigned lpr;
531 int s;
532
533 unit = DZ_I2C(minor(tp->t_dev));
534 line = DZ_PORT(minor(tp->t_dev));
535 sc = dz_cd.cd_devs[unit];
536
537 /* check requested parameters */
538 if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
539 return (EINVAL);
540
541 tp->t_ispeed = t->c_ispeed;
542 tp->t_ospeed = t->c_ospeed;
543 tp->t_cflag = cflag;
544
545 if (ospeed == 0) {
546 (void) dzmctl(sc, line, 0, DMSET); /* hang up line */
547 return (0);
548 }
549
550 s = spltty();
551
552 lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
553
554 switch (cflag & CSIZE)
555 {
556 case CS5:
557 lpr |= DZ_LPR_5_BIT_CHAR;
558 break;
559 case CS6:
560 lpr |= DZ_LPR_6_BIT_CHAR;
561 break;
562 case CS7:
563 lpr |= DZ_LPR_7_BIT_CHAR;
564 break;
565 default:
566 lpr |= DZ_LPR_8_BIT_CHAR;
567 break;
568 }
569 if (cflag & PARENB)
570 lpr |= DZ_LPR_PARENB;
571 if (cflag & PARODD)
572 lpr |= DZ_LPR_OPAR;
573 if (cflag & CSTOPB)
574 lpr |= DZ_LPR_2_STOP;
575
576 DZ_WRITE_WORD(dr_lpr, lpr);
577
578 (void) splx(s);
579 return (0);
580 }
581
582 static unsigned
583 dzmctl(struct dz_softc *sc, int line, int bits, int how)
584 {
585 unsigned status;
586 unsigned mbits;
587 unsigned bit;
588 int s;
589
590 s = spltty();
591
592 mbits = 0;
593
594 bit = (1 << line);
595
596 /* external signals as seen from the port */
597
598 status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr;
599
600 if (status & bit)
601 mbits |= DML_DCD;
602
603 status = DZ_READ_BYTE(dr_ring);
604
605 if (status & bit)
606 mbits |= DML_RI;
607
608 /* internal signals/state delivered to port */
609
610 status = DZ_READ_BYTE(dr_dtr);
611
612 if (status & bit)
613 mbits |= DML_DTR;
614
615 if (sc->sc_brk & bit)
616 mbits |= DML_BRK;
617
618 switch (how)
619 {
620 case DMSET:
621 mbits = bits;
622 break;
623
624 case DMBIS:
625 mbits |= bits;
626 break;
627
628 case DMBIC:
629 mbits &= ~bits;
630 break;
631
632 case DMGET:
633 (void) splx(s);
634 return (mbits);
635 }
636
637 if (mbits & DML_DTR) {
638 DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit);
639 } else {
640 DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit);
641 }
642
643 if (mbits & DML_BRK) {
644 sc->sc_brk |= bit;
645 DZ_WRITE_BYTE(dr_break, sc->sc_brk);
646 } else {
647 sc->sc_brk &= ~bit;
648 DZ_WRITE_BYTE(dr_break, sc->sc_brk);
649 }
650
651 (void) splx(s);
652 return (mbits);
653 }
654
655 /*
656 * This is called by timeout() periodically.
657 * Check to see if modem status bits have changed.
658 */
659 static void
660 dzscan(void *arg)
661 {
662 struct dz_softc *sc;
663 struct tty *tp;
664 int n, bit, port;
665 unsigned csr;
666 int s;
667
668 s = spltty();
669
670 for (n = 0; n < dz_cd.cd_ndevs; n++) {
671
672 if (dz_cd.cd_devs[n] == NULL)
673 continue;
674
675 sc = dz_cd.cd_devs[n];
676
677 for (port = 0; port < sc->sc_type; port++) {
678
679 tp = sc->sc_dz[port].dz_tty;
680 bit = (1 << port);
681
682 if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) {
683 if (!(tp->t_state & TS_CARR_ON))
684 (*tp->t_linesw->l_modem) (tp, 1);
685 } else if ((tp->t_state & TS_CARR_ON) &&
686 (*tp->t_linesw->l_modem)(tp, 0) == 0) {
687 DZ_WRITE_BYTE(dr_tcr,
688 (DZ_READ_WORD(dr_tcrw) & 255) & ~bit);
689 }
690 }
691
692 /*
693 * If the RX interrupt rate is this high, switch
694 * the controller to Silo Alarm - which means don't
695 * interrupt until the RX silo has 16 characters in
696 * it (the silo is 64 characters in all).
697 * Avoid oscillating SA on and off by not turning
698 * if off unless the rate is appropriately low.
699 */
700
701 csr = DZ_READ_WORD(dr_csr);
702
703 if (sc->sc_rxint > (16*10)) {
704 if ((csr & DZ_CSR_SAE) == 0)
705 DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE);
706 } else if ((csr & DZ_CSR_SAE) != 0)
707 if (sc->sc_rxint < 10)
708 DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE));
709
710 sc->sc_rxint = 0;
711 }
712 (void) splx(s);
713 callout_reset(&dzscan_ch, hz, dzscan, NULL);
714 }
715
716 /*
717 * Called after an ubareset. The DZ card is reset, but the only thing
718 * that must be done is to start the receiver and transmitter again.
719 * No DMA setup to care about.
720 */
721 void
722 dzreset(struct device *dev)
723 {
724 struct dz_softc *sc = (void *)dev;
725 struct tty *tp;
726 int i;
727
728 for (i = 0; i < sc->sc_type; i++) {
729 tp = sc->sc_dz[i].dz_tty;
730
731 if (((tp->t_state & TS_ISOPEN) == 0) || (tp->t_wopen == 0))
732 continue;
733
734 dzparam(tp, &tp->t_termios);
735 dzmctl(sc, i, DML_DTR, DMSET);
736 tp->t_state &= ~TS_BUSY;
737 dzstart(tp); /* Kick off transmitter again */
738 }
739 }
740