FreeBSD/Linux Kernel Cross Reference
sys/chips/dz_hdw.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: dz_hdw.c,v $
29 * Revision 2.20 93/11/17 16:11:15 dbg
30 * Import kern/time_out.h for hz, timeout, untimeout.
31 * [93/06/10 dbg]
32 *
33 * Revision 2.19 93/05/30 21:07:06 rvb
34 * Added modem CTS/RTS flow control protocol.
35 * [93/05/29 09:43:38 af]
36 *
37 * Revision 2.18 93/05/15 19:36:06 mrt
38 * machparam.h -> machspl.h
39 *
40 * Revision 2.17 93/05/10 20:07:41 rvb
41 * Fixed types.
42 * [93/05/06 09:59:28 af]
43 *
44 * Revision 2.16 93/03/26 17:57:56 mrt
45 * Removed all uses of minor() and dev_t.
46 * [93/03/17 af]
47 *
48 * Revision 2.15 93/02/05 08:18:44 danner
49 * splx -> spltty.
50 * [93/02/04 danner]
51 *
52 * Revision 2.14 93/01/14 17:15:57 danner
53 * Proper spl typing.
54 * [92/11/30 af]
55 *
56 * Revision 2.13 92/05/05 10:04:09 danner
57 * Adapted to new cons_simple_tint() interface.
58 * Also, optimized to invoke the start routine less often.
59 * [92/04/14 12:41:44 af]
60 *
61 * Revision 2.12 92/02/19 16:45:42 elf
62 * Typo.
63 * [92/02/10 17:10:52 af]
64 *
65 * Revision 2.11 91/08/24 11:51:49 af
66 * Spl for 3min, padding of regmap here, a lot of code migrated
67 * elsewhere to become chip-indep, pseudo-dma is gone.
68 * Did not think I changed so much, oops.
69 * [91/08/02 02:31:34 af]
70 *
71 * Revision 2.10 91/06/25 20:53:35 rpd
72 * Tweaks to make gcc happy.
73 * [91/06/25 rpd]
74 *
75 * Revision 2.9 91/06/19 11:47:32 rvb
76 * mips->DECSTATION; vax->VAXSTATION
77 * [91/06/12 14:01:30 rvb]
78 *
79 * File moved here from mips/PMAX since it tries to be generic;
80 * it is used on the PMAX and the Vax3100.
81 * [91/06/04 rvb]
82 *
83 * Revision 2.8 91/05/14 17:21:08 mrt
84 * Correcting copyright
85 *
86 * Revision 2.7 91/05/13 06:03:44 af
87 * Made use of modem control code optional: patch dz_uses_modem_control
88 * if you need it, or call dz_set_modem_control().
89 * [91/05/12 16:06:26 af]
90 *
91 * Revision 2.6 91/02/14 14:33:44 mrt
92 * In interrupt routine, drop priority as now required.
93 * [91/02/12 12:45:12 af]
94 *
95 * Revision 2.5 91/02/05 17:40:35 mrt
96 * Added author notices
97 * [91/02/04 11:13:03 mrt]
98 *
99 * Changed to use new Mach copyright
100 * [91/02/02 12:10:54 mrt]
101 *
102 * Revision 2.4 91/01/08 16:18:17 rpd
103 * Modified dz_param never to use 7bits per char.
104 * Now we can use the serial lines even in non-raw mode,
105 * which means we can login, for instance.
106 * [90/12/31 af]
107 *
108 * Revision 2.3 90/12/05 23:31:02 af
109 * Extensive additions for modem support, pmaxen.
110 * Still to be tested: autoanswer modems.
111 * [90/12/03 23:16:10 af]
112 *
113 * Revision 2.1.1.1 90/11/01 03:37:41 af
114 * Created, from the DEC specs:
115 * "DECstation 3100 Desktop Workstation Functional Specification"
116 * Workstation Systems Engineering, Palo Alto, CA. Aug 28, 1990.
117 * and
118 * "DECstation 5000/200 KN02 System Module Functional Specification"
119 * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
120 * [90/09/03 af]
121 */
122 /*
123 * File: dz_hdw.c
124 * Author: Alessandro Forin, Carnegie Mellon University
125 * Date: 9/90
126 *
127 * Hardware-level operations for the DZ Serial Line Driver
128 */
129
130 #include <dz_.h>
131 #if NDZ_ > 0
132 #include <bm.h>
133 #include <platforms.h>
134
135 #include <mach_kdb.h>
136
137 #include <kern/kern_io.h>
138 #include <kern/time_out.h>
139
140 #include <machine/machspl.h> /* spl definitions */
141 #include <device/io_req.h>
142 #include <device/tty.h>
143
144 #include <chips/busses.h>
145 #include <chips/screen_defs.h>
146 #include <chips/serial_defs.h>
147
148 #include <chips/dz_7085.h>
149
150
151 #ifdef DECSTATION
152 #include <mips/mips_cpu.h>
153 #include <mips/PMAX/kn01.h>
154 #define DZ_REGS_DEFAULT (vm_offset_t)PHYS_TO_K1SEG(KN01_SYS_DZ)
155 #define PAD(n) char n[6];
156 #endif /*DECSTATION*/
157
158 #ifdef VAXSTATION
159 #define DZ_REGS_DEFAULT 0
160 #define wbflush()
161 #define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4))
162 #define PAD(n) char n[2];
163 #endif /*VAXSTATION*/
164
165 #ifndef PAD
166 #define PAD(n)
167 #endif
168
169 typedef struct {
170 volatile unsigned short dz_csr; /* Control and Status */
171 PAD(pad0)
172 volatile unsigned short dz_rbuf; /* Rcv buffer (RONLY) */
173 PAD(pad1)
174 volatile unsigned short dz_tcr; /* Xmt control (R/W)*/
175 PAD(pad2)
176 volatile unsigned short dz_tbuf; /* Xmt buffer (WONLY)*/
177 # define dz_lpr dz_rbuf /* Line parameters (WONLY)*/
178 # define dz_msr dz_tbuf /* Modem status (RONLY)*/
179 PAD(pad3)
180 } dz_padded_regmap_t;
181
182
183 /* this is ok both for rcv (char) and xmt (csr) */
184 #define LINEOF(x) (((x) >> 8) & 0x3)
185
186 /*
187 * Driver status
188 */
189 struct dz7085_softc {
190 dz_padded_regmap_t *regs;
191 unsigned short breaks;
192 unsigned short fake; /* missing rs232 bits */
193 int polling_mode;
194 unsigned short prev_msr;
195 char softCAR;
196 } dz7085_softc_data[NDZ_];
197
198 typedef struct dz7085_softc *dz7085_softc_t;
199
200 dz7085_softc_t dz7085_softc[NDZ_];
201
202 static void check_car(
203 register struct tty *tp,
204 int car);
205 static void check_ring(
206 register struct tty *tp,
207 int ring,
208 int oring);
209
210 void dz7085_softCAR(
211 int unit,
212 int line,
213 boolean_t on)
214 {
215 if (on)
216 dz7085_softc[unit]->softCAR |= 1<<line;
217 else
218 dz7085_softc[unit]->softCAR &= ~(1 << line);
219 }
220
221 static
222 short dz7085_speeds[] =
223 { 0, DZ_LPAR_50, DZ_LPAR_75, DZ_LPAR_110, DZ_LPAR_134_5, DZ_LPAR_150,
224 0, DZ_LPAR_300, DZ_LPAR_600, DZ_LPAR_1200, DZ_LPAR_1800, DZ_LPAR_2400,
225 DZ_LPAR_4800, DZ_LPAR_9600, DZ_LPAR_MAX_SPEED, 0 };
226
227
228 /*
229 * Definition of the driver for the auto-configuration program.
230 */
231
232 boolean_t
233 dz7085_probe(
234 vm_offset_t addr,
235 struct bus_device *ui);
236
237 static void
238 dz7085_attach(
239 register struct bus_device *ui);
240
241 vm_offset_t dz7085_std[NDZ_] = { DZ_REGS_DEFAULT, };
242 struct bus_device *dz7085_info[NDZ_];
243 struct bus_driver dz_driver =
244 { dz7085_probe, 0, dz7085_attach, 0, dz7085_std, "dz", dz7085_info, };
245
246 /*
247 * Adapt/Probe/Attach functions
248 */
249
250 static boolean_t dz7085_full_modem = FALSE;
251 boolean_t dz7085_uses_modem_control = FALSE;
252 /* patch this with adb */
253
254 void dz7085_param(
255 struct tty *tp,
256 int line); /* forward */
257
258 int dz7085_mctl(
259 int dev,
260 int bits,
261 int how);
262
263 void dz7085_start(
264 struct tty *tp);
265
266 int dz7085_getc(
267 int unit,
268 int line,
269 boolean_t wait,
270 boolean_t raw);
271
272 void dz7085_putc(
273 int unit,
274 int line,
275 int c);
276
277 void dz7085_pollc(
278 int unit,
279 boolean_t on);
280
281 void dz7085_set_modem_control(
282 dz7085_softc_t sc,
283 boolean_t on);
284
285 /*
286 * Set up console vectors to point to DZ.
287 */
288 void set_dz_address(
289 int unit,
290 vm_offset_t regs,
291 boolean_t has_modem)
292 {
293 dz7085_std[unit] = regs;
294 dz7085_full_modem = has_modem & dz7085_uses_modem_control;
295
296 /* Do this here */
297 console_probe = dz7085_probe;
298 console_param = dz7085_param;
299 console_start = dz7085_start;
300 console_putc = dz7085_putc;
301 console_getc = dz7085_getc;
302 console_pollc = dz7085_pollc;
303 console_mctl = dz7085_mctl;
304 console_softCAR = dz7085_softCAR;
305
306 }
307
308 boolean_t
309 dz7085_probe(
310 vm_offset_t xxx,
311 struct bus_device *ui)
312 {
313 int unit = ui->unit;
314 dz7085_softc_t sc;
315 register int cntr;
316 register dz_padded_regmap_t *regs;
317
318 static int probed_once = 0;
319
320 regs = (dz_padded_regmap_t *)dz7085_std[unit]; /* like the old days! */
321 if (regs == 0)
322 return 0;
323 /*
324 * If this is not there we are toast
325 */
326 if (check_memory(regs, 0))
327 return 0;
328
329 if (probed_once++)
330 return 1;
331
332 sc = &dz7085_softc_data[unit];
333 dz7085_softc[unit] = sc;
334 sc->regs = regs;
335
336 for (cntr = unit*NDZ_LINE; cntr < NDZ_LINE*(unit+1); cntr++) {
337 console_tty[cntr]->t_addr = (char*)regs;
338 console_tty[cntr]->t_state |= TS_MIN;
339 }
340
341 /* pmaxen et al. lack many modem bits */
342 dz7085_set_modem_control(sc, dz7085_full_modem);
343
344 regs->dz_tcr = 0;/* disable all lines, drop RTS,DTR */
345 return 1;
346 }
347
348 boolean_t dz7085_timer_started = FALSE;
349 void dz7085_scan(); /* forward */
350
351 static void
352 dz7085_attach(
353 register struct bus_device *ui)
354 {
355 int unit = ui->unit;
356 extern int tty_inq_size;
357 int i;
358
359 /* We only have 4 ttys, but always at 9600
360 * Give em a lot of room
361 */
362 tty_inq_size = 2048;
363 for (i = 0; i < (NDZ_*NDZ_LINE); i++)
364 ttychars(console_tty[i]);
365
366 if (!dz7085_timer_started) {
367 dz7085_timer_started = TRUE;
368 dz7085_scan();
369 }
370
371 #if NBM > 0
372 if (SCREEN_ISA_CONSOLE()) {
373 printf("\n sl0: "); lk201_attach(0, unit);
374 printf("\n sl1: "); mouse_attach(0, unit);
375 printf("\n sl2: \n sl3: ");
376 if (rcline == 3) printf("( rconsole )");
377 } else {
378 #endif /*NBM > 0*/
379 printf("\n sl0:\n sl1:\n sl2:\n sl3: ( alternate console )");
380 #if NBM > 0
381 }
382 #endif
383 }
384
385 /*
386 * Would you like to make a phone call ?
387 */
388 void dz7085_set_modem_control(
389 dz7085_softc_t sc,
390 boolean_t on)
391 {
392 if (on)
393 /* your problem if the hardware then is broke */
394 sc->fake = 0;
395 else
396 sc->fake = DZ_MSR_CTS3|DZ_MSR_DSR3|DZ_MSR_CD3|
397 DZ_MSR_CTS2|DZ_MSR_CD2;
398 }
399
400 /*
401 * Polled I/O (debugger)
402 */
403 void
404 dz7085_pollc(
405 int unit,
406 boolean_t on)
407 {
408 dz7085_softc_t sc = dz7085_softc[unit];
409
410 if (on) {
411 sc->polling_mode++;
412 #if NBM > 0
413 screen_on_off(unit, TRUE);
414 #endif /* NBM > 0 */
415 } else
416 sc->polling_mode--;
417 }
418
419 /*
420 * Interrupt routine
421 */
422 void dz_intr(
423 int unit,
424 spl_t spllevel)
425 {
426 dz7085_softc_t sc = dz7085_softc[unit];
427 register dz_padded_regmap_t *regs = sc->regs;
428 register short csr;
429
430 csr = regs->dz_csr;
431
432 if (csr & DZ_CSR_TRDY) {
433 register int c;
434
435 c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), FALSE);
436 if (c == -1) {
437 /* no more data for this line */
438 regs->dz_tcr &= ~(1 << LINEOF(csr));
439 c = cons_simple_tint(unit*NDZ_LINE + LINEOF(csr), TRUE);
440 /* because funny race possible ifnot */
441 }
442 if (c != -1) {
443 regs->dz_tbuf = (c & 0xff) | sc->breaks;
444 /* and leave it enabled */
445 }
446 }
447 if (sc->polling_mode)
448 return;
449
450 while (regs->dz_csr & DZ_CSR_RDONE) {
451 short c = regs->dz_rbuf;
452 spl_t oldspl;
453
454 #ifdef DECSTATION
455 oldspl = splhigh();
456 splx(spllevel);
457 #endif /*DECSTATION*/
458 cons_simple_rint(unit*NDZ_LINE+LINEOF(c), LINEOF(c),
459 c&0xff, c&0xff00);
460 #ifdef DECSTATION
461 splx(oldspl);
462 #endif /*DECSTATION*/
463 }
464 }
465
466 /*
467 * Start transmission on a line
468 */
469 void dz7085_start(
470 struct tty *tp)
471 {
472 register dz_padded_regmap_t *regs;
473 register int line;
474
475 line = tp->t_dev;
476
477 regs = (dz_padded_regmap_t*)tp->t_addr;
478 regs->dz_tcr |= (1<<(line&3));
479
480 /* no, we do not need a char out to interrupt */
481 }
482
483 /*
484 * Get a char from a specific DZ line
485 */
486 int
487 dz7085_getc(
488 int unit,
489 int line,
490 boolean_t wait,
491 boolean_t raw)
492 {
493 dz7085_softc_t sc = dz7085_softc[unit];
494 spl_t s = spltty();
495 register dz_padded_regmap_t *regs = sc->regs;
496 unsigned short c;
497 int rl;
498
499 again:
500 /*
501 * wait till something in silo
502 */
503 while ((regs->dz_csr & DZ_CSR_RDONE) == 0 && wait)
504 delay(10);
505 c = regs->dz_rbuf;
506
507 /*
508 * check if right line. For keyboard, rconsole is ok too
509 */
510 rl = LINEOF(c);
511 if (wait && (line != rl) &&
512 !((line == DZ_LINE_KEYBOARD) && rcline == rl))
513 goto again;
514 /*
515 * bad chars not ok
516 */
517 if ((c & (DZ_RBUF_PERR | DZ_RBUF_OERR | DZ_RBUF_FERR)) && wait)
518 goto again;
519
520 splx(s);
521
522 /*
523 * if nothing found return -1
524 */
525 if ( ! (c & DZ_RBUF_VALID))
526 return -1;
527
528 #if NBM > 0
529 if ((rl == DZ_LINE_KEYBOARD) && !raw && SCREEN_ISA_CONSOLE())
530 return lk201_rint(SCREEN_CONS_UNIT(), c, wait, sc->polling_mode);
531 else
532 #endif /* NBM > 0 */
533 return c & DZ_RBUF_CHAR;
534 }
535
536 /*
537 * Put a char on a specific DZ line
538 */
539 void dz7085_putc(
540 int unit,
541 int line,
542 int c)
543 {
544 dz7085_softc_t sc = dz7085_softc[unit];
545 register dz_padded_regmap_t *regs = sc->regs;
546 spl_t s = spltty();
547
548 /*
549 * do not change the break status of other lines
550 */
551 c = (c & 0xff) | sc->breaks;
552
553 /*
554 * Xmit line info only valid if TRDY,
555 * but never TRDY if no xmit enabled
556 */
557 if ((regs->dz_tcr & DZ_TCR_LNENB) == 0)
558 goto select_it;
559
560 while ((regs->dz_csr & DZ_CSR_TRDY) == 0)
561 delay(100);
562
563 /*
564 * see if by any chance we are already on the right line
565 */
566 if (LINEOF(regs->dz_csr) == line)
567 regs->dz_tbuf = c;
568 else {
569 unsigned short tcr;
570 select_it:
571 tcr = regs->dz_tcr;
572 regs->dz_tcr = (1 << line) | (tcr & 0xff00);
573 wbflush();
574
575 do
576 delay(2);
577 while ((regs->dz_csr & DZ_CSR_TRDY) == 0 ||
578 (LINEOF(regs->dz_csr) != line));
579
580 regs->dz_tbuf = c;
581 wbflush();
582
583 /* restore previous settings */
584 regs->dz_tcr = tcr;
585 }
586
587 splx(s);
588 }
589
590
591 void dz7085_param(
592 register struct tty *tp,
593 register int line)
594 {
595 register dz_padded_regmap_t *regs;
596 register int lpr;
597
598 line = tp->t_dev;
599 regs = dz7085_softc[line/NDZ_LINE]->regs;
600
601 /*
602 * Do not let user fool around with kbd&mouse
603 */
604 #if NBM > 0
605 if (screen_captures(line)) {
606 tp->t_ispeed = tp->t_ospeed = B4800;
607 tp->t_flags |= TF_LITOUT;
608 }
609 #endif /* NBM > 0 */
610 regs->dz_csr = DZ_CSR_MSE|DZ_CSR_RIE|DZ_CSR_TIE;
611 if (tp->t_ispeed == 0) {
612 (void) (*console_mctl)(tp->t_dev, TM_HUP, DMSET);
613 /* hang up line */
614 return;
615 }
616 /* 19200/38400 here */
617 lpr = dz7085_speeds[tp->t_ispeed] | (line&DZ_LPAR_LINE) | DZ_LPAR_ENABLE;
618 lpr |= DZ_LPAR_8BITS;
619
620 if ((tp->t_flags & (TF_ODDP|TF_EVENP)) == TF_ODDP)
621 lpr |= DZ_LPAR_ODD_PAR;
622
623 if (tp->t_ispeed == B110)
624 lpr |= DZ_LPAR_STOP;
625 regs->dz_lpr = lpr;
626 }
627
628 /*
629 * This is a total mess: not only are bits spread out in
630 * various registers, but we have to fake some for pmaxen.
631 */
632 int dz7085_mctl(
633 int dev,
634 int bits,
635 int how)
636 {
637 register dz_padded_regmap_t *regs;
638 register int unit;
639 register int tcr, msr, brk, n_tcr, n_brk;
640 int b;
641 spl_t s;
642 dz7085_softc_t sc;
643
644 unit = dev;
645
646 /* no modem support on lines 0 & 1 */
647 /* XXX break on 0&1 */
648 if ((unit & 2) == 0)
649 return TM_LE|TM_DTR|TM_CTS|TM_CAR|TM_DSR;
650
651 b = 1 ^ (unit & 1); /* line 2 ? */
652
653 sc = dz7085_softc[unit>>2];
654 regs = sc->regs;
655 s = spltty();
656
657 tcr = ((regs->dz_tcr | (sc->fake>>4)) & 0xf00) >> (8 + b*2);
658 brk = (sc->breaks >> (8 + (unit&3))) & 1; /* THE break bit */
659
660 n_tcr = (bits & (TM_RTS|TM_DTR)) >> 1;
661 n_brk = (bits & TM_BRK) >> 9;
662
663 /* break transitions, must 'send' a char out */
664 bits = (brk ^ n_brk) & 1;
665
666 switch (how) {
667 case DMSET:
668 tcr = n_tcr;
669 brk = n_brk;
670 break;
671
672 case DMBIS:
673 tcr |= n_tcr;
674 brk |= n_brk;
675 break;
676
677 case DMBIC:
678 tcr &= ~n_tcr;
679 brk = 0;
680 break;
681
682 case DMGET:
683 msr = ((regs->dz_msr|sc->fake) & 0xf0f) >> (b*8);
684 (void) splx(s);
685 return (tcr<<1)|/* DTR, RTS */
686 ((msr&1)<<5)|/* CTS */
687 ((msr&2)<<7)|/* DSR */
688 ((msr&0xc)<<4)|/* CD, RNG */
689 (brk << 9)|/* BRK */
690 TM_LE;
691 }
692 n_tcr = (regs->dz_tcr & ~(3 << (8 + b*2))) |
693 (tcr << (8 + b*2));
694
695 regs->dz_tcr = n_tcr;
696 sc->fake = (sc->fake & 0xf0f) | (n_tcr<<4&0xf000);
697
698 sc->breaks = (sc->breaks & ~(1 << (8 + (unit&3)))) |
699 (brk << (8 + (unit&3)));
700 if(bits) (*console_putc)( unit>>2, unit&3, 0);/* force break, now */
701 (void) splx(s);
702 return 0;/* useless to compute it */
703 }
704
705 /*
706 * Periodically look at the CD signals:
707 * they do not generate interrupts.
708 */
709 void dz7085_scan()
710 {
711 register i;
712 register dz_padded_regmap_t *regs;
713 register msr;
714 register struct tty *tp;
715
716 for (i = 0; i < NDZ_; i++) {
717 dz7085_softc_t sc = dz7085_softc[i];
718 register int temp;
719
720 if (sc == 0)
721 continue;
722 regs = sc->regs;
723
724 tp = console_tty[i * NDZ_LINE];
725
726 msr = regs->dz_msr | (sc->fake & 0xf0f);
727 if ((temp = sc->softCAR) != 0) {
728 if (temp & 0x4)
729 msr |= DZ_MSR_CD2 | DZ_MSR_CTS2;
730 if (temp & 0x8)
731 msr |= DZ_MSR_CD3 | DZ_MSR_CTS3;
732 }
733
734 /* Lines 0 and 1 have carrier on by definition */
735
736 check_car(&tp[0], 1);
737 check_car(&tp[1], 1);
738 check_car(&tp[2], msr & DZ_MSR_CD2);
739 check_car(&tp[3], msr & DZ_MSR_CD3);
740
741 /* nothing else to do if no msr transitions */
742 if ((temp = sc->prev_msr) == msr)
743 continue;
744 else
745 sc->prev_msr = msr;
746
747 /* see if we have an incoming call */
748 #define RING (DZ_MSR_RI2|DZ_MSR_RI3)
749 if ((msr & RING) != (temp & RING)) {
750 /*printf("%s %x->%x\n", "ET Phone RI", temp & RING, msr & RING);*/
751 check_ring(&tp[2], msr & DZ_MSR_RI2, temp & DZ_MSR_RI2);
752 check_ring(&tp[3], msr & DZ_MSR_RI3, temp & DZ_MSR_RI3);
753 }
754 #undef RING
755 /* see if we must do flow-control */
756 if ((msr ^ temp) & DZ_MSR_CTS2) {
757 tty_cts(&tp[2], msr & DZ_MSR_CTS2);
758 }
759 if ((msr ^ temp) & DZ_MSR_CTS3) {
760 tty_cts(&tp[3], msr & DZ_MSR_CTS3);
761 }
762 }
763 timeout(dz7085_scan, 0, 2*hz);
764 }
765
766 static void dz7085_hup(
767 register struct tty *tp)
768 {
769 (*console_mctl)(tp->t_dev, TM_DTR, DMBIC);
770 }
771
772 static void check_car(
773 register struct tty *tp,
774 int car)
775 {
776 if (car) {
777 /* cancel modem timeout if need to */
778 if (car & (DZ_MSR_CD2|DZ_MSR_CD3))
779 untimeout(dz7085_hup, tp);
780
781 /* I think this belongs in the MI code */
782 if (tp->t_state & TS_WOPEN)
783 tp->t_state |= TS_ISOPEN;
784 /* carrier present */
785 if ((tp->t_state & TS_CARR_ON) == 0)
786 (void)ttymodem(tp, 1);
787 } else if ((tp->t_state&TS_CARR_ON) && ttymodem(tp, 0) == 0)
788 (*console_mctl)( tp->t_dev, TM_DTR, DMBIC);
789 }
790
791 int dz7085_ring_timeout = 60; /* seconds, patchable */
792
793 static void check_ring(
794 register struct tty *tp,
795 int ring,
796 int oring)
797 {
798 if (ring == oring)
799 return;
800 if (ring) {
801 (*console_mctl)( tp->t_dev, TM_DTR, DMBIS);
802 /* give it ample time to find the right carrier */
803 timeout(dz7085_hup, tp, dz7085_ring_timeout*hz);
804 }
805 }
806 #endif /* NDZ_ > 0 */
Cache object: 2ef425a4b66f42c1ee67634e3208c32a
|