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