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